من كابوس الإصدارات اليدوية إلى الأتمتة: كيف أنقذنا ‘Semantic Release’ من جحيم الترقيم العشوائي؟

ليلة خميس لا تُنسى: حين كان الإصدار يدوياً

أذكرها وكأنها البارحة، ليلة خميس وكنا على وشك إنهاء أسبوع عمل طويل. الفريق كله كان يجهز نفسه للعودة إلى البيت، لكن كان هناك تحديث عاجل لا بد من إطلاقه. “شغلة بسيطة يا أبو عمر، مجرد إصلاح لـ bug صغير”، قال لي أحد المطورين الشباب في الفريق.

بكل ثقة، قمنا بدمج التغيير في الفرع الرئيسي. جاءت اللحظة الحاسمة: تحديث رقم الإصدار. كان الإصدار الحالي v1.4.2. بما أنه مجرد إصلاح خطأ (bug fix)، كان يجب أن يصبح v1.4.3. لكن في عجلة الأمر، وبسبب الإرهاق، قام زميلي بكتابة v1.5.0. خطأ بسيط، أليس كذلك؟

في الدقائق التالية، بدأت هواتفنا بالرنين. العملاء يشتكون من أن التحديث لم يصلهم، وأنظمة الكاش (Caching) عند المستخدمين لم تتعرف على التغيير الطفيف لأن القفزة في الرقم أوهمتها بوجود تغيير ضخم. والأدهى من ذلك، أننا نسينا توثيق هذا التغيير البسيط في ملف CHANGELOG.md (سجل التغييرات). عشنا ساعتين من الجحيم في محاولة لتصحيح الخطأ، وسحب الإصدار، وإعادة إصداره بالرقم الصحيح، وتحديث السجل يدوياً. تلك الليلة، وأنا أحتسي كوب الميرمية، قلت لنفسي: “خلص، بكفي! لازم نلاقي حل لهالـ ‘شغلانة’ اليدوية المقرفة”.

ما هو الجحيم الذي كنا نعيش فيه؟

قصتي ليست فريدة من نوعها. العديد من فرق التطوير، خصوصاً في بداياتها، تعاني من نفس المشاكل عند إدارة إصدارات برمجياتها يدوياً. كانت فوضى حقيقية، ويمكن تلخيصها في عدة نقاط:

  • الترقيم العشوائي: كل مطور لديه “رأيه” في رقم الإصدار القادم. هل هو 1.2.10 أم 1.3.0؟ النقاش بحد ذاته كان يستهلك وقتاً ثميناً.
  • سجلات التغيير المنسية: كتابة الـ CHANGELOG كانت مهمة مؤجلة دائماً، وفي معظم الأحيان تُنسى تماماً. وعندما نتذكرها، نحاول جاهدين تصفح تاريخ الـ Git لنفهم ما الذي تغير بالفعل.
  • الأخطاء البشرية القاتلة: كما حدث في قصتي، خطأ بسيط في كتابة رقم يمكن أن يسبب مشاكل متتالية. الإنسان يخطئ، خصوصاً تحت الضغط.
  • الوقت المهدر: عملية الإصدار اليدوية كانت تستغرق من نصف ساعة إلى ساعة كاملة من التركيز الشديد، وهي عملية مملة ومتكررة كان يمكن استغلال وقتها في تطوير ميزات جديدة.

الأساس: فهم الترقيم الدلالي (Semantic Versioning)

قبل أن نتحدث عن الأداة السحرية التي أنقذتنا، يجب أن نفهم المبدأ الذي تقوم عليه. هذا المبدأ هو الترقيم الدلالي (Semantic Versioning) أو اختصاراً SemVer. إنه ليس مجرد أرقام عشوائية، بل هو عقد واتفاق بينك وبين مستخدمي برنامجك.

ما هو الترقيم الدلالي (SemVer)؟

ببساطة، هو معيار لترقيم الإصدارات يتكون من ثلاثة أجزاء: MAJOR.MINOR.PATCH.

  • PATCH (تصحيح): يتم زيادة هذا الرقم (مثلاً من 1.2.0 إلى 1.2.1) عندما تقوم بإصلاح أخطاء (bug fixes) لا تؤثر على طريقة عمل البرنامج الأساسية (backward-compatible).
  • MINOR (ثانوي): يتم زيادة هذا الرقم (مثلاً من 1.2.1 إلى 1.3.0) عندما تضيف ميزات جديدة، لكنها لا تكسر التوافق مع الإصدارات السابقة (backward-compatible).
  • MAJOR (رئيسي): يتم زيادة هذا الرقم (مثلاً من 1.3.0 إلى 2.0.0) عندما تقوم بتغيير جذري يكسر التوافق مع الإصدارات السابقة (breaking change). هذا يعني أن من يستخدم الإصدار القديم قد يحتاج لتغيير شيء في كوده ليعمل مع الإصدار الجديد.

