بوابة إصدار CI للاختبار الداخلي

استخدم Decision Gate كعملية سير عمل بوابة الإصدار.

هذا الدليل يوثق كيفية قيام Decision Gate بتحديد مؤهلات الإصدار من خلال استخدام أدلة CI الحتمية. الهدف هو إظهار طبقة سياسة حقيقية وقابلة للتدقيق دون استبدال نظام CI.

لماذا هذا صارم

  • فصل الاهتمامات: تقوم CI بتنفيذ الاختبارات؛ يقوم Decision Gate بتقييم السياسة وإصدار قرار حتمي.
  • مدفوع بالأدلة: القرار يعتمد على حزمة أدلة مُصدرة بدلاً من سجلات CI الضمنية.
  • مخرجات قابلة للتدقيق: يقوم Decision Gate بتصدير حزمة تشغيل تحتوي على مسار القرار الحالي وبيانات سلامة. لا يثبت التحقق من حزمة التشغيل بمفرده إعادة التشغيل الدلالية، أو صحة الأدلة، أو صحة التاريخ المقبول، أو الربط الخارجي، أو عدم الإنكار.
  • حتمي: نفس مجموعة الأدلة تؤدي إلى نفس القرار.

ما هو Gated

تتحقق عملية تدفق علامة الإصدار من أن الإصدار مؤهل بناءً على:

  • التنسيق، والتحقق من الأخطاء، واختبارات الوحدة
  • أولويات اختبار النظام P0 و P1 (ليست مراحل خارطة الطريق)
  • cargo-deny
  • فحوصات انحراف المولد
  • تغطية كاملة لـ SBOM لكل إصدار موضوع
  • التحقق من شهادة الأصل لكل إصدار موضوع
  • التحقق من توقيع OIDC بدون مفتاح لحمولات الأثر والأصل
  • سياسة الثغرات تمر (High/Critical محجوبة + KEV محجوبة بأي شدة)
  • تشغيلات التعبئة الجافة (Python + TypeScript)
  • اختبار دخان Docker
  • اتساق العلامة/الإصدار (تتطابق العلامة مع إصدار مساحة العمل)

إذا كان هناك أي متطلب مفقود أو خاطئ، فإن البوابة ترفض الإفراج.

حزمة الأدلة

تكتب سير عمل الإصدار حزمة أدلة JSON وتتحقق من كل حقل مطلوب كقيمة منطقية دقيقة. يقوم الغلاف بإنشاء سجل واحد من النوع العدائي ويقدمه مباشرة للشرط الدقيق تحت سلطة المتصل المستمدة من الحدود ووقت الاستلام. تعترف بوابة القرار بهذا السجل ضد مجال السجل المغلق الدقيق وسياسة استخدام الأدلة؛ لا يدخل أي ربط خيالي للمتصل، أو JSON ديناميكي، أو شرط مرتبط بالمزود في قانون السيناريو المعتمد.

مثال (شكل فقط):

{
  "release": {
    "tag": "v0.1.0",
    "version": "0.1.0",
    "tag_matches_version": true,
    "sha": "<git sha>",
    "generated_at": 1710000000000,
    "sbom_path": ".tmp/ci/sbom/decision-gate.sbom.spdx.json"
  },
  "checks": {
    "fmt": true,
    "clippy": true,
    "cargo_deny": true,
    "generate_all": true,
    "unit_tests": true,
    "system_tests_p0": true,
    "system_tests_p1": true,
    "sbom": true,
    "sbom_complete": true,
    "sbom_verified": true,
    "provenance_verified": true,
    "signature_verified": true,
    "vuln_policy_pass": true,
    "package_dry_run": true,
    "docker_smoke": true
  }
}

سيناريو السياسة

تُعبر بوابة الإصدار كسيناريو قياسي لDecision Gate:

  • القالب: configs/ci/release_gate_scenario.json
  • السياسة: يجب أن تكون جميع الشروط صحيحة (متطلب واحد كامل من RET And)
  • الاكتساب: تستهدف عملية تقديم واحدة ذات حدود معينة الحالة الدقيقة مباشرة.
  • التنفيذ: تشغيل سيناريو مباشر (ليس فحصًا مسبقًا) لذا يتم إنتاج حزمة تشغيل

