Skip to content

fix(ci): unbreak the Manage Issues lock job - #3880

Merged
marcusrbrown merged 2 commits into
mainfrom
frobot/fix-lock-threads-token-length-2026-09-10
Sep 13, 2026
Merged

marcusrbrown merged 2 commits into
mainfrom
frobot/fix-lock-threads-token-length-2026-09-10

Conversation

@fro-bot

@fro-bot fro-bot commented Sep 10, 2026

Copy link
Copy Markdown
Owner

The Manage Issues → Lock job has failed on every scheduled run for at least ten consecutive days. Not flaky, not rate-limited — rejected at the door.

##[error]"github-token" length must be less than or equal to 100 characters long

Root cause

dessant/lock-threads v6.0.0 — the SHA this workflow pins — validates its token input with Joi.string().trim().max(100) (src/schema.js:116 @ v6.0.0). The runner-issued GITHUB_TOKEN outgrew 100 characters, so the action refuses a perfectly valid credential before it does any work. Nothing in this repo is misconfigured; the ceiling moved underneath us.

Upstream fixed it in v6.0.2 — .max(1000), closing dessant/lock-threads#55. The v6.0.0 → v6.0.2 span is two patch releases: 6.0.1 bumps dependencies, 6.0.2 is the schema fix. No major drift, no behavior change beyond the validation bound.

The fix

One line: repin 7266a7c (v6.0.0) → 89ae32b (v6.0.2), the commit that the annotated tag v6.0.2 dereferences to, plus a comment explaining why the pin can't drift back.

Why a bot is touching a version pin at all

Renovate owns routine bumps, and it does see this one — it's on the dependency dashboard (#2828) as dessant/lock-threads v6.0.0 → Updates: v6.0.2. It will never open a PR for it:

// .github/renovate.json5
{
  description: 'Disable patch updates except for select dependencies.',
  matchUpdateTypes: ['patch'],
  matchPackageNames: ['!python', '!typescript'],
  enabled: false,
}

Patch updates are off repo-wide. That rule is fine for reducing churn and wrong for upstream bug-fix patches to pinned actions, which is the only channel those fixes travel through. The blind spot is the actual finding here; the repin is just the immediate repair. Broadening the rule is a policy change, not an autoheal, so it stays out of this PR — see the run summary for the deferred note.

Verification

pnpm bootstrap, check-types, lint, and test (79 files / 3672 tests) all pass on this branch. The real proof is the next scheduled Manage Issues run at 30 1 * * * reaching the lock step instead of erroring on input validation — or dispatch it manually to confirm sooner.

Risk

Low and reversible: revert the pin to 7266a7c to restore the previous state exactly. Worth naming, though — the Lock job has been a no-op for ten days, so the first successful run will process the whole accumulated backlog of no-issue-activity / no-pr-activity threads at once. That's the intended behavior finally happening, not a new hazard, but it will look like a burst.

🤖 Generated by Fro Bot · run 34435374053

The Lock job has failed on every scheduled run since at least 2026-08-31
with `"github-token" length must be less than or equal to 100 characters
long`. dessant/lock-threads v6.0.0 validates the input with
`Joi.string().trim().max(100)`; the runner-issued GITHUB_TOKEN outgrew
that bound, so the action rejected a perfectly valid credential before
doing any work. v6.0.2 raises the limit to 1000 (upstream issue #55) and
changes nothing else functional.

Renovate sees the update on the dependency dashboard but will never open
a PR for it: `.github/renovate.json5` disables patch updates for
everything except python and typescript. Upstream bug-fix patches to
pinned actions are therefore a standing blind spot, which is how a broken
job stayed broken for ten days.

Pin moved to the commit that tag v6.0.2 dereferences to.
@fro-bot

fro-bot commented Sep 10, 2026

Copy link
Copy Markdown
Owner Author

Fro Bot — Remediation Pass (categories 1–4)

Daily reactive autohealing sweep for fro-bot/.github. One fix landed; the rest of the control plane is clean. Full findings below, anchored here because this PR is the run's only mutation.

1. Errored PRs — none

Three open PRs, all green on both signal sources:

PR Author Check runs Legacy commit statuses
#3877 renovate/github-actions fro-bot (bot) 18 pass, 4 skipping success (Private Leak Scan)
#3878 fix/issue-trigger-credentials marcusrbrown 18 pass, 2 skipping success (Private Leak Scan)
#3879 renovate/bfra-me-.github-4.x fro-bot (bot) 14 pass, 4 skipping success (Private Leak Scan)

All three authors are trusted, all head branches are local, nothing to repair. main itself has no failed runs.

2. Security — nothing actionable

One open Dependabot alert: @humanfs/node < 0.16.8 (GHSA moderate, recursive copy follows symlinks out of the source tree). It's a development-scope transitive under eslint, reachable only through @bfra.me/eslint-config. Moderate, not critical/high, so it falls outside this run's remediation mandate. pnpm audit --prod is clean: zero advisories across 32 production dependencies.

Code scanning shows four open alerts, all of them OpenSSF Scorecard probe results (VulnerabilitiesID, BranchProtectionID, FuzzingID, CIIBestPracticesID) rather than findings in this repo's code. BranchProtectionID is a guardrail report, not a defect — untouched by design.

3. Control-plane integrity — clean

  • SHA pinning: 137 uses: references across .github/workflows/ and .github/actions/. Every third-party one is a full 40-char commit SHA carrying a # vX.Y.Z comment; the rest are local ./ refs. Zero floating tags, zero bare pins.
  • Strip-only TypeScript: no enum, namespace, parameter properties, or import x = require(...) anywhere in scripts/*.ts. The erasable-syntax-only rule and Test Scripts Load both agree.
  • Least privilege: every workflow declares a top-level permissions: block. The eleven job-level write grants are each narrow and justified (security-events for CodeQL/Scorecard, issues/pull-requests for the issue loops, id-token for OIDC publish). scorecard.yaml sits at read-all.
  • Guard integrity: wiki-authority guard, privacy gates, and branch protection untouched. This run wrote nothing under knowledge/** or metadata/**.

4. Code quality — clean

pnpm bootstrap, check-types, lint, and test all pass on main and on this branch. 79 test files, 3672 tests, 3 todo, zero failures. No mechanical lint or format fixes were available to apply.

The one thing that was actually broken

Manage Issues → Lock has failed on every scheduled run since at least 2026-08-31 — ten consecutive days of silent decay in a job nobody watches. Root cause and repair are in this PR's description. Short version: dessant/lock-threads v6.0.0 caps github-token at 100 characters, the runner's token outgrew that, and the action rejects a valid credential before doing any work. v6.0.2 raises the bound. One-line repin.

Version truth comes from the upstream release source — the dessant/lock-threads releases/tags API plus src/schema.js read at each tag SHA. No major drift: v6.0.0 → v6.0.2 is two patch releases inside the same major.


Needs Human Attention

1. Renovate's patch-disable rule is a standing blind spot for upstream bug fixes

  • Path: .github/renovate.json5, the first packageRules entry (matchUpdateTypes: ['patch'], enabled: false, exempting only python and typescript).
  • Root cause: every patch release is suppressed repo-wide. That's correct for churn reduction and wrong for upstream bug-fix patches to SHA-pinned actions, which have no other delivery channel. The lock-threads failure above is the concrete cost: Renovate listed v6.0.0 → v6.0.2 on the Dependency Dashboard (Dependency Dashboard #2828) and never opened a PR, while the job failed daily for ten days.
  • Smallest safe fix: add a narrower packageRules entry after the disable rule that re-enables patch updates for matchManagers: ['github-actions'] only. That keeps npm patch churn suppressed while letting action bug fixes flow. A broader "enable all patches" flip is a bigger policy change and should not be done reflexively.
  • Constraint: do not remove the disable rule outright — it is deliberate, and npm patch volume in this repo is high.
  • Verify: after the change, a Renovate dry run (or the next scheduled run) should propose action-only patch PRs; confirm no npm patch PRs appear.
  • Related open issues: Renovate: reusable-workflow deps fall outside the GitHub Actions group rule #3792 and CI: no Renovate config validation gate on a preset that ships org-wide #3793 both describe adjacent Renovate coverage gaps. Consider addressing the three together rather than piecemeal.

2. @humanfs/node moderate advisory — deliberately not actioned

  • Path: package.json (no overrides block exists today); the package is transitive under @bfra.me/eslint-configeslint.
  • Root cause: @humanfs/node < 0.16.8, dev-scope only. Patched in >= 0.16.8.
  • Smallest safe fix, if it ever escalates: a pnpm.overrides floor of >=0.16.8. This repo already has tooling for exactly that shape — scripts/check-override-floors.ts runs in pnpm lint and will reject a floor set below the advisory's patched range.
  • Do not retry now: moderate severity plus dev-only scope means this does not meet the critical/high bar for autonomous remediation. Let Renovate's eslint bumps carry it. Escalate only if the severity is revised upward or the package reaches a production path.

3. Durable knowledge this run could not persist

This job delivers via branch-pr and cannot write knowledge/**. Two findings are worth a wiki page, captured by a working-dir run:

  • A version-pinning policy that suppresses patch updates converts every upstream bug-fix patch into an invisible, indefinitely-deferred failure. The failure mode is silent because the broken job is itself the automation nobody reviews. Generalizes beyond this repo — the same rule shape exists across the fleet.
  • Third-party actions can validate credentials with hardcoded length bounds. GITHUB_TOKEN length is not a stable contract, so a Joi.string().max(N) on a token input is a time bomb with an unknown fuse. Worth noting on the GitHub Actions CI topic page as a distinct class from the usual auth failures — the error text says "github-token", which reads as a wiring bug and sends you to the wrong place. (Compare docs/solutions/workflow-issues/required-github-token-for-agent-steps-2026-06-22.md, which teaches "start debugging at the credential wiring" — correct advice that, here, leads to a dead end, because the wiring was fine and the validator was wrong.)

🤖 Generated by Fro Bot · run 34435374053

@marcusrbrown
marcusrbrown enabled auto-merge (squash) September 13, 2026 02:13
@marcusrbrown
marcusrbrown merged commit f13ff4f into main Sep 13, 2026
18 checks passed
@marcusrbrown
marcusrbrown deleted the frobot/fix-lock-threads-token-length-2026-09-10 branch September 13, 2026 02:14
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.

2 participants