نسخه را با GitHub Actions ببند، ولی فقط وقتی قانون کامیت روشن است
نسخهگذاری دستی خراب میشود چون چند فایل باید یک عدد را بگویند و آدم وسط انتشار یادش میرود کدام را عوض کرده. `package.json` یک نسخه است، برچسب git نسخه دیگر، و یادداشت انتشار یا ننوشته شده یا با diff نمیخواند. GitHub Actions این کار تکراری را خوب برمیدارد. جادو نیست. اگر قانون کامیت و مرز شاخه روشن نباشد، فقط همان بینظمی را سریعتر منتشر میکند.
workflow فایل YAML است که میگوید با کدام رویداد چه شود. برای نسخه، رویداد معمولاً push به شاخه انتشار است یا ساخت دستی که انسان عمداً زده، نه هر push به هر شاخه.
مشکل دستی همان ناهماهنگی است، نه کندی
نسخه ناهماهنگ اعتماد را میشکند. مصرفکننده بسته نمیداند کدام عدد راست است. مشارکتکننده نمیداند تغییر ناسازگار بوده یا رفع اشکال. این را با «ساعت تلفشده» اندازه نگیر. با تعداد جایی اندازه بگیر که نسخه باید یکی باشد و نیست: فایل بسته، برچسب، یادداشت انتشار، و اگر تصویر کانتینر داری برچسب تصویر.
اتوماسیون این فهرست را یک جا جلو میبرد. تحلیل پیام کامیت از آخرین انتشار، تعیین bump، بهروزرسانی فایل نسخه، ساخت برچسب، و در صورت نیاز انتشار بسته. به شرطی که ورودیاش قابل اعتماد باشد.
Semver بدون قرارداد کامیت اتوماتیک نمیشود
نسخهگذاری معنایی سه عدد است. MAJOR برای تغییر ناسازگار، MINOR برای قابلیت سازگار، PATCH برای رفع سازگار. GitHub Actions خودش نمیفهمد تغییر تو کدام است مگر قاعده را به آن بدهی.
رایجترین قاعده پیام کامیت قراردادی است. `fix:` برای patch، `feat:` برای minor، و علامت شکست مثل `feat!:` یا پاورقی `BREAKING CHANGE:` برای major. workflow از آخرین برچسب به بعد پیامها را میخواند و بالاترین bump لازم را برمیدارد. این دستیار هوشمند نیست. مفسر قاعدهای است که تیم قبول کرده.
اگر نصف تیم پیام آزاد مینویسد، محاسبه نسخه دروغ میگوید. یا قاعده را در بازبینی PR اعمال کن، یا bump را دستی و صریح کن و اتوماسیون فقط برچسب و یادداشت را بسازد. هر دو شریفاند. مخلوطشان نه.
ابزارهای شناختهشده مثل semantic-release یا release-please همین ایده را بستهبندی کردهاند. اسم ابزار را به نسخه خاصی قفل نکن. رفتار را قفل کن: ورودی پیام کامیت یا changeset، خروجی برچسب و یادداشت، و یک PR یا کامیت نسخه که قابل بازبینی باشد.
تریگر را به شاخه انتشار محدود کن
اگر هر push به `main` نسخه میزند، توسعه روزمره هم انتشار میشود. اگر کار جاری روی شاخه دیگر است و فقط ادغام به `main` یعنی انتشار، تریگر را همانجا بگذار. برای پیشانتشار، شاخه یا برچسب جدا با پسوند روشن بهتر از این است که beta و stable یک شمارنده را شریک شوند و کسی نفهمد کدام تصویر روی پروداکشن است.
برچسب git نشانگر ماندگار تاریخ است. قرارداد نام را ثابت نگه دار، مثلاً `v` بهعلاوه semver. برچسب میتواند workflow بعدی را راه بیندازد: ساخت تصویر، انتشار npm، یا استقرار. این آبشار مفید است به شرطی که هر مرحله مجوز جدا و شکست قابلدیدن داشته باشد. یک workflow غول که هم نسخه میزند هم به پروداکشن میرود، وقتی محاسبه نسخه غلط باشد پروداکشن را هم غلط میکند.
مجوز را کم کن و راز را داخل فایل نگذار
workflow انتشار به نوشتن محتوا یا برچسب و گاهی `contents: write` و `id-token` برای انتشار بسته نیاز دارد. همان را بده، نه بیشتر. توکن شخصی را در YAML سختکد نکن. از secret مخزن یا محیط GitHub استفاده کن، و محیط را اگر میخواهی تأیید دستی قبل از انتشار پروداکشن داشته باشی.
`GITHUB_TOKEN` پیشفرض برای خیلی از کارها کافی است و با مجوز job محدود میشود. اگر ابزاری اصرار به توکن بلندمدت دارد، سؤال کن آیا واقعاً لازم است یا عادت سند قدیمی است.
اول جایی تمرین کن که برچسب اضافی ارزان باشد
workflow نسخه را اول روی مخزن آزمون یا شاخهای که برچسبش به مشتری نمیرسد امتحان کن. باگ محاسبه نسخه، اگر روی مخزن اصلی باشد، دهها برچسب و انتشار الکی میسازد. پاک کردنشان از نوشتن workflow سختتر است.
لاگ را صریح کن: آخرین برچسب دیدهشده، پیامهایی که شمرده شدهاند، bump محاسبهشده، و اینکه آیا واقعاً برچسب ساخته شد. خطای مجوز معمولاً از تنظیم مخزن یا `permissions` job است. محاسبه غلط نسخه معمولاً از پیام کامیت ناسازگار یا از این است که تاریخچه shallow کلون شده و برچسب قبلی دیده نمیشود. `fetch-depth: 0` را وقتی لازم داری که ابزار باید تا آخرین برچسب برگردد، نه بهصورت عادت کور.
تصویر و بسته را به همان نسخه وصل کن
برای اپ Node، بهروزرسانی نسخه در `package.json`، برچسب، و انتشار npm باید یک تصمیم باشند. اگر بسته عمومی است، انتشار را به ساخت برچسب گره بزن نه به هر کامیت، تا نسخه npm با برچسب git یکی باشد.
برای تصویر کانتینر، همان نسخه را برچسب تصویر کن. `latest` بهتنهایی نقطه بازگشت نیست. برچسب نسخه است که میگوید کدام ساخت دیروز سالم بود. چند سرویس اگر هر کدام شمارنده خودشان را داشته باشند اشکالی ندارد. اشکال این است که یک سرویس دو برچسب متفاوت برای یک digest داشته باشد و سند استقرار یکی را بگوید و کلاستر دیگری را.
پرسشهای کوتاه
**هر پروژه باید semantic-release داشته باشد؟** نه. اگر هفتهای یک انتشار دستی داری و فایل نسخه یکی است، اتوماسیون شاید بیش از درد باشد. وقتی چند فایل و چند مصرفکننده باید یک عدد را ببینند، workflow میارزد.
**روی هر push به main نسخه بزنم؟** فقط اگر main واقعاً خط انتشار است. وگرنه توسعه را انتشار میکنی.
**یادداشت انتشار را مدل بنویسد؟** میتواند پیشنویس از روی کامیت بسازد. منبع حقیقت همچنان بازه کامیت و قاعده bump است، نه لحن پاراگراف.