diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 75c25f0..ba50226 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -1,15 +1,15 @@ # CI runs first; build only proceeds if all checks pass. # # Push to dev: typecheck + lint + test + build :dev + : -# Push to main: typecheck + lint + test + build :main + : +# Push to main: typecheck + lint + test + build : (no moving tag) # Tag v* (release): typecheck + lint + test + build :latest + : + : # -# Both dev and main are gated AND built: dev is the working line, main the -# protected/integration line, each its own deployable image (:dev / :main). -# Running CI again on the main merge commit is intentional — main is -# validated and built in its own right. The v* release tag is the ONLY -# trigger that publishes :latest (the production pointer) plus the -# immutable : tag. +# Both dev and main are gated AND built. dev pushes move the :dev tag; main +# pushes publish only the immutable : image — no :main tag, because +# :latest (release-only) is the single production pointer and a :main alias +# would just duplicate it. Running CI on the main merge commit is intentional: +# main is validated and its : image is the rollback point. The v* release +# tag is the ONLY trigger that publishes :latest plus the immutable :. # # Successive pushes to the SAME ref supersede each other (see concurrency # below), so rapid pushes don't stack identical work; dev and main runs are @@ -142,7 +142,7 @@ jobs: build: name: Build & push image needs: [typecheck, lint, test] - # Build on dev, main, and v* tag pushes. dev → :dev, main → :main, + # Build on dev, main, and v* tag pushes. dev → :dev, main → (sha only), # tag → :latest + :; every build also gets an immutable :. if: github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') runs-on: python-ci @@ -171,7 +171,8 @@ jobs: TAGS="$TAGS,${{ env.IMAGE }}:dev" ;; refs/heads/main) - TAGS="$TAGS,${{ env.IMAGE }}:main" + # main publishes only the immutable : image (set above) — + # no :main tag; :latest (release-only) is the production pointer. BUILD_VERSION="main" ;; refs/tags/*)