Files
home-network-k3s-impl/ci/lint.sh
jakman85andClaude Opus 5.5 0c6ee4921d
gate / gate (pull_request) Successful in 2m54s
gate / conformance (pull_request) Has been skipped
fix(renovate): document and probe the five token scopes Renovate needs; lint daemon-bound actions
Run 350 cleared platform init (/user 200, /version 200, /repos 200), then stopped at
GET /api/v1/orgs/Home-Network with Gitea's own 403:
  token does not have at least one of required scope(s), required=[read:organization],
  token scope=read:package,write:repository,read:user
The workflow's header listed only those three scopes, and the operator minted exactly that.
Renovate's initRepo -> isOrg needs read:organization, and Gitea files /issues and /labels under
the issue scope, which the dashboard and PR labels need: write:issue.

- renovate.yaml: corrects the scope list (read:user, read:organization, write:repository,
  write:issue, read:package), with the call each serves. A new preflight step probes them with
  GETs, the token passed to curl on stdin, and names a missing scope instead of Renovate's bare
  "Authentication failure".
- ci/lint.sh: rejects workflow `uses:` lines that need a Docker daemon (docker://,
  renovatebot/github-action, docker/*-action), the class fixed in #84.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 01:55:39 -05:00

61 lines
2.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# ci/lint.sh — Stage 1: yaml/lint. Runs in CI without a cluster (live now).
# Lints all YAML in the repo against ci/yamllint.yaml.
set -euo pipefail
CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck disable=SC1091
source "${CI_DIR}/lib.sh"
log "Stage: yaml/lint"
require_tool yamllint "Install: pip install 'yamllint==${YAMLLINT_VERSION}'"
# Lint tracked + untracked (not yet committed) YAML; skip .git and artifact dirs.
cd "$REPO_ROOT"
mapfile -t files < <(
{ git ls-files '*.yaml' '*.yml' 2>/dev/null
git ls-files --others --exclude-standard '*.yaml' '*.yml' 2>/dev/null
} | sort -u
)
# Fallback for a non-git checkout.
if [ "${#files[@]}" -eq 0 ]; then
mapfile -t files < <(find . -path ./.git -prune -o \( -name '*.yaml' -o -name '*.yml' \) -print)
fi
if [ "${#files[@]}" -eq 0 ]; then
ok "no YAML files to lint"
exit 0
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"
# A workflow must not use an action that needs a Docker daemon: jobs on this runner get NONE, by
# decision (decisions/2026-10-29-image-pipeline.md; act_runner maps docker_host to `-`). Such an
# action is valid YAML and passes every other stage, then dies at runtime with
# "failed to connect to the docker API at unix:///var/run/docker.sock". renovatebot/github-action
# did exactly that on every Renovate run until 2026-10-30 (run 343). Run the tool's image as the
# job `container:` instead (see .gitea/workflows/renovate.yaml). Container (`docker://`) actions
# and Docker's own daemon-bound actions are rejected for the same reason. Comments are ignored.
daemon_uses='uses:[[:space:]]*["'\'']?(docker://|renovatebot/github-action|docker/(build-push|setup-buildx|setup-qemu|login)-action)'
bad=0
while IFS= read -r hit; do
err "${hit%%:*}: needs a Docker daemon, which jobs here do not get: $(echo "${hit#*:*:}" | sed -E 's/^[[:space:]]+//')"
bad=1
done < <(grep -HnE "^[^#]*${daemon_uses}" .gitea/workflows/*.y*ml 2>/dev/null || true)
[ "$bad" -eq 0 ] || exit 1
ok "no workflow uses a Docker-daemon-bound action"