Skip to content

[finding] docs-drift-check.yml hand-maintains a transient-status classifier that actions/github-script already accepts as a declared input #9576

Description

@os-steve

Filed unassigned by the domain:devx os-dev seat while landing #9424 / PR #9574. Observation, not a defect: the code in question is correct and does what its card asked. Recording, not claiming.

The observation

PR #9423 landed ~35 lines of hand-written retry machinery in .github/workflows/docs-drift-check.yml — a TRANSIENT_NETWORK_CODES set, an isTransient(error) predicate over 5xx / 429 / secondary-rate-limit 403, and a deliver(label, call) retry wrapper with its own delay table.

actions/github-script@v9 already accepts that policy as two declared inputs (present since v6, verified against the action's action.yml on the v9 tag):

retries: 3retry-exempt-status-codes: 400,401,404,422 # action default: 400,401,403,404,422

They drive octokit's retry plugin, which re-issues any request whose status is not exempt plus network-level failures — the same class, minus the hand-maintained code. Dropping 403 from the exempt list is what buys the secondary-rate-limit case that PR #9423 identified; keeping 400/401/404/422 exempt is what keeps a malformed request, a wrong target and an over-long body failing on the first answer.

PR #9574 took this route for merge-queue-triage.yml precisely so a second copy of the classifier would not exist. This card records the other half: the first copy could stop being hand-maintained too.

What would NOT be free

Not a mechanical swap, which is why this is a finding rather than a task:

  1. Scope widens from delivery to the whole step. PR ci(docs-drift): tolerate transient API failures when delivering the advisory, loudly #9423's wrapper retries only listComments / createComment; the input retries every octokit call in the script. That is a widening of retry, not of tolerance — a spent retry still throws, so the scan still fails the job — but it is a real behavioural change and should be stated, not assumed harmless.
  2. The degrade() half stays. Only the classifier and the retry loop dissolve; the job summary, the warning annotation and the green-on-undelivered decision are workflow-specific and would remain hand-written.
  3. The delay table is not preserved exactly. PR ci(docs-drift): tolerate transient API failures when delivering the advisory, loudly #9423 chose [3000, 9000] deliberately; octokit's plugin has its own schedule.

Whether that trade is worth touching a just-landed file is a triage call, not mine. The cost of leaving it is one hand-maintained copy of a rule the platform already declares — small, but it is the copy that a third instance would be tempted to clone.

Ref: #9373 · PR #9423 · #9424 · PR #9574 · #9575


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions