EduFlow
Git و GitHub
⁦0%⁩

الوحدة 4 · عادات احترافية

حماية main: الـ CI مع Actions والـ Rulesets

17 دقراءة 4 داكتشف الخطأ

الدرس في لمحة

أضف workflow في GitHub Actions يفحص كل pull request، ثم احمِ main بـ ruleset بحيث لا تصل التغييرات إليه إلا عبر pull request نجحت فحوصه.

  1. 1أعطِ الموقع الشخصي شيئًا يُفحص
  2. 2أول workflow لك
  3. 3مشاهدته وهو يعمل
  4. 4احمِ main بـ ruleset
  5. 5ما الذي تستطيع فعله الآن

لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.

كل ما سبق اعتمد على تذكّرك أنت. أن تتذكّر تشغيل فحص الـ HTML، وأن تفتح pull request بدل الرفع إلى main، وألّا ترفع بالقوة أبدًا. والناس ينسون، خصوصًا في الحادية عشرة ليلًا قبل التقدّم إلى وظيفة. ينقل هذا الدرس هذه العادات من رأسك إلى GitHub: آلة تشغّل الفحوص على كل pull request، وقواعد تجعل تغيير main بأي طريقة أخرى مستحيلًا.

أعطِ الموقع الشخصي شيئًا يُفحص

التكامل المستمر (continuous integration) يحتاج إلى أمر يفشل حين يكون هناك خطأ. ولموقع HTML، فإن أداة التحقّق (validator) بداية جيدة. في موقعك الشخصي، على فرع جديد:

Terminal
git switch -c add-ci
npm init -y
npm install --save-dev html-validate
npm pkg set scripts.test="html-validate index.html projects.html"
echo '{ "extends": ["html-validate:recommended"] }' > .htmlvalidate.json
npm test

node_modules/ موجود أصلًا في .gitignore منذ درسين؛ سجّل في commit كلًا من package.json و package-lock.json و .htmlvalidate.json. وإن أبلغ npm test عن مشكلات، فهذا هو المقصود: أصلحها، أو دوّنها لأول تشغيل للـ CI. وفي موقع شخصي جديد كثيرًا ما يجد هذا:

Text
index.html
  1:1  error  DOCTYPE should be uppercase  doctype-style

أول workflow لك

تشغّل GitHub Actions الـ workflows المعرَّفة في ملفات YAML تحت .github/workflows/. أنشئ واحدًا:

.github/workflows/ci.yml
name: CI

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 24
          cache: npm
      - run: npm ci
      - run: npm test

اقرأه من الأعلى إلى الأسفل:

  • on يسرد الأحداث (events) التي تبدأ الـ workflow: أي pull request إلى main (عند فتحه، أو تحديثه بـ commits جديدة)، وعمليات الرفع إلى main بعد الدمج.
  • jobs يحتوي job واحدًا، check. هذا المعرّف يصبح اسم الـ status check الذي يعرضه GitHub على الـ pull request.
  • runs-on يختار runner، وهو آلة افتراضية جديدة يوفّرها GitHub. وتبدأ فارغة في كل مرة.
  • steps تُنفَّذ بالترتيب. uses يشغّل action منشورًا: actions/checkout ينسخ الـ repository إلى الـ runner، و actions/setup-node يثبّت Node.js 24 ويخزّن تنزيلات npm مؤقتًا. و run ينفّذ أمر shell: npm ci يثبّت بالضبط ما يسرده package-lock.json، و npm test يشغّل أداة التحقّق.

أي خطوة تنتهي بخطأ تُفشل الـ job. سجّل الـ workflow في commit، وارفع الفرع، وافتح pull request.

مشاهدته وهو يعمل

خلال ثوانٍ يعرض الـ pull request فحصًا، “CI / check (pull_request)”، بنقطة صفراء أثناء التشغيل. ثم علامة صح خضراء، أو علامة خطأ حمراء. انقر Details لترى السجلّ الكامل لكل خطوة؛ والخطوة الفاشلة تكون موسّعة، وتعرض ناتج أداة التحقّق نفسه الذي ستحصل عليه محليًا.

لإصلاح فحص أحمر، افعل ما تفعله مع ملاحظات المراجعة: أنشئ commit على الفرع نفسه وارفعه. يعمل الـ workflow مجددًا على الـ commit الجديد. اعتد على قراءة هذه السجلّات. الـ CI لا يحكم عليك؛ إنه زميل يعيد تشغيل الفحوص في كل مرة دون أن يملّ.

مسار من اليسار إلى اليمين: فرع feature، ثم رفع، ثم pull request، ثم بوّابتان متجاورتان، نجاح فحص الـ CI وموافقة المراجعة، ثم الدمج في main. وسهم محجوب يبيّن أن الـ ruleset يرفض الرفع المباشر إلى main. فرع pull request CI: check مراجعة دمج main رفع مباشر: مرفوض
الطريق المحمي إلى main

احمِ main بـ ruleset

