عمليات سير العمل التي تركّز على الموظف - من الطلب إلى الإنتاج

1. نظرة عامة

مرحبًا بك في "اليوم الثاني". على الرغم من أنّ إنشاء تطبيق والنقر على "نشر" هو أمر رائع، إلا أنّ عدد الزيارات في العالم الحقيقي يؤدي إلى حدوث أخطاء في العالم الحقيقي. بدلاً من قضاء وقتك في التعامل مع YAML أو البحث في السجلات، يمكنك إنشاء مجموعة من البرامج المتخصصة لإدارة البنية الأساسية التشغيلية نيابةً عنك. يوضّح لك هذا الدرس التطبيقي حول الترميز كيف تسهّل الحزمة الموحّدة من Google Cloud (Eventarc وCloud Run وFirestore وCloud Build وBigQuery) على الوكلاء استرداد المفاتيح السرية بأمان، وبث السجلات، ومعالجة المشاكل بدون أي إعدادات إضافية.

نظرة عامة

في هذا الدرس التطبيقي حول الترميز، ستنشئ لعبة مغامرات الديناصورات DinoQuest المستندة إلى Gemini من البداية، وستربطها بسلسلة CI/CD متكاملة تعمل بالذكاء الاصطناعي الوكيل. في النهاية، سيكون لديك:

  • تطبيق ويب DinoQuest يعمل على Cloud Run (اسم الخدمة: dinoquest)
  • مسار تحليل السجلّات الذي ينقل سجلّات Cloud Run إلى BigQuery وينشئ لوحة بيانات تفاعلية خاصة بإحصاءات الألعاب
  • Remediation Agent (remediation-agent): هو وكيل إصلاح ADK الذي يتتبّع أخطاء Cloud Run ويصلحها تلقائيًا، ويتم نشره كخدمة Cloud Run مستقلة يتم تشغيلها بواسطة Eventarc.
  • وكيل التكامل المستمر (ci-agent) الذي يقرأ اختلاف طلب السحب، ويحدد نطاق الاختبارات بذكاء، وينشئ صورة Docker من خلال Cloud Build، وينشر حالة عملية الإيداع مرة أخرى إلى GitHub
  • وكيل النشر المستمر الذي يسجّل مستوى خطورة النشر، ويقسّم الزيارات، ويرصد المقاييس، ويُجري عمليات الترقية أو الرجوع إلى الإصدار السابق تلقائيًا

أهداف الدورة التعليمية

  • كيفية نشر تطبيق Vite + FastAPI كامل الميزات على Cloud Run كحاوية واحدة
  • كيفية ضبط "مصادقة Firebase" وFirestore لتطبيق React
  • كيفية إنشاء وكيل ADK ونشره ليتفاعل مع أحداث Pub/Sub من خلال Eventarc
  • كيفية توجيه سجلّات Cloud Run إلى BigQuery والاستعلام عن إحصاءات الألعاب
  • كيفية كتابة مهارات مستقلة للدمج المتواصل والنشر التجريبي

المتطلبات

  • مشروع Google Cloud تم تفعيل الفوترة فيه
  • مشروع Firebase (يمكن أن يكون مشروع GCP نفسه)
  • حساب على GitHub ونسخة من مستودع DinoQuest
  • إمكانية الوصول إلى Antigravity باستخدام Gemini (أداة تشغيل الوكلاء من Google)
  • تم تثبيت واجهة سطر الأوامر (CLI) والمصادقة عليها، راجِع تعليمات التثبيت أدناهgcloud
  • node ≥ 18 وnpm
  • python3 ≥ 3.11
  • git وgh (GitHub CLI)

تثبيت gcloud CLI

macOS

brew install --cask google-cloud-sdk

أو نزِّل برنامج التثبيت من cloud.google.com/sdk/docs/install.

Windows

winget install Google.CloudSDK

أو نزِّل أداة التثبيت لنظام التشغيل Windows (ملف ‎.exe) من cloud.google.com/sdk/docs/install وشغِّلها.

بعد التثبيت، عليك إعداد المصادقة:

gcloud init
gcloud auth login
gcloud auth application-default login

2. إعداد Firebase

يحتاج كل وكيل إلى بيانات للاستدلال عليها. تستخدم DinoQuest كلاً من Firestore وFirebase Auth لتوفير طبقة بيانات جاهزة للإنتاج يمكن لوكلائنا اكتشافها واستكشافها وتعديلها لاحقًا باستخدام اللغة الطبيعية.

بما أنّ هذا التطبيق تم إنشاؤه من خلال AI Studio، فهو متكامل بشكل كبير مع Firebase. يوفّر استخدام Firebase العديد من المزايا، وأهمّها بنية أساسية آمنة مسبقًا وإمكانية الوصول إلى البيانات المُدارة بدون أي إعدادات إضافية، ما يضمن حماية حالة لعبتك منذ اليوم الأول.

أ. إنشاء مشروع Firebase

  1. انتقِل إلى console.firebase.google.com
  2. انقر على إضافة مشروع (يتم إخفاء هذا الخيار في خيار إنشاء مشروع جديد) → اختَر مشروع Google Cloud Platform الحالي (أو أنشئ مشروعًا جديدًا).
  3. إيقاف "إحصاءات Google" إذا طُلب منك ذلك → إنشاء مشروع (أو يمكنك استخدام الإعداد التلقائي)

ب. تفعيل "المصادقة باستخدام Google"

  1. في وحدة تحكّم Firebase، انتقِل إلى الأمان → المصادقة (البدء) → طريقة تسجيل الدخول
  2. انقر على Google → فعِّل تفعيل → احفظ عنوان البريد الإلكتروني المخصّص للدعم → حفظ

ج. إضافة المضيف المحلي كنطاق معتمَد

  1. في قسم المصادقة، انقر على علامة التبويب الإعدادات.
  2. ضِمن النطاقات المسموح بها، تأكَّد من إدراج localhost (يجب أن يكون مدرَجًا تلقائيًا).

د. إنشاء قاعدة بيانات Firestore

  1. انتقِل إلى قاعدة البيانات والتخزين → قاعدة بيانات Firestore → إنشاء قاعدة بيانات
  2. اختَر الإصدار العاديالتالي
  3. اختَر المنطقة us-central1 (أو المنطقة المطابقة لمنطقة Cloud Run).
  4. اختَر البدء في وضع الإنتاجإنشاء

بعد إنشاء قاعدة البيانات، سجِّل معرّف قاعدة البيانات، وسيبدو على النحو التالي: (default) ما لم تسمِّه.

E. ضبط قواعد الأمان في Firebase

في قاعدة بيانات Firestore → القواعد، استبدِل القواعد التلقائية بما يلي:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // ===============================================================
    // Helper Functions
    // ===============================================================
    function isAuthenticated() {
      return request.auth != null;
    }
    
    function isOwner(userId) {
      return isAuthenticated() && request.auth.uid == userId;
    }

    function isValidUser(data) {
      return data.keys().hasAll(['uid', 'email']) &&
             data.uid is string && data.uid.size() > 0 &&
             (data.email == null || (data.email is string && data.email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")));
    }

    function isValidDinosaur(data) {
      return data.keys().hasAll(['userId', 'name', 'type']) &&
             data.userId == request.auth.uid &&
             data.name is string && data.name.size() > 0 && data.name.size() < 50 &&
             data.type in ['Speedy', 'Tank', 'Balanced', 'Agile'];
    }

    function isValidGame(data) {
      return data.keys().hasAll(['userId', 'score']) &&
             data.userId == request.auth.uid &&
             data.score is number && data.score >= 0;
    }


    match /users/{userId} {
      allow read: if isOwner(userId);
      allow create: if isOwner(userId) && isValidUser(request.resource.data);
      allow update: if isOwner(userId) && isValidUser(request.resource.data);

      match /dinosaurs/{dinoId} {
        allow read: if isOwner(userId);
        allow create: if isOwner(userId) && isValidDinosaur(request.resource.data);
        allow update: if isOwner(userId) && isValidDinosaur(request.resource.data);
      }

      match /games/{gameId} {
        allow read: if isOwner(userId);
        allow create: if isOwner(userId) && isValidGame(request.resource.data);
      }

      match /seenAnnouncements/{announcementId} {
        allow read, create: if isOwner(userId);
      }
    }

    match /announcements/{announcementId} {
      allow read: if isAuthenticated();
    }

    // Default deny
    match /{document=**} {
      allow read, write: if false;
    }

    match /scores/{scoreId} {
      allow read: if true;
      allow create: if isAuthenticated();
      allow update: if false;
    }
  }
}

