Automate immutable production deployments
Test and publish container images / test (push) Successful in 2m43s
Test and publish container images / publish (push) Successful in 2m56s

This commit is contained in:
BuTzZ
2026-07-29 13:00:50 +02:00
parent 2e84f4eae4
commit 2064570913
34 changed files with 1779 additions and 215 deletions
+67 -8
View File
@@ -18,10 +18,10 @@ jobs:
test:
runs-on: ubuntu-latest
container:
image: node:22-bookworm
image: node:22-bookworm@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37
steps:
- name: Check out source
uses: actions/checkout@v4
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Install test dependencies
run: |
@@ -45,10 +45,13 @@ jobs:
if: ${{ gitea.event_name == 'push' }}
needs:
- test
concurrency:
group: watermaps-production-publish
cancel-in-progress: false
runs-on: ubuntu-latest
steps:
- name: Check out source
uses: actions/checkout@v4
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
- name: Log in to the Gitea Container Registry
env:
@@ -60,11 +63,11 @@ jobs:
printf '%s\n' "$REGISTRY_TOKEN" |
docker login "$REGISTRY" --username "$REGISTRY_USERNAME" --password-stdin
- name: Build images for the triggering commit
- name: Build application images for the triggering commit
env:
REVISION: ${{ gitea.sha }}
run: |
test "$(printf '%s' "$REVISION" | wc -c)" -eq 40
[[ "$REVISION" =~ ^[0-9a-f]{40}$ ]]
docker build \
--label "org.opencontainers.image.revision=$REVISION" \
--label "org.opencontainers.image.source=${{ gitea.server_url }}/${{ gitea.repository }}" \
@@ -77,12 +80,68 @@ jobs:
--tag "$REGISTRY/$REGISTRY_OWNER/watermaps-route-data:$REVISION" \
.
- name: Push immutable commit images
- name: Push immutable images and build their release manifest
env:
REVISION: ${{ gitea.sha }}
run: |
docker push "$REGISTRY/$REGISTRY_OWNER/watermaps:$REVISION"
docker push "$REGISTRY/$REGISTRY_OWNER/watermaps-route-data:$REVISION"
set -Eeuo pipefail
push_and_resolve() {
local tagged_image="$1"
local push_output digest repository
if ! push_output="$(docker push "$tagged_image" 2>&1)"; then
printf '%s\n' "$push_output" >&2
return 1
fi
printf '%s\n' "$push_output" >&2
digest="$(
printf '%s\n' "$push_output" |
sed -nE 's/.*digest: (sha256:[0-9a-f]{64}).*/\1/p' |
tail -n 1
)"
[[ "$digest" =~ ^sha256:[0-9a-f]{64}$ ]]
repository="${tagged_image%:*}"
printf '%s@%s\n' "$repository" "$digest"
}
app_image="$(
push_and_resolve \
"$REGISTRY/$REGISTRY_OWNER/watermaps:$REVISION"
)"
route_data_image="$(
push_and_resolve \
"$REGISTRY/$REGISTRY_OWNER/watermaps-route-data:$REVISION"
)"
docker build \
--file deploy/release.Dockerfile \
--build-arg "REVISION=$REVISION" \
--build-arg "SOURCE=${{ gitea.server_url }}/${{ gitea.repository }}" \
--build-arg "APP_IMAGE=$app_image" \
--build-arg "ROUTE_DATA_IMAGE=$route_data_image" \
--tag "$REGISTRY/$REGISTRY_OWNER/watermaps-release:$REVISION" \
.
docker push "$REGISTRY/$REGISTRY_OWNER/watermaps-release:$REVISION"
- name: Publish the atomic main release pointer
env:
REVISION: ${{ gitea.sha }}
run: |
current_main_revision="$(
git ls-remote --exit-code origin refs/heads/main |
awk 'NR == 1 { print $1 }'
)"
if [[ "$current_main_revision" != "$REVISION" ]]; then
printf 'Commit %s is no longer the main tip; immutable images stay published without moving main.\n' \
"$REVISION"
exit 0
fi
docker tag \
"$REGISTRY/$REGISTRY_OWNER/watermaps-release:$REVISION" \
"$REGISTRY/$REGISTRY_OWNER/watermaps-release:main"
docker push "$REGISTRY/$REGISTRY_OWNER/watermaps-release:main"
- name: Log out from the registry
if: always()