يتم إنشاء السيناريو في وقت التشغيل عن طريق استبدال عناصر النمط:

  • {{SCENARIO_ID}} -> معرف السيناريو الفريد

كيف يعمل في CI

تقوم سير العمل للإصدار بتنفيذ التسلسل التالي:

  1. يقوم بتشغيل فحوصات CI (fmt، clippy، الاختبارات، deny، التعبئة، اختبار الدخان).
  2. يولد أدلة سلسلة التوريد للإصدار باستخدام scripts/ci/supply_chain_generate.sh (الموضوعات، SBOMs، الأصل، التوقيعات بدون مفتاح، آثار الضعف).
  3. يتحقق من أدلة سلسلة التوريد باستخدام scripts/ci/supply_chain_verify.sh كحاجز صارم.
  4. يكتب حزمة أدلة إصدار Decision Gate، بما في ذلك القيم البوليانية الجديدة للتحقق من سلسلة التوريد.
  5. يتحقق من القيم البوليانية المطلوبة، ثم يبدأ خادم MCP محلي باستخدام configs/presets/ci-release-gate.toml وقائمة المفاتيح البيئية الدقيقة الخاصة به.
  6. يقيم السيناريو باستخدام مجموعة الأدلة.
  7. يصدر ويتحقق من حزمة التشغيل.
  8. يحمّل العناصر الأثرية:
    • مجموعة الأدلة
    • رانباك
    • حزمة أدلة سلسلة التوريد (SBOM/الأصل/التوقيعات/آثار الثغرات)
    • حمولة القرار والملخص
    • اسم الأداة: decision-gate-release-gate

تنفذ العملية في scripts/ci/ci_release_gate.sh ويتم استدعاؤها بواسطة سير عمل الإصدار.

موقف توزيع المصدر فقط

يتوقف هذا المستودع حاليًا عند الإصدارات المميزة، التي تركز على المصدر. لا يزال .github/workflows/release.yml يولد أدلة إصدار مدققة، ولكن لا توجد عملية نشطة تنشر الحزم أو صور الحاويات إلى السجلات العامة.

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

التشغيل محليًا

يمكنك تشغيل نفس بوابة الإصدار محليًا مع حزمة أدلة مخصصة:

python3 - <<'PY'
import json
from pathlib import Path

Path("evidence/release_evidence.json").write_text(json.dumps({
    "release": {
        "tag": "v0.1.0",
        "version": "0.1.0",
        "tag_matches_version": True,
        "sha": "local",
        "generated_at": 0,
        "sbom_path": "evidence/sbom/decision-gate.sbom.spdx.json",
    },
    "checks": {
        "fmt": True,
        "clippy": True,
        "cargo_deny": True,
        "generate_all": True,
        "unit_tests": True,
        "system_tests_p0": True,
        "system_tests_p1": True,
        "sbom": True,
        "package_dry_run": True,
        "docker_smoke": True,
    },
}, indent=2))
PY

bash scripts/ci/ci_release_gate.sh \
  --evidence-file evidence/release_evidence.json \
  --output-dir evidence/release-runpack \
  --config configs/presets/ci-release-gate.toml

إذا كانت أي فحص غير صحيح، يخرج البرنامج برمز غير صفري وستظهر ملخص القرار سبب الرفض.

لتشغيل توليد سلسلة التوريد المتوازية المحلية + التحقق قبل تقييم البوابة:

bash scripts/ci/verify_all.sh --release-parity

العناصر التي يجب فحصها

  • decision_payload.json: حمولة استجابة Decision Gate الخام
  • decision_summary.json: نوع القرار + السماح/الرفض
  • runpack/manifest.json: بيان تشغيل حتمي للـ runpack
  • runpack_verify.json: مخرجات التحقق من runpack
  • Docs/architecture/decision_gate_ci_and_workflow_architecture.md
  • configs/ci/release_gate_scenario.json
  • scripts/ci/ci_release_gate.sh