انقر على نشر.

و. إضافة تطبيق ويب والحصول على الإعدادات

  1. انتقِل إلى إعدادات المشروع (رمز الترس) → علامة التبويب عام.
  2. انتقِل إلى تطبيقاتك → انقر على إضافة تطبيق → اختَر رمز الويب ().
  3. أدخِل اسمًا dinoquestتسجيل التطبيق
  4. انسخ العنصر firebaseConfig المعروض، ستحتاج إليه بعد لحظات

3- تشغيل اللعبة

دور الوكيل: البيئة قبل أن نتمكّن من إعداد العملاء للعمل، نحتاج إلى عالم يديرونه. في هذه الخطوة، سننشر إصدار "اليوم الأول" من DinoQuest. يؤدي ذلك إلى إنشاء الخدمة المباشرة والسجلات والحالة التي سيكتشفها سربنا ويديرها لاحقًا.

نظرة عامة

يُرجى اختيار أحد الخيارَين أدناه. يؤدي كل منهما إلى إنشاء GEMINI_API_KEY تستخدمه بشكل مماثل في كل خطوة لاحقة، بدون الحاجة إلى إجراء أي تغييرات أخرى.

أ. إعداد مفتاح Gemini API

تتيح لك Vertex AI إنشاء مفتاح Gemini API مرتبط مباشرةً بمشروعك على Google Cloud Platform (GCP) ويتم تحصيل رسومه من خلاله، وذلك باستخدام حساب الخدمة التلقائي للمشروع، بدون الحاجة إلى حساب منفصل على AI Studio.

  1. صدِّر رقم تعريف مشروع Google Cloud Platform باتّباع الخطوات التالية:
    export PROJECT_ID=<YOUR_PROJECT_ID>
    
  2. فعِّل واجهات برمجة التطبيقات المطلوبة وامنح الأذونات اللازمة لحساب الخدمة التلقائي في Compute Engine:
    gcloud auth application-default set-quota-project $PROJECT_ID
    gcloud config set project $PROJECT_ID
    
    # Enable Vertex AI, Compute Engine, and Generative Language APIs
    gcloud services enable aiplatform.googleapis.com \
                           compute.googleapis.com \
                           generativelanguage.googleapis.com
    
    # Grant Vertex AI User role to the default compute service account
    PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
      --role="roles/aiplatform.user" \
      --condition=None
    
  3. افتح صفحة مفاتيح واجهة برمجة التطبيقات في Vertex AI في Cloud Console.
  4. انقر على إنشاء بيانات اعتماد → اختَر مفتاح واجهة برمجة التطبيقات.
  5. في مربّع حوار الإنشاء:
    • أدخِل اسمًا للمفتاح Dino_Key
    • ضَع علامة في المربّع المصادقة على طلبات البيانات من واجهة برمجة التطبيقات من خلال حساب خدمة.
    • ضمن "حساب الخدمة"، اختَر حساب خدمة الحوسبة التلقائي (PROJECT_NUMBER-compute@developer.gserviceaccount.com).
    • في صفحة اختيار قيود واجهة برمجة التطبيقات، ضَع علامة في المربّع بجانب GEMINI API.
    • انقر على إنشاء
  6. انسخ المفتاح الذي تم إنشاؤه.

الخيار (ب) — AI Studio (الأسرع للتطوير المحلي)

  1. افتح aistudio.google.com.
  2. انقر على الحصول على مفتاح واجهة برمجة التطبيقات في الشريط الجانبي الأيمن
  3. انقر على إنشاء مفتاح واجهة برمجة تطبيقات → اختَر مشروعك على Google Cloud Platform → انسخ المفتاح

يتم ضبط أي من المفتاحين على GEMINI_API_KEY في الخطوات التالية، ويتعامل الخلفية معهما بشكل مماثل.

إنشاء نسخة طبق الأصل من المستودع

يقع مستودع الدورة التدريبية في https://github.com/gca-americas/dinoquest. يُرجى تشعّبه في حسابك على GitHub أولاً. سيتولّى الموظف العمل على مستودعك بدلاً منك.

بعد إنشاء نسخة طبق الأصل، استنسِخ فرع main من مستودع DinoQuest الذي أنشأت نسخة طبق الأصل منه وأدخِل دليل المشروع:

git clone https://github.com/YOUR_GITHUB_USERNAME/dinoquest.git
cd dinoquest

ب. إعداد متغيرات البيئة

في كل وحدة طرفية جديدة من Bash تفتحها أثناء هذا الدرس التطبيقي حول الترميز، احرص على ضبط متغيرات البيئة الأساسية هذه. استبدِل قيم العناصر النائبة بتفاصيل مشروعك الفعلية:

أولاً، عليك تصدير عنوان URL الخاص بمستودع GitHub:

export GITHUB_REPO_URL=https://github.com/YOUR_GITHUB_USERNAME/dinoquest

بعد ذلك، صدِّر متغيرات البيئة المتبقية:

export PROJECT_ID=your-project-id
export GOOGLE_CLOUD_PROJECT=$PROJECT_ID
export CLOUD_RUN_REGION=us-central1
export GOOGLE_GENAI_USE_VERTEXAI=True
export HARNESS_EVENTS_TOPIC=projects/$PROJECT_ID/topics/harness-events
export CLOUD_BUILD_REPO=<YOUR_GITHUB_USERNAME>-dinoquest

تأكَّد من أنّ البنية تبدو صحيحة:

dinoquest/
├── backend/          # FastAPI backend (serves frontend + Gemini API calls)
├── frontend/         # React/Vite frontend
├── skills/           # Agentic CI/CD skill files
├── Dockerfile        # Multi-stage build (React → Python)
├── start.sh          # Local dev launcher
└── README.md

ب. إنشاء ملف بيئة الخلفية

أولاً، صدِّر مفتاح Gemini API:

export GEMINI_API_KEY=YOUR_GEMINI_API_KEY_FROM_STEP_2

بعد ذلك، أنشئ ملف .env:

cat > backend/.env <<EOF
GEMINI_API_KEY=$GEMINI_API_KEY
GOOGLE_GENAI_USE_VERTEXAI=False
GOOGLE_CLOUD_PROJECT=$PROJECT_ID
EOF

ج. تفعيل خدمة "فحص التطبيقات من Firebase" / حساب الخدمة (لخدمة Cloud Run)

عند التشغيل على Cloud Run، تستخدم الخلفية بيانات الاعتماد التلقائية للتطبيق للتواصل مع Firebase، ولا حاجة إلى ملف مفتاح حساب الخدمة. ستلتقط firebase_admin.initialize_app() المكالمة في backend/main.py تلقائيًا.

للتطوير المحلي، عليك إثبات هويتك مرة واحدة:

gcloud auth application-default login