نصيحة من أبو عمر: فهم وتطبيق SemVer يدوياً هو الخطوة الأولى نحو النضج في عملية التطوير. حتى لو لم تستخدم الأتمتة بعد، ابدأ اليوم بتطبيق هذا المعيار في مشاريعك. إنه يضيف احترافية وثقة لعملك.

المنقذ: ‘الإصدار الدلالي’ (Semantic Release) يدخل المشهد

الترقيم الدلالي رائع، لكن تطبيقه يدوياً لا يزال عرضة للخطأ البشري. هنا يأتي دور semantic-release. إنها ليست مجرد أداة، بل هي منظومة عمل كاملة تندمج مع مسار التكامل والنشر المستمر (CI/CD) الخاص بك لأتمتة عملية الإصدار بأكملها.

ماذا تفعل semantic-release بالزبط؟

  1. تقرأ رسائل الـ commits في الـ Git الخاص بك.
  2. بناءً على صيغة الرسائل، تقرر تلقائياً أي جزء من رقم الإصدار يجب زيادته (MAJOR, MINOR, or PATCH).
  3. تنشئ سجل تغييرات (CHANGELOG.md) محدث وجميل تلقائياً.
  4. تنشئ Git Tag جديد بالإصدار الجديد.
  5. تنشر الحزمة البرمجية (Package) إلى مستودع مثل npm أو Docker Hub.
  6. وأخيراً، تقوم بعمل commit جديد يحتوي على ملف package.json المحدث وسجل التغييرات.

كل هذا يحدث بضغطة زر (أو بالأحرى، بعد كل عملية git push على الفرع الرئيسي) وبدون أي تدخل بشري.

كيف يعمل هذا السحر؟ رحلة الـ Commit الآلي

قد يبدو الأمر سحرياً، لكنه يعتمد على قاعدة بسيطة جداً: رسائل الـ Commit المنظمة (Structured Commit Messages). تعتمد semantic-release على معيار يسمى Conventional Commits.

1. رسائل الـ Commit المنظمة

بدلاً من كتابة رسائل عشوائية مثل “update code” أو “fixed bug”، يجب أن تتبع صيغة محددة. أهمها:

  • fix: تُستخدم عندما تصلح خطأ. هذا سيؤدي إلى زيادة رقم الـ PATCH.
  • feat: تُستخدم عندما تضيف ميزة جديدة. هذا سيؤدي إلى زيادة رقم الـ MINOR.

وإذا كان تغييرك يكسر التوافق (Breaking Change)، يمكنك الإشارة إلى ذلك في الـ footer الخاص بالرسالة:


feat: allow provided config object to extend other configs

BREAKING CHANGE: `extends` key in config file is now used for extending other config files

وجود BREAKING CHANGE: في الرسالة سيؤدي إلى زيادة رقم الـ MAJOR.

هناك أنواع أخرى مثل docs:, style:, refactor:, test:, chore: التي لا تؤثر على رقم الإصدار ولكنها تظهر في سجل التغييرات لتنظيمه.

2. التحليل والنشر عبر CI/CD

عندما تقوم بالدفع (push) إلى فرعك الرئيسي (مثل main أو master)، يبدأ مسار الـ CI/CD بالعمل. يقوم بتشغيل أمر semantic-release، الذي يقوم بالخطوات التي ذكرناها سابقاً: يحلل الـ commits منذ آخر إصدار، يحدد الرقم الجديد، يولد سجل التغييرات، وينشر الإصدار.

يلا نطبق: دليل عملي لإعداد Semantic Release

لنقم بإعداد بسيط للمشروع باستخدام GitHub Actions. هذا مثال لمشروع Node.js.

المتطلبات الأساسية

  • مشروع Node.js مع ملف package.json.
  • مستودع Git على GitHub.
  • حساب في npm (إذا كنت ستنشر الحزمة).

الخطوات

1. تثبيت الحزم اللازمة:


npm install --save-dev semantic-release @semantic-release/git @semantic-release/changelog

2. إضافة إعدادات semantic-release:

أنشئ ملفاً باسم .releaserc.json في جذر مشروعك، أو أضف قسماً جديداً في ملف package.json:


// في ملف .releaserc.json
{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    ["@semantic-release/npm", {
      "npmPublish": true
    }],
    ["@semantic-release/git", {
      "assets": ["package.json", "CHANGELOG.md"],
      "message": "chore(release): ${nextRelease.version} [skip ci]nn${nextRelease.notes}"
    }]
  ]
}

هذا الإعداد يخبر الأداة بمراقبة فرع main، واستخدام الإضافات (plugins) لتحليل الـ commits، إنشاء سجل التغييرات، نشر الحزمة على npm، وتحديث ملفات package.json و CHANGELOG.md.

3. إعداد مسار العمل (Workflow) في GitHub Actions:

أنشئ ملفاً جديداً في مشروعك بالمسار التالي: .github/workflows/release.yml


name: Release
on:
  push:
    branches:
      - main
