--- # Stage 1 of the infra pipeline: static checks only. No cluster access, no # credentials or mutation. It runs only when YAML-related paths change. # # Stages 2 (kubectl --dry-run=server) and 3 (k3d / molecule) come later and DO # need cluster access; keep them in separate workflows so a credential problem # there can never block this one. name: yaml on: push: branches: [main] paths: - '**/*.yaml' - '**/*.yml' - '.yamllint.yml' - '.gitea/workflows/lint.yml' pull_request: paths: - '**/*.yaml' - '**/*.yml' - '.yamllint.yml' - '.gitea/workflows/lint.yml' jobs: yaml: runs-on: self-hosted steps: - uses: actions/checkout@v4 - name: Bootstrap uv # Pin the tool for reproducibility; PyPI also avoids another setup action. run: | python3 -m pip install --user --break-system-packages \ --index-url https://pypi.org/simple --quiet uv==0.11.7 echo "$HOME/.local/bin" >> "$GITHUB_PATH" - name: Install yamllint # The WAN drops at random (see CLAUDE.md); retry rather than fail a run. run: | for i in 1 2 3 4 5; do uv tool install yamllint --quiet && break echo "attempt $i failed"; sleep 10 done uv tool list | grep -q yamllint - name: yamllint # --no-warnings so line-length stays advisory. Errors block. # netboot/ is vendored upstream and excluded in .yamllint.yml, # but they are also excluded here so the file list stays small. run: | export PATH="$HOME/.local/bin:$PATH" files=$(git ls-files '*.yaml' '*.yml' | grep -vE '^apps/netboot/') yamllint -c .yamllint.yml --no-warnings -f parsable $files