د. إنشاء ملف إعداد تطبيق Firebase

في الدليل frontend/، أنشئ firebase-applet-config.json باستخدام الإعدادات من الخطوة السابقة:

{
  "apiKey": "YOUR_API_KEY",
  "authDomain": "YOUR_PROJECT_ID.firebaseapp.com",
  "projectId": "YOUR_PROJECT_ID",
  "storageBucket": "YOUR_PROJECT_ID.appspot.com",
  "messagingSenderId": "YOUR_SENDER_ID",
  "appId": "YOUR_APP_ID",
  "firestoreDatabaseId": "(default)"
}

ملاحظة: يجب أن يتطابق firestoreDatabaseId مع معرّف قاعدة البيانات الذي أنشأته في الخطوة السابقة. إذا كنت قد استخدمت الإعداد التلقائي، اتركه على "(default)".

إجراء تغييرات على المستودع:

git add frontend/firebase-applet-config.json
git commit -m "chore: add firebase config"
git push origin main

ج. تشغيل DinoQuest محليًا

1. تفعيل واجهات برمجة التطبيقات المطلوبة

gcloud services enable \
  run.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com \
  secretmanager.googleapis.com \
  firestore.googleapis.com \
  logging.googleapis.com \
  pubsub.googleapis.com \
  eventarc.googleapis.com \
  aiplatform.googleapis.com \
  bigquery.googleapis.com \
  aiplatform.googleapis.com

2. بدء DinoQuest

ينشئ النص البرمجي start.sh الواجهة الأمامية المستندة إلى React ويسلّم الوحدة الطرفية إلى الخلفية المستندة إلى FastAPI، والتي تعرض الملفات الثابتة المجمّعة:

cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt -q

cd ..
# Force-remove the Vertex AI flag from the current terminal session to avoid conflicts
unset GOOGLE_GENAI_USE_VERTEXAI
./start.sh

افتح http://localhost:8000 في المتصفّح. من المفترَض أن تظهر لك شاشة عنوان DinoQuest. سجِّل الدخول باستخدام حساب Google، وأنشئ أول ديناصور، وتأكَّد من حفظه في Firestore.

تحديد المشاكل وحلّها: إذا ظهرت لك صفحة فارغة أو أخطاء في مصادقة Firebase، تحقَّق مرّة أخرى من أنّ frontend/firebase-applet-config.json يتضمّن القيم الصحيحة وأنّ localhost مدرَج في قائمة النطاقات المسموح بها.

E. نشر DinoQuest على Cloud Run

1. إعداد مشروعك

export PROJECT_ID=$(gcloud config get-value project)

3- إنشاء مستودع Artifact Registry

gcloud artifacts repositories create dinoquest \
  --repository-format=docker \
  --location=$CLOUD_RUN_REGION \
  --description="DinoQuest container images"

4. تخزين مفتاح Gemini API في Secret Manager

echo -n $GEMINI_API_KEY | \
  gcloud secrets create gemini-api-key --data-file=-

# Grant the default compute service account access to the secret
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud secrets add-iam-policy-binding gemini-api-key \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

5- إنشاء صورة الحاوية باستخدام Cloud Build

gcloud builds submit \
  --tag $CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/app:latest .

يؤدي هذا الأمر إلى تشغيل ملف Dockerfile المتعدد المراحل: يتم إنشاء تطبيق React أولاً، ثم يتم تجميع الناتج في صورة FastAPI. تستغرق العملية من 3 إلى 5 دقائق تقريبًا.

6. النشر على Cloud Run

أولاً، صدِّر عنوان البريد الإلكتروني للمشرف:

export ADMIN_EMAIL=<YOUR_TEST_ACCOUNT_EMAIL>

بعد ذلك، يمكنك نشر الخدمة:

gcloud run deploy dinoquest \
  --image=$CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/app:latest \
  --region=$CLOUD_RUN_REGION \
  --platform=managed \
  --allow-unauthenticated \
  --memory=128Mi \
  --set-secrets="GEMINI_API_KEY=gemini-api-key:latest" \
  --set-env-vars="ADMIN_EMAILS=$ADMIN_EMAIL" \
  --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=False" \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=$PROJECT_ID"

عند اكتمال الأمر، تطبع Cloud Run عنوان URL للخدمة. انسخ عنوان URL هذا، وستحتاج إليه لتأكيد النطاق في Firebase.

7. تفويض نطاق Cloud Run في Firebase

للسماح للمستخدمين بتسجيل الدخول من تطبيقك الذي تم نشره، يجب إضافة عنوان URL الخاص بـ Cloud Run إلى النطاقات المصرّح بها في Firebase:

  1. ارجع إلى وحدة تحكّم Firebaseالمصادقة → الإعدادات → النطاقات المسموح بها
  2. انقر على إضافة نطاق.
  3. الصِق عنوان URL لخدمة Cloud Run (مثل dinoquest-xxxxx.us-central1.run.app) — أزِل البادئة https://
  4. انقر على حفظ.

8. تعبئة بيانات قائمة الصدارة

لإضفاء بعض "الحيوية" الأولية على لعبتك وضمان توفّر بيانات لدى العملاء، يمكنك إضافة بعض النتائج الأولية إلى قائمة الصدارة.

  1. تأكَّد من أنّك في الدليل الجذر dinoquest:
    cd ~/dinoquest
    
  2. أنشئ بيئة افتراضية وفعِّلها:
    python3 -m venv venv
    source venv/bin/activate
    
  3. ثبِّت تبعية Firestore المطلوبة:
    pip install google-cloud-firestore
    
  4. شغِّل النص البرمجي الخاص بإنشاء البيانات الأولية:
    python3 prep/seed_scores.py
    
  5. إيقاف البيئة الافتراضية:
    deactivate
    

يمكنك الآن فتح عنوان URL للخدمة في المتصفّح، وستكون لعبة DinoQuest متاحة بالكامل.

4. إعداد مسرح "ديناصور"

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

نظرة عامة

أ. نشر تطبيق Dino Theater على Cloud Run

أولاً، ارجع إلى الدليل الرئيسي واستنسِخ رمز Dino Theater:

