หน้าจอการจัดส่งแสดงการหมดเวลาและ Jenkins ไม่บันทึกอะไรเลย ซึ่งเป็นสัญญาณของการเชื่อมต่อที่ไม่เคยมาถึง GitHub ส่ง webhook เป็น HTTP POST ขาออกจากโครงสร้างพื้นฐานของตัวเองไปยัง payload URL ที่คุณกำหนดค่าไว้ VPN ปกป้อง Jenkins โดยการปฏิเสธการเชื่อมต่อแบบนั้นโดยตรง ไม่มีอะไรเสียหายในทั้งสองฝ่าย ปัญหาคือทิศทางของคำขอ

สิ่งที่การจัดส่งพยายามทำจริง ๆ

GitHub แปลงชื่อโฮสต์ใน payload URL แล้วเชื่อมต่อจากอินเทอร์เน็ตสาธารณะ ถ้า URL นั้นชี้ไปที่ที่อยู่ส่วนตัว หรือชื่อที่แปลงได้เฉพาะภายในเครือข่ายของคุณ ความพยายามจะล้มเหลวก่อนที่จะมีการส่งคำขอใด ๆ ถ้าชี้ไปที่ชื่อสาธารณะที่ edge ของคุณทิ้ง ความพยายามจะหมดเวลาแทน

ความแตกต่างนี้สำคัญต่อการวินิจฉัย ความล้มเหลวของ DNS และพอร์ตที่ถูกกรองดูเหมือนไม่มีอะไรเกิดขึ้นฝั่ง Jenkins และทั้งคู่ปรากฏบน GitHub เป็นการจัดส่งที่ล้มเหลวพร้อมเหตุผลต่างกันที่แนบมา อ่านเหตุผลนั้นก่อนเปลี่ยน URL

อุโมงค์ที่หมุนออกไปข้างนอกไม่ได้สร้างผู้ฟัง นั่นคือส่วนที่ผู้คนคาดว่าจะทำงานต่างออกไป

สามวิธีในการแก้ทิศทางการเชื่อมต่อ

ทุกวิธีเปลี่ยนว่าใครเป็นผู้เริ่มการเชื่อมต่อ และมีเพียงสามรูปแบบ

ApproachWho initiatesWhat you give up
Relay serviceAn outbound client inside the networkA third party sees every payload
Reverse tunnel or ingressThe public edge, into a controlled listenerAn inbound surface you must secure
Runner or pollingThe agent, outbound to GitHubInstant delivery, replaced by a schedule

การดึงข้อมูลเป็นระยะเป็นวิธีที่หรูหราน้อยที่สุดและดูแลง่ายที่สุด relay ให้ผลตอบกลับเกือบทันทีโดยไม่ต้องเปิดพอร์ต runner มักเป็นคำตอบที่ถูกต้องเมื่อความลับของ payload ตัดบุคคลที่สามออก เพราะงานสามารถรันบนเครื่องที่อยู่ในเครือข่ายอยู่แล้ว

เลือกจากสิ่งที่คุณดูแลได้ ไม่ใช่จากสิ่งที่ฟังดูทันสมัย

ส่งต่อการจัดส่งออกไปข้างนอกด้วย smee

สร้างช่องทางบนบริการ relay และเก็บ URL ไว้ ภายในเครือข่าย ให้ติดตั้งไคลเอนต์และส่งต่อการจัดส่งไปยังเส้นทางที่ Jenkins คาดหวัง payload URL ในการตั้งค่าที่เก็บจะกลายเป็น URL ของช่องทาง โดยตั้งประเภทเนื้อหาเป็น application/json

sudo npm install --global smee-client
smee -u CHANNEL_URL --path /github-webhook/ --port 8080

รายละเอียดสามอย่างตัดสินว่ามันจะทำงานหรือไม่ เส้นทางต้องตรงกับสิ่งที่ Jenkins คาดหวังสำหรับเหตุการณ์ GitHub ซึ่งโดยค่าเริ่มต้นคือ /github-webhook/ Jenkins ต้องรับฟังบนพอร์ตที่คุณให้ไคลเอนต์ และ Jenkins URL ที่กำหนดในงานต้องสอดคล้องกับเส้นทางนั้น ไม่เช่นนั้นเหตุการณ์จะมาถึงแล้วถูกทิ้ง

ความไม่ตรงกันของเครื่องหมายทับท้ายจะสร้าง 404 ซึ่งอ่านดูเหมือนการจัดส่งล้มเหลวและไม่ใช่

รันให้อยู่รอดทั้งสัปดาห์

ไคลเอนต์เบื้องหน้าจะตายไปพร้อมเทอร์มินัล และ webhook ทำงานได้หนึ่งวันแล้วหยุด ให้ unit ที่มี Restart=always แก่มัน รันเป็นผู้ใช้ Jenkins และอ่าน journal หลังการจัดส่งจริงครั้งแรก ขั้นตอนสุดท้ายนั้นคือสิ่งที่แยก relay ที่ทำงานได้ออกจาก relay ที่กำหนดค่าไว้

[Unit]
Description=smee webhook relay
After=network.target

[Service]
Type=simple
Restart=always
RestartSec=2
User=jenkins
ExecStart=/usr/bin/smee -u CHANNEL_URL --path /github-webhook/ --port 8080

[Install]
WantedBy=multi-user.target

ทดสอบด้วย push จริงแทนปุ่มเล่นซ้ำ การเล่นซ้ำจะฝึก payload ที่เก็บไว้ของ relay ไม่ใช่เส้นทางจาก GitHub ถึงช่องทางของคุณ จึงอาจผ่านได้ในขณะที่การจัดส่งสดยังล้มเหลว

แจ้งเตือนเมื่อ unit หยุด relay ที่ล่มอยู่นั้นเงียบโดยธรรมชาติ และความเงียบคือสิ่งที่คุณกำลังดีบักอยู่แล้ว

relay เห็นอะไรได้บ้าง และเมื่อใดไม่ควรใช้

relay ทำให้ payload สิ้นสุด จึงเห็นชื่อที่เก็บ ข้อมูล commit และทุกอย่างที่เหตุการณ์พามา ปฏิบัติต่อ URL ของช่องทางเป็นปลายทางสาธารณะ เก็บ secret token ของ Jenkins ให้กำหนดค่าไว้เพื่อให้การจัดส่งปลอมถูกปฏิเสธ และจำกัด token ที่ Jenkins ใช้ให้เหลือขั้นต่ำที่จำเป็น

ถ้าความลับของ payload ตัดสิ่งนั้นออก runner ที่โฮสต์เองหรืออุโมงค์ย้อนกลับที่ผ่านการรับรอง คือคำตอบ

relay ตอนนี้เป็นโครงสร้างพื้นฐาน และสมควรได้รับการตรวจทานเช่นเดียวกับ build ที่มันกระตุ้น หมุนช่องทางถ้ามันรั่ว และบันทึกวันที่คุณตรวจสอบการจัดส่งสดครั้งล่าสุด ใส่วันที่นั้นใน runbook ข้าง URL ของช่องทาง relay ที่ไม่มีใครตรวจทานมาหนึ่งปีคือปลายทางสาธารณะที่ไม่มีใครเป็นเจ้าของ

บทความที่เกี่ยวข้อง