תבניות pipeline
candidate: תג אחד לכל ה-pipeline (dotenv)
Section titled “candidate: תג אחד לכל ה-pipeline (dotenv)”job אחד מחשב את הזהות פעם אחת. כל job מאוחר מקבל אותה דרך needs, ואף אחד לא מחשב מחדש.
candidate: stage: test script: - echo "CANDIDATE=${CI_COMMIT_BRANCH}-$(date -u +%Y%m%d)-${CI_COMMIT_SHORT_SHA}" | tee candidate.env artifacts: reports: {dotenv: candidate.env}פורמט: <BRANCH>-YYYYMMDD-<SHA קצר>, למשל dev-20261001-78e24670.
איך מוודאים: ב-log של candidate מופיעה השורה CANDIDATE=…; ב-job מאוחר echo "$CANDIDATE" מדפיס אותה.
build loop
Section titled “build loop”build: stage: build needs: [candidate, test] script: - | for svc in $SERVICES; do docker build -t "$IMAGE_REPO/$svc:$CANDIDATE" -f "services/$svc/Dockerfile" services/ done- ה-context הוא
services/, לאservices/$svc: ה-Dockerfileמעתיקcommon/trident(תיקיית אחות משותפת). ראה docker/overview. - ה-
-tנותן את השם המלא כולל ה-tag.
איך מוודאים: ב-log כל service מסתיים ב-naming to …/<SERVICE>:<CANDIDATE>. ואחר כך על ה-VM: docker image ls --format '{{.Repository}}:{{.Tag}}'.
publish loop
Section titled “publish loop”publish: stage: publish needs: [candidate, build] script: - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY" - | for svc in $SERVICES; do docker push "$IMAGE_REPO/$svc:$CANDIDATE" done--password-stdin: ה-token לא נכנס לשורת הפקודה.docker pushמקבל רק את שם ה-image; בלי-t,-fאו context.- בלי
docker loginה-push נכשל ב-denied: access forbidden. - לעולם לא
latest, ולא retag.
איך מוודאים: Project → Deploy → Container registry מציג repository לכל service עם tag <CANDIDATE>. פרטים: gitlab/registry.
multi-line: - | מול כמה פריטים
Section titled “multi-line: - | מול כמה פריטים”broken: script: - for s in $SERVICES; do - echo "$s" - done
works: script: - | for s in $SERVICES; do echo "$s" doneאיך מוודאים: Pipeline editor → Validate, והרצה: ה-job works מדפיס שורה לכל service.
YAML quoting של :
Section titled “YAML quoting של :”פריט script עם : (נקודתיים+רווח) חייב מרכאות סביב כולו. הכללים והדוגמה: keywords.
promote family: extends + rules
Section titled “promote family: extends + rules”.promote הוא תבנית אחת; שלושה jobs שונים רק ב-TARGET_ENV וב-rules.
.promote: extends: .with-ci-scripts stage: promote needs: [candidate, publish] script: - bash .ci/scripts/promote.sh "$TARGET_ENV" "$CANDIDATE"
promote:dev: extends: .promote variables: {TARGET_ENV: dev} rules: [{if: '$CI_COMMIT_BRANCH == "dev"'}]
promote:staging: extends: .promote variables: {TARGET_ENV: staging} rules: [{if: '$CI_COMMIT_BRANCH == "main"'}]- ה-
.with-ci-scriptsעושהgit cloneשלtrident-ciל-.ciעםoauth2:${TRIDENT_GIT_TOKEN}(include מביא YAML, לא קבצים). promote:devשמקבל403: ה-variable ריק? ראה gitlab/variables (Protect ON ב-branch לא מוגן).- ה-CI כותב רק
versions/<ENV>.yaml, ו-Argo מסנכרן. אין שום פקודת cluster ב-job.
שער ידני ל-prod: needs + environment + resource_group
Section titled “שער ידני ל-prod: needs + environment + resource_group”promote:prod: extends: .promote variables: {TARGET_ENV: prod} needs: [candidate, promote:staging] rules: [{if: '$CI_COMMIT_BRANCH == "main"', when: manual}] environment: {name: production} resource_group: production- אותו
promote.sh, אותו job-template; ההבדל הואwhen: manual. needs: [candidate, promote:staging]: prod מקבל את ה-candidate של ה-pipeline הזה, לא "מה שנמצא עכשיו ב-staging". לכן לא מחשבים$CANDIDATEמחדש.- כפתור ▶ ב-pipeline ישן מקדם את ה-candidate הישן. זה מכוון.
- לא לוחצים על
promote:prodלפני שבדקת ש-staging תקין (/infoמחזירversionו-environmentנכונים).
promote:prod: למצוא וללחוץ
Section titled “promote:prod: למצוא וללחוץ”promote:prod הוא job ידני של אותו pipeline של main (לא pipeline נפרד). הוא כותב versions/prod.yaml ב-gitops, ו-Argo מסנכרן.
trident-source → Build → Pipelines → the main pipeline (the run whose candidate you validated) → stage promote → promote:prod → click ▶ (Run)git -C <REPO> pullgit -C <REPO> log origin/main -1 --format='%h %an %s' -- <FILE># TRIDENT: git -C trident-gitops log origin/main -1 --format='%h %an %s' -- apps/trident/versions/prod.yamlאיך מוודאים: ה-job ירוק; ב-trident-gitops commit חדש (promote(prod): <CANDIDATE>) ב-versions/prod.yaml; ב-Argo האפליקציה של prod Synced + Healthy בלי למחוק כלום.
include דק
Section titled “include דק”include: - project: "$TRIDENT_GROUP/trident-ci" ref: main file: pipelines/source.ymlה-repo של הקוד מכיל רק את ה-include; הלוגיקה חיה ב-trident-ci. שינוי ב-pipeline = commit ל-trident-ci. TRIDENT_GROUP הוא group variable (path, ללא Mask).
self-test job
Section titled “self-test job”repo ה-CI מוכיח שה-runner והקבצים עובדים:
stages: [check]check: stage: check tags: [trident] script: - docker info --format '{{.ServerVersion}}' - git --version - for f in pipelines/*.yml; do python3 -c "import sys,yaml; yaml.safe_load(open('$f'))" && echo "ok $f"; done - bash -n scripts/*.shאיך מוודאים: כל הפקודות עוברות; bash -n הוא בדיקת syntax בלבד. אם ה-job נתקע ב-"no runner for tags trident": gitlab/runners (scope).
idempotent push (no-op כש-אין שינוי)
Section titled “idempotent push (no-op כש-אין שינוי)”ה-push של promote חייב לעבור גם כשה-tag כבר כתוב: בלי שינוי אין commit.
git add <DIR>/<ENV>.yaml# TRIDENT: git add apps/trident/versions/<ENV>.yamlif ! git diff --cached --quiet; then git commit -q -m "promote(<ENV>): <CANDIDATE>" git push -q origin HEAD:<BRANCH>figit rev-parse HEADgit diff --cached --quiet יוצא 0 כשאין שינוי. פקודה בתנאי של if לא נחשבת ל-set -e, ולכן ה-script לא מת. ה-script המלא: bash/templates. הוסף [skip ci] להודעה אם ה-push מפעיל pipeline לולאתי ב-repo עם CI.