cd ~
git clone https://github.com/gca-americas/dinoquest-theater.git
cd dinoquest-theater
  1. إنشاء الحاوية ونقلها:
    gcloud builds submit --tag $CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/dino-theater:latest .
    
  2. إعداد حساب الخدمة والأذونات:
    # Create the service account
    gcloud iam service-accounts create dino-theater
    
    # Create the Pub/Sub topic (if you haven't yet)
    gcloud pubsub topics create harness-events
    
    # Create the subscription
    gcloud pubsub subscriptions create harness-events-theater \
      --topic=harness-events
    
    # Grant subscriber role
    gcloud pubsub subscriptions add-iam-policy-binding harness-events-theater \
      --member="serviceAccount:dino-theater@${PROJECT_ID}.iam.gserviceaccount.com" \
      --role="roles/pubsub.subscriber"
    
  3. نشر التطبيق:
    gcloud run deploy dino-theater \
      --image $CLOUD_RUN_REGION-docker.pkg.dev/$PROJECT_ID/dinoquest/dino-theater:latest \
      --region=$CLOUD_RUN_REGION \
      --service-account=dino-theater@${PROJECT_ID}.iam.gserviceaccount.com \
      --set-env-vars="GOOGLE_CLOUD_PROJECT=$PROJECT_ID" \
      --allow-unauthenticated \
      --min-instances=1
    
    ملاحظة: --min-instances=1 يُنصح بإبقائه نشطًا للحفاظ على اتصال SSE بين الأحداث.
  4. التأكّد من أنّه يعمل: افتح عنوان URL للخدمة الذي تم نشره في المتصفّح (مثلاً، https://dino-theater-xxx-uc.a.run.app/demo).

5- ‫Agentic DevOps في بيئة التطوير المتكاملة

دور الوكيل: Native Antigravity لسدّ الفجوة بين بيئة التطوير المتكاملة (IDE) والسحابة الإلكترونية، نربط Antigravity بخوادم MCP المُدارة من Google Cloud. يمنح ذلك الوكيل المضمّن "عينَين" على مشروعك، ما يتيح له تحليل السجلات والتحقّق من المقاييس وفهم البنية الأساسية بدون الحاجة إلى إدارة مفاتيح واجهة برمجة التطبيقات أو التبديل إلى وحدة التحكّم.

قبل تشغيل أي مهارات، عليك ضبط إذن وصول Antigravity إلى Google Cloud وتحميل أدلة استخدام مهارة DinoQuest.

أ. تثبيت خدمة MCP المُدارة من Google

تتيح خدمة Managed MCP من Google الوصول إلى جميع واجهات برمجة التطبيقات في Google Cloud من خلال نقطة نهاية واحدة مستضافة.

المصادقة باستخدام "بيانات الاعتماد التلقائية للتطبيق":

gcloud auth application-default login

ب. ضبط ملف mcp_config.json

أنشئ mcp_config.json أو عدِّله في دليل إعدادات Antigravity (عادةً ~/.gemini/antigravity/mcp_config.json) أو من وحدة التحكّم. يمنح ذلك Antigravity إذن الوصول إلى أدوات Google Cloud وGitHub التي تحتاج إليها المهارات:

{
  "mcpServers": {
    "google-developer-knowledge": {
      "serverUrl": "https://developerknowledge.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-bigquery": {
      "serverUrl": "https://bigquery.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-cloud-logging": {
      "serverUrl": "https://logging.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-cloud-monitoring": {
      "serverUrl": "https://monitoring.googleapis.com/mcp",
      "authProviderType": "google_credentials",
      "disabledTools": [
        "get_dashboard",
        "list_dashboards"
      ]
    },
    "google-cloud-run": {
      "serverUrl": "https://run.googleapis.com/mcp",
      "authProviderType": "google_credentials",
      "disabledTools": [
        "deploy_service_from_image",
        "deploy_service_from_archive",
        "deploy_service_from_file_contents"
      ]
    },
    "google-cloud-sql": {
      "serverUrl": "https://sqladmin.googleapis.com/mcp",
      "authProviderType": "google_credentials",
      "disabled": true
    },
    "google-cloud-trace": {
      "serverUrl": "https://cloudtrace.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-error-reporting": {
      "serverUrl": "https://clouderrorreporting.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-firestore": {
      "serverUrl": "https://firestore.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "google-resource-manager": {
      "serverUrl": "https://cloudresourcemanager.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    },
    "gemini-cloud-assist": {
      "serverUrl": "https://geminicloudassist.googleapis.com/mcp",
      "authProviderType": "google_credentials"
    }
  }
}

ج. تحميل المهارات إلى Antigravity (اختياري)

يكتشف Antigravity المهارات في أدلة معيارية محدّدة. انسخ مهارات DinoQuest من المستودع الذي نسخته إلى مجلد مهارات Antigravity العام:

# Create the standard skills directory if it doesn't exist
mkdir -p ~/.gemini/antigravity/skills

# Copy all DinoQuest skills into the global skills folder
cp -r skills/* ~/.gemini/antigravity/skills/

د. إعادة تشغيل Antigravity(اختياري)

لتطبيق التغييرات mcp_config.json وتحميل المهارات التي تم نسخها حديثًا، أعِد تشغيل تطبيق Antigravity.

بعد إعادة التشغيل:

  1. تأكَّد من أنّ خوادم MCP الخاصة بكل من google وgithub تعرض الحالة "متصل" باللون الأخضر في الإعدادات.
  2. تأكَّد من ظهور مهارات DinoQuest في قائمة المهارات.

ملاحظة: تحتوي كل مهارة على جدول ## Configuration في أعلى SKILL.md. بعد النسخ، عليك تعديل القيم في ~/.gemini/antigravity/skills//SKILL.md لتتطابق مع مشروعك.

E. إصلاح خدمة السحابة الإلكترونية في بيئة التطوير المتكاملة المحلية

  1. تفعيل الخطأ: افتح عنوان URL الذي تم نشره لتطبيق DinoQuest (من الخطوة الأخيرة) في المتصفّح.
  2. الانتقال إلى قائمة الصدارة: انقر على زر قائمة الصدارة. إنّ عملية تنفيذ قائمة الصدارة الحالية غير فعّالة عمدًا، إذ ستحاول تحميل كمية كبيرة من البيانات إلى الذاكرة، ما يؤدي إلى حدوث خطأ "نفاد الذاكرة".
  3. في "إدارة وكيل Antigravity" (Agent HUB)، اطلب منه المساعدة في استرداد الخطأ وربما إصلاح السبب الجذري.
  • الطلب 1: أريد معرفة المشكلة في dinoquest.
  • الطلب 2: هل يمكنك الاطّلاع على الرمز البرمجي للعبة Dinoquest وإصلاح الخطأ الذي تسبّب في نفاد الذاكرة؟

6. نقل السجلات إلى BigQuery وإنشاء إحصاءات

دور الوكيل: وكيل بيانات يجب ألا يستغرق تحويل السجلات الأولية إلى استراتيجية منتج قابلة للتنفيذ ساعات من معالجة البيانات يدويًا. باستخدام Data Agent Kit وBigQuery MCP، ننشئ مسارًا لعملية "Zero ETL" ينقل السجلات مباشرةً إلى BigQuery، ما يسمح للوكيل بإنشاء لوحة بيانات متميّزة للإحصاءات في أقل من دقيقتَين.

تُعدّ مهارة log-router-bq-report مخزَنًا في Cloud Logging ينقل سجلّات Cloud Run الخاصة بـ DinoQuest باستمرار إلى BigQuery، ثم يطلب البيانات لإنشاء تقارير عن عدد الزيارات وإحصاءات حول أداء اللعبة.

نظرة عامة

أ. ضبط متغيّرات المهارة

افتح skills/log-router-bq-report/SKILL.md في مستودع DinoQuest وعدِّل قسم الإعدادات في أعلى الصفحة:

| Variable      | Your Value         |
|---------------|--------------------|
| SERVICE_NAME  | dinoquest          |
| BQ_DATASET    | dinoquest_logs     |
| LOG_SINK_NAME | dinoquest-bq-sink  |

ب. تشغيل المهارة في Antigravity

افتح Antigravity باستخدام مستودع DinoQuest كمرجع وأخبِر Gemini بما يلي:

Run the log-router-bq-report skill

ستتمكّن المهارة من إجراء ما يلي:

  1. حلّ مشكلة مشروع Google Cloud Platform تلقائيًا
  2. تحقَّق مما إذا كان مخزَن BigQuery متوفّرًا، وإذا لم يكن متوفّرًا، سيتم إنشاء مجموعة البيانات والمخزَن.
  3. منح أذونات إدارة الهوية وإمكانية الوصول: سيمنح هذا الإجراء writerIdentity الحوض دور محرِّر بيانات BigQuery في مجموعة البيانات.

ملاحظة: تمامًا مثل مصرف Eventarc، قد تظهر لك رسالة تحذير من gcloud أثناء هذه العملية: "يُرجى تذكُّر منح serviceAccount:service-... دور "محرِّر بيانات BigQuery" في مجموعة البيانات." تتعامل المهارة مع ذلك تلقائيًا.

ج. استخدام Antigravity لإنشاء التقرير

ما عليك سوى أن تطلب من Antigravity "إعداد مصدر سجلّات BigQuery وإنشاء تقرير الإحصاءات". سيفعل الوكيل ما يلي:

  1. ضبط البنية الأساسية: أنشئ مجموعة بيانات BigQuery ومخزَن Cloud Logging.
  2. إدارة الأذونات: منح أدوار إدارة الهوية وإمكانية الوصول (IAM) اللازمة تلقائيًا لهوية كاتب المصدر.
  3. إنشاء إحصاءات: يمكنك تحليل السجلّات وإنشاء لوحة بيانات HTML تفاعلية مميّزة تتضمّن بيانات قياس أداء اللعبة وتحليل نسبة الفوز.

7. Self-Healing Remediation Agent

دور الوكيل: وكيل هندسة موثوقية الموقع عندما تتعطّل خدمة الإنتاج في الساعة 2 صباحًا، لن تحتاج إلى الاستيقاظ. يعمل هذا الوكيل كأول مستجيب. يتم تشغيلها من خلال سجلّات أخطاء Cloud Run عبر Eventarc، وتعمل تلقائيًا على تحليل العطل واقتراح إصلاح وبدء مسار المعالجة، وكل ذلك قبل حتى تسجيل الدخول إلى وحدة التحكّم.

‫DinoAgent هو وكيل ADK يستمع إلى سجلّات أخطاء Cloud Run من خلال Eventarc، ويشخّص السبب الأساسي، ويعالجه تلقائيًا، إما عن طريق زيادة الذاكرة أو إعادة توجيه الزيارات أو إرسال طلب سحب لرمز إصلاح على GitHub.

نظرة عامة

أ. إنشاء نسخة طبق الأصل من مستودع Remediation Agent

cd ~
git clone https://github.com/gca-americas/dinoquest-reme-agent.git
cd dinoquest-reme-agent

بنية المشروع:

dinoquest-reme-agent/
├── main.py              # Service entrypoint — receives Eventarc HTTP POST, runs agent
├── runner.py            # ADK Runner + session service
├── agent.py             # LlmAgent definition, loads skill from file
├── tools.py             # Cloud Run v2 API tools (list/get/rollback/update)
├── skills/
   └── remediation/
       ├── SKILL.md     # Agent playbook — edit this to change behavior
       └── scripts/     # Shell scripts for the code-fix track
           ├── clone_repo.sh
           ├── read_file.sh
           ├── apply_fix.sh
           ├── commit_branch.sh
           ├── open_pr.sh
           └── rollback_fix.sh
├── requirements.txt
└── Dockerfile

ب. إعداد إذن الوصول إلى GitHub (مسار إصلاح الأخطاء البرمجية)

تنسخ قناة إصلاح الأخطاء البرمجية مستودع DinoQuest، وتقرأ ملفات المصدر، وتطبّق التصحيحات، وتفتح طلبات الدمج. يجب أن يتضمّن رمز دخول شخصي على GitHub بنطاق repo.

  1. انتقِل إلى github.com/settings/tokensإنشاء رمز مميّز جديد (كلاسيكي)
  2. أدخِل اسمًا، واختَر النطاق repoإنشاء رمز مميّز → انسخ الرمز

تخزينها في Secret Manager:

أولاً، صدِّر رمز GitHub المميز:

export GH_TOKEN=ghp_YOUR_TOKEN_HERE

بعد ذلك، أنشئ كلمة المرور السرية:

echo -n $GH_TOKEN | \
  gcloud secrets create github-token --data-file=-

ج. إعداد إشعارات Slack (اختياري)

عند اكتمال عملية الإصلاح، ينشر DinoAgent ملخصًا على قناة Slack.

  1. انتقِل إلى api.slack.com/appsإنشاء تطبيق جديد → من البداية
  2. أدخِل اسمًا للتطبيق DinoAgent، واختَر مساحة العمل → إنشاء تطبيق
  3. ضمن الميزاتالويب هوك الواردة → فعِّل الخيار
  4. انقر على إضافة رابط ويب جديد إلى مساحة العمل (Add New Webhook to Workspace) → اختَر قناة → سماح (Allow)
  5. انسخ رابط ويب هوك (https://hooks.slack.com/services/...).

تخزينها في Secret Manager:

export SLACK_TOKEN=YOUR_SLACK_WEBHOOK
echo -n "https://hooks.slack.com/services/$SLACK_TOKEN" | \
  gcloud secrets create slack-webhook --data-file=-

د. إنشاء حساب خدمة DinoAgent

gcloud iam service-accounts create remediation-agent \
  --display-name="Cloud Run Remediation Agent"

export SA="remediation-agent@${PROJECT_ID}.iam.gserviceaccount.com"

for ROLE in \
  roles/run.admin \
  roles/iam.serviceAccountUser \
  roles/eventarc.eventReceiver \
  roles/aiplatform.user \
  roles/artifactregistry.reader \
  roles/secretmanager.secretAccessor \
  roles/pubsub.publisher \
  roles/logging.viewer; do
  gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SA}" --role="$ROLE" \
    --condition=None
done

امنحها إذن الوصول إلى المفاتيح السرية:

for SECRET in github-token slack-webhook; do
  gcloud secrets add-iam-policy-binding $SECRET \
    --member="serviceAccount:${SA}" \
    --role="roles/secretmanager.secretAccessor"
done

E. إنشاء DinoAgent ونشره على Cloud Run

# Get Project Number for the CIAgent URL
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export CIAGENT_URL=https://ci-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app
export SA="remediation-agent@${PROJECT_ID}.iam.gserviceaccount.com"
export GITHUB_REPO_URL=https://github.com/YOUR_REPO
HARNESS_EVENTS_TOPIC=projects/$PROJECT_ID/topics/harness-events


AGENT_IMAGE="$CLOUD_RUN_REGION-docker.pkg.dev/${PROJECT_ID}/dinoquest/remediation-agent:latest"
gcloud builds submit --tag $AGENT_IMAGE .


gcloud run deploy remediation-agent \
  --image=$AGENT_IMAGE \
  --region=$CLOUD_RUN_REGION \
  --service-account=$SA \
  --memory=2Gi \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID},GOOGLE_GENAI_USE_VERTEXAI=True" \
  --set-env-vars="GITHUB_REPO_URL=${GITHUB_REPO_URL}" \
  --set-secrets="SLACK_WEBHOOK_URL=slack-webhook:latest" \
  --set-env-vars="HARNESS_EVENTS_TOPIC=${HARNESS_EVENTS_TOPIC}" \
  --set-env-vars="CIAGENT_URL=${CIAGENT_URL}" \
  --set-secrets="GITHUB_TOKEN=github-token:latest" \
  --no-allow-unauthenticated \
  --min-instances=1 \
  --no-cpu-throttling \
  --timeout=300

و. ربط مشغّل Eventarc

أنشئ موضوع Pub/Sub لتلقّي سجلّات أخطاء Cloud Run:

gcloud pubsub topics create cloud-run-errors

أنشئ مصرفًا في Cloud Logging يفلتر سجلّات الأخطاء من خدمة dinoquest ويوجهها إلى الموضوع:

export SERVICE_NAME=dinoquest
FILTER="resource.type=\"cloud_run_revision\" resource.labels.service_name=\"$SERVICE_NAME\" severity=ERROR NOT logName=~\"cloudaudit\" NOT httpRequest.requestUrl=~\"/_ah/health\""

gcloud logging sinks create cloud-run-errors-sink \
  pubsub.googleapis.com/projects/${PROJECT_ID}/topics/cloud-run-errors \
  --log-filter="$FILTER"

ملاحظة: عند تنفيذ الأمر أعلاه، ستعرض gcloud رسالة معلومات تقول: "يُرجى تذكُّر منح serviceAccount:service-... دور "ناشر Pub/Sub" في الموضوع". وتتولّى الخطوة التالية تنفيذ ذلك بالضبط.

امنح هوية الكاتب في الحاوية (حساب الخدمة المذكور في التحذير) الإذن بالنشر:

SINK_SA=$(gcloud logging sinks describe cloud-run-errors-sink \
  --format='value(writerIdentity)')

gcloud pubsub topics add-iam-policy-binding cloud-run-errors \
  --member="${SINK_SA}" --role="roles/pubsub.publisher"

تأكَّد من أنّها نشطة:

gcloud eventarc triggers describe remediation-trigger --location=$CLOUD_RUN_REGION

امنح Eventarc الإذن بتفعيل أداة الإصلاح:

gcloud run services add-iam-policy-binding remediation-agent \
  --region=$CLOUD_RUN_REGION \
  --member="serviceAccount:${SA}" \
  --role="roles/run.invoker"

أنشئ مشغّل Eventarc:

gcloud eventarc triggers create remediation-trigger \
  --location=$CLOUD_RUN_REGION \
  --destination-run-service=remediation-agent \
  --destination-run-region=$CLOUD_RUN_REGION \
  --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
  --transport-topic=projects/${PROJECT_ID}/topics/cloud-run-errors \
  --service-account=${SA}

أصبحت عملية الحلّ الآن تلقائية بالكامل. بالإضافة إلى مجرد توسيع نطاق البنية الأساسية، يحلّل DinoAgent الأسباب الجذرية بشكل مفصّل في الرمز البرمجي للتطبيق، ويطبّق رمز تصحيح دلاليًا، ويستخدم ميزة التواصل من وكيل إلى وكيل (A2A) لتسليم الإصلاح إلى وكيل التكامل المستمر من أجل التحقّق منه ونشره. يمكنك استكشاف تفاصيل التنفيذ في قاعدة رموز reme-agent.

8. إعداد وكيل CI

دور الوكيل: مسار CI توقَّف عن التعامل مع ملفات YAML المعقّدة وبرامج الإنشاء اليدوية. يدير هذا الوكيل التفاصيل التشغيلية لطلبات السحب. يقرأ هذا النظام تغييرات الرموز البرمجية، ويفهم السياق، ويحدّد نطاق الاختبارات اللازمة، وينشئ صور Docker من خلال Cloud Build، ما يضمن أنّ كل عملية إيداع "معتمدة من الوكيل" قبل وصولها إلى الفرع الرئيسي.

ci-agent هو وكيل مستقل لمسار الدمج المستمر يتم نشره كخدمة Cloud Run. يرسل عمليات إنشاء Docker إلى Cloud Build، ويطلب إكمالها، ويتأكّد من الصورة في Artifact Registry، ويُبلغ GitHub.

نظرة عامة

لماذا يجب استخدام وكيل لخط أنابيب التكامل المستمر؟ على عكس النصوص البرمجية الثابتة التقليدية، يوفّر مسار CI المستنِد إلى الوكيل ما يلي:

  1. تصنيف النطاق المعرفي: يحدّد هذا التصنيف بذكاء عمق الاختبار المطلوب، ويتنقّل بين عمليات التحقّق من النوع أو اختبارات الوحدات أو مجموعات الدمج الكاملة، وذلك استنادًا إلى التأثير الدلالي لتغييرات الرمز.
  2. إدارة طلبات السحب الذاتية: يمكن للوكيل إنشاء طلبات سحب تلقائيًا، ونشر ملخّصات تفصيلية للتغييرات، وحتى إدارة عمليات فحص الأسرار وعمليات تدقيق الأمان بدون تدخل بشري.
  3. تشخيص الأعطال في الوقت الفعلي: عندما يتعذّر إنشاء إصدار، لا يعرض الوكيل السجلات فحسب، بل يحلّل تتبُّع تسلسل استدعاء الدوال البرمجية، ويحدّد السبب المحتمل، وينشر تشخيصًا يمكن لشخص عادي قراءته مباشرةً في طلب السحب.

أ. استنساخ مستودع CIAgent

cd ~
git clone https://github.com/gca-americas/dinoquest-ci-agent.git
cd dinoquest-ci-agent

ب. إنشاء حساب خدمة CIAgent

gcloud iam service-accounts create ci-agent \
  --display-name="CIAgent CI Pipeline"

export SA="ci-agent@${PROJECT_ID}.iam.gserviceaccount.com"

# Grant necessary roles to the service account
for ROLE in \
  roles/cloudbuild.builds.editor \
  roles/cloudbuild.builds.builder \
  roles/artifactregistry.reader \
  roles/artifactregistry.writer \
  roles/aiplatform.user \
  roles/secretmanager.secretAccessor \
  roles/pubsub.publisher \
  roles/developerconnect.admin; do
  gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SA}" --role="$ROLE" \
    --condition=None
done



# ci-agent needs to act as itself when running build steps
gcloud iam service-accounts add-iam-policy-binding $SA \
  --member="serviceAccount:${SA}" \
  --role="roles/iam.serviceAccountUser"

ج. ربط مستودع GitHub بـ Cloud Build

يرسل CIAgent عمليات الإنشاء من خلال repoSource، ما يتطلّب ربط مستودع GitHub بخدمة Cloud Build Developer Connect.

  1. انتقِل إلى وحدة تحكّم Google Cloud Platform → Cloud Build → المستودعات
  2. انقر على ربط المستودع.
  3. اختَر GitHub (تطبيق Cloud Build GitHub).
  4. منح الإذن واختيار مستودع YOUR_GITHUB_USERNAME/dinoquest
  5. انقر على ربط ثم على تخطّي عندما يُطلب منك إنشاء مشغّل.
  6. دوِّن اسم الاتصال (يكون اسم المستخدم على GitHub أو اسمًا مشابهًا له عادةً).

د. منح CIAgent إذن الوصول إلى المفاتيح السرية

سنعيد استخدام الأسرار التي تم إنشاؤها سابقًا لـ DinoAgent:

gcloud secrets add-iam-policy-binding github-token \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

gcloud secrets add-iam-policy-binding slack-webhook-ci \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

E. إنشاء CIAgent ونشره على Cloud Run

# Set up required variables for orchestration
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export CDAGENT_URL=https://cd-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app
export CI_AGENT_URL=ci-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app
export GITHUB_OWNER="YOUR_GITHUB_USERNAME"
export CLOUD_BUILD_CONNECTION="YOUR_CONNECTION_NAME"  # Update this if your connection name is different
export CLOUD_BUILD_REPO="YOUR_GITHUB_USERNAME-dinoquest" # Update this if your connection name is different

export SLACK_TOKEN=YOUR_SLACK_WEBHOOK
echo -n "https://hooks.slack.com/services/$SLACK_TOKEN" | \
  gcloud secrets create slack-webhook-ci --data-file=-

export SA="ci-agent@${PROJECT_ID}.iam.gserviceaccount.com"
AGENT_IMAGE="$CLOUD_RUN_REGION-docker.pkg.dev/${PROJECT_ID}/dinoquest/ci-agent:latest"
gcloud builds submit --tag $AGENT_IMAGE .

gcloud run deploy ci-agent \
  --image=$AGENT_IMAGE \
  --region=$CLOUD_RUN_REGION \
  --service-account=$SA \
  --memory=1Gi \
  --timeout=600 \
  --allow-unauthenticated \
  --min-instances=1 \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID},GOOGLE_GENAI_USE_VERTEXAI=True" \
  --set-env-vars="HARNESS_EVENTS_TOPIC=${HARNESS_EVENTS_TOPIC}" \
  --set-env-vars="HOST=${CI_AGENT_URL},PROTOCOL=https" \
  --set-secrets="SLACK_WEBHOOK_URL=slack-webhook-ci:latest" \
  --set-env-vars="GITHUB_OWNER=${GITHUB_OWNER},GITHUB_REPO=dinoquest" \
  --set-env-vars="CLOUD_BUILD_CONNECTION=${CLOUD_BUILD_CONNECTION},CLOUD_BUILD_REPO=${CLOUD_BUILD_REPO},CLOUD_BUILD_REGION=${CLOUD_RUN_REGION}" \
  --set-env-vars="CDAGENT_URL=${CDAGENT_URL}" \
  --set-secrets="GITHUB_TOKEN=github-token:latest" \
  --min-instances=1

و. إعداد أمر يبدأ بشرطة مائلة في Slack

  1. انتقِل إلى api.slack.com/appsإنشاء تطبيق جديدمن البداية
  2. أدخِل اسمًا للتطبيق CIAgent، واختَر مساحة العمل → إنشاء تطبيق
  3. ضمن الميزاتأوامر تبدأ بشرطة مائلةإنشاء أمر جديد
  4. الأمر: /runci
  5. عنوان URL للطلب: عنوان URL لخدمة CIAgent Cloud Run من الأعلى مع إضافة /slack (مثلاً https://ci-agent-xxx-.us-central1.run.app/slack)
  6. الوصف المختصر: Trigger CI
  7. حفظ
  8. ضمن الإعداداتتثبيت التطبيق، انقر على التثبيت في Workspace و"السماح".

يعمل وكيل CI كـ "عقل" يستند إلى خدمات Google Cloud القوية، مثل Cloud Build وArtifact Registry. بعد التحقّق من صحة الإصدار، يتم بدء مرحلة النشر النهائية من خلال استدعاء "وكيل النشر المستمر" عبر التطبيق إلى التطبيق، ما يضمن عملية تسليم سلسة بين دورات الإنشاء والإصدار.

9- إعداد عملية النشر

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

cd-agent هو وكيل نشر آلي للنسخة التجريبية يتم نشره كخدمة Cloud Run. يتلقّى هذا النظام طلبات نشر A2A من ci-agent، ويحسب نتيجة تقييم مدى الخطورة، ويضبط نسبة Canary معايرة حسب مستوى الخطورة، ويراقب المقاييس، ويُجري الترقية أو التراجع تلقائيًا. ويتعلّم أيضًا من عمليات النشر السابقة باستخدام Firestore.

نظرة عامة

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

  1. مشاركة السياق الذكية: تنقل الوكلاء ذكريات الجلسة الكاملة واختلافات طلبات السحب ونتائج المخاطر، ما يضمن حصول الوكيل التالي على "السبب" الكامل قبل بدء العمل.
  2. المصافحات المعرفية: يمكن للوكلاء التفاوض على البوابات. على سبيل المثال، يمكن أن يطلب وكيل النشر المستمر إجراء اختبارات دخان محدّدة من وكيل التكامل المستمر أثناء طرح إصدار تجريبي محدود للتحقّق من إصلاح في الوقت الفعلي.
  3. الإصلاح التعاوني: في حال تعذّر عملية نشر، يمكن أن يرسل "وكيل التسليم المستمر" إشعارًا استباقيًا إلى "وكيل الإصلاح" يتضمّن المقاييس التي تعذّر نشرها، ما يؤدي إلى بدء تحليل مستقل للسبب الجذري قبل حتى أن يتم إرسال إشعار إلى أحد الموظفين.
  4. التفاوض بشأن الموارد: يمكن للوكلاء التفاوض بشأن احتياجات البنية الأساسية. على سبيل المثال، يمكن أن يطلب "وكيل التكامل المستمر" من "وكيل الإصلاح" توفير المزيد من سعة الإنشاء إذا رصد إعادة هيكلة واسعة النطاق، أو يمكن أن يقترح "وكيل التسليم المستمر" توسيع نطاق مجموعة الإنتاج قبل إصدار رئيسي.
  5. موافقة عدّة وكلاء: بالنسبة إلى التغييرات عالية الخطورة، يمكن لعدّة وكلاء (مثل وكيل الأمان ووكيل CD) إجراء "موافقة مشتركة" من خلال A2A، ما يضمن عدم إنشاء الرمز البرمجي ونشره فحسب، بل أيضًا الالتزام بسياسات الأمان قبل طرحه في مرحلة الإنتاج.

أ. استنساخ مستودع CDAgent

cd ~
git clone https://github.com/gca-americas/dinoquest-cd-agent.git
cd dinoquest-cd-agent

ب. إنشاء قاعدة بيانات Firestore

يخزّن CDAgent أنماط ذاكرة النشر في Firestore:

gcloud firestore databases create \
  --region=$CLOUD_RUN_REGION \
  --project=$PROJECT_ID

(إذا سبق لك إنشاء قاعدة بيانات في هذا المشروع، يمكنك تخطّي هذه الخطوة.)

ج. إنشاء حساب خدمة CDAgent

gcloud iam service-accounts create cd-agent \
  --display-name="CDAgent Canary Deployer"

export SA="cd-agent@${PROJECT_ID}.iam.gserviceaccount.com"

# Grant necessary roles
for ROLE in \
  roles/run.developer \
  roles/iam.serviceAccountUser \
  roles/artifactregistry.reader \
  roles/artifactregistry.writer \
  roles/monitoring.viewer \
  roles/datastore.user \
  roles/aiplatform.user \
  roles/run.admin \
  roles/pubsub.publisher; do
  gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:${SA}" --role="$ROLE" \
    --condition=None
done

د. منح CDAgent إذن الوصول إلى المفاتيح السرية

سنعيد استخدام رمز GitHub المميز وخطاف الويب Slack من وقت سابق، وسنمنح حساب خدمة الحوسبة Cloud Run إذن الوصول إلى مفتاح Gemini API حتى يتمكّن التطبيق الذي تم نشره من استخدامه:

gcloud secrets add-iam-policy-binding github-token \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

gcloud secrets add-iam-policy-binding slack-webhook-cd \
  --member="serviceAccount:${SA}" \
  --role="roles/secretmanager.secretAccessor"

# Grant the compute service account access to Gemini API key
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
gcloud secrets add-iam-policy-binding gemini-api-key \
  --project=$PROJECT_ID \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

E. إنشاء CDAgent ونشره على Cloud Run

export GITHUB_OWNER="YOUR_GITHUB_USERNAME"

export CD_AGENT_URL=cd-agent-${PROJECT_NUMBER}.${CLOUD_RUN_REGION}.run.app

export SLACK_TOKEN=YOUR_SLACK_WEBHOOK
echo -n "https://hooks.slack.com/services/$SLACK_TOKEN" | \
  gcloud secrets create slack-webhook-cd --data-file=-

AGENT_IMAGE="$CLOUD_RUN_REGION-docker.pkg.dev/${PROJECT_ID}/dinoquest/cd-agent:latest"
gcloud builds submit --tag $AGENT_IMAGE .


export SA="cd-agent@${PROJECT_ID}.iam.gserviceaccount.com"


gcloud run deploy cd-agent \
  --image=$AGENT_IMAGE \
  --region=$CLOUD_RUN_REGION \
  --service-account=$SA \
  --memory=1Gi \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
  --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=True" \
  --set-env-vars="HOST=${CD_AGENT_URL},PROTOCOL=https" \
  --set-env-vars="CD_TARGET_SERVICE=dinoquest" \
  --set-env-vars="HARNESS_EVENTS_TOPIC=${HARNESS_EVENTS_TOPIC}" \
  --set-env-vars="GITHUB_OWNER=${GITHUB_OWNER}" \
  --set-env-vars="GITHUB_REPO=dinoquest" \
  --set-env-vars="DEMO_MODE=true" \
  --set-env-vars="LEADERBOARD_ENABLED=true" \
  --set-secrets="SLACK_WEBHOOK_URL=slack-webhook-cd:latest" \
  --set-secrets="GITHUB_TOKEN=github-token:latest" \
  --allow-unauthenticated \
  --min-instances=1 \
  --no-cpu-throttling \
  --timeout=300

ملاحظة: تحافظ --min-instances=1 --no-cpu-throttling على تشغيل الجهاز الافتراضي لكي يتمكّن من الاستجابة بسرعة لطلبات Slack وA2A.

يُعدّ وكيل التسليم المتواصل (CD) هو المسؤول النهائي عن بيئة التشغيل الفعلي. ويقيّم هذا النظام مخاطر كل عملية نشر، وينفّذ عملية نشر تجريبية مضبوطة على المخاطر، ويتتبّع المقاييس في الوقت الفعلي. في حال رصد أي حالات شاذة، يبدأ في تنفيذ عملية استرجاع تلقائية.

10. توسيع نطاق العمل: الوصول إلى المستوى 2 باستخدام Agent Swarm

أ. اختبار Full Swarm

  1. تفعيل الخطأ: افتح عنوان URL الذي تم نشره لتطبيق DinoQuest (من الخطوة الأخيرة) في المتصفّح.
  2. الانتقال إلى قائمة الصدارة: انقر على زر قائمة الصدارة. إنّ عملية تنفيذ قائمة الصدارة الحالية غير فعّالة عمدًا، إذ ستحاول تحميل كمية كبيرة من البيانات إلى الذاكرة، ما يؤدي إلى حدوث خطأ "نفاد الذاكرة".
  3. انتظار الوكيل: في غضون 60 ثانية تقريبًا، سيتلقّى remediation-agent حدث الخطأ من خلال Eventarc وسيبدأ في تشخيص المشكلة.
  4. التحقّق من Slack: من المفترض أن يظهر لك إشعار في قناة Slack على النحو التالي:ملخّص إجراءات DinoAgent التصحيحية
    • الخدمة: dinoquest
    • النسخة التي تعذّر نشرها: dinoquest-xxxx-xxxx
    • الدليل: "تم تجاوز حد الذاكرة البالغ 128 ميغابايت، حيث تم استخدام 13 ضعفًا من ميغابايت".
    • سبب سوء هذه المراجعة: كانت نقطة النهاية /api/leaderboard غير فعّالة في xxxxx، ما أدّى إلى حدوث خطأ OOM.
    • الإجراء المتّخذ: زيادة الذاكرة من xMi إلى yGi للخدمة dinoquest تم إنشاء نسخة جديدة.
    • طلب السحب الخاص بالسبب الجذري: https://github.com/YOUR_USERNAME/DinoQuest/pull/x
  5. التحقّق من الإصلاحات:
    • GitHub: تحقَّق من مستودعك بحثًا عن فرع جديد وطلب سحب. أصلح الوكيل الرمز البرمجي للتطبيق لإصلاح تسرب الذاكرة الأساسي.
    • Cloud Run: في وحدة تحكّم Google Cloud Platform، ستظهر لك مراجعة جديدة لخدمة dinoquest مع تخصيص الذاكرة المعدَّل.
    • قائمة الصدارة: جرِّب قائمة الصدارة مرة أخرى، من المفترض أن يتم تحميلها الآن بنجاح بفضل زيادة الذاكرة وإصلاح الرمز البرمجي في النهاية.

ب. التطوّر: تنفيذ قواعد المستوى 2 من اللعبة

ستضيف ميزة جديدة مهمة: المستوى 2 (تدمير الكويكبات). ويسمح ذلك للديناصورات التي حققت أعلى النتائج بالانتقال إلى وضع لعب جديد.

  1. الرجوع إلى مستودع dinoquest:
    cd ~/dinoquest
    
  2. إنشاء فرع جديد والتبديل إليه:
    git checkout -b level_2
    
  3. تطبيق حزمة المستوى 2: شغِّل النص البرمجي المتوفّر لتعديل قاعدة الرموز البرمجية المحلية باستخدام مواد عرض المستوى 2 ومكوّناته ومنطق اللعبة:
    bash level_2_backup/levelup.sh
    
  4. تنفيذ التغييرات ودفعها:
    git add .
    git commit -m "feat: add Level 2"
    git push origin level_2
    

بدلاً من استخدام curl لتشغيل البرنامج يدويًا، سنستخدم أمر الخط المائل في Slack الذي أعددته سابقًا. هذه هي طريقة التفاعل مع مسار CI المستقل في سيناريو واقعي.

  1. افتح Slack وانتقِل إلى أي قناة تم تثبيت تطبيق CIAgent فيها.
  2. ابدأ عملية إنشاء CI من خلال كتابة الأمر التالي:
    /runci run ci on branch level_2
    
  3. متابعة مستوى التقدّم:
    • Slack: سيؤكّد الوكيل استلام أمرك وسينشر آخر المعلومات أثناء تقدّم عملية الإنشاء.
    • مسرح الديناصورات: شاهِد "فقاعات الأفكار" بينما يصنّف الوكيل التغيير ويرسل مهمة Cloud Build ويتواصل مع وكيل التسليم المتواصل.
    • GitHub: تحقَّق من طلب السحب level_2، وسيظهر لك العميل وهو ينشر حالات عمليات الدمج وتعليقًا يتضمّن تقريرًا كاملاً عن التكامل المستمر.
  4. مشاهدة العملية:
    • تحقَّق من مسرح الديناصورات للاطّلاع على طريقة تفكير وكيل التكامل المستمر وتصنيفه للتغيير وتشغيله لسلسلة العمليات.
    • راجِع طلب السحب على GitHub للاطّلاع على حالة الالتزام والتقرير النهائي اللذين نشرهما CI Agent.

11. الخاتمة

لقد أنشأت مجموعة أدوات DevOps كاملة مستندة إلى الذكاء الاصطناعي على Google Cloud:

المكوّن

وظيفتها

DinoQuest (‫Cloud Run dinoquest)

لعبة من إنشاء Gemini: واجهة مستخدم أمامية باستخدام React وواجهة خلفية باستخدام FastAPI

‫Firebase Auth + Firestore

مصادقة المستخدم وتخزين ملف الديناصور الشخصي

Remediation Agent (Cloud Run + Eventarc)

وكيل هندسة موثوقية الموقع الذي يعالج تلقائيًا أخطاء نفاد الذاكرة وأخطاء الرموز البرمجية

log-router-bq-report

عامل البيانات الذي ينقل السجلات إلى BigQuery ويُنشئ الإحصاءات

CIAgent (Cloud Run)

وكيل التكامل المستمر الذي يحدّد نطاق الاختبارات وينشئ الصور ويطلب التسليم المستمر من خلال A2A

CDAgent (Cloud Run)

برنامج وكيل للتسليم المتواصل (CD) ينفّذ عمليات نشر تجريبية مع تحديد مستوى المخاطر وإمكانية التراجع التلقائي

يتم تخزين جميع سلوكيات "الوكيل" في الدليل skills/ ككتيبات لعب بتنسيق Markdown. ويمكنك تغيير السلوك من خلال تعديل المهارة وليس الرمز. تعمل المهارات على Antigravity مع Gemini ويتم استدعاؤها من خلال إخبار الوكيل بالمهارة التي يجب تنفيذها.