Skip to content

docs: write down the six CI gotchas that keep costing afternoons - #85

Merged
nkg merged 1 commit into
mainfrom
docs/ci-gotchas
Sep 19, 2026
Merged

nkg merged 1 commit into
mainfrom
docs/ci-gotchas

Conversation

@nkg

@nkg nkg commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Each of these was found the expensive way across the HordiaLabs consumers --
ship a fix, watch it not work, find out why -- and the reasoning then ended up
in an inline comment in whichever repo happened to hit it. The next person
re-derives it. Collecting them where every consumer already looks.

  1. cancel-in-progress: false does not protect QUEUED runs. It governs only the
    run already executing; a pending run is evicted whenever a newer one joins
    the group, whatever the flag says. Bursts of 3+ merges silently lose the
    middle commits. Fix is a per-sha group key, not a flag. Also covers
    event_name in the key, and why workflow_run/issue_comment/issues/
    pull_request_review workflows must never carry cancel-in-progress at all.

  2. GITHUB_TOKEN can never write .github/workflows/. workflows is not a
    grantable permissions: scope -- it is a platform rule, not a setting anyone
    forgot. Needs an App installation token, and a dedicated App at that.

  3. Actions cannot open a PR until can_approve_pull_request_reviews is on, and
    the repo-level value overrides the org-level one, so the same workflow
    works in one repo and not its neighbour.

  4. git diff-tree -r <sha> returns ZERO paths for a merge commit, so a path
    check over "what did this commit change" silently never fires on merges to
    main -- the only case that matters. Diff against the first parent.

  5. What the Free plan withholds, and how each absence presents: no branch
    protection, org secrets invisible to private repos, a SEPARATE Dependabot
    secret store, no Advanced Security. None of them name the plan in the error.

  6. Higher scanner recall reads as a regression. The v3 gitleaks -> betterleaks
    swap (~70% -> ~99% recall) makes repos that scanned clean start failing on
    placeholders. Includes the value-scoped .gitleaks.toml pattern, and the
    negative control that proves an allowlist is not secretly path-scoped.

Claims verified against this repo rather than written from memory: the
upload-sarif input exists on container-security, docker-build and trivy-repo;
permission-workflows exists on setup-token; diff-tree returning 0 paths on a
merge commit was reproduced.

Indexed from README.md and examples/README.md.

Why here

Every consumer already pulls from this repo, and examples/pre-push-hook.md sets the precedent for a portable doc that gets copied into consumer docs/. The alternative — leaving each lesson in the inline comment of whichever repo happened to hit it — is what produced the need for this.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EoicTZniGXry3W7YFZBsSM

Each of these was found the expensive way across the HordiaLabs consumers --
ship a fix, watch it not work, find out why -- and the reasoning then ended up
in an inline comment in whichever repo happened to hit it. The next person
re-derives it. Collecting them where every consumer already looks.

  1. cancel-in-progress: false does not protect QUEUED runs. It governs only the
     run already executing; a pending run is evicted whenever a newer one joins
     the group, whatever the flag says. Bursts of 3+ merges silently lose the
     middle commits. Fix is a per-sha group key, not a flag. Also covers
     event_name in the key, and why workflow_run/issue_comment/issues/
     pull_request_review workflows must never carry cancel-in-progress at all.

  2. GITHUB_TOKEN can never write .github/workflows/. `workflows` is not a
     grantable permissions: scope -- it is a platform rule, not a setting anyone
     forgot. Needs an App installation token, and a dedicated App at that.

  3. Actions cannot open a PR until can_approve_pull_request_reviews is on, and
     the repo-level value overrides the org-level one, so the same workflow
     works in one repo and not its neighbour.

  4. `git diff-tree -r <sha>` returns ZERO paths for a merge commit, so a path
     check over "what did this commit change" silently never fires on merges to
     main -- the only case that matters. Diff against the first parent.

  5. What the Free plan withholds, and how each absence presents: no branch
     protection, org secrets invisible to private repos, a SEPARATE Dependabot
     secret store, no Advanced Security. None of them name the plan in the error.

  6. Higher scanner recall reads as a regression. The v3 gitleaks -> betterleaks
     swap (~70% -> ~99% recall) makes repos that scanned clean start failing on
     placeholders. Includes the value-scoped .gitleaks.toml pattern, and the
     negative control that proves an allowlist is not secretly path-scoped.

Claims verified against this repo rather than written from memory: the
upload-sarif input exists on container-security, docker-build and trivy-repo;
permission-workflows exists on setup-token; diff-tree returning 0 paths on a
merge commit was reproduced.

Indexed from README.md and examples/README.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EoicTZniGXry3W7YFZBsSM
@nkg
nkg merged commit 59d4a87 into main Sep 19, 2026
12 checks passed
@nkg
nkg deleted the docs/ci-gotchas branch September 19, 2026 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant