بناء أوامر YAML لأتمتة تشغيل السكربتات التلقائية عند كل Push

دقائق القراءة: 6

بناء أوامر YAML لأتمتة تشغيل السكربتات التلقائية عند كل Push

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

الفكرة ليست مجرد تشغيل سكربت بعد رفع الكود، بل بناء خط تنفيذ منضبط يضمن فحص الجودة، تثبيت الاعتماديات، تشغيل الاختبارات، ثم تنفيذ مهام إضافية مثل بناء الحاويات أو النشر المرحلي. وهذا جوهر ما هو الـ CI/CD؟ ولماذا نؤتمت عمليات اختبار ونشر الأكواد؟ في المشاريع الحديثة.

في هذا المقال سنبني ملف workflow متقدم يعمل عند كل push، ونشرح كيف تنظم الأوامر، وكيف تمنع التكرار، وكيف تربط ذلك بمعمارية تشغيل آمنة قابلة للتوسع على مستوى الفرق والخوادم.

لماذا نستخدم YAML لتعريف التشغيل التلقائي؟

ملف YAML ليس مجرد تنسيق نصي، بل طبقة توصيف declarative تحدد ماذا يجب أن يحدث ومتى وبأي ترتيب. هذا مهم جداً في بيئات CI/CD لأن كل خطوة تصبح موثقة ومراجعة ضمن الكود.

بدلاً من تخزين منطق التنفيذ في خادم غير مرئي، تستطيع عبر workflow file جعل مسار البناء جزءاً من دورة التطوير نفسها. بهذه الطريقة، أي تعديل في الفحوصات أو الأوامر يخضع إلى مراجعة pull request وليس إلى تغييرات يدوية مبعثرة.

البنية الأساسية لملف التشغيل عند كل Push

إذا كنت قد قرأت مقدمة في GitHub Actions: كتابة أول مسار عمل (Workflow) فستعرف أن الملف يوضع عادة داخل المسار .github/workflows/. ما يهمنا هنا هو تصميمه بشكل هندسي يسمح بإضافة مراحل لاحقة دون كسر البنية.

أبسط عناصر الملف هي:

  • اسم المسار name
  • المحفز on
  • الوظائف jobs
  • بيئة التشغيل runs-on
  • الخطوات steps

مثال عملي كامل لتشغيل سكربتات عند كل عملية رفع

الملف التالي ينفذ أربع مراحل أساسية: سحب الكود، تثبيت البيئة، تشغيل سكربت فحص، ثم تشغيل سكربت نشر أو بناء داخلي. المثال مناسب لمشروع يحتوي على سكربتات Bash داخل مجلد scripts.

name: Run automation scripts on push

on:
  push:
    branches:
      - main
      - develop
      - "feature/**"

