النشر من CI/CD
انشر عند كل دفع من GitHub Actions أو GitLab CI/CD، ببيانات اعتماد محدودة ومهمّة تفشل حين يفشل النشر.
يفعل خطّ النشر أربعة أشياء: يثبّت الـ CLI، ويسجّل الدخول ببيانات اعتماد محفوظة في نظام CI، وينشئ التطبيق في المرّة الأولى أو يحدّثه في كل مرّة بعدها، وينتظر النشر حتى تفشل المهمّة حين يفشل. يفعل قالبان جاهزان هذا بالضبط. تعرضهما هذه الصفحة كاملين، وتشرح كل جزء منهما، وتتناول ما قد يسوء.
1. أنشئ بيانات اعتماد لخطّ النشر
لا تُعِد استخدام بيانات الاعتماد التي على جهازك. أنشئ واحدة لـ CI وحده، لا تحمل إلا ما يحتاج إليه خطّ النشر، حتى يمكن إبطالها دون تسجيل خروجك، ولا تستطيع أكثر من النشر إن تسرّبت.
export ISOGRID_CONFIG_HOME="$(mktemp -d)"
isogrid --api https://api.isogrid.skyvault.pro login \
--scope application:create,application:write-any \
--name github-ci
يفتح المتصفّح على صفحة الموافقة. تحقّق من المؤسّسة الظاهرة هناك: بيانات الاعتماد مثبّتة عليها وستُرفض في أي مكان آخر. وافِق، ثم انسخ الرمز من الإعدادات المؤقّتة واحذفها:
jq -r '.contexts[].token' "$ISOGRID_CONFIG_HOME/config.json"
rm -rf "$ISOGRID_CONFIG_HOME"
استخدام ISOGRID_CONFIG_HOME مؤقّت يُبقي تسجيل دخولك أنت كما هو. ودونه، ستحلّ
بيانات الاعتماد الجديدة محلّ الموجودة في ~/.isogrid/config.json لذلك العنوان،
وستحتاج إلى isogrid login --force لاستعادة بياناتك.
أيّ نطاقات
| النطاق | ما يستطيعه خطّ النشر به |
|---|---|
application:create |
إنشاء التطبيق في التشغيل الأول. |
application:write-any |
تعديل كل تطبيق في المؤسّسة وبناؤه ونشره. |
application:deploy-any |
بناء كل تطبيق ونشره وتشغيله وإيقافه، دون تعديل إعداداته. |
ينشئ القالبان التطبيق إن لم يكن موجودًا، فيحتاجان إلى application:create
وapplication:write-any. وبعد أن يوجد، يمكنك إنشاء بيانات اعتماد أضيق دون
application:create. ولا يكفي application:deploy-any إلا إن كان خطّ النشر لا
يمرّر أي إعدادات أبدًا: لا --env-file ولا تغيير للفرع.
النطاق لا يضيف أبدًا إلى ما تملكه. يُقاطَع مع دورك ومجموعاتك في كل طلب، فالنطاق الذي لا تملكه يُسقط بصمت، وخفض صلاحياتك يضيّق بيانات اعتماد خطّ النشر أيضًا. وهناك أشياء لا تستطيعها بيانات الاعتماد أبدًا، مهما طلبت: الفوترة، وتعيين المسؤولين، وإنشاء بيانات الاعتماد أو إبطالها. انظر الأدوار ومجموعات الصلاحيات والوصول.
تدوم بيانات الاعتماد 90 يومًا ما لم تختر مدّة أقصر في صفحة الموافقة. ضع تذكيرًا في تقويمك لاستبدالها قبل ذلك.
2. أبلغ نظام CI
| الإعداد | GitHub Actions | GitLab CI/CD |
|---|---|---|
ISOGRID_TOKEN |
secret (سرّ) في المستودع | متغيّر CI/CD، Masked (مُقنَّع) |
ISOGRID_API_URL |
variable (متغيّر) في المستودع، مثل https://api.isogrid.skyvault.pro |
متغيّر CI/CD |
ISOGRID_APP |
متغيّر اختياري. افتراضيه اسم المستودع. | متغيّر اختياري. افتراضيه اسم المشروع. |
ISOGRID_CLUSTER |
اختياري. slug المنطقة؛ لازم حين تكون أكثر من منطقة مفتوحة لك. | كذلك |
ISOGRID_TIER |
اختياري. نوع النسخة؛ أصغر ما في المنطقة افتراضيًا. | كذلك |
ISOGRID_NETWORK |
اختياري. slug الشبكة؛ شبكة مؤسّستك افتراضيًا. | كذلك |
ISOGRID_ENV_FILE |
اختياري. ملف dotenv في المستودع يُطبَّق في كل نشر. | كذلك |
في GitHub تجدها تحت Settings → Secrets and variables → Actions (الإعدادات ←
الأسرار والمتغيّرات ← Actions). وفي GitLab تحت Settings → CI/CD → Variables
(الإعدادات ← CI/CD ← المتغيّرات)؛ وعلّم ISOGRID_TOKEN بـ Protected (محميّ)
أيضًا إن كانت الفروع المحميّة وحدها تنشر.
تقرأ الـ CLI ISOGRID_TOKEN من البيئة ولا تكتبه على القرص أبدًا، فخطّ
النشر الذي يخزّن المجلّد الرئيسي مؤقّتًا لا ينقل الرمز إلى المهام اللاحقة.
3. أضف خطّ النشر
تكتب الـ CLI الملف نيابةً عنك:
isogrid ci init github --app shop --cluster eu-west # .github/workflows/isogrid-deploy.yml
isogrid ci init gitlab --app shop --cluster eu-west # .gitlab-ci.yml
isogrid ci init github --output - # print it instead
القيم التي تمرّرها (--app، --cluster، --tier، --network، --env-file)
تُكتب في الملف. وكل ما تغفله يُقرأ من متغيّرات CI أعلاه. ولا يُستبدل ملف موجود
دون --force. وبعد الكتابة، يطبع الأمر المتغيّرات التي بقي ضبطها.
يمكنك أيضًا تنزيل القالبين دون الـ CLI:
curl -fsSL https://api.isogrid.skyvault.pro/api/v1/cli/ci-templates/github -o .github/workflows/isogrid-deploy.yml
curl -fsSL https://api.isogrid.skyvault.pro/api/v1/cli/ci-templates/gitlab -o .gitlab-ci.yml
قبل التشغيل الأول
يجب أن يكون المستودع مربوطًا بمؤسّستك ومفتوحًا للشخص الذي يستخدم خطّ النشر بيانات
اعتماده. يعرضه isogrid repos list حين يكون كذلك؛ ويجب أن يتضمّن العمود YOU
القيمتين create-app وdeploy. انظر مستودعات Git.
قالب GitHub Actions
# Deploy to ISOGrid from GitHub Actions.
#
# Save as .github/workflows/isogrid-deploy.yml (or generate it with
# `isogrid ci init github`). On every push to main, and whenever you run it by
# hand, it installs the ISOGrid CLI and either updates the application and
# deploys the pushed commit, or - the first time - creates the application.
#
# Set these in the repository (Settings -> Secrets and variables -> Actions):
#
# Secrets
# ISOGRID_TOKEN A CLI credential. Mint a narrow one for CI: run
# `isogrid login --scope application:create,application:write-any --name github-ci`
# on your machine, then copy the token from
# ~/.isogrid/config.json. Never commit it.
#
# Variables
# ISOGRID_API_URL Your platform's API, e.g. https://api.isogrid.skyvault.pro
# ISOGRID_APP Application name (default: this repository's name)
# ISOGRID_CLUSTER Region slug (optional when only one region is open to you)
# ISOGRID_TIER Instance type name (optional: the region's smallest)
# ISOGRID_NETWORK Network slug (optional: your organization's network)
# ISOGRID_ENV_FILE A dotenv file in the repository to apply (optional)
#
# The repository must already be connected to the organization through the
# ISOGrid GitHub app (`isogrid repos list` shows it once it is).
name: Deploy to ISOGrid
on:
push:
branches: [main]
workflow_dispatch:
# One deployment of a branch at a time; a newer push waits rather than racing.
concurrency:
group: isogrid-deploy-${{ github.ref }}
cancel-in-progress: false
env:
ISOGRID_API_URL: ${{ vars.ISOGRID_API_URL }}
ISOGRID_TOKEN: ${{ secrets.ISOGRID_TOKEN }}
ISOGRID_APP: ${{ vars.ISOGRID_APP || github.event.repository.name }}
ISOGRID_CLUSTER: ${{ vars.ISOGRID_CLUSTER }}
ISOGRID_TIER: ${{ vars.ISOGRID_TIER }}
ISOGRID_NETWORK: ${{ vars.ISOGRID_NETWORK }}
ISOGRID_ENV_FILE: ${{ vars.ISOGRID_ENV_FILE }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# Only needed for ISOGRID_ENV_FILE: the platform clones the repository
# itself to build it.
- uses: actions/checkout@v4
- name: Install the ISOGrid CLI
run: |
curl -fsSL "$ISOGRID_API_URL/api/v1/cli/install.sh" | ISOGRID_INSTALL_DIR="$HOME/.local/bin" sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Deploy
run: |
set -eu
isogrid version
ENV_ARGS=""
if [ -n "$ISOGRID_ENV_FILE" ]; then
ENV_ARGS="--env-file $ISOGRID_ENV_FILE"
fi
# --exact: an application called "api" must not be taken for "api-gateway".
if isogrid apps get "$ISOGRID_APP" --exact --json > /dev/null 2>&1; then
# Builds this exact commit and waits; the step fails if the build or
# the deployment does.
isogrid apps update "$ISOGRID_APP" \
--branch "${{ github.ref_name }}" \
$ENV_ARGS \
--deploy --ref "${{ github.sha }}" --wait
else
isogrid apps create \
--name "$ISOGRID_APP" \
--provider github \
--url "${{ github.server_url }}/${{ github.repository }}" \
--branch "${{ github.ref_name }}" \
--cluster "$ISOGRID_CLUSTER" \
--tier "$ISOGRID_TIER" \
--network "$ISOGRID_NETWORK" \
$ENV_ARGS \
--wait
fi
قالب GitLab CI/CD
# Deploy to ISOGrid from GitLab CI/CD.
#
# Save as .gitlab-ci.yml at the root of the project (or generate it with
# `isogrid ci init gitlab`), or merge the job into the one you have. On every
# push to the default branch, and when run by hand, it installs the ISOGrid CLI
# and either updates the application and deploys the pushed commit, or - the
# first time - creates the application.
#
# Set these under Settings -> CI/CD -> Variables:
#
# ISOGRID_TOKEN A CLI credential; mark it Masked (and Protected if only
# protected branches deploy). Mint a narrow one for CI:
# `isogrid login --scope application:create,application:write-any --name gitlab-ci`
# on your machine, then copy the token from
# ~/.isogrid/config.json. Never commit it.
# ISOGRID_API_URL Your platform's API, e.g. https://api.isogrid.skyvault.pro
#
# and optionally override the defaults below the same way (project variables
# take precedence over the values written in this file):
#
# ISOGRID_APP Application name (default: the project's name)
# ISOGRID_CLUSTER Region slug (optional when only one region is open to you)
# ISOGRID_TIER Instance type name (optional: the region's smallest)
# ISOGRID_NETWORK Network slug (optional: your organization's network)
# ISOGRID_ENV_FILE A dotenv file in the repository to apply (optional)
#
# The project must already be connected to the organization through the
# ISOGrid GitLab integration (`isogrid repos list` shows it once it is).
stages:
- deploy
variables:
ISOGRID_APP: "$CI_PROJECT_NAME"
ISOGRID_CLUSTER: ""
ISOGRID_TIER: ""
ISOGRID_NETWORK: ""
ISOGRID_ENV_FILE: ""
isogrid-deploy:
stage: deploy
image: alpine:3.20
# One deployment of a branch at a time.
resource_group: isogrid-$CI_COMMIT_REF_SLUG
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- if: $CI_PIPELINE_SOURCE == "web"
before_script:
- apk add --no-cache curl
- curl -fsSL "$ISOGRID_API_URL/api/v1/cli/install.sh" | ISOGRID_INSTALL_DIR=/usr/local/bin sh
- isogrid version
script:
- |
set -eu
ENV_ARGS=""
if [ -n "$ISOGRID_ENV_FILE" ]; then
ENV_ARGS="--env-file $ISOGRID_ENV_FILE"
fi
# --exact: an application called "api" must not be taken for "api-gateway".
if isogrid apps get "$ISOGRID_APP" --exact --json > /dev/null 2>&1; then
# Builds this exact commit and waits; the job fails if the build or
# the deployment does.
isogrid apps update "$ISOGRID_APP" \
--branch "$CI_COMMIT_REF_NAME" \
$ENV_ARGS \
--deploy --ref "$CI_COMMIT_SHA" --wait
else
isogrid apps create \
--name "$ISOGRID_APP" \
--provider gitlab \
--url "$CI_PROJECT_URL" \
--branch "$CI_COMMIT_REF_NAME" \
--cluster "$ISOGRID_CLUSTER" \
--tier "$ISOGRID_TIER" \
--network "$ISOGRID_NETWORK" \
$ENV_ARGS \
--wait
fi
يُعطى --provider gitlab صراحةً، فيعمل كذلك GitLab المستضاف ذاتيًا الذي لا يحتوي
عنوانه على "gitlab"، ويحمل $CI_PROJECT_URL المجموعات المتداخلة كما هي.
ما يفعله خطّ النشر، خطوةً بخطوة
يثبّت الـ CLI من منصّتك، مع التحقّق من بصمتها. الـ CLI والمنصّة من الجيل نفسه دائمًا، لأن إحداهما تقدّم الأخرى.
يسأل عن وجود التطبيق بـ apps get --exact. ودون --exact، سيُظنّ تطبيق جديد
اسمه api هو api-gateway الموجود، وسينشر خطّ النشر الشيء الخطأ.
يحدّثه إن كان موجودًا. يُبقي --branch التطبيق متتبّعًا للفرع الذي دُفع إليه.
ويبني --deploy --ref <commit> ذلك الإيداع بعينه، لا ما يشير إليه الفرع لحظة بدء
البناء، فلا يمكن لدفعتين متقاربتين أن تنشر إحداهما شيفرة الأخرى. ويدمج
--env-file الملف في بيئة التطبيق؛ والمفاتيح التي حذفتها من الملف تبقى على
التطبيق ما لم تضف --replace-env.
ينشئه في المرّة الأولى، من المستودع الذي أطلق التشغيل. وتعني القيم الفارغة لـ
--cluster و--tier و--network القيم الافتراضية.
ينتظر. لا يعود --wait إلا بعد انتهاء البناء والنشر، ويخرج بالرمز 1 حين
يفشل أيّهما، بما في ذلك نشر تُراجع عنه إلى النسخة السابقة. ورمز الخروج هذا هو ما
يُفشل المهمّة.
يشغّل نشرًا واحدًا في كل مرّة لكل فرع: concurrency في GitHub،
وresource_group في GitLab. الدفعة الثانية تنتظر الأولى بدل أن تسابقها.
كتابة خطّك الخاص
جوهر القالبين خمسة أسطر من أوامر الصدفة، فيمكن لأي نظام CI قادر على تشغيل صدفة أن يستخدمها:
curl -fsSL "$ISOGRID_API_URL/api/v1/cli/install.sh" | sh
if isogrid apps get "$APP" --exact --json > /dev/null 2>&1; then
isogrid apps update "$APP" --branch "$BRANCH" --deploy --ref "$COMMIT_SHA" --wait
else
isogrid apps create --name "$APP" --provider github --url "$REPO_URL" --branch "$BRANCH" --wait
fi
بديل: بناء الصورة في CI
إن كان خطّ النشر لديك يبني صورة حاوية أصلًا، فدعه يدفع الصورة إلى سجلّ مؤسّستك ودع المنصّة تنشرها، بدل البناء مرّة ثانية.
أنشئ التطبيق مرّة واحدة، من الصورة:
isogrid apps create --name worker --provider registry --url acme/worker:latest --cluster eu-west
ثم يدفع كل تشغيل وسمًا جديدًا ويوجّه التطبيق إليه:
docker build -t "$REGISTRY/$NAMESPACE/worker:$COMMIT_SHA" .
docker push "$REGISTRY/$NAMESPACE/worker:$COMMIT_SHA"
isogrid apps update worker --tag "$COMMIT_SHA" --deploy --wait
يحتاج خطّ النشر إلى بيانات اعتماد السجلّ بجانب ISOGRID_TOKEN: حساب آلي من صفحة
Images (الصور) في وحدة التحكّم، يُحفظ في ISOGRID_REGISTRY_USER مع
ISOGRID_REGISTRY_PASSWORD سرًّا أو متغيّرًا مُقنَّعًا، إضافةً إلى
ISOGRID_REGISTRY (مضيف السجلّ) وISOGRID_NAMESPACE (مساحة أسمائك). يحمل
القالبان هذه المهمّة معلَّقة في أسفل الملف. ويجب أن تكون أسماء الصور بحروف صغيرة،
فاضبط ISOGRID_APP صراحةً حين لا يكون اسم المستودع كذلك.
حين تسوء الأمور
اجعل isogrid whoami أول أمر في المهمّة ما دمت تضبط الأمور. يطبع لمن تعود بيانات
الاعتماد، والمؤسّسة المثبّتة عليها، والصلاحيات التي ستُسمح لها فعلًا.
"not signed in". ISOGRID_TOKEN فارغ في المهمّة. في GitHub، لا يُمرَّر السرّ
إلى سير العمل الذي تُطلقه نسخ متفرّعة (forks). وفي GitLab، لا يُمرَّر المتغيّر
Protected إلى الفروع غير المحميّة.
انتهت صلاحية بيانات الاعتماد، أو أُبطلت. أنشئ واحدة جديدة واستبدل السرّ. لا شيء آخر يحتاج إلى تغيير.
خطأ صلاحيات في apps create. تفتقر بيانات الاعتماد إلى application:create،
أو أنك لا تملكه بنفسك. يبيّن whoami أيّهما.
خطأ صلاحيات في apps update. لا تستطيع بيانات الاعتماد تعديل ذلك التطبيق أو
نشره. إمّا أنها تفتقر إلى application:write-any، وإمّا أنها لا تملك إلا
application:deploy-any والأمر مرّر إعدادًا (--env-file، أو --branch مختلفًا).
"is not a repository you have been given access to"، أو "You do not have
'repo:deploy' on acme/api". الرمز يعمل باسمك، وأنت لا تستطيع البناء من ذلك
المستودع. شخص آخر ربط الحساب الذي يأتي عبره المستودع ولم يفتحه لك. اطلب منه، أو من
مسؤول إن كان قد غادر، أن يشغّل isogrid repos grant acme/api --member you@example.com --preset repo-deployer. وإن كان المستودع مفتوحًا لـ المسؤولين وكنت منهم، فأنشئ بيانات
الاعتماد مع github:manage في نطاقاتها أيضًا: فعلى هذه الصلاحية يقوم وصول المسؤولين
إلى المستودعات. انظر مستودعات Git.
"pinned to" مؤسّسة أخرى. وُوفق على بيانات الاعتماد بينما كان المتصفّح يعرض
مؤسّسة مختلفة، أو أن ISOGRID_ORGANIZATION أو --organization يسمّي مؤسّسة ليست
مثبّتة عليها. بدّل المؤسّسة في وحدة التحكّم وأنشئ بيانات الاعتماد مجدّدًا.
"choose a region with --cluster". أكثر من منطقة مفتوحة لك. اضبط
ISOGRID_CLUSTER.
انتهت مهلة المهمّة لكن النشر اكتمل. توقّف --wait بعد --timeout (20 دقيقة
افتراضيًا)؛ واستمرّ النشر. ارفعها بـ --timeout 40m لعمليات البناء البطيئة.
فشلت المهمّة والموقع ما زال يعمل. لم تصبح النسخة الجديدة سليمة أبدًا فأُعيدت
السابقة. وهذا فشل يستحقّ أن تفشل المهمّة من أجله. اقرأ isogrid apps logs <app>.
رموز الخروج
| الرمز | المعنى |
|---|---|
0 |
تمّ النشر، أو لا شيء يُغيَّر. |
1 |
فشل شيء ما: خطأ من واجهة API أو خطأ صلاحيات، أو بناء فاشل، أو نشر فاشل أو متراجَع عنه، أو انتهاء المهلة. |
2 |
استُدعي الأمر بشكل خاطئ: خيار مجهول، أو قيمة ناقصة، أو delete دون --yes. يكاد يكون دائمًا خطأً في ملف خطّ النشر. |