אתם יכולים להגדיר ולשלוח פייפליין של Image Builder באופן פרוגרמטי באמצעות ה-CLI של gcloud, Terraform או ספריות לקוח כמו Go. הגדרת הפייפליין באופן פרוגרמטי מאפשרת לכם להגדיר את הגדרות התשתית, קובצי אימג' של מערכת ההפעלה הבסיסיים, פעולות ההתאמה האישית ובדיקות האימות בקובצי תצורה הצהרתיים.
לפני שמתחילים
- מבצעים את השלבים להגדרת הסביבה שמפורטים בקטע הכנת הסביבה.
- אם אתם מתכוונים לפרוס את צינור עיבוד הנתונים באמצעות Terraform או להפוך את ה-builds לאוטומטיים ממאגר, חברו את המאגר שלכם ב-GitHub, ב-GitLab או ב-Bitbucket באמצעות מאגרי Cloud Build (
2nd gen) או קישורי Developer Connect. - אם אתם מתכוונים להשתמש ב-Terraform, התקינו את Terraform CLI בגרסה 1.3 ואילך.
-
אם עדיין לא עשיתם את זה, תצטרכו להגדיר אימות.
אימות הוא התהליך שבו מאמתים את הזהות שלכם כדי לקבל גישה לממשקי API ולשירותים של Google Cloud . כדי להריץ קוד או דוגמאות מסביבת פיתוח מקומית, אפשר לבצע אימות ל-Compute Engine באחת מהדרכים האלה:
צריך לבחור את הכרטיסייה הרלוונטית לאופן שבו תכננתם להשתמש בדוגמאות בדף הזה:
gcloud
-
התקינו את ה-CLI של Google Cloud. אחר כך, אתחלו את ה-CLI של Google Cloud באמצעות הפקודה הבאה:
gcloud initאם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
- הגדרת אזור ותחום כברירת מחדל.
-
התקינו את ה-CLI של Google Cloud.
-
אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
אם אתם משתמשים במעטפת מקומית, צרו פרטי כניסה לאימות מקומי בחשבון המשתמש:
gcloud auth application-default login
אם אתם משתמשים ב-Cloud Shell, אתם לא צריכים לעשות את זה.
אם מוחזרת שגיאת אימות ואתם משתמשים בספק זהויות חיצוני (IdP), ודאו ש נכנסתם ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
התקינו את ה-CLI של Google Cloud.
-
אם אתם משתמשים בספק זהויות חיצוני (IdP), קודם אתם צריכים להיכנס ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
-
אם אתם משתמשים במעטפת מקומית, צרו פרטי כניסה לאימות מקומי בחשבון המשתמש:
gcloud auth application-default login
אם אתם משתמשים ב-Cloud Shell, אתם לא צריכים לעשות את זה.
אם מוחזרת שגיאת אימות ואתם משתמשים בספק זהויות חיצוני (IdP), ודאו ש נכנסתם ל-CLI של gcloud באמצעות המאגר המאוחד לניהול זהויות.
Terraform
כדי להשתמש בסביבת פיתוח מקומית בדוגמאות של Terraform שבדף הזה, מתקינים ומפעילים את ה-CLI של gcloud, ואז מגדירים את Application Default Credentials באמצעות פרטי הכניסה של המשתמש.
למידע נוסף, ראו הגדרת אימות לסביבת פיתוח מקומית.
המשך
כדי להשתמש בסביבת פיתוח מקומית בדוגמאות של Go שבדף הזה, מתקינים ומפעילים את ה-CLI של gcloud, ואז מגדירים את Application Default Credentials באמצעות פרטי הכניסה של המשתמש.
למידע נוסף, ראו הגדרת אימות לסביבת פיתוח מקומית.
התפקידים הנדרשים
כדי לקבל את ההרשאות שדרושות ליצירה ולשליחה של צינורות עיבוד נתונים להתאמה אישית של תמונות באופן פרוגרמטי, בקשו מהאדמין להקצות לכם את התפקידים הבאים ב-IAM בפרויקט:
- עריכה ב-Cloud Build (
roles/cloudbuild.builds.editor) - משתמש בחשבון שירות (
roles/iam.serviceAccountUser)
להסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.
יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.
יצירת קובצי תצורה
כדי להגדיר את צינור עיבוד הנתונים באמצעות ה-CLI של gcloud או Terraform, צריך ליצור שני קובצי תצורה:
-
imagebuilder.yaml: מגדיר את מתכון ההתאמה האישית של קובץ האימג', כולל קובץ האימג' של מערכת ההפעלה הבסיסית, הגדרות התשתית של ה-worker VM, פרטי הפלט של קובץ האימג' המטורגט ושלבי ההתאמה האישית העוקבים, כמו הפעלת סקריפטים של מעטפת, העברת קבצים או הפעלה מחדש. -
cloudbuild.yaml: מתזמר את השלבים של תהליך ה-build ב-Cloud Build, כולל ניתוח, אימות, יצירה, בדיקה ופרסום של קובץ האימג' של מערכת ההפעלה בהתאמה אישית.
אם אתם שולחים את ה-build באמצעות Go, אתם צריכים רק ליצור את הקובץ imagebuilder.yaml ולהעלות אותו לקטגוריה של Cloud Storage, כי הדוגמה של Go מגדירה את שלבי התזמור של Cloud Build בקוד.
יצירת קובץ התצורה של התמונה
כדי לציין את הגדרות האימג', יוצרים קובץ בשם imagebuilder.yaml בספרייה המקומית. רשימה מלאה של כל שדות הסכימה הנתמכים ופעולות ההתאמה האישית מופיעה במאמרים סכימת מתכון להתאמה אישית ופעולות נתמכות להתאמה אישית.
קובץ ה-imagebuilder.yaml לדוגמה הבא מגדיר פייפליין שיוצר קובץ אימג' מותאם אישית של Ubuntu 22.04 LTS באמצעות worker VM e2-standard-4 באזור ובתחום (zone) שציינתם, ומבצע עדכון של חבילת המערכת.
apiVersion: imagebuilder.gcp.com/v1 kind: OSImageCustomization metadata: name: customized-ubuntu-baseline description: "Ubuntu 22.04 LTS custom OS baseline image" infrastructureConfig: machineType: e2-standard-4 zone: ZONE debug: false source: imageFamily: projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts destinations: - diskImage: name: custom-ubuntu-v1 family: custom-ubuntu-family project: PROJECT_ID storageLocations: - REGION spec: config: skipSystemTests: false steps: - name: "System Package Update" action: Shell inputs: command: "apt-get update -y && apt-get upgrade -y"
מחליפים את הערכים הזמניים הבאים לשמירת מקום:
PROJECT_ID: מזהה הפרויקט.-
REGION: מיקום האחסון של קובץ האימג' של היעד, לדוגמהus-east1אוeurope-west1. חשוב לוודא שאתם עומדים בדרישות הבאות לגבי אזורים וזמינות:- אפשר להשתמש ב-Image Builder רק באזורים שבהם Cloud Build זמין.
- ה-worker VM
ZONEחייב להיות בתוך ה-REGIONשציינתם. - כדי לצמצם את זמן האחזור ברשת ולמנוע חיובים על תעבורת נתונים יוצאת לכמה אזורים, ודאו שהאזור של ה-worker VM, קטגוריית ה-staging ב-Cloud Storage, המאגר ב-Artifact Registry ומיקום האחסון של קובץ האימג' נמצאים באותו אזור.
-
ZONE: אזור שנמצא בתוךREGIONשציינתם, לדוגמהus-east1-bאוeurope-west1-b.
יצירת קובץ ה-build של התזמור
יוצרים קובץ בשם cloudbuild.yaml באותה ספרייה. הקובץ הזה קורא לשלבים של קונטיינר Image Builder כדי ליצור, לאמת ולפרסם את קובץ האימג' של מערכת ההפעלה בהתאמה אישית.
substitutions: _GCS_WORKDIR: 'gs://STAGING_BUCKET_NAME/workdir/' _IMAGE_BUILDER_CONFIG_PATH: 'imagebuilder.yaml' _SERVICE_ACCOUNT: 'projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL' _IMAGE_OUTPUT_PATH: 'image-builder/binaryOut' _ARTIFACT_REGISTRY_RESOURCE_URI: 'projects/PROJECT_ID/locations/REGION/repositories/REPOSITORY_NAME/packages/PACKAGE_NAME/versions/v${BUILD_ID}' steps: # Step 1: Parse configs and run OS customization on worker VM - name: 'REGION-docker.pkg.dev/image-builder-official/release/builder:stable' script: | #!/usr/bin/env bash /build id: 'imagebuilder-customize' results: - name: image_builder_telemetry_metrics - name: base_image attestationType: "https://cloudbuild.googleapis.com/attestations/build_content_restrictions" attestationContent: base_image # Step 2: Validate by running system boot checks on a test VM - name: 'REGION-docker.pkg.dev/image-builder-official/release/validator:stable' script: | #!/usr/bin/env bash /validate id: 'imagebuilder-validate' results: - name: image_builder_telemetry_metrics # Step 3: Register image in Compute Engine and upload tar files to Artifact Registry - name: 'REGION-docker.pkg.dev/image-builder-official/release/builder:stable' script: | #!/usr/bin/env bash /publish id: 'imagebuilder-publish' results: - name: image_builder_telemetry_metrics options: automapSubstitutions: true requestedVerifyOption: VERIFIED substitutionOption: ALLOW_LOOSE dynamicSubstitutions: true logging: CLOUD_LOGGING_ONLY artifacts: generic_artifacts: - folder: '${_IMAGE_OUTPUT_PATH}' registry_path: '${_ARTIFACT_REGISTRY_RESOURCE_URI}' timeout: '3600s'
מחליפים את הערכים הזמניים הבאים לשמירת מקום:
-
STAGING_BUCKET_NAME: קטגוריה קיימת של Cloud Storage בפרויקט, שתשמש כסביבת עבודה זמנית להכנת הנתונים. אם אין לכם קטגוריה, אתם יכולים ליצור אחת באמצעות הפעלתgcloud storage buckets create gs://STAGING_BUCKET_NAME. אם אתם פורסים את צינור עיבוד הנתונים באמצעות Terraform, Terraform יוצר את הקטגוריה הזו באופן אוטומטי. -
PROJECT_ID: מזהה הפרויקט ב- Google Cloud . -
REGION: Google Cloud האזור של מאגר Artifact Registry, לדוגמהus-east1אוeurope-west1. -
SERVICE_ACCOUNT_EMAIL: כתובת האימייל של חשבון השירות שהגדרתם עם הרשאות ה-IAM הנדרשות. -
REPOSITORYו-PACKAGE: מאגר היעד ושם החבילה שנוצרו ב-Artifact Registry. כדי להגדיר את המרשם של Artifact Registry, קראו את המאמר הגדרת Artifact Registry.
יצירה ושליחה של צינור עיבוד הנתונים של ה-build
כדי להריץ את צינור עיבוד הנתונים להתאמה אישית של תמונות, שולחים גרסת build באמצעות ה-CLI של gcloud, פורסים את צינור עיבוד הנתונים באמצעות Terraform או שולחים גרסת build באמצעות ספריית הלקוח של Go. בוחרים אחת מהכרטיסיות הבאות:
gcloud
כדי לפרוס ולהריץ את צינור עיבוד הנתונים להתאמה אישית של קובץ האימג', מריצים את הפקודה gcloud builds submit מהספרייה המקומית של הטרמינל שמכילה את שני קובצי התצורה:
gcloud builds submit . \
--config=cloudbuild.yaml \
--project=PROJECT_ID \
--service-account="projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL" \
--region=REGION
מחליפים את מה שכתוב בשדות הבאים:
-
PROJECT_ID: מזהה הפרויקט ב- Google Cloud . -
REGION: האזור ב- Google Cloud שבו רוצים להריץ את משימת הצינור להתאמה אישית של תמונות. -
SERVICE_ACCOUNT_EMAIL: כתובת האימייל של חשבון השירות שמוגדר עם הרשאות ה-IAM הנדרשות.
הפקודה הזו מעלה את סביבת העבודה להתאמה אישית, רושמת את ההפעלה של Cloud Build ומפעילה את הקונטיינרים של התזמור.
Terraform
כדי להקצות את התשתית שנדרשת לבנייה ולאימות אוטומטיים של קובצי אימג' מותאמים אישית של מערכת ההפעלה, אתם יכולים להשתמש ב-Terraform. ההגדרה הזו של Terraform מבצעת את המשימות הבאות:
- מפעילים את ממשקי ה-API הנדרשים של Google Cloud .
- יוצרת קטגוריה ייעודית של Cloud Storage (
workdir_bucket) לאחסון יומנים זמניים ופריטי מידע שנוצרו בתהליך פיתוח התוכנה. - מגדיר טריגר לפיתוח גרסת Build של Cloud (
image_builder_trigger) שמקושר לחיבור של מאגר GitHub ב-Developer Connect.
יצירת קובצי התצורה של Terraform
כדי לארגן ולפרוס את תשתית הצינור באמצעות Terraform, מבצעים את השלבים הבאים:
יוצרים ספרייה ייעודית בתחנת העבודה המקומית או בסביבת ה-CI/CD, בנפרד ממאגר האפליקציות, ועוברים אליה:
mkdir terraform-image-builder && cd terraform-image-builder
בספרייה הזו, יוצרים את חמשת קובצי התצורה הבאים של Terraform:
-
terraform.tfvars: מגדיר ערכים למשתנים ספציפיים לפרויקט. -
main.tf: מקצה משאבים בפרויקט ב- Google Cloud , כולל הפעלת ממשקי ה-API הנדרשים, יצירת קטגוריית ה-Staging ב-Cloud Storage (workdir_bucket) ופריסת טריגר לפיתוח גרסת Build של Cloud Build (image_builder_trigger). -
outputs.tf: מגדיר את ערכי הפלט שמוצגים במסוף אחרי הפריסה, כמו מזהה הטריגר ושם הקטגוריה של ה-Staging. -
providers.tf: מציין את הגרסה הנדרשת של Terraform (>= 1.3) ומגדיר את הספק של Google Cloud (hashicorp/google). -
variables.tf: הגדרה של משתני הקלט, ערכי ברירת המחדל וכללי האימות לפריסה.
בוחרים אחת מהכרטיסיות הבאות כדי להציג ולהעתיק את ההגדרות של כל קובץ לספרייה המקומית:
terraform.tfvarsבקובץ הזה מצוינים ערכי הפרמטרים של הסביבה שלכם למשתנים שהוצהרו:
project_id = "PROJECT_ID" builder_service_account = "SERVICE_ACCOUNT_EMAIL" github_repo_name = "projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION/repositories/REPO_NAME" region = "REGION" trigger_name = "TRIGGER_NAME" cloudbuild_yaml_path = "CLOUDBUILD_YAML_PATH" image_builder_config_path = "RECIPE_PATH" gcs_lifecycle_age_days = LIFECYCLE_DAYS ar_repository_id = "REPOSITORY_NAME" ar_package_name = "PACKAGE_NAME"
מחליפים את ה-placeholders הבאים במשאבים הקיימים:
-
PROJECT_ID: מזהה הפרויקט הקיים ב-Google Cloud . -
SERVICE_ACCOUNT_EMAIL: כתובת האימייל של חשבון השירות של ה-build שהגדרתם בקטע הגדרת חשבון שירות ל-Image Builder. -
LOCATION,CONNECTIONו-REPO_NAME: האזור המארח של Developer Connect, שם החיבור והקישור למאגר שהגדרתם בקטע קישור למאגר. -
CLOUDBUILD_YAML_PATH: הנתיב היחסי לקובץcloudbuild.yamlבספרייה המקומית. אין צורך להוסיף אתcloudbuild.yamlלמאגר Git. -
RECIPE_PATH: הנתיב היחסי לקובץ המתכון להתאמה אישית שלimagebuilder.yaml, שנמצא במאגר Git. REPOSITORY_NAME: מאגר Artifact Registry הגנרי הקיים שנוצר בהגדרת Artifact Registry.
מחליפים את הפלייסהולדרים הבאים של המשאבים שנוצרו ב-Terraform:
-
REGION: האזור ב- Google Cloudשבו Terraform מקצה את קטגוריית ה-Staging של Cloud Storage ואת הטריגר לפיתוח גרסת Build של Cloud Build, לדוגמהus-central1. -
TRIGGER_NAME: השם של הטריגר החדש של מאגר Cloud Build שנוצר על ידי Terraform, לדוגמהgit-push-os-builder. -
LIFECYCLE_DAYS: תקופת השמירה בימים לפני שפריטי המידע שנוצרו על ידי Terraform בקטגוריית ה-staging של Cloud Storage נמחקים באופן אוטומטי, לדוגמה30. -
PACKAGE_NAME: השם שאתם רוצים ש-Terraform ישתמש בו לחבילה שנוצרה במאגר Artifact Registry. החבילה הזו מאחסנת גרסאות של קובצי אימג' של מערכת ההפעלה שפורסמו, לדוגמהubuntu-custom.
main.tfבקובץ הזה מצהירים על משאבי התשתית העיקריים ועל מקורות הנתונים לפריסה:
# Main resource configurations for Image Builder. # 1. Enable Required APIs resource "google_project_service" "apis" { for_each = toset([ "compute.googleapis.com", "cloudbuild.googleapis.com", "artifactregistry.googleapis.com", "serviceusage.googleapis.com", "cloudresourcemanager.googleapis.com", "iam.googleapis.com", "storage.googleapis.com" ]) project = var.project_id service = each.key disable_on_destroy = false } # 2. Project data source to retrieve Project Number data "google_project" "project" { project_id = var.project_id depends_on = [google_project_service.apis] } locals { builder_sa = var.builder_service_account } # 3. Storage Bucket for Image Builder Workdir resource "google_storage_bucket" "workdir_bucket" { name = var.gcs_bucket_name != "" ? var.gcs_bucket_name : "${var.project_id}-vm-builder-workdir" project = var.project_id location = var.region force_destroy = true uniform_bucket_level_access = true lifecycle_rule { action { type = "Delete" } condition { age = var.gcs_lifecycle_age_days } } depends_on = [google_project_service.apis] } # 4. Cloud Build Trigger resource "google_cloudbuild_trigger" "image_builder_trigger" { name = var.trigger_name location = var.region project = var.project_id description = "Trigger that runs Image Builder customization" service_account = var.builder_service_account != "" ? "projects/${var.project_id}/serviceAccounts/${var.builder_service_account}" : null repository_event_config { repository = replace(var.github_repo_name, "gitRepositoryLinks", "repositories") push { branch = "^main$" } } filename = var.cloudbuild_yaml_path substitutions = { _GCS_WORKDIR = "gs://${google_storage_bucket.workdir_bucket.name}/workdir/" _SERVICE_ACCOUNT = "projects/${var.project_id}/serviceAccounts/${local.builder_sa}" _IMAGE_OUTPUT_PATH = "image-builder/binaryOut" _PROJECT_ID = var.project_id _LOCATION = var.region _REPOSITORY_NAME = var.ar_repository_id _PACKAGE_NAME = var.ar_package_name _IMAGE_BUILDER_CONFIG_PATH = var.image_builder_config_path _ARTIFACT_REGISTRY_RESOURCE_URI = "projects/${var.project_id}/locations/${var.region}/repositories/${var.ar_repository_id}/packages/${var.ar_package_name}/versions/v$${BUILD_ID}" } depends_on = [ google_project_service.apis ] }outputs.tfהקובץ הזה מגדיר את מאפייני הפלט שמוחזרים למסוף אחרי הפריסה:
output "builder_service_account" { value = local.builder_sa description = "The email representation of the resolved Image Builder service account." } output "workdir_bucket" { value = google_storage_bucket.workdir_bucket.name description = "The name of the storage workdir bucket." } output "artifact_registry_repository" { value = "projects/${var.project_id}/locations/${var.region}/repositories/${var.ar_repository_id}" description = "The fully qualified resource path of the Artifact Registry repository." } output "cloud_build_trigger_id" { value = google_cloudbuild_trigger.image_builder_trigger.trigger_id description = "The unique ID for the created Cloud Build Trigger." }providers.tfבקובץ הזה מגדירים את הגרסה הנדרשת של Terraform ואת הגדרות האזור:
terraform { required_version = ">= 1.3" required_providers { google = { source = "hashicorp/google" version = ">= 5.0, < 7.0" } } } provider "google" { project = var.project_id region = var.region }variables.tfבקובץ הזה מצהירים על כל משתני הקלט וכללי האימות הנדרשים והאופציונליים:
variable "project_id" { type = string description = "The target Project ID where resources will be created." validation { condition = can(regex("^[a-z0-9-]{6,30}$", var.project_id)) error_message = "The project_id must consist of lowercase letters, numbers, and hyphens, and be between 6 and 30 characters." } } variable "region" { type = string default = "us-central1" description = "Location used for cloud build triggers, storage buckets, and artifact registry." } variable "github_repo_name" { type = string default = "" description = "Developer Connect github repository details, format: projects/PROJECT_ID/locations/LOCATION/connections/CONNECTION/repositories/REPO_LINK" validation { condition = can(regex("^projects/[^/]+/locations/[^/]+/connections/[^/]+/(gitRepositoryLinks|repositories)/[^/]+$", var.github_repo_name)) error_message = "The github_repo_name must follow either the Cloud Build v2 repository link format (using '/repositories/') or the Developer Connect resource format (using '/gitRepositoryLinks/')." } } variable "builder_service_account" { type = string default = "" description = "The email representation of the pre-existing Image Builder service account. If omitted, the default Cloud Build service account will be used." } variable "gcs_bucket_name" { type = string default = "" description = "Custom name for the workdir storage bucket. If left empty, a default name using the project ID will be constructed." } variable "gcs_lifecycle_age_days" { type = number default = 30 description = "The number of days after which temporary logs and artifacts in the storage workdir bucket are deleted." } variable "ar_repository_id" { type = string default = "vm-images" description = "The repository ID for the generic Artifact Registry hosting the final OS image tarballs." } variable "ar_package_name" { type = string default = "image-builder" description = "The package name under which the generic OS image artifact will be registered in Artifact Registry." } variable "trigger_name" { type = string default = "custom-os-image-builder" description = "The name of the Cloud Build trigger." } variable "cloudbuild_yaml_path" { type = string default = "cloudbuild.yaml" description = "The path to the cloudbuild.yaml configuration file relative to the repository root." } variable "image_builder_config_path" { type = string default = "imagebuilder.yaml" description = "The path to the imagebuilder.yaml configuration file relative to the repository root." }-
כדי לפרוס את ההגדרות, מריצים את הפקודות הבאות בספרייה שמכילה את קובצי Terraform:
- מפעילים את הספרייה:
terraform init
- מאמתים את התחביר:
terraform validate
- צפייה בתצוגה מקדימה של הפריסה:
terraform plan
- מחילים את ההגדרה:
terraform apply
- מפעילים את הספרייה:
המשך
לפני שמריצים את הדוגמה הזו, צריך להעלות את קובץ התצורה imagebuilder.yaml לקטגוריית ה-staging ב-Cloud Storage, למשל gs://STAGING_BUCKET_NAME/imagebuilder.yaml.
כדי לשלוח build של Cloud Build שמריץ את צינור עיבוד הנתונים של Image Builder באמצעות ספריית הלקוח של Cloud Build ב-Go, משתמשים בדוגמה הבאה:
אימות ומעקב אחרי ה-build
כדי לעקוב אחרי ההתקדמות של צינור עיבוד הנתונים של ה-build, מבצעים את השלבים הבאים:
נכנסים לדף Cloud Build במסוף Google Cloud .
בתפריט הניווט, לוחצים על History כדי לראות את המשימות הפעילות או שהושלמו.
ברשימה Builds, לוחצים על Build ID של ה-build כדי לבדוק את יומני ההרצה של הקונטיינר. ביומנים מוצגים השלבים שמתבצעים ב-worker VM, כמו עדכונים של חבילות מערכת או פקודות מעטפת בהתאמה אישית, ואחריהם תוצאות של בדיקות אימות מה-test VM ורישום הפלט הסופי.
המאמרים הבאים
- כדי להגדיר ולהפעיל גרסאות build חוזרות או אוטומטיות משורת הפקודה:
- אימות מקור התמונה