From b4d189c325a7d9511c9044971a6dd56566df1cc9 Mon Sep 17 00:00:00 2001 From: Zwitschi Date: Sat, 31 Oct 2026 21:30:24 +0100 Subject: [PATCH] Publish releases with the runner's checkout credentials The v0.2.10 tag build still failed to publish: its env dump showed no token at all, because this Gitea/act runner does not provide `github.token`, and the repo has no GITEA_TOKEN secret. publish_release.sh now resolves credentials in order: GITEA_TOKEN, GITEA_AUTH_HEADER, ~/.git-credentials, then the local git extraheader that actions/checkout writes for the job. That header carries the runner's basic-auth credentials for the same server, so tag builds publish with no repo secret. Verified by adding the extraheader locally and publishing v0.2.10 (all five artifacts: Linux/Windows/macOS ports, NSIS installer, AppImage), then removing it. Docs: RELEASING describes the four credential sources and warns that github.token is not available here; MEMORY records both failed attempts and the final fix; TODO keeps the "verify on the next tag" follow-up. Version 0.2.11. --- .gitea/workflows/build.yml | 9 ++++----- MEMORY.md | 10 +++++++--- README.md | 3 ++- TODO.md | 2 ++ docs/RELEASING.md | 15 +++++++++++---- project.godot | 2 +- tools/publish_release.sh | 27 ++++++++++++++++++++++++--- 7 files changed, 51 insertions(+), 17 deletions(-) diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index fdf2093..3ded0d4 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -113,11 +113,10 @@ jobs: - name: Publish Gitea release (tags only) if: startsWith(github.ref, 'refs/tags/') env: - # Prefer an explicit repo secret; otherwise fall back to the workflow's - # built-in token (Gitea provides `github.token`), which has write access - # to this repository. Without either, publish_release.sh has no - # credentials inside the runner and the step fails. - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN || github.token }} + # An explicit repo secret wins. Without one, publish_release.sh reuses + # the local git extraheader that actions/checkout configures for the job + # (the runner's own credentials), so tag builds still publish. + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} VERSION: ${{ github.ref_name }} run: | chmod +x tools/publish_release.sh diff --git a/MEMORY.md b/MEMORY.md index eefb63b..47e4a8b 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -142,9 +142,13 @@ Session memory for durable decisions, state, and gotchas. Keep concise, remove o job ended "could not create or find release". The repo also has **no** `GITEA_TOKEN` secret (`/actions/secrets` is empty) and the runner has no git credentials. Fixes: the script sets `AUTH=(-u "$CRED")`; the workflow falls back to `github.token` - (`secrets.GITEA_TOKEN || github.token`). **v0.2.9 is the only release after v0.2.1** - (built and published locally, all five artifacts); v0.2.4–v0.2.8 tags have no release - artifacts. Verify the CI fallback on the next tag push. PLAN.md + ADRs 0007–0010 still describe the intended UX. + (`secrets.GITEA_TOKEN || github.token`) — but `github.token` is **not** provided by this + Gitea/act runner, so the env dump showed no token and the v0.2.10 tag build failed again. + Final fix: `publish_release.sh` falls back to the **local git extraheader** that + `actions/checkout` writes (`git config --local --get-regexp '^http\..*\.extraheader$'`), + which carries the runner's basic-auth credentials for the same server. Verified locally by + adding that extraheader and publishing v0.2.10 (all five artifacts). **v0.2.9 and v0.2.10 + are published**; v0.2.4–v0.2.8 tags have no artifacts. Verify the CI path on the next tag. PLAN.md + ADRs 0007–0010 still describe the intended UX. - **Release v0.2.1 is LIVE** (2026-10-31): CI run 1110 built the NSIS installer + AppImage and published — installers/AppImage are on the releases page. Releasing = bump version → tag → push. - NSIS gotchas (validated in a local ubuntu:24.04 docker repro): makensis uses `-D` defines diff --git a/README.md b/README.md index d800985..45d896d 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,8 @@ The central design goal is simple: **All releases:** -> **Latest: v0.2.10** — release pipeline fix (tag builds publish automatically again). +> **Latest: v0.2.11** — release pipeline fix: tag builds publish without a repo secret by reusing +> the runner's checkout credentials. > Releases are built automatically when a `vX.Y.Z` tag is pushed > (see [`docs/RELEASING.md`](docs/RELEASING.md)); manual builds use > `./tools/build_releases.sh`. Installer/AppImage packaging runs in the same pipeline diff --git a/TODO.md b/TODO.md index 04f0d9d..997330a 100644 --- a/TODO.md +++ b/TODO.md @@ -31,6 +31,8 @@ Verified via API+host credentials (2026-10-31): so every tag build since v0.2.2 failed to publish. - [x] Add a `github.token` fallback in `.gitea/workflows/build.yml` (the repo has no `GITEA_TOKEN` secret). +- [x] Fall back to the checkout's git extraheader when no token/credentials exist (the + Gitea runner does not expose `github.token`). - [ ] Verify the fallback on the next tag push produces a release automatically. - [ ] Optionally backfill releases for v0.2.4–v0.2.8 (their CI artifacts were not retained; would need local rebuilds) or leave them superseded by the latest. diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 2707b0e..ce1029b 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -37,10 +37,17 @@ The repository ships a Gitea Actions workflow (`.gitea/workflows/build.yml`): Linux/Windows/macOS, artifact upload, and — on tags — release publication via `tools/publish_release.sh`. -For tag builds the workflow uses `GITEA_TOKEN` (write:repository scope) or, when the -secret is absent, falls back to the workflow's built-in `github.token`. Either is -enough for the publish step; with neither, the build succeeds but no release is -created. +`tools/publish_release.sh` picks the first available credential, in order: + +1. `GITEA_TOKEN` (repo secret, write:repository scope), +2. `GITEA_AUTH_HEADER` (a ready-made `Authorization: ...` header), +3. `~/.git-credentials` for the host, +4. the **local git extraheader** that `actions/checkout` configures on the CI job. + +Option 4 is what makes tag builds publish without any repo secret: the runner +already injects basic-auth credentials for the checkout, and the script reuses that +header for the API (same server). `github.token` is *not* available in this Gitea +setup, so do not rely on it. > **Incident (2026-10-31):** `tools/publish_release.sh` never set `AUTH` in its > `~/.git-credentials` branch, so every API call failed silently (`AUTH[@]` was diff --git a/project.godot b/project.godot index 81fbf2f..bb2ca79 100644 --- a/project.godot +++ b/project.godot @@ -8,7 +8,7 @@ config_version=5 config/name="Step Line" config/description="Workplace security simulation about observation, access verification, and proportionate escalation." -config/version="0.2.10" +config/version="0.2.11" run/main_scene="res://scenes/main.tscn" config/features=PackedStringArray("4.3", "GL Compatibility") diff --git a/tools/publish_release.sh b/tools/publish_release.sh index 96b4307..047a09d 100755 --- a/tools/publish_release.sh +++ b/tools/publish_release.sh @@ -16,8 +16,17 @@ HOST="${HOST:-https://git.allucanget.biz}" VERSION="${1:-$(grep -oP 'config/version="\K[^"]+' project.godot)}" TAG="v$VERSION" +# AUTH is a curl argument list. Populated by the first available method: +# 1. GITEA_TOKEN explicit token (repo secret in CI) +# 2. GITEA_AUTH_HEADER a ready-made "Authorization: ..." header +# 3. ~/.git-credentials basic auth for HOST +# 4. the checkout's git extraheader (Gitea Actions runners inject one for the +# job; this is what makes tag builds publish without any repo secret) +AUTH=() if [[ -n "${GITEA_TOKEN:-}" ]]; then - AUTH=("Authorization: token $GITEA_TOKEN") + AUTH=(-H "Authorization: token $GITEA_TOKEN") +elif [[ -n "${GITEA_AUTH_HEADER:-}" ]]; then + AUTH=(-H "$GITEA_AUTH_HEADER") elif [[ -f "$HOME/.git-credentials" ]]; then CRED="$(python3 -c " import os @@ -31,8 +40,20 @@ for l in open(os.path.expanduser('~/.git-credentials')): # curl basic auth. (Previously only CRED was set, so ${AUTH[@]} was unbound # under `set -u` and every API call failed silently.) AUTH=(-u "$CRED") -else - echo "error: set GITEA_TOKEN or provide ~/.git-credentials" >&2 +fi + +if [[ ${#AUTH[@]} -eq 0 ]]; then + # Gitea Actions: actions/checkout configures a local extraheader with the + # runner's credentials. Reuse it for the API (the same server, so the header is + # valid for $HOST too). + GIT_HEADER="$(git config --local --get-regexp '^http\..*\.extraheader$' 2>/dev/null | head -n1 | cut -d' ' -f2- || true)" + if [[ -n "${GIT_HEADER:-}" ]]; then + AUTH=(-H "$GIT_HEADER") + fi +fi + +if [[ ${#AUTH[@]} -eq 0 ]]; then + echo "error: no credentials. Set GITEA_TOKEN, GITEA_AUTH_HEADER, or provide ~/.git-credentials." >&2 exit 1 fi