forked from baron/baron-sso
127 lines
7.4 KiB
Bash
127 lines
7.4 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
publish_workflow="$repo_root/.gitea/workflows/production_image_publish.yml"
|
|
staging_deploy_workflow="$repo_root/.gitea/workflows/staging_image_deploy.yml"
|
|
deploy_workflow="$repo_root/.gitea/workflows/production_image_deploy.yml"
|
|
image_compose="$repo_root/deploy/templates/docker-compose.images.yaml"
|
|
bundle_script="$repo_root/scripts/deploy/build_image_deploy_bundle.sh"
|
|
remote_deploy_script="$repo_root/scripts/deploy/upload_and_run_image_deploy.sh"
|
|
|
|
fail() {
|
|
echo "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
[[ -f "$publish_workflow" ]] || fail "production image publish workflow must exist."
|
|
[[ -f "$staging_deploy_workflow" ]] || fail "staging image deploy workflow must exist."
|
|
[[ -f "$deploy_workflow" ]] || fail "production image deploy workflow must exist."
|
|
[[ -f "$image_compose" ]] || fail "image-based production compose template must exist."
|
|
[[ -f "$bundle_script" ]] || fail "shared image deployment bundle script must exist."
|
|
[[ -f "$remote_deploy_script" ]] || fail "shared image remote deploy script must exist."
|
|
|
|
grep -Fq "name: Publish Baron SSO Production Images" "$publish_workflow" \
|
|
|| fail "publish workflow must have the expected name."
|
|
grep -Fq "workflow_dispatch:" "$publish_workflow" \
|
|
|| fail "publish workflow must be manually dispatchable."
|
|
if grep -Fq "source_ref:" "$publish_workflow"; then
|
|
fail "publish workflow must not accept an arbitrary source_ref; production images must be built from dev."
|
|
fi
|
|
grep -Fq "ref: dev" "$publish_workflow" \
|
|
|| fail "publish workflow must checkout the dev branch."
|
|
grep -Fq "version_prefix:" "$publish_workflow" \
|
|
|| fail "publish workflow must accept a version prefix."
|
|
grep -Fq 'git rev-parse --short=4 HEAD' "$publish_workflow" \
|
|
|| fail "publish workflow must derive the final image tag from the checked-out commit hash."
|
|
grep -Fq 'image_tag="${VERSION_PREFIX}.${short_sha}"' "$publish_workflow" \
|
|
|| fail "publish workflow must append the 4-character commit hash as the last version segment."
|
|
grep -Fq "steps.version.outputs.image_tag" "$publish_workflow" \
|
|
|| fail "publish workflow must use the computed image tag for pushed images."
|
|
grep -Fq "Upload pushed images to WORKS Drive archive" "$publish_workflow" \
|
|
|| fail "publish workflow must archive the exact pushed images to WORKS Drive."
|
|
grep -Fq "docker pull" "$publish_workflow" \
|
|
|| fail "publish workflow must pull the pushed image before WORKS archive upload."
|
|
grep -Fq "scripts/docker-image/upload_works_drive.sh" "$publish_workflow" \
|
|
|| fail "publish workflow must use the shared WORKS Drive image archive script."
|
|
grep -Fq "docker/login-action@v3" "$publish_workflow" \
|
|
|| fail "publish workflow must login to the shared registry."
|
|
grep -Fq "docker/build-push-action@v5" "$publish_workflow" \
|
|
|| fail "publish workflow must build and push images."
|
|
for image in backend userfront adminfront devfront orgfront; do
|
|
grep -Fq "/baron_sso/${image}:" "$publish_workflow" \
|
|
|| fail "publish workflow must push ${image} image."
|
|
done
|
|
|
|
grep -Fq "name: Deploy Baron SSO Staging Images" "$staging_deploy_workflow" \
|
|
|| fail "staging deploy workflow must have the expected name."
|
|
grep -Fq "image_tag:" "$staging_deploy_workflow" \
|
|
|| fail "staging deploy workflow must accept the same immutable image tag as production."
|
|
grep -Fq "IMAGE_TAG must look like vX.YYMM.ab12" "$bundle_script" \
|
|
|| fail "shared bundle script must validate the commit-hash image tag format."
|
|
grep -Fq "IMAGE_DEPLOY_ENV: stage" "$staging_deploy_workflow" \
|
|
|| fail "staging deploy workflow must select the stage deployment environment."
|
|
grep -Fq "deploy/templates/docker-compose.images.yaml" "$staging_deploy_workflow" \
|
|
|| fail "staging deploy workflow must pass the image-based compose template through the shared bundle script."
|
|
grep -Fq "scripts/deploy/build_image_deploy_bundle.sh" "$staging_deploy_workflow" \
|
|
|| fail "staging deploy workflow must use the shared bundle script."
|
|
grep -Fq "scripts/deploy/upload_and_run_image_deploy.sh" "$staging_deploy_workflow" \
|
|
|| fail "staging deploy workflow must use the shared remote deploy script."
|
|
|
|
grep -Fq "name: Deploy Baron SSO Production Images" "$deploy_workflow" \
|
|
|| fail "deploy workflow must have the expected name."
|
|
grep -Fq "image_tag:" "$deploy_workflow" \
|
|
|| fail "deploy workflow must accept an image tag."
|
|
grep -Fq "v1.2606.ab12" "$deploy_workflow" \
|
|
|| fail "deploy workflow must document the commit-hash image tag format with an example."
|
|
grep -Fq "IMAGE_TAG must look like vX.YYMM.ab12" "$bundle_script" \
|
|
|| fail "deploy workflow must rely on the shared commit-hash image tag validation."
|
|
grep -Fq "IMAGE_DEPLOY_ENV: production" "$deploy_workflow" \
|
|
|| fail "deploy workflow must select the production deployment environment."
|
|
grep -Fq 'APP_ENV=${app_env}' "$bundle_script" \
|
|
|| fail "shared bundle script must write APP_ENV from the selected deployment environment."
|
|
grep -Fq "deploy/templates/docker-compose.images.yaml" "$deploy_workflow" \
|
|
|| fail "deploy workflow must pass the image-based compose template through the shared bundle script."
|
|
grep -Fq "scripts/deploy/build_image_deploy_bundle.sh" "$deploy_workflow" \
|
|
|| fail "production deploy workflow must use the shared bundle script."
|
|
grep -Fq "scripts/deploy/upload_and_run_image_deploy.sh" "$deploy_workflow" \
|
|
|| fail "production deploy workflow must use the shared remote deploy script."
|
|
grep -Fq "Same image tag contract as staging" "$deploy_workflow" \
|
|
|| fail "production deploy workflow must document that it uses the same image tag as staging."
|
|
grep -Fq "TRAEFIK_PUBLIC_NETWORK=traefik-public" "$bundle_script" \
|
|
|| fail "shared bundle script must write Traefik public network env."
|
|
grep -Fq "docker compose --env-file .env -f docker-compose.yml pull" "$remote_deploy_script" \
|
|
|| fail "shared remote deploy script must pull the requested image version before running."
|
|
grep -Fq "docker compose --env-file .env -f docker-compose.yml up -d" "$remote_deploy_script" \
|
|
|| fail "shared remote deploy script must start the stack after pulling images."
|
|
|
|
if grep -Eq 'docker (build|commit)' "$staging_deploy_workflow" "$deploy_workflow"; then
|
|
fail "staging/production deploy workflows must never build or commit images remotely."
|
|
fi
|
|
|
|
if grep -Eq '^[[:space:]]+build:' "$image_compose"; then
|
|
fail "image-based production compose template must not contain build sections."
|
|
fi
|
|
for image_var in BACKEND_IMAGE_NAME USERFRONT_IMAGE_NAME ADMINFRONT_IMAGE_NAME DEVFRONT_IMAGE_NAME ORGFRONT_IMAGE_NAME; do
|
|
grep -Fq "\${${image_var}}:\${IMAGE_TAG}" "$image_compose" \
|
|
|| fail "image compose must use ${image_var} with IMAGE_TAG."
|
|
done
|
|
grep -Fq "APP_ENV=\${APP_ENV:-production}" "$image_compose" \
|
|
|| fail "image compose must run services with production APP_ENV default."
|
|
grep -Fq "traefik_public:" "$image_compose" \
|
|
|| fail "image compose must keep Traefik public network wiring."
|
|
|
|
tmp_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
cp "$repo_root/deploy/templates/.env.template" "$tmp_dir/.env"
|
|
cp "$image_compose" "$tmp_dir/docker-compose.yml"
|
|
sed -i 's/{{INSTANCE_NAME}}/policy/g; s/{{PORT_PREFIX}}/26/g' "$tmp_dir/.env"
|
|
|
|
IMAGE_TAG=v9.9999.ab12 \
|
|
BACKEND_IMAGE_NAME=registry.example/baron_sso/backend \
|
|
USERFRONT_IMAGE_NAME=registry.example/baron_sso/userfront \
|
|
ADMINFRONT_IMAGE_NAME=registry.example/baron_sso/adminfront \
|
|
DEVFRONT_IMAGE_NAME=registry.example/baron_sso/devfront \
|
|
ORGFRONT_IMAGE_NAME=registry.example/baron_sso/orgfront \
|
|
docker compose --env-file "$tmp_dir/.env" -f "$tmp_dir/docker-compose.yml" config >/dev/null
|