jobs:
  automation:
    runs-on: ubuntu-latest

    env:
      APP_ENV: ci
      PROJECT_NAME: sample-app

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set execute permissions
        run: chmod +x scripts/*.sh

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y jq curl

      - name: Run lint script
        run: ./scripts/lint.sh

      - name: Run test script
        run: ./scripts/test.sh

      - name: Run build script
        run: ./scripts/build.sh

هذا النموذج بسيط في ظاهره، لكنه يعكس مفهوماً مهماً: كل خطوة قابلة للعزل والتشخيص. إذا فشل سكربت الفحص فلن ينتقل المسار إلى البناء. هذا يقلل من استهلاك الموارد ويحسن قابلية تتبع الخطأ داخل pipeline logs.

كيف نبني السكربتات نفسها بطريقة مناسبة للأتمتة؟

من الأخطاء الشائعة أن يكون ملف YAML جيداً، بينما السكربتات نفسها غير حتمية أو تعتمد على تدخل يدوي. لذلك يجب أن تكون السكربتات:

  1. قابلة للتشغيل دون أسئلة تفاعلية.
  2. تعيد exit code صحيحاً.
  3. تكتب سجلات واضحة تسهل التتبع.
  4. لا تخزن أسراراً داخل النص البرمجي.

مثال على سكربت فحص جيد:

#!/usr/bin/env bash
set -euo pipefail

echo "Starting lint checks..."
npm ci
npm run lint

echo "Lint completed successfully."

استخدام set -euo pipefail يجعل السكربت أكثر صرامة، لأنه يوقف التنفيذ فور حدوث خطأ أو استخدام متغير غير معرف. هذا مهم جداً في بيئات الأتمتة حيث الصمت عند الفشل قد يقود إلى نشر نسخة معيبة.

تشغيل الأوامر وفق الفروع والسياسات التشغيلية

ليس من الحكمة تنفيذ نفس الإجراءات على كل الفروع. عادةً تنفذ اختبارات سريعة على فروع الميزات، بينما يتم تشغيل بناء كامل أو نشر مرحلي على main. هذه الممارسة تتكامل مع حماية الفروع (Branch Protection) ومنع رفع الأكواد الخاطئة للنسخة الحية.

يمكنك إضافة شروط دقيقة داخل الخطوات نفسها:

- name: Deploy staging
  if: github.ref == 'refs/heads/main'
  run: ./scripts/deploy-staging.sh

هذه الآلية تعطيك تحكماً دقيقاً دون الحاجة إلى تكرار ملف كامل لكل فرع. كما أنها تجعل المسار قابلاً للتوسع مع نمو الفريق وتعدد البيئات مثل dev وstaging وproduction.

ربط الأتمتة ببناء الحاويات والخدمات

في المشاريع الحديثة، تشغيل السكربتات بعد push لا يتوقف عند الفحص فقط، بل يمتد لبناء صور Docker وتشغيل اختبارات التكامل. وإذا كنت تريد تأسيس هذا الجزء جيداً فراجع مشكلة “الكود يعمل على جهازي فقط” وكيف يحلها Docker نهائياً؟ وكتابة أول ملف docker-compose.yml خطوة بخطوة.

مثال على إضافة خطوة بناء حاوية:

- name: Build Docker image
  run: docker build -t sample-app:${{ github.sha }} .

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

أفضل الممارسات الأمنية عند تشغيل السكربتات تلقائياً

لا تضع مفاتيح API أو بيانات SSH أو كلمات المرور داخل ملفات YAML أو سكربتات Bash. استخدم مخزن الأسرار الخاص بالمنصة، ومرر القيم عبر متغيرات بيئية محكومة الصلاحيات ومقيدة على مستوى البيئة أو الفرع.

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

كما يُفضّل تفعيل ضوابط التوازي، خاصة إذا كان الفريق يرفع تعديلات كثيرة خلال وقت قصير. الهدف هو منع أكثر من تنفيذ متزامن من التنافس على نفس البيئة أو نفس المورد.

concurrency:
  group: deploy-main
  cancel-in-progress: true

أخطاء شائعة عند كتابة أوامر YAML

  • الخلط بين المسافات وtabs مما يكسر البنية.
  • كتابة سكربتات طويلة جداً داخل الحقل run بدلاً من فصلها في ملفات مستقلة.
  • تشغيل كل شيء على كل push دون فلترة للفروع.
  • إهمال حالات الفشل وعدم التحقق من exit status.
  • ربط النشر المباشر بالرفع إلى الفرع الرئيسي دون مراجعة أو اختبارات كافية.

وفي المشاريع الجماعية، من المفيد الجمع بين الأتمتة على مستوى المستودع، وبين الفحوصات المحلية قبل الرفع عبر استخدام Git Hooks لأتمتة فحص وتنسيق الكود قبل أي عملية Push. هذا يوزع مسؤولية الجودة بين جهاز المطور ومنصة التنفيذ المركزية.

خاتمة

بناء أوامر YAML لتشغيل السكربتات التلقائية عند كل push ليس مهمة شكلية، بل قرار معماري يؤثر مباشرة في جودة الكود، سرعة التسليم، واستقرار الخوادم. كل سطر تكتبه في ملف التشغيل يمثل قاعدة تنفيذ يمكن الاعتماد عليها لاحقاً في الفحص، البناء، النشر، وإدارة الحاويات.

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

7 comments

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *