Skip to content
Apothem
أدلّة التشغيل

مراسم دمج طلب السحب للمشرف المنفرد

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

المرجع المعياري لدمج طلبات السحب ذاتيًا في ظل حماية الفرع الخاصة بالمشروع. تشترط الحماية الفعّالة على main 0 مراجعات موافِقة وتترك enforce_admins مُعطَّلًا، كما هو مُسجَّل في صفحة حماية الفرع. لذلك يدمج المشرف طلب السحب الخاص به مباشرةً. ولا تنطبق مراسم التبديل المؤقت الواردة في هذه الصفحة إلا عندما تشترط الحماية موافقةً وتفرضها على المسؤولين.


1. الانسداد

تحمل حماية main الفعّالة ما يلي:

  • required_pull_request_reviews.required_approving_review_count: 0
  • enforce_admins: false

في ظل هذه الإعدادات لا يوجد انسداد. يُدمَج طلب سحب المشرف باستخدام gh pr merge <pr-number> --squash --delete-branch متى أصبحت فحوص الحالة المطلوبة الخاصة به خضراء وحُلَّت محادثات المراجعة الخاصة به.

لا يوجد انسداد إلا عندما تحمل الحماية كلا هذين الإعدادين الأكثر صرامة:

  • required_pull_request_reviews.required_approving_review_count: 1
  • enforce_admins: true

هذه القواعد صحيحة لسيناريوهات تعدّد المشرفين (كل تغيير يصل إلى main عبر طلب سحب راجعه قرين؛ والمسؤولون غير مُعفَين). لكنها تُنتِج انسدادًا للمشرفين المنفردين: تمنع سياسة GitHub الموافقة الذاتية على طلب سحب أنشأته بنفسك، ويمنع enforce_admins=true تجاوز gh pr merge --admin لمتطلّب الموافقة على المراجعة. ومع enforce_admins: false، يتجاوز --admin متطلّب الموافقة ولا حاجة إلى أي تبديل، لكنه يتجاوز أيضًا الفحوص المطلوبة الحمراء، لذا تأكّد من أنها خضراء قبل استخدامه.

توجد ثلاثة مسارات للحلّ:

المسارمتى يُستخدَم
تعيين required_approving_review_count: 0 بشكل دائم (الإعداد الفعّال)اعتمِده فقط إذا كان المستودع سيبقى بمشرف منفرد إلى أجل غير مسمّى؛ فهو ينقض نية المراجعة في الحماية
مراسم التبديل المؤقتللدمج الذاتي من المشرف المنفرد بينما تشترط الحماية موافقةً مع enforce_admins=true؛ تحافظ على ثابت الحماية خارج نافذة الدمج
توفير هوية روبوت CI بصلاحية كتابةاعتمِده فقط إذا كان انضمام عدة مشرفين وشيكًا؛ فموافقة الروبوت تُقوّض نية المراجعة البشرية في الحماية

يستخدم هذا المستودع حاليًا مسار الموافقة الصفرية الدائمة. ومراسم التبديل المؤقت هي المسار المعياري متى اشترطت الحماية موافقةً وفرضتها على المسؤولين.

2. مراسم التبديل المؤقت

ثابت المراسم: حالة الحماية في بداية المراسم تساوي حالة الحماية في نهايتها. ولا يعيش التخفيف إلا داخل نافذة الدمج.

الصيغة اليدوية:

# 1. Open the PR, push branch, wait for CI green.
gh pr create --base main --head <feature-branch> --title "..." --body "..."
gh pr checks <pr-number>            # poll until all green

# 2. Relax approver-count to 0.
gh api repos/<owner>/<repo>/branches/main/protection/required_pull_request_reviews \
    -X PATCH -F required_approving_review_count=0

# 3. Squash-merge with admin override (admin override now succeeds because the
#    review-approval requirement is the only block enforce_admins refuses).
gh pr merge <pr-number> --squash --delete-branch --admin

# 4. Restore approver-count to 1.
gh api repos/<owner>/<repo>/branches/main/protection/required_pull_request_reviews \
    -X PATCH -F required_approving_review_count=1

الصيغة المُغلَّفة: راجِع scripts/dev/admin_merge.py للاطّلاع على غلاف Python الذرّي الذي ينفّذ الخطوات 2 ← 3 ← 4 في تسلسل واحد غير تفاعلي مع أمان التراجع عبر try / finally عند فشل الخطوة 3.

python scripts/dev/admin_merge.py <pr-number>

3. الثوابت

  • تقليص نافذة التبديل إلى أدنى حدّ. تُنفَّذ الخطوات 2 ← 3 ← 4 في تسلسل واحد غير تفاعلي. لا تكون الحماية في حالتها المُخفَّفة إلا طوال مدة استدعاء واجهة برمجة تطبيقات الدمج — أقل من ثانية واحدة في كل تشغيل مُلاحَظ.
  • الاستعادة غير مشروطة. تُنفَّذ الخطوة 4 حتى عند فشل الخطوة 3 (تضمن عبارة try / finally في الغلاف الاستعادة في أي مسار خروج). ولا تترك محاولة دمج فاشلة الحماية مُخفَّفة.
  • بوابة CI محفوظة طوال الوقت، ما دام enforce_admins مُفعَّلًا. لا يتأثّر required_status_checks بالتبديل؛ ومع enforce_admins: true لا يزال الدمج يتطلّب أن تكون سياقات فحص الحالة المُهيَّأة خضراء. ومع enforce_admins: false، يتجاوز دمج --admin في الخطوة 3 أيضًا الفحوص المطلوبة الحمراء، لذا لا تُشغِّل المراسم في تلك الحالة.
  • مسار التدقيق مرئي. يظهر تعليق gh pr merge --admin في البيانات الوصفية لدمج طلب السحب؛ وتظهر عمليات التبديل عبر واجهة برمجة تطبيقات الحماية في سجلّ تدقيق المستودع تحت هوية المشرف.

4. متى لا تُستخدَم المراسم

ما دامت الحماية تشترط 0 مراجعات موافِقة أو تترك enforce_admins مُعطَّلًا، فالمراسم غير ضرورية: ادمج مباشرةً كما يصف القسم 1.

المراسم مخصّصة لـ الدمج الذاتي لطلبات سحب المشرف نفسه. وعندما يتوفّر مراجع قرين (مساهم بصلاحية كتابة)، يكون المسار القياسي gh pr review --approve + gh pr merge --squash --delete-branch هو الصحيح، وتغدو المراسم غير ضرورية.

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

5. تدقيق تشغيل سابق

يترك كل استدعاء للمراسم أثرًا على ثلاثة أسطح دائمة يمكن للمُشغِّل تفحّصها لاحقًا:

  • بيانات الدمج الوصفية لطلب السحب. يُرجِع gh pr view <pr-number> --json mergedBy,mergedAt,mergeCommit الجهة المُنفِّذة للدمج، وطابع وقت الدمج، وقيمة SHA لكوميت الـsquash. وتطابق الجهة mergedBy هوية المُشرِف الذي نفّذ الخطوة 3.
  • سجلّ تدقيق المستودع. يربط gh api /repos/<owner>/<repo>/actions/runs --jq '.workflow_runs[] | select(.event=="push")' تشغيل CI اللاحق للدمج بكوميت الدمج؛ ويُظهر سجلّ تدقيق قاعدة الحماية في المستودع (السجلّ عبر gh api /repos/<owner>/<repo>/branches/main/protection أو عبر واجهة Settings → Branches) عمليتَي التبديل في الخطوة 2 والخطوة 4 المُحيطتين بنافذة الدمج.
  • تاريخ git لدى المُشرِف. يسرد git log main --first-parent --oneline كل كوميت دمج squash على main مع رقم طلب السحب المقابل في عنوان الكوميت (اللاحقة (#<pr-number>) وفق الافتراضي في gh pr merge --squash)، ويتيح للمُشغِّل تتبّع أي إنزال سابق رجوعًا إلى طلب السحب الخاص به وإلى استدعاء إجراء الدمج الإداري.

عندما يكون scripts/dev/admin_merge.py هو نقطة الدخول، يُسمّي سجلّه غير التفاعلي (stderr) استدعاءات واجهة برمجة تطبيقات الحماية الثلاثة واستدعاء واجهة برمجة تطبيقات الدمج بالتسلسل؛ وتوجيه stderr عبر أنبوب إلى tee (2>&1 | tee) يلتقط جزءًا تدقيقيًا لكل تشغيل دون الاعتماد على احتفاظ GitHub بالسجلّ من جانبه.

On this page