From 45719f284cdd30a7fd835e04aaeb716e1749ae07 Mon Sep 17 00:00:00 2001 From: Benny Date: Mon, 21 Sep 2026 20:57:52 -0400 Subject: [PATCH] feat(deploy): build+push release image on every merge to main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Was tag-push-or-manual-dispatch only. Adds a push:main trigger so main stays continuously deployable without needing a version tag for every change. Also fixes a real bug this surfaced while testing the D17 registry-TLS fix: the old tag logic unconditionally retagged :latest on every run, including manual test dispatches off a feature branch — one such dispatch, done while verifying the previous commit, silently overwrote :latest with a feature-branch build. Tag resolution now only moves :latest on an actual main push or a version tag; a manual dispatch gets its own manual-- tag and leaves :latest alone. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01R2ZKeWkZV7ehf7fivrAkkG --- .gitea/workflows/release.yml | 29 +++++++++++++++++++++++------ deploy/README.md | 7 +++++-- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 580949a..c808c49 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -2,6 +2,7 @@ name: Release image on: push: + branches: [main] tags: ['v*'] workflow_dispatch: @@ -36,20 +37,36 @@ jobs: username: BBergle password: ${{ secrets.REGISTRY_TOKEN }} - - name: Resolve image tag + # `latest` should only ever mean "what's actually on main" (or a tagged release) — not + # whatever a manual test dispatch off some feature branch happened to build. Learned the + # hard way: a manual dispatch off this very branch, while verifying the fix above, silently + # overwrote `latest` under the old unconditional-tags logic. Building the full tag list here + # in bash (rather than a conditional expression inline in the tags: block below) means there's + # never a blank line for build-push-action to choke on when latest isn't included. + - name: Resolve image tags id: tag run: | + IMG=registry.bbergle.com:9537/bbergle/bike-app if [ "${{ gitea.ref_type }}" = "tag" ]; then - echo "value=${{ gitea.ref_name }}" >> "$GITHUB_OUTPUT" + VALUE="${{ gitea.ref_name }}" + UPDATE_LATEST=true + elif [ "${{ gitea.ref_name }}" = "main" ] && [ "${{ gitea.event_name }}" = "push" ]; then + VALUE="main-$(git rev-parse --short HEAD)" + UPDATE_LATEST=true else - echo "value=manual-$(date -u +%Y%m%d%H%M%S)" >> "$GITHUB_OUTPUT" + VALUE="manual-$(date -u +%Y%m%d%H%M%S)-$(git rev-parse --short HEAD)" + UPDATE_LATEST=false fi + { + echo "tags<> "$GITHUB_OUTPUT" - uses: docker/build-push-action@v6 with: context: . file: Dockerfile push: true - tags: | - registry.bbergle.com:9537/bbergle/bike-app:latest - registry.bbergle.com:9537/bbergle/bike-app:${{ steps.tag.outputs.value }} + tags: ${{ steps.tag.outputs.tags }} diff --git a/deploy/README.md b/deploy/README.md index dc30ad4..1d8a844 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -73,8 +73,11 @@ stays editable by hand afterward regardless of what the template pre-fills. ## Publishing the image `.gitea/workflows/release.yml` builds this Dockerfile and pushes it to the Gitea container -registry at `registry.bbergle.com:9537/bbergle/bike-app` on a `v*` tag push, or on manual -`workflow_dispatch`. Not `192.168.0.3:3000` (Gitea's own plain-HTTP address) directly — Docker +registry at `registry.bbergle.com:9537/bbergle/bike-app` on every push to `main` (tagged +`main-`, and `latest`), on a `v*` tag push (tagged with the tag name, and `latest`), or +on manual `workflow_dispatch` (tagged `manual--` only — a manual dispatch +never moves `latest`, so testing a feature branch can't clobber what's actually deployable). Not +`192.168.0.3:3000` (Gitea's own plain-HTTP address) directly — Docker refuses any non-localhost registry over plain HTTP by default, so `registry.bbergle.com:9537` is an NPMplus proxy host in front of Gitea's registry that terminates TLS with a self-signed cert. See `docs/DECISIONS.md` D17 for the full setup (cert, NPMplus proxy host, `certs.d` trust, and the