jobs:
  release:
    name: Create Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Run tests
        run: npm test

      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release

ملاحظة هامة: ستحتاج إلى إضافة NPM_TOKEN الخاص بك كـ “secret” في إعدادات مستودعك على GitHub ليتمكن من النشر على npm.

وهكذا، في كل مرة تقوم فيها بدمج تغييراتك في فرع main، سيتم تشغيل هذا المسار، وإذا كانت هناك commits جديدة بصيغة صحيحة، سيتم إنشاء إصدار جديد تلقائياً. وداعاً للكوابيس!

نصائح من أبو عمر (من الكيس 🤓)

  • ابدأ بالتدريج: لا تخف من الأتمتة. ابدأ بمشروع جانبي صغير لتفهم الآلية قبل تطبيقها على مشاريعك الكبيرة.
  • ثقّف فريقك: أهم جزء في هذه المنظومة هو التزام الفريق بكتابة رسائل commit صحيحة. عقد ورشة عمل صغيرة، اشرح لهم أهمية feat و fix، ووفر لهم دليلاً مرجعياً.
  • استخدم أدوات مساعدة: أدوات مثل commitizen تجبر المطورين على كتابة رسائل commit بالصيغة الصحيحة عبر واجهة تفاعلية بسيطة.
  • احمِ فرعك الرئيسي: استخدم قواعد حماية الفروع (Branch Protection Rules) في GitHub لمنع الدفع المباشر إلى main وفرض مراجعة الكود (Pull Requests). هذا يضمن أن الكود الذي يصل إلى الفرع الرئيسي عالي الجودة وجاهز للإصدار.

الخلاصة: من الفوضى إلى النظام بضغطة زر 🚀

التحول من الإصدارات اليدوية إلى نظام مؤتمت باستخدام semantic-release كان واحداً من أفضل القرارات التقنية التي اتخذناها. لقد حررنا من مهمة مملة وعرضة للخطأ، وأعطانا الثقة في كل إصدار نطلقه. لم نعد نقلق بشأن “هل نسيت تحديث سجل التغييرات؟” أو “ما هو رقم الإصدار الصحيح؟”.

نصيحتي الأخيرة لك: لا تدع عملية الإصدار تكون “شغلانة” تثقل كاهل فريقك. استثمر قليلاً من الوقت في إعداد الأتمتة، وركز على ما يهم حقاً: كتابة كود رائع وحل مشاكل حقيقية. صدقني، ستشكرني لاحقاً.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

أدوات وانتاجية

كانت ملاحظاتي الرقمية ثقباً أسود: كيف أنقذني Obsidian من جحيم المعرفة المبعثرة وبنى لي ‘دماغي الثاني’؟

بصفتي أبو عمر، مبرمج فلسطيني، كنت أغرق في فوضى ملاحظاتي الرقمية. في هذه المقالة، أسرد لكم كيف انتشلني تطبيق Obsidian من هذا الجحيم، وساعدني في...

19 مايو، 2026 قراءة المزيد
​معمارية البرمجيات

كان تاريخ قراراتنا ضبابياً: كيف أنقذتنا ‘سجلات القرارات المعمارية’ (ADRs) من جحيم الأسئلة المتكررة؟

في عالم تطوير البرمجيات سريع الخطى، غالباً ما ننسى "لماذا" اتخذنا قراراً معمارياً معيناً. أشارككم تجربتي كـ "أبو عمر" وكيف أنقذتنا سجلات القرارات المعمارية (ADRs)...

19 مايو، 2026 قراءة المزيد
خوارزميات

كانت حساباتنا تتكرر إلى ما لا نهاية: كيف أنقذتنا ‘البرمجة الديناميكية’ من جحيم التعقيد الأسي؟

أشارككم قصة من الميدان، من أيام كانت الخوادم تئن تحت وطأة الحسابات المتكررة. تعالوا نكتشف معًا كيف كانت "البرمجة الديناميكية" طوق النجاة الذي حول التعقيد...

19 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كانت واجهاتنا خليطاً فوضوياً: كيف أنقذنا ‘نظام التصميم’ من جحيم عدم الاتساق؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف انتقلنا من فوضى الواجهات وعدم الاتساق إلى نظام وتناغم بفضل "نظام التصميم". هذه ليست مجرد مقالة تقنية،...

19 مايو، 2026 قراءة المزيد
برمجة وقواعد بيانات

كنا نعدل قاعدة البيانات يدوياً بخوف: كيف أنقذتنا ‘هجرات قواعد البيانات’ (Database Migrations) من جحيم التحديثات الفوضوية؟

أشارككم قصة من ليالي البرمجة الطويلة، وكيف انتقلنا من التعديل اليدوي المرعب لقواعد البيانات إلى عالم منظم وآمن بفضل "هجرات قواعد البيانات". مقالة لكل مبرمج...

19 مايو، 2026 قراءة المزيد
البودكاست