الفحص الناجح لا يفيد إلا إذا انتظره الدمج. وهذا ما يفرضه الـ ruleset (مجموعة القواعد). على GitHub، افتح Settings في الـ repository، ثم Rules، ثم Rulesets، واختر New ruleset، ثم New branch ruleset:

  1. سمِّه “Protect main” واضبط Enforcement status على Active.
  2. تحت Target branches، أضف الفرع الافتراضي.
  3. أبقِ Restrict deletions و Block force pushes محدَّدين.
  4. حدّد Require a pull request before merging. في repository تعمل عليه وحدك اضبط عدد الموافقات المطلوبة على 0 (لا تستطيع الموافقة على الـ pull request الخاص بك)؛ وفي الفريق، 1 أو أكثر.
  5. حدّد Require status checks to pass، وأضف الفحص check، واحفظ.

الآن حاول تخطّي العملية:

Terminal
git switch main
git commit --allow-empty -m "Sneak a commit onto main"
git push origin main
Text
remote: error: GH013: Repository rule violations found for refs/heads/main.

يُرفض الرفع، ويبقى الـ commit المحلي دون أن يُمسّ. كل تغيير على main يمرّ الآن عبر pull request، ويبقى زر الدمج معطّلًا حتى يصبح الفحص أخضر. شغّل git reset --hard origin/main لتتخلّص من الـ commit الفارغ.

الـ rulesets مجانية في الـ repositories العامة؛ أما في الخاصة فتحتاج إلى خطة مدفوعة مثل GitHub Pro أو Team. وقد ترى أيضًا branch protection rules الأقدم في الإعدادات. إنها تؤدّي مهمّة مشابهة؛ لكن الـ rulesets أحدث، ويمكن تركيبها في طبقات، ويستطيع أي شخص لديه صلاحية القراءة أن يرى القواعد المطبّقة.

ما الذي تستطيع فعله الآن

انظر من أين بدأ الموقع الشخصي: مجلد فيه index.html. صار الآن repository بسجلّ مقروء، وفروع تُدمج أو يُعاد تأسيسها بنظافة، و remote على GitHub تصل إليه بمصادقة سليمة، و issues تشرح سبب وجود كل عمل، وإصدارات موسومة بـ tags، وفرع main لا يقبل إلا pull requests مراجَعة ومفحوصة آليًا. وتستطيع التراجع عن معظم الأخطاء، وتعرف أيّ طريقة تراجع تناسب كلًا منها.

وأهمّ من الأوامر، صار لديك النموذج: الـ commits لقطات مرتبطة بآبائها، والـ branches والـ tags أسماء دالّة، والـ HEAD هو حيث تقف، والـ remotes نسخ أخرى من الرسم البياني نفسه. وحين يفاجئك Git مستقبلًا، شغّل git log --oneline --graph --all، وارسم ما تراه، وغالبًا سيكون الأمر التالي واضحًا.

أهم النقاط

  • الـ workflow ملف YAML في .github/workflows/؛ يحدّد on الأحداث، وتعمل الـ jobs على runners، وكل خطوة في steps إما تستخدم action عبر uses أو تنفّذ أمرًا عبر run.
  • كل job يبلّغ عن status check على الـ pull request، يظهر كعلامة صح خضراء أو علامة خطأ حمراء مع السجلّات الكاملة.
  • الـ branch ruleset على main يستطيع منع الرفع بالقوة والحذف، واشتراط pull request، واشتراط نجاح status checks مسمّاة.
  • الـ status check المطلوب يُطابَق باسم الـ job، ولا يقترح GitHub إلا الفحوص التي أبلغت عن نتيجتها من قبل، لذا شغّل الـ workflow قبل أن تشترطه.
  • الحلقة المكتملة هي فرع، ثم رفع، ثم pull request، ثم فحص آلي، ثم مراجعة، ثم دمج، ولا أحد يستطيع تخطّي خطوة.

قراءات إضافية

تحقّق من فهمك

4 أسئلة

السؤال 1 من 4

يبدأ الـ workflow الخاص بك بـ on: pull_request. متى يعمل؟

السؤال 2 من 4

يفشل الـ CI job عند npm ci بخطأ مفاده أن package.json غير موجود. الخطوة الأولى هي run: npm ci. ما المشكلة؟

السؤال 3 من 4

أضفت ruleset على main يشترط pull request. ماذا يحدث حين تشغّل git push origin main ولديك commit محلي؟

السؤال 4 من 4

أعدت تسمية الـ job في الـ workflow من check إلى html. والآن يعرض كل pull request الفحص المطلوب check بالحالة “Expected — Waiting for status to be reported”، ولا شيء يمكن دمجه. لماذا؟

تدريب

اكتشف الخطأ

أصلح الـ CI workflow

كتب زميل ملف .github/workflows/ci.yml ليشغّل فحص الـ HTML في الموقع الشخصي على كل pull request إلى main. لكنه لا يظهر أبدًا على الـ pull requests، وحتى بعد إصلاح ذلك سيظل يفشل. حدّد الأسطر الثلاثة الخاطئة.

حدّد السطر أو الأسطر التي تظنها خاطئة، ثم تحقّق.