Cloud Run Deploy
cloud-run-deploy@1.0.0 Template Roll an image out to Google Cloud Run, wire Secret Manager secrets, and health-check the new revision.
Start from it
flightstack template use cloud-run-deploy What it does
Ship a container image to Cloud Run with gcloud run services update (keeps every setting you did not name) or gcloud run deploy (creates the service if needed), optionally set env vars and Secret Manager secrets, then probe the service before calling the deploy done. Emits url and revision.
Inputs
-
projectstring required - Google Cloud project id.
-
regionstring required - Cloud Run region, e.g. us-central1.
-
servicestring required - Cloud Run service name.
-
imagestring required - Image to deploy. Prefer a digest, e.g. the
imageRefoutput of docker-build-push, so the deploy is the exact build that was tested. -
modeupdate | deploy defaultupdate updatechanges only the image and the settings named here and fails if the service does not exist - safest for a service whose runtime account, scaling and secrets are managed elsewhere.deploycreates the service when it is missing.-
envVarsobject - Plain environment variables to set (--update-env-vars). Never secrets.
-
secretsobject - Environment variables read from Secret Manager (--update-secrets), e.g. DATABASE_URL: db-url:latest.
-
noTrafficboolean defaultfalse - Create the revision without sending it traffic. Pair with
tagto get a preview URL. -
tagstring - Revision tag, which gets its own URL (https://TAG---SERVICE-...run.app).
-
extraArgsstring - Extra flags for the gcloud command, e.g. "--memory 1Gi".
-
healthPathstring - Path to GET after the deploy, e.g. /health. The job fails unless it returns 2xx within the retry window. Empty skips the check.
-
healthTimeoutSecondsnumber default120 - How long to keep retrying the health check.
Definition
name: Cloud Run Deploy
description: >-
Roll a container image out to a Google Cloud Run service, optionally wire
Secret Manager secrets into it, and check the new revision answers before
calling the deploy done.
triggers:
- type: push
branches: [main]
jobs:
deploy:
name: Deploy API
type: plugin/cloud-run-deploy
with:
project: my-project
region: us-central1
service: api
image: "${{ steps.image.outputs.imageRef }}"
healthPath: /health
plugin:
name: cloud-run-deploy
displayName: Cloud Run Deploy
description: >-
Ship an image to Cloud Run with `gcloud run services update` (keeps every
setting you did not name) or `gcloud run deploy` (creates the service if
needed), then probe the service URL. Emits `url` and `revision`.
category: deploy
supportedPlatforms:
- linux
- macos
parameters:
type: object
properties:
project:
type: string
description: Google Cloud project id.
region:
type: string
description: Cloud Run region, e.g. us-central1.
service:
type: string
description: Cloud Run service name.
image:
type: string
description: >-
Image to deploy. Prefer a digest, e.g. the `imageRef` output of
docker-build-push, so the deploy is the exact build that was tested.
mode:
type: string
enum: [update, deploy]
default: update
description: >-
`update` changes only the image and the settings named here and
fails if the service does not exist - safest for a service whose
runtime account, scaling and secrets are managed elsewhere. `deploy`
creates the service when it is missing.
envVars:
type: object
description: Plain environment variables to set (--update-env-vars). Never secrets.
secrets:
type: object
description: >-
Environment variables read from Secret Manager (--update-secrets),
e.g. DATABASE_URL: db-url:latest.
noTraffic:
type: boolean
default: false
description: >-
Create the revision without sending it traffic. Pair with `tag` to
get a preview URL.
tag:
type: string
default: ""
description: Revision tag, which gets its own URL (https://TAG---SERVICE-...run.app).
extraArgs:
type: string
default: ""
description: Extra flags for the gcloud command, e.g. "--memory 1Gi".
healthPath:
type: string
default: ""
description: >-
Path to GET after the deploy, e.g. /health. The job fails unless it
returns 2xx within the retry window. Empty skips the check.
healthTimeoutSeconds:
type: number
default: 120
description: How long to keep retrying the health check.
required: [project, region, service, image]
script: |
set -euo pipefail
if ! command -v gcloud >/dev/null 2>&1; then
echo "gcloud is not installed on this agent." >&2
exit 1
fi
if [ -n "${GCP_SA_KEY:-}" ]; then
keyfile="$(mktemp)"
trap 'rm -f "$keyfile"' EXIT
printf '%s' "$GCP_SA_KEY" > "$keyfile"
gcloud auth activate-service-account --key-file "$keyfile" --quiet
elif [ -n "${GOOGLE_APPLICATION_CREDENTIALS:-}" ]; then
gcloud auth activate-service-account --key-file "$GOOGLE_APPLICATION_CREDENTIALS" --quiet
else
echo "note: no GCP_SA_KEY or GOOGLE_APPLICATION_CREDENTIALS; using the agent's active gcloud account."
fi
common=(--project "{{project}}" --region "{{region}}" --quiet)
if [ "{{mode}}" = "update" ]; then
args=(run services update "{{service}}" --image "{{image}}")
else
args=(run deploy "{{service}}" --image "{{image}}")
fi
envs=""
{{#each envVars}}
envs="${envs:+$envs,}{{@key}}={{this}}"
{{/each}}
if [ -n "$envs" ]; then args+=(--update-env-vars "$envs"); fi
secrets=""
{{#each secrets}}
secrets="${secrets:+$secrets,}{{@key}}={{this}}"
{{/each}}
if [ -n "$secrets" ]; then args+=(--update-secrets "$secrets"); fi
if [ "{{noTraffic}}" = "true" ]; then args+=(--no-traffic); fi
tag="{{tag}}"
if [ -n "$tag" ]; then args+=(--tag "$tag"); fi
echo "--- gcloud ${args[*]}"
gcloud "${args[@]}" "${common[@]}" {{extraArgs}}
url="$(gcloud run services describe "{{service}}" "${common[@]}" --format 'value(status.url)')"
revision="$(gcloud run services describe "{{service}}" "${common[@]}" --format 'value(status.latestReadyRevisionName)')"
if [ -n "$tag" ]; then
url="$(echo "$url" | sed "s#https://#https://$tag---#")"
fi
echo "revision $revision at $url"
fs-output url "$url"
fs-output revision "$revision"
path="{{healthPath}}"
if [ -z "$path" ]; then
exit 0
fi
deadline=$(( $(date +%s) + {{healthTimeoutSeconds}} ))
while :; do
code="$(curl -s -o /dev/null -w '%{http_code}' "$url$path" || echo 000)"
case "$code" in
2*) echo "health check $url$path -> $code"; exit 0 ;;
esac
if [ "$(date +%s)" -ge "$deadline" ]; then
echo "health check $url$path still returns $code after {{healthTimeoutSeconds}}s" >&2
exit 1
fi
echo "health check $url$path -> $code, retrying"
sleep 5
done