From 0ff21d5b8e57be992b60e8fb49eca368d64f2e20 Mon Sep 17 00:00:00 2001 From: Timothy Date: Sat, 11 Jul 2026 21:44:36 +0200 Subject: [PATCH] ci: restore bump-prod-compose auto-deploy job on v* release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The auto-pin-to-prod job designed on the unmerged `ci/auto-bump-prod-compose` branch (3d6ac883) never landed on main — so v* releases (v26.5.0, v26.6.0) did NOT auto-bump the server-management compose pin (it sat at 26.5.0). The docs (homelab-docs Docker/ErsatzTV.md, ci-cd.md) described the auto-bump as if live. Restore the job verbatim (its credentials already exist: the `ersatztv-ci-deploy` write deploy key, id 5, on server-management + the SERVERMGMT_DEPLOY_KEY secret here). On a v* tag, after the test-gated image builds, it rewrites the pinned `ersatztv:` tag in docker/bumblebee/stacks/media-servers/compose.yaml and pushes to server-management `master` → the Gitea->Komodo webhook redeploys prod with a pre-deploy backup. Idempotent (no-op if already pinned). docs/ci-cd.md updated to match (release procedure + the stale ":prod pin" claim, which was actually an immutable : pin since 2026-07-07). Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/docker-build.yml | 38 +++++++++++++++++++++++++++++++ docs/ci-cd.md | 13 +++++++---- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml index 6a06566dd..c611616f2 100644 --- a/.gitea/workflows/docker-build.yml +++ b/.gitea/workflows/docker-build.yml @@ -341,3 +341,41 @@ jobs: else echo "Parity-doc reminder: nothing to flag." fi + + # Prod GitOps deploy: on a v* release, after the test-gated image is built and + # pushed (:prod + :), rewrite the pinned ersatztv tag in the + # server-management media-servers compose so the Gitea->Komodo webhook redeploys + # (its pre-deploy hook backs up first). Keeps prod pinned + backed up rather than a + # floating :prod (see docs/ci-cd.md + homelab-docs/Docker/ErsatzTV.md). Credentials: + # write deploy key `ersatztv-ci-deploy` (id 5) on server-management + the + # SERVERMGMT_DEPLOY_KEY secret here. server-management's default branch is `master`. + bump-prod-compose: + name: Bump prod compose tag (server-management) + runs-on: ubuntu-latest + needs: [build] + if: startsWith(github.ref, 'refs/tags/v') + steps: + - name: Bump ersatztv prod tag in media-servers compose + run: | + set -euo pipefail + VERSION="${GITHUB_REF_NAME#v}" + mkdir -p ~/.ssh + printf '%s\n' "${{ secrets.SERVERMGMT_DEPLOY_KEY }}" > ~/.ssh/id_deploy + chmod 600 ~/.ssh/id_deploy + ssh-keyscan -p 22 192.168.1.95 >> ~/.ssh/known_hosts 2>/dev/null + export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_deploy -o IdentitiesOnly=yes -o UserKnownHostsFile=$HOME/.ssh/known_hosts" + rm -rf /tmp/svrmgmt + git clone --depth 1 ssh://gitea@192.168.1.95:22/timothy/server-management.git /tmp/svrmgmt + cd /tmp/svrmgmt + FILE="docker/bumblebee/stacks/media-servers/compose.yaml" + sed -i -E "s|(image: 192\.168\.1\.95:3000/timothy/ersatztv:)[^[:space:]]+|\1${VERSION}|" "$FILE" + if git diff --quiet "$FILE"; then + echo "media-servers compose already pins ersatztv:${VERSION}; nothing to do" + exit 0 + fi + git config user.name "ersatztv-ci" + git config user.email "ci@tblindustries.be" + git add "$FILE" + git commit -m "chore(ersatztv): bump prod chicorytv to ${VERSION} [ci auto-deploy]" + git push origin HEAD:master + echo "Pushed prod bump -> ersatztv:${VERSION}; media-servers webhook will deploy with pre-deploy backup." diff --git a/docs/ci-cd.md b/docs/ci-cd.md index 02bb517b4..cf8ff9181 100644 --- a/docs/ci-cd.md +++ b/docs/ci-cd.md @@ -20,7 +20,7 @@ Upstream's final release was **`v26.3.0`** (archived). Our line continues from t | `v26.3.1` | Upstream 26.3.0 **rebuilt on our infra** (Gitea CI/registry, fork ffmpeg base) — **no application changes**. A patch bump, because nothing functional changed. | | `v26.4.0` | Reserved for our **first release that carries actual app changes** (e.g. the #1 M3U fix). Later 2026 releases: `26.5.0`, `26.6.0`, …; a new year resets to `27.1.0`. | -**Cutting a release:** push a `vYY.N.P` tag on `main` → CI builds `:prod` + `:` + `:`; server-management does the prod switch (server-management#481). +**Cutting a release:** push a `vYY.N.P` tag on `main` → CI builds `:prod` + `:` + `:`, then the **`bump-prod-compose`** job rewrites the pinned `ersatztv:` tag in the server-management media-servers compose (via the `ersatztv-ci-deploy` write deploy key, id 5 on server-management + the `SERVERMGMT_DEPLOY_KEY` secret here) and pushes to its `master` branch → the Gitea→Komodo webhook redeploys prod with a pre-deploy backup. **No manual pin bump needed** (the job is idempotent: a no-op if the compose already pins that version). **Gotcha:** never put a `[skip ci]` token in a commit you intend to tag — Gitea reads skip-ci from the *tagged* commit and will **suppress the release build**. (Also, `workflow_dispatch` on a tag ref isn't supported on this Gitea version, so the tag *push* must do the triggering.) Release commits, and anything you'll tag, must not contain skip-ci. @@ -29,7 +29,8 @@ Upstream's final release was **`v26.3.0`** (archived). Our line continues from t ## The workflow: `.gitea/workflows/docker-build.yml` Single workflow. Gating jobs `test` + `migrations` run in parallel and gate `build`; a -non-blocking `docs-reminder` job runs on PRs only (see below). +non-blocking `docs-reminder` job runs on PRs only (see below); a `bump-prod-compose` job +runs only on `v*` tags (after `build`) to auto-deploy prod (see "Cutting a release"). ### Triggers & tags @@ -40,9 +41,11 @@ non-blocking `docs-reminder` job runs on PRs only (see below). | push tag `v*` | ✅ | ✅ | `:prod` + `:` + `:` | | `workflow_dispatch` | ✅ | ✅ | only if ref is `main`/`v*`, else build-only (no push) | -`:latest` is the **test/dev** channel (every `main` commit). Prod pins **`:prod`**, -never `:latest` — enforced in the prod compose (server-management#481). `:prod` is -only produced by pushing a `v*` tag. +`:latest` is the **test/dev** channel (every `main` commit). Prod pins the immutable +**`:`** tag (e.g. `ersatztv:26.7.0`) in the compose — never `:latest`, and no +longer a floating `:prod` (pinned since 2026-07-07) — so a redeploy is reproducible and +gated by the `bump-prod-compose` commit. Both `:prod` and `:` are produced by +pushing a `v*` tag; the `bump-prod-compose` job pins the `:` form. Concurrency is scoped **per event+ref** (`group: ersatztv-build-${{ github.event_name }}-${{ github.ref }}`, `cancel-in-progress` for PRs): PR runs parallelize across PRs, a new sync auto-cancels