Is possible have multiple cloudbuild.yaml files per subdirectory?
For example:
my-app:
- service1
- cloudbuild.yaml
- service2
- cloudbuild.yaml
cloudbuild.yaml
The answer is almost correct. This will not work, because you forgot to include ".", which tells to upload and build the current directory. The correct way to include a sub/child cloudbuild.yaml would then be:
# Include cloudbuild sub step
- name: 'gcr.io/cloud-builders/gcloud'
args:
- 'builds'
- 'submit'
- '.'
- '--config'
- 'cloudbuild.yaml'
Yes, definitely! Are you trying to initialize the builds of service1 and service2 from my-app/cloudbuild.yaml?
Example of using a meta config to initialize other builds: https://github.com/GoogleCloudPlatform/cloudbuild-integration-testing/blob/master/cloudbuild.meta.yaml
Here is a cloudbuild.meta.yaml building off of your example:
steps:
- id: 'build service1'
name: 'gcr.io/cloud-builders/gcloud'
args: ['builds', 'submit', '--config service1/cloudbuild.yaml']
waitFor: ['-'] #start in parallel
- id: 'build service2'
name: 'gcr.io/cloud-builders/gcloud'
args: ['builds', 'submit', '--config service2/cloudbuild.yaml']
waitFor: ['-'] # start in parallel
Related
I have a GCP project where I continuously deploy changes (PRs) made to a GitHub repository to a cloud-run service using cloud build triggers
the way i set it up at first is that i use GCP GUI
this results in a trigger in cloud-build\
the cloud-build trigger has the yaml file that looks like this
- name: gcr.io/cloud-builders/docker
args:
- build
- '--no-cache'
- '-t'
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
- .
- '-f'
- Dockerfile
id: Build
- name: gcr.io/cloud-builders/docker
args:
- push
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
id: Push
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
args:
- run
- services
- update
- $_SERVICE_NAME
- '--platform=managed'
- '--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
- >-
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS
- '--region=$_DEPLOY_REGION'
- '--quiet'
id: Deploy
entrypoint: gcloud
images:
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
options:
substitutionOption: ALLOW_LOOSE
substitutions:
_PLATFORM: managed
_SERVICE_NAME: bordereau
_DEPLOY_REGION: europe-west1
_LABELS: gcb-trigger-id=((a long random id goes here))
_TRIGGER_ID: ((an other long random id goes here))
_GCR_HOSTNAME: eu.gcr.io
tags:
- gcp-cloud-build-deploy-cloud-run
- gcp-cloud-build-deploy-cloud-run-managed
- bordereau
when ever this trigger is run, a new cloud-run revision is created like this
then i can create a url that points to a specific url like this
that helps me access each revision using its unique URL
i tried many ways to eddit the cloud-build YAML file to give each revision a unique URL automaticly ( not manually through the GCP GUI ) but i dont seem to find a way! i tried many keywords, and read the documentation but that didnt help either!
any help is very much appreciated.
it would be great if the revision URL (tag) was something unique and short like first charecters of the commit SHA or the PR number
Usually you can do like that (see step id: tag)
- name: gcr.io/cloud-builders/docker
args:
- build
- '--no-cache'
- '-t'
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
- .
- '-f'
- Dockerfile
id: Build
- name: gcr.io/cloud-builders/docker
args:
- push
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
id: Push
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
args:
- run
- services
- update
- $_SERVICE_NAME
- '--platform=managed'
- '--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
- >-
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID,$_LABELS
- '--region=$_DEPLOY_REGION'
- '--quiet'
id: Deploy
entrypoint: gcloud
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
args:
- -c
- |
export sha=$COMMIT_SHA
export CUSTOM_TAG=${sha:0:8}
export CURRENT_REV=$(gcloud alpha run services describe $_SERVICE_NAME --region=$_DEPLOY_REGION --platform=managed --format='value(status.traffic[0].revisionName)')
gcloud run services update-traffic $_SERVICE_NAME --set-tags=$$CUSTOM_TAG=$$CURRENT_REV --region=$_DEPLOY_REGION --platform=managed
id: tag
entrypoint: bash
images:
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
options:
substitutionOption: ALLOW_LOOSE
substitutions:
_PLATFORM: managed
_SERVICE_NAME: bordereau
_DEPLOY_REGION: europe-west1
_LABELS: gcb-trigger-id=((a long random id goes here))
_TRIGGER_ID: ((an other long random id goes here))
_GCR_HOSTNAME: eu.gcr.io
tags:
- gcp-cloud-build-deploy-cloud-run
- gcp-cloud-build-deploy-cloud-run-managed
- bordereau
In that custom tag, I put the 8 first character of the commit SHA
You can note the weird env var COMMIT_SHA copy to a local env var. It's a strange thing with CloudBuild.
Lets say I have a cloudbuild.yaml file that looks like this:
steps:
- name: 'gcr.io/cloud-builders/docker'
id: build
args: ['build', '-t', 'us.gcr.io/${PROJECT_ID}/image_name', '--build-arg', 'secret=$$SECRET', '.']
secretEnv: ['SECRET']
images:
- 'us.gcr.io/${PROJECT_ID}/image_name'
availableSecrets:
secretManager:
- versionName: projects/project/secrets/my_secret/versions/latest
env: 'SECRET'
Right now, the --build-arg is assigning to the Docker secret arg the value $SECRET instead of the value actually stored in the secret. How can I access the secret value during this step? All of the examples I can find online say to add a bash entrypoint however only for steps that aren't actually doing the build call.
It's a usual issue with Cloud Build and Secret Manager integration. You can access to the secret only in a script, not in entry-point and arguments (your case)
Try that
steps:
- name: 'gcr.io/cloud-builders/docker'
id: build
entrypoint: 'bash'
args:
- -c
- |
docker build -t us.gcr.io/${PROJECT_ID}/image_name --build-arg secret=$$SECRET .
secretEnv: ['SECRET']
The syntax for assigning secrets to docker args seems to be slightly different to that for normal environment variables. The following snippet is taken from a working project of my own and correctly accesses the secret, and you can see the difference compared to the normal environment variables:
...
env:
- PROJECT_ID=$PROJECT_ID
- NO_DEPLOY=$_NO_DEPLOY
- NO_E2E=$_NO_E2E
secretEnv:
- "EXAMPLE_API_KEY"
args:
- --destination=gcr.io/$PROJECT_ID/api
- --cache=true
- --build-arg=PROJECT_ID
- --build-arg=EXAMPLE_API_KEY
- --build-arg=NO_DEPLOY
- --build-arg=NO_E2E
availableSecrets:
secretManager:
- versionName: projects/$PROJECT_ID/secrets/example-api-key/versions/latest
env: "EXAMPLE_API_KEY"
...
I'm using cloudbuild to deploy new version of my app when a new commit appears in github.
Everything is working good.
Now I'm trying to setup a variable substitution in the trigger configuration, because I want to put my version number in the trigger once, so that I can find the deployed correct version without modifying cloudbuild configuration file.
Variabile substitution works great in my cloudbuild file, for example:
(cloudbuild.yaml)
# TEST: PRINT VARIABLE IN LOG
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args: ['-c', 'echo', '${_VERSION}']
# DEPLOY APP
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy", "-v", "${_VERSION}", "app.yaml"]
dir: 'frontend'
timeout: "20m"
${_VERSION} is correctly replaced with the string I put into my trigger.
Now I want to obtain the same result in app.yaml file, substituting an env variabile, something like:
(app.yaml)
runtime: nodejs
env: flex
service: backend
env_variables:
VERSION: "${_VERSION}"
TEST_ENV: "read from google"
When I read TEST_ENV from my app, it works, but _VERSION is not replaced.
Any suggestion?
When you perform this step
# DEPLOY APP
- name: "gcr.io/cloud-builders/gcloud"
args: ["app", "deploy", "-v", "${_VERSION}", "app.yaml"]
dir: 'frontend'
timeout: "20m"
The app.yaml is provided as-is to the gcloud command, and it's not evaluated. You have to update it manually. Something like this
# REPLACE: PUT THE CORRECT VALUE IN APP.YAML FILE
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args: ['-c', 'sed', "-i", "sed -i "s/\$${_VERSION}/${_VERSION}/g", 'app.yaml']
Of course if you let the
env_variables:
VERSION: "${_VERSION}"
as-is in your app.yaml file. You can change this replacement string
I want to add this solution in case someone has problems with the one proposed by giullade (in my case, cloudbuild gave me an error in executing the sed command).
I also changed my replacement string to one more readable and to avoid escaping the $ sign.
# Step 0: REPLACE variables in app.yaml file
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
dir: 'backend'
args:
- '-c'
- |
sed -i "s/__VERSION/${_VERSION}/g" app-staging.yaml
and in my app.yaml:
env_variables:
VERSION_ENV: "__VERSION"
How does one pass a secret from Google Secrets Manager (GSM) to a Cloud Function when using Cloud Build? The below cloudbuild.yaml has three steps. Further, I'm using volumes to create permanent storage between build steps. I can confirm GSM retrieval by Cloud Build. However, when I attempt to pass a secret in yaml format using --env-vars-file I encounter the following error ...
Already have image (with digest): gcr.io/cloud-builders/gcloud
ERROR: gcloud crashed (AttributeError): 'str' object has no attribute 'items'
cloudbuild.yaml:
steps:
- name: 'gcr.io/cloud-builders/gcloud'
volumes:
- name: 'secrets'
path: '/secrets'
entrypoint: "bash"
args:
- "-c"
- |
echo -n 'gsm_secret:' > /secrets/my-secret-file.txt
- name: 'gcr.io/cloud-builders/gcloud'
volumes:
- name: 'secrets'
path: '/secrets'
entrypoint: "bash"
args:
- "-c"
- |
gcloud components update
gcloud beta secrets versions access --secret=MySecret latest >> /secrets/my-secret-file.txt
cat /secrets/my-secret-file.txt
- name: 'gcr.io/cloud-builders/gcloud'
volumes:
- name: 'secrets'
path: '/secrets'
args: [
'functions', 'deploy', 'gsm-foobar',
'--project=[...]',
'--trigger-http',
'--runtime=go111',
'--region=us-central1',
'--memory=256MB',
'--timeout=540',
'--entry-point=GSM',
'--allow-unauthenticated',
'--source=https://source.developers.google.com/[...]',
'--service-account', '[...]#appspot.gserviceaccount.com',
'--env-vars-file', '/secrets/my-secret-file.txt'
]
Update:
Usage of volumes is not required as /workspace is permanent storage between steps in Cloud Build. Also, gcloud components update is no longer necessary as the default Cloud SDK version, as of today, is 279.0.0
A Solution:
steps:
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: "bash"
args:
- "-c"
- |
echo "gsm_secret: $(gcloud beta secrets versions access --secret=MySecret latest)" > /workspace/my-secret-file.txt
cat /workspace/my-secret-file.txt
- name: 'gcr.io/cloud-builders/gcloud'
args: [
'functions', 'deploy', 'gsm-foobar',
[...]
'--entry-point=GSM',
'--allow-unauthenticated',
'--source=https://source.developers.google.com/[...]',
'--service-account', '[...]#appspot.gserviceaccount.com',
'--env-vars-file=/workspace/my-secret-file.txt'
]
On second read, I realize your 2nd step puts the secret value in the file. I think you're missing the newline.
NB I've not tried this for myself!
Ensure you have a newline at the end of your secrets file.
See: https://cloud.google.com/functions/docs/env-var
Update: tried it ;-)
I think your issue was the final newline.
Using the following in a step prior to the deployment, works:
echo "gsm_secret: $(gcloud beta secrets versions access --secret=MySecret latest)" > /secrets/my-secret-file.txt
Or, more simply, perhaps:
steps:
- name: "gcr.io/cloud-builders/gcloud"
entrypoint: /bin/bash
args:
- "-c"
- |
gcloud functions deploy ... \
--set-env-vars=NAME=$(gcloud beta secrets versions access --secret=name latest)
Also, see secretEnv. This is a more elegant mechanism..This functionality should perhaps be augmented by Google to support secret manager (in addition to KMS).
As of 2021 February 10, you can access Secret Manager secrets directly from Cloud Build using the availableSecrets field:
steps:
- id: 'deploy'
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- 'gcloud functions deploy --set-env-vars=SECRET=$$MY_SECRET'
secretEnv: ['MY_SECRET']
availableSecrets:
secretManager:
- versionName: 'projects/my-project/secrets/my-secret/versions/latest'
env: 'MY_SECRET'
Documentation
The Problem
A GitHub trigger set up in Google Cloud Build doesn't actually substitute the configured values while running the Build (cloudbuild.yaml)
This is the Google Cloud Build config
cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/gcloud'
id: 'decrypt .npmrc'
args:
- kms
- decrypt
- --ciphertext-file=npmrc.enc
- --plaintext-file=/root/.npmrc
- --location=global
- --keyring=my-keyring
- --key=npm-key
- --project=${_CLOUD_KMS_PROJECT}
volumes:
- name: 'home'
path: /root/
- name: 'gcr.io/cloud-builders/npm'
id: 'install'
args: ['install']
env:
- HOME=/root/
volumes:
- name: 'home'
path: /root/
- name: 'gcr.io/cloud-builders/npm'
id: 'test'
args: ['run', 'test']
- name: gcr.io/$PROJECT_ID/skaffold:alpha
id: 'deploy'
args: ['run', '-f=${_SKAFFOLD_FILE}']
env:
- CLOUDSDK_COMPUTE_ZONE=${_CLOUDSDK_COMPUTE_ZONE}
- CLOUDSDK_CONTAINER_CLUSTER=${_CLOUDSDK_CONTAINER_CLUSTER}
substitutions:
_SKAFFOLD_FILE: dummy.yaml
_CLOUDSDK_COMPUTE_ZONE: us-west1-a
_CLOUDSDK_CONTAINER_CLUSTER: dummy
timeout: 1000s
Curiously, when triggering the build via a gcloud SDK call it works ✅ ex:
gcloud builds submit --config=cloudbuild.yaml --substitutions=_SKAFFOLD_FILE=skaffold.yaml,_CLOUDSDK_COMPUTE_ZONE=us-west1-a,_CLOUDSDK_CONTAINER_CLUSTER=skaffold .
Some more context
Cloud Build Trigger dashboard (img)
Trigger configuration with substitutions (img)
Missing substitutions in Build history from triggered build (img)
In contrast: Correctly substituted values when running gcloud builds submit (img)