أتمتة توليد Changelog و GitHub Releases بـ release-please
لو بتقعد كل أسبوع 20 دقيقة تفتح CHANGELOG.md وتلصق فيه "أضفنا كذا، صلّحنا كذا" يدويًا، وبعدين تفتح تاب GitHub Releases وتلصق نفس الكلام تاني، وتزوّد رقم الـ version في package.json بإيدك — ده شغل روبوت بتعمله إنت. release-please من Google بيعمل الثلاثة دول من commits الموجودة عندك أصلاً، بدون ما تتعلم أداة جديدة. الناتج: Release PR واحد بيقعد مفتوح على main، لمّا تعمله merge، بيتولّد CHANGELOG محدّث، tag جديد، و GitHub Release رسمي — كله في 15 ثانية.
المشكلة باختصار
الـ CHANGELOG اليدوي بيفشل لأربع أسباب. الأول: الناس بتنساه. الثاني: بيتكتب يوم الـ release بس، فبيعتمد على ذاكرة اللي بيكتب. الثالث: الـ version في package.json والـ tag في git والـ release على GitHub — ثلاثتهم لازم يطابقوا، وده بيحصل مرة من كل عشرة. الرابع: في monorepo فيه 5 packages، الشغل ده بيتضرب في 5. الحل المنطقي إن الـ source of truth يكون الـ commits نفسها، طالما إنت بتكتبها بصيغة منظّمة.
مثال بسيط الأول: ليه Conventional Commits أصلاً
تخيّل إنك قاعد في مطعم، والجرسون بدل ما يقولّك "عندنا أكل"، بيقولّك: "الطبق الجديد: مكرونة بالبشاميل. التعديل على الطبق القديم: الكبسة بقت بتوابل أقل. مشكلة اتحلّت: الحمّص مبقاش فيه ملح زيادة." ده بالظبط اللي Conventional Commits بتعمله للـ git: بتخلّي كل commit يقول لنفسه هو feature جديد، تصليح bug، ولا مجرد تنسيق.
كل commit بيبدأ بـ نوع محدد:
feat:ميزة جديدة → بيزوّد الـ minor version (1.2.0 → 1.3.0)fix:تصليح bug → بيزوّد الـ patch version (1.2.0 → 1.2.1)feat!:أوBREAKING CHANGE:→ بيزوّد الـ major version (1.2.0 → 2.0.0)chore:,docs:,refactor:,test:→ مش بتظهر في الـ changelog غالبًا
التعريف العلمي الدقيق
Conventional Commits هي مواصفة (specification) لصياغة رسائل الـ commits بصيغة قابلة للقراءة آليًا، مبنية فوق Semantic Versioning (SemVer). كل رسالة بتتكوّن من type + scope اختياري + description. الأدوات اللي بتلتزم بالمواصفة دي تقدر تستنتج رقم الإصدار التالي بدون تدخّل بشري. release-please بيطبّق نفس المنطق ده: بيفحص كل الـ commits من آخر tag، يحدّد أكبر نوع فيهم (major > minor > patch)، ويحسب الـ version الجديد.
إزاي release-please بيشتغل فعلاً
الـ flow بسيط لدرجة مدهشة:
- إنت بتدفع commits عادي على
mainبصيغة Conventional Commits. - release-please بيشتغل كـ GitHub Action على كل push.