From aacf361bb8044ce481e22750b7d89df8a7b6ba11 Mon Sep 17 00:00:00 2001 From: Keith Jackson Date: Thu, 29 Oct 2026 20:58:15 -0500 Subject: [PATCH] fix(renovate): the workflow still named renovate.json, so every run since #79 died with ENOENT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #79 renamed the config to renovate.json5 and left configurationFile pointing at the old name. Runs 315-322 (2026-10-22..29) all failed in ~1s before Renovate started. Also add a ci/lint.sh assertion that every workflow configurationFile: resolves to a real path — valid YAML, so yamllint could not catch it, and the gate stayed green throughout. Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/renovate.yaml | 6 ++- ci/lint.sh | 15 ++++++ .../2026-10-29-renovate-config-filename.md | 48 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 decisions/2026-10-29-renovate-config-filename.md diff --git a/.gitea/workflows/renovate.yaml b/.gitea/workflows/renovate.yaml index 91798e6..3fbb161 100644 --- a/.gitea/workflows/renovate.yaml +++ b/.gitea/workflows/renovate.yaml @@ -152,7 +152,11 @@ jobs: # Pinned, and Renovate maintains this pin itself: renovate.json's enabledManagers # includes `github-actions`, and `helpers:pinGitHubActionDigests` is in its `extends`. # This is the one dependency in the repo whose updater is its own updater. - configurationFile: renovate.json + # MUST match the file's real name. #79 renamed it to renovate.json5 and left this line + # saying `renovate.json`; every scheduled run from 2026-10-18 then died in ~1s with + # ENOENT before Renovate started, and nothing in the gate noticed. ci/lint.sh now + # asserts that every `configurationFile:` here names a file that exists. + configurationFile: renovate.json5 token: ${{ secrets.RENOVATE_TOKEN }} env: # Self-hosted Gitea. `platform` + `endpoint` were the two values renovate.json's own diff --git a/ci/lint.sh b/ci/lint.sh index be703aa..e5307fe 100755 --- a/ci/lint.sh +++ b/ci/lint.sh @@ -27,3 +27,18 @@ fi yamllint -c "${CI_DIR}/yamllint.yaml" -f "${YAMLLINT_FORMAT:-standard}" "${files[@]}" ok "yaml/lint passed (${#files[@]} files)" + +# A workflow's `configurationFile:` must name a file that exists. Renovate's did not after #79 +# renamed renovate.json -> renovate.json5, and every scheduled run failed with ENOENT for 11 days +# while the gate stayed green. Valid YAML, so yamllint cannot see it. +missing=0 +while IFS=: read -r wf _ value; do + value="${value#*configurationFile:}" + value="$(echo "$value" | sed -E 's/#.*//; s/^[[:space:]"'\'']+//; s/[[:space:]"'\'']+$//')" + if [ -n "$value" ] && [ ! -e "$value" ]; then + err "${wf}: configurationFile '${value}' does not exist in the repo" + missing=1 + fi +done < <(grep -nE '^[[:space:]]*configurationFile:' .gitea/workflows/*.y*ml 2>/dev/null || true) +[ "$missing" -eq 0 ] || exit 1 +ok "workflow configurationFile references resolve" diff --git a/decisions/2026-10-29-renovate-config-filename.md b/decisions/2026-10-29-renovate-config-filename.md new file mode 100644 index 0000000..bd30d4f --- /dev/null +++ b/decisions/2026-10-29-renovate-config-filename.md @@ -0,0 +1,48 @@ +--- +date: 2026-10-29 +branch: fix/renovate-config-filename +title: Renovate has failed every run since #79 — the workflow still named renovate.json +--- + +## What changed + +**`.gitea/workflows/renovate.yaml`** — `configurationFile: renovate.json` → `renovate.json5`. + +PR #79 (`fix/renovate-invalid-config`) renamed the config to `renovate.json5` and did not update +the one line in the workflow that names it. Measured 2026-10-29 from the Gitea Actions log of run +322 (task 513, schedule, 08:15 UTC): + + Error: ENOENT: no such file or directory, stat '/workspace/Home-Network/home-network-k3s-impl/renovate.json' + +Runs 315–322 (2026-10-22 → 10-29, every one listed) are all `failure` on the `schedule` event, +each failing in about one second. Renovate never started. `RENOVATE_TOKEN` **does** exist as a +repository Actions secret (listed by name via the API; value not read), so the token preflight +passes and this filename is the only blocker observed. + +**`ci/lint.sh`** — a new assertion after yamllint: every non-comment `configurationFile:` key in +`.gitea/workflows/*.y*ml` must name a path that exists. This is valid YAML, so yamllint cannot see +it, and the gate stayed green through 11 days of failures. + +## What I verified + +- The root cause, from the run log quoted above, and that `origin/main` has `renovate.json5` and + no `renovate.json` (`git ls-tree`). +- The new guard, both ways, run standalone: on this branch it prints + `workflow configurationFile references resolve`, rc 0. With the line reverted to `renovate.json` + it prints `configurationFile 'renovate.json' does not exist in the repo`, rc 1. My first version + also matched its own explanatory comment in the workflow and failed. That is why the grep is + anchored to non-comment lines. +- Toolbox gate: result and rc are reported in the PR, not predicted here. + +## What I did NOT verify + +- **Renovate has still never completed a run.** This removes the observed blocker. Others may + follow it. The test is a `workflow_dispatch` with `dry_run: true` after merge, and its log is + the first evidence that Renovate authenticates, extracts dependencies, and honours `.json5`. +- **The `enabledManagers: ["regex"]` vs `custom.regex` question** (#73, #77) is still open. The + same dry-run log answers it: look for the regex/custom manager's dependency-extraction count. +- **No alert for "Renovate keeps failing".** The guard prevents this specific cause from recurring. + Nothing notices a scheduled workflow that is red every day. That gap stays open. +- **Sensitive path.** `.gitea/**` and `ci/**` are both in `approval-policy.json`. CI will block + on `approval-policy` until the operator posts `/approve-override` as a review. The local gate + reports that stage as N/A.