fix(ci): register from the runner's own directory with an absolute state path
CI / Analyze & Test (push) Successful in 11s
CI / Release APK (push) Successful in 22s

Registration failed with `open .runner: permission denied`. runner.file was
the relative `.runner`, which resolves against the caller's working directory
— the repo the admin ran sudo from, which the service account cannot write.
The same applied to .runner.lock, so the single-process guard was skipped too.

Two fixes rather than one, because either alone leaves a trap: runner.file is
now absolute, and register runs with cwd set to the runner's home. An earlier
draft did cd there; that was lost when the script was rewritten for a system
service, and an absolute path is what makes it not matter next time.

Also drops --labels from the register call, which gitea-runner ignores and
warns about whenever the config file defines labels, and rewrites a config that
exists while nothing is registered yet — such a config is provisional, not in
use, and leaving a broken one in place was what required manual cleanup here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 23:53:04 +09:00
parent ae2033865c
commit 7981ca2022
+20 -11
View File
@@ -168,15 +168,22 @@ fi
# ── Config ───────────────────────────────────────────────────────────────── # ── Config ─────────────────────────────────────────────────────────────────
say "Config" say "Config"
CONFIG="$RUNNER_HOME/config.yaml" CONFIG="$RUNNER_HOME/config.yaml"
if [[ -f "$CONFIG" ]]; then if [[ -f "$CONFIG" && -f "$RUNNER_HOME/.runner" ]]; then
echo " $CONFIG exists, leaving it alone" # Registered: this config is in use, do not touch it.
echo " $CONFIG exists and the runner is registered — leaving it alone"
else else
if [[ -f "$CONFIG" ]]; then
echo " $CONFIG exists but nothing is registered yet — rewriting it"
fi
cat > "$CONFIG" <<YAML cat > "$CONFIG" <<YAML
log: log:
level: info level: info
runner: runner:
file: .runner # Absolute on purpose: a relative path resolves against whatever directory
# the command was invoked from, which for `register` is wherever the admin
# happened to be standing — typically a repo this account cannot write.
file: ${RUNNER_HOME}/.runner
# One at a time: a 2-ABI NDK compile plus Gradle will saturate this box, and # One at a time: a 2-ABI NDK compile plus Gradle will saturate this box, and
# concurrent jobs would only contend for it. # concurrent jobs would only contend for it.
capacity: 1 capacity: 1
@@ -208,14 +215,16 @@ if [[ -f "$RUNNER_HOME/.runner" ]]; then
echo " already registered ($RUNNER_HOME/.runner) — skipping." echo " already registered ($RUNNER_HOME/.runner) — skipping."
echo " To re-register: delete that file AND remove the runner in Gitea." echo " To re-register: delete that file AND remove the runner in Gitea."
else else
sudo -u "$RUNNER_USER" HOME="$RUNNER_HOME" \ # Run from the runner's own directory: register writes .runner and
"$BIN" register \ # .runner.lock relative to cwd unless told otherwise, and this account
--no-interactive \ # cannot write wherever the admin invoked the script from.
--instance "$INSTANCE" \ # --labels is deliberately absent: gitea-runner ignores it when the config
--token "$RUNNER_TOKEN" \ # file defines labels, and warns that it is doing so.
--name "$RUNNER_NAME" \ sudo -u "$RUNNER_USER" env HOME="$RUNNER_HOME" sh -c '
--labels "${LABEL}:host" \ cd "$1" || exit 1
--config "$CONFIG" exec "$2" register --no-interactive \
--instance "$3" --token "$4" --name "$5" --config "$6"
' sh "$RUNNER_HOME" "$BIN" "$INSTANCE" "$RUNNER_TOKEN" "$RUNNER_NAME" "$CONFIG"
# register writes .runner into the cwd it was given; make sure it landed. # register writes .runner into the cwd it was given; make sure it landed.
[[ -f "$RUNNER_HOME/.runner" ]] || { [[ -f "$RUNNER_HOME/.runner" ]] || {
echo " registration produced no .runner in $RUNNER_HOME" >&2 echo " registration produced no .runner in $RUNNER_HOME" >&2