چرا webhookهای GitHub در برابر Jenkins پشت VPN به پایان زمان میرسند
GitHub وبهوکها را به سمت داخل میفرستد، بنابراین VPNی که از Jenkins محافظت میکند آنها را رد میکند. تحویل را از طریق relay به بیرون بفرستید یا وبهوک را با عاملی که نظرسنجی میکند جایگزین کنید.
صفحه تحویل یک پایان زمان نشان میدهد و Jenkins چیزی ثبت نمیکند، که نشانه اتصالی است که هرگز نرسید. GitHub وبهوک را بهصورت یک HTTP POST خروجی از زیرساخت خودش به payload URL که پیکربندی کردهاید میفرستد. یک VPN از Jenkins محافظت میکند یعنی دقیقاً همین نوع اتصال را رد میکند. هیچچیز در هیچکدام از دو طرف خراب نیست. مشکل جهت درخواست است.
تحویل در واقع چه چیزی را میآزماید
GitHub نام میزبان در payload URL را تفکیک میکند و از اینترنت عمومی به آن متصل میشود. اگر آن URL به یک نشانی خصوصی اشاره کند، یا به نامی که فقط داخل شبکه شما تفکیک میشود، تلاش پیش از ارسال هر درخواستی شکست میخورد. اگر به نام عمومی اشاره کند که لبه شما آن را دور میریزد، در عوض تلاش به پایان زمان میرسد.
این تمایز برای عیبیابی مهم است. شکست DNS و پورت فیلترشده هر دو طوری به نظر میرسند که گویی در سمت Jenkins چیزی رخ نداده، و هر دو در GitHub بهصورت تحویل ناموفق با دلیلی متفاوت ضمیمهشده ظاهر میشوند. پیش از تغییر URL آن دلیل را بخوانید.
تونلی که به سمت بیرون شماره میگیرد شنونده ایجاد نمیکند. دقیقاً همین بخش است که مردم انتظار دارند متفاوت کار کند.
سه راه برای اصلاح جهت اتصال
هر راهحل تغییر میدهد که چه کسی اتصال را آغاز میکند، و فقط سه شکل وجود دارد.
| Approach | Who initiates | What you give up |
|---|---|---|
| Relay service | An outbound client inside the network | A third party sees every payload |
| Reverse tunnel or ingress | The public edge, into a controlled listener | An inbound surface you must secure |
| Runner or polling | The agent, outbound to GitHub | Instant 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 تولید میکند که مانند شکست تحویل خوانده میشود و چنین نیست.
اجرای آن بهگونهای که از هفته جان سالم به در ببرد
کلاینت پیشزمینه با ترمینال میمیرد، و وبهوکها یک روز کار میکنند و سپس متوقف میشوند. به آن یک 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ی که هیچکس یک سال بازبینی نکرده باشد یک نقطه پایانی عمومی است که هیچکس مالک آن نیست.