ci: prod follows :prod (remove version-pin bump-prod-compose job)
Build ErsatzTV Image / Docs update reminder (pull_request) Successful in 18s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m2s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 9m56s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Has been skipped
Build ErsatzTV Image / Docs update reminder (push) Has been skipped
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 8m1s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (push) Successful in 10m1s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 5m24s

Timothy reversed the version-pin decision: prod's media-servers compose now
follows the floating :prod tag, redeployed by Komodo Global Auto Update. The
bump-prod-compose job (#275) rewrote a :<version> pin, which would flip :prod ->
:26.8.0 on the next release — remove it. docs/ci-cd.md reconciled to the :prod
model (+ flags the open caveat: verify Global Auto Update runs the #553
pre-deploy backup, else releases deploy without a backup).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #277.
This commit is contained in:
2026-07-11 22:20:14 +02:00
co-authored by Claude Opus 4.8
parent 57adb1b0cc
commit 1b5efd7b9d
2 changed files with 8 additions and 46 deletions
-38
View File
@@ -341,41 +341,3 @@ 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 + :<version>), 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."
+8 -8
View File
@@ -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` + `:<version>` + `:<sha>`, then the **`bump-prod-compose`** job rewrites the pinned `ersatztv:<version>` 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).
**Cutting a release:** push a `vYY.N.P` tag on `main` → CI builds `:prod` + `:<version>` + `:<sha>`. Prod's `media-servers` compose **follows the floating `:prod` tag** (Timothy's decision, 2026-07-11 — reverted from the version-pin approach), so **Komodo's Global Auto Update** (`poll_for_updates` is on for all stacks) detects the new `:prod` digest and redeploys the media-servers stack — no CI push to server-management, no manual pin bump. ⚠️ **Open caveat:** confirm Global Auto Update runs the #553 host-side **pre-deploy backup** hook; if it doesn't, a release would deploy without a backup — fall back to a manual `execute DeployStack media-servers` (which *does* run pre-deploy). See `homelab-docs/Docker/ErsatzTV.md` + the `komodo` skill.
**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,8 +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); a `bump-prod-compose` job
runs only on `v*` tags (after `build`) to auto-deploy prod (see "Cutting a release").
non-blocking `docs-reminder` job runs on PRs only (see below). Prod deploy is **not** a CI
job — it's Komodo Global Auto Update off the `:prod` tag (see "Cutting a release").
### Triggers & tags
@@ -41,11 +41,11 @@ runs only on `v*` tags (after `build`) to auto-deploy prod (see "Cutting a relea
| push tag `v*` | ✅ | ✅ | `:prod` + `:<version>` + `:<short-sha>` |
| `workflow_dispatch` | ✅ | ✅ | only if ref is `main`/`v*`, else build-only (no push) |
`:latest` is the **test/dev** channel (every `main` commit). Prod pins the immutable
**`:<version>`** 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 `:<version>` are produced by
pushing a `v*` tag; the `bump-prod-compose` job pins the `:<version>` form.
`:latest` is the **test/dev** channel (every `main` commit). Prod's compose **follows the
floating `:prod`** tag (reverted from the 2026-07-07 version pin on 2026-07-11) — never
`:latest`. Both `:prod` and `:<version>` are produced by pushing a `v*` tag; prod tracks
`:prod` and is redeployed by Komodo Global Auto Update (see "Cutting a release"). The
immutable `:<version>` tags remain for reproducible rollback (`docker run …:26.6.0`).
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