diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index bd85c6a..47ce699 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -39,11 +39,11 @@ # Prerequisites (Settings → Actions → Secrets on RunicGateway/installer): # REGISTRY_USER — Gitea username the token below belongs to # REGISTRY_TOKEN — Gitea access token with `write:repository`, so it can push -# the bump commit + tag and create the release. -# Also: `main` must accept a direct push from that user (disable branch -# protection for it, or add it as an exception) — the bump commit lands on main. +# the release tag and create the release. # -# The bump commit carries `[skip ci]`, so it does not re-trigger this workflow. +# `main` needs NO push exception: this workflow tags and publishes, and never +# writes to a branch. Keeping it that way is deliberate — a first release that +# depends on a write to a protected branch fails at the worst possible moment. name: Release installer @@ -66,7 +66,8 @@ env: jobs: release: runs-on: ubuntu-latest - # Don't loop on our own bump commit (belt-and-suspenders with [skip ci]). + # Vestigial since this workflow stopped writing a bump commit, and kept as + # belt-and-braces in case one ever returns. # Quoted because the expression contains a colon (`chore(release):`), which an # unquoted YAML scalar would misparse as a mapping value. if: "${{ !contains(github.event.head_commit.message, 'chore(release): bump version') }}" @@ -300,33 +301,45 @@ jobs: ls -l dist && echo "----" && cat dist/SHA256SUMS # ── RELEASE ENGINE: commit the bump, tag, push ─────────────────────── - - name: Commit version bump and push tag + # Tag only — `main` is never pushed to. + # + # This step used to commit the version bump back to main first, and it has + # never executed in any repo that carries it: an EMPTY template expression + # written literally in the comment below (the `$`+`{{ }}` token, spelled + # out here for that reason) makes the runner fail to build the script and + # skip the step WITHOUT failing the job. link/release.yml carried the same + # bug for six releases, which is why its Cargo.toml still says 0.1.0 while + # its tags reach v1.1.1 — the release API creates the tag when it + # publishes, so the pipeline worked by accident. + # + # It also would have been declined if it had run: `main` is protected, and + # the bundle job proved that on 2026-08-05 (`pre-receive hook declined`). + # A first release must not depend on a write to a protected branch. + # + # So the tag is the version, as in servuo-plugins. The version is still + # written into Cargo.toml before building, so a released binary + # self-reports correctly; it is simply not committed back. The next + # version is computed from the newest tag, never from the file. + - name: Push the release tag if: ${{ steps.plan.outputs.release == 'true' }} env: REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | set -euo pipefail - VERSION="${{ steps.plan.outputs.version }}" TAG="${{ steps.plan.outputs.tag }}" # Secrets can arrive with a trailing newline (depending on how they were # pasted); a stray CR/LF corrupts the remote URL ("credential url cannot - # be parsed"). Strip line breaks before building the URL. Passing them via - # env (not inline ${{ }}) also keeps a newline from breaking this script. + # be parsed"). Strip line breaks before building the URL. They are passed + # via env rather than interpolated into this script, so a newline cannot + # break it — do NOT write a template token literally in a comment here, + # or the runner will skip this step without failing the job. CI_USER="$(printf '%s' "${REGISTRY_USER}" | tr -d '\r\n')" CI_TOKEN="$(printf '%s' "${REGISTRY_TOKEN}" | tr -d '\r\n')" git config user.name "installer-ci" git config user.email "ci@whitlocktech.com" git remote set-url origin \ "https://${CI_USER}:${CI_TOKEN}@${GITEA_HOST}/${REPO}.git" - - git add Cargo.toml Cargo.lock - if ! git diff --cached --quiet; then - git commit -m "chore(release): bump version to ${TAG} [skip ci]" - git push origin "HEAD:main" - else - echo "Version unchanged (first release) — no bump commit needed." - fi # The tag may already exist when finishing a run that died after # tagging (see the plan step). `git tag` on an existing name fails # under `set -e`; pushing an identical existing tag is a harmless