Skip to content

fix(tcfeed): one unreadable repository must not end the batch - #126

Merged
ralyodio merged 1 commit into
masterfrom
worktree-tcfeed-skip-404
Aug 13, 2026
Merged

fix(tcfeed): one unreadable repository must not end the batch#126
ralyodio merged 1 commit into
masterfrom
worktree-tcfeed-skip-404

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

A live run of 16 repositories stopped after 3 and said nothing about the 13 it never reached.

· wp-cli/wp-cli — https://github.com/wp-cli/wp-cli/pull/6390
· 0-AI-UG/cate — https://github.com/0-AI-UG/cate/pull/574
· withcoral/coral — https://github.com/withcoral/coral/pull/2174
tcfeed: Command failed: gh api repos/haproxy/haproxy/pulls?state=all&head=ralyodio:threatcrush-scan&per_page=1
gh: Not Found (HTTP 404)

Why

haproxy/haproxy has pull requests turned off — it takes patches on a mailing list. GitHub answers 404 for the pulls endpoint while the repository itself reads normally, so gh repo view succeeds and nothing earlier catches it:

$ gh api repos/haproxy/haproxy --jq .full_name
haproxy/haproxy
$ gh api "repos/haproxy/haproxy/pulls?state=all&per_page=1"
gh: Not Found (HTTP 404)

The "asked once" lookup was the only gh call in prTarget without a guard. It threw, sailed past the loop's try around openPr — which only ever wrapped openPr — and ended the run.

Two changes, and the second is the one that matters

  1. The pulls lookup treats 404 as a skip reason: does not accept pull requests. That is true, useful, and worth printing.
  2. The loop wraps prTarget as well as openPr. Every known failure now returns a reason rather than throwing, but prTarget makes a dozen API calls against repositories nobody here controls, and the failure mode when one of them surprises it is losing the rest of the batch silently. One repository is allowed to be unreadable; a run is not allowed to end because of it.

Verified

tsc --strict --noEmit clean.

Skips with the reason:

$ tcfeed pr haproxy/haproxy --dry-run
· haproxy/haproxy — skipped: does not accept pull requests

And — the actual bug — no longer stops before reaching the next repository:

$ tcfeed pr haproxy/haproxy serverpod/serverpod --dry-run
· haproxy/haproxy — skipped: does not accept pull requests
· serverpod/serverpod — dry run

🤖 Generated with Claude Code

A run of sixteen stopped after three and reported nothing about the
thirteen it never reached.

haproxy/haproxy has pull requests turned off — it takes patches on a
mailing list — so GitHub answers 404 for its pulls endpoint while the
repository itself reads normally, and nothing earlier caught it. The
"asked once" lookup was the only gh call in prTarget without a guard, so
it threw, went past the loop's try around openPr, and ended the run.

Two changes, because the second is the one that matters:

- the pulls lookup treats 404 as a repository that does not accept pull
  requests, which is a skip reason and a true one.
- the loop wraps prTarget as well as openPr. Every known failure now
  returns a reason rather than throwing, but prTarget makes a dozen API
  calls against repositories nobody here controls, and the failure mode
  when one of them surprises it is losing the rest of the batch silently.
  One repository is allowed to be unreadable. A run is not allowed to end
  because of it.

Verified: haproxy alone skips with the reason, and haproxy followed by
another repository no longer stops before reaching it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

ThreatCrush Security Scan

67 finding(s)

HIGH/CRITICAL: 11 | MEDIUM: 55 | LOW: 1

Severity Rule Location
HIGH secret-aws-access-key prd/0003-detect-hardcoded-secrets-before-they-are-committed-or-served.md:126
HIGH sh-eval-expansion .githooks/pre-commit:26
HIGH sh-remote-script-execution apps/web/public/install.sh:272
HIGH sh-remote-script-execution apps/web/public/install.sh:320
HIGH secret-generic-credential modules/spend-guard/config/example.conf.toml:13
HIGH secret-generic-credential modules/spend-guard/README.md:84
HIGH secret-generic-credential PRD.md:268
HIGH tls-verification-disabled prd/0004-find-dangerous-code-patterns-without-pretending-to-be-a-compiler.md:121
HIGH tls-verification-disabled prd/0004-find-dangerous-code-patterns-without-pretending-to-be-a-compiler.md:122
HIGH sh-remote-script-execution scripts/smoke-test.sh:46
HIGH sh-remote-script-execution scripts/smoke-test.sh:47
MEDIUM insecure-temp-file .githooks/commit-msg:16
MEDIUM insecure-temp-file .githooks/post-commit:20
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:70
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/init.ts:79
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:88
MEDIUM js-shell-exec-interpolation apps/cli/src/commands/service.ts:111
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:121
MEDIUM sql-template-interpolation apps/cli/src/core/state.ts:125
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:31
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:33
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:34
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:35
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:36
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:43
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:49
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:56
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:63
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:82
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:84
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:85
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:93
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:98
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:105
MEDIUM js-shell-exec-interpolation apps/cli/src/daemon/firewall/adapters.ts:112
MEDIUM js-shell-exec-interpolation apps/cli/src/index.ts:419
MEDIUM js-unescaped-html-sink apps/web/src/app/about/page.tsx:180
MEDIUM js-unescaped-html-sink apps/web/src/app/about/page.tsx:184
MEDIUM js-open-redirect apps/web/src/app/auth/login/page.tsx:50
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:125
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:153
MEDIUM js-unescaped-html-sink apps/web/src/app/blog/[slug]/page.tsx:157
MEDIUM js-unescaped-html-sink apps/web/src/app/get-whitepaper/page.tsx:346
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:211
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:215
MEDIUM js-unescaped-html-sink apps/web/src/app/layout.tsx:219
MEDIUM js-unescaped-html-sink apps/web/src/app/page.tsx:120
MEDIUM js-unescaped-html-sink apps/web/src/app/store/[slug]/page.tsx:107
MEDIUM js-open-redirect apps/web/src/components/funding/FundingClient.tsx:97
MEDIUM manifest-install-lifecycle-script package.json:24

…and 17 more. Full results in the Security tab.

Snippets are redacted; ThreatCrush never prints matched credential material.

@ralyodio
ralyodio merged commit fa8996f into master Aug 13, 2026
11 checks passed
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