From a83a127e312734a6eab984266ad5874f1917d1fd Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Tue, 18 Aug 2026 18:54:39 -0400 Subject: [PATCH 1/2] fix(ci): run the unclaim step under bash The workflow shipped in #103 and failed on every close, on its second line, before reaching the API: shell: sh -e {0} /var/run/act/workflow/0.sh: 2: set: Illegal option -o pipefail Inside `container:` the act runner selects sh, not bash, and `set -o pipefail` is a bashism. homebrew-formula.yml carries the same line without trouble because it runs with no container, on the host image where bash is the default -- so "another workflow does it" was not the evidence it looked like, and the comment now says so where the next person will read it. pipefail is kept rather than dropped for POSIX's sake: the lookup is `curl -sSf ... | jq`, so without it an API error yields empty output, an empty label id, and a cheerful "nothing to do" on every close. A silent no-op is the one outcome worse than a failing job here. Validated end to end against scratch issues rather than by reading it: with the label present the step returns 204 and the label is gone, and against an issue that never carried it the step also returns 204 and exits 0 -- which is what makes it safe to run on every close rather than only claimed ones. Still untested: whether secrets.GITEA_TOKEN carries issue-write scope. The old run never got far enough to find out. If it 403s, the fix is one line -- secrets.PACKAGE_TOKEN, which is a user PAT. Closes #102 --- .gitea/workflows/unclaim.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitea/workflows/unclaim.yml b/.gitea/workflows/unclaim.yml index ea29eef..23e9509 100644 --- a/.gitea/workflows/unclaim.yml +++ b/.gitea/workflows/unclaim.yml @@ -42,6 +42,13 @@ jobs: steps: - name: Drop the claim label + # **Inside a container the act runner selects `sh`, not bash**, so + # `set -o pipefail` fails the job on its second line with "Illegal + # option" and the step never reaches the API. `homebrew-formula.yml` + # carries the same `set -euo pipefail` without trouble because it + # runs with **no container**, on the host image where bash is the + # default — so "another workflow does it" is not evidence here. + shell: bash env: # The automatic Actions token, as release.yml uses for the # floor tag. It needs no more than write access to this repo. From 7be4a02e31f5a005065037004c5798302b89937f Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Tue, 18 Aug 2026 19:08:50 -0400 Subject: [PATCH 2/2] fix(ci): give the unclaim step a CA bundle Second defect in the same workflow. The shell fix took -- the step ran under `bash --noprofile --norc -e -o pipefail` -- and got one layer further before failing: curl: (77) error setting certificate file: /etc/ssl/certs/ca-certificates.crt ubuntu:24.04 ships no CA bundle, and --no-install-recommends skips the ca-certificates that curl recommends, so curl came up unable to verify TLS against our own Gitea. This was avoidable by reading the repo rather than reasoning about it: ci.yml (twice), desktop-assets.yml, android-apk.yml and release.yml all spell out `ca-certificates curl ... jq` for exactly this reason. The convention was written down five times already. Validated in the real image this time rather than by extracting the script and running it on the host, which is what missed this: the step now succeeds inside `docker run ubuntu:24.04` against a scratch issue -- label present, 204, label gone -- and the previous version reproduces `curl: (77)` in the same image. Both checked, then the scratch issue was deleted. The DELETE also keeps its response body now and prints it on a non-204. Whether the automatic token carries issue-write scope is still unproven, because both failures happened before the API call, and "403" without Gitea's own sentence would cost another merge to interpret. Closes #102 --- .gitea/workflows/unclaim.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.gitea/workflows/unclaim.yml b/.gitea/workflows/unclaim.yml index 23e9509..4ccba07 100644 --- a/.gitea/workflows/unclaim.yml +++ b/.gitea/workflows/unclaim.yml @@ -58,8 +58,15 @@ jobs: run: | set -euo pipefail + # `ca-certificates` is named because `--no-install-recommends` + # skips it, and `ubuntu:24.04` ships no CA bundle of its own — + # so curl comes up unable to verify TLS against our own Gitea + # and fails with "error setting certificate file" (exit 77). + # Every other containerised workflow here spells it out for the + # same reason; this one did not, and cost a release cycle. apt-get update -qq - apt-get install -y -qq --no-install-recommends curl jq >/dev/null + apt-get install -y -qq --no-install-recommends \ + ca-certificates curl jq >/dev/null label_id=$( curl -sSf -H "Authorization: token $TOKEN" "$API/labels?limit=100" | @@ -78,8 +85,14 @@ jobs: # label answers the same as one that did, which is what makes # this safe to run on *every* close rather than only the ones # that were claimed. + # The body is captured, not discarded, so a refusal is + # diagnosable from this log alone. Whether the automatic + # token carries issue-write scope is still unproven, and + # "DELETE returned 403" without Gitea's own sentence costs + # another merge to find out which of the two it is. + body=$(mktemp) code=$( - curl -sS -o /dev/null -w '%{http_code}' -X DELETE \ + curl -sS -o "$body" -w '%{http_code}' -X DELETE \ -H "Authorization: token $TOKEN" \ "$API/issues/$ISSUE/labels/$label_id" ) @@ -88,6 +101,7 @@ jobs: 204) echo "unclaim: #$ISSUE is closed and unclaimed" ;; *) echo "unclaim: DELETE returned $code for #$ISSUE" >&2 + cat "$body" >&2 exit 1 ;; esac