Skip to content

feat(workflows): close code-scanning issues whose alerts are no longer open #2763

Description

@jkim323

Summary

create-gh-code-scanning-issues.yml can create and update alert-tracking issues, but it has no path that closes one. When an alert is fixed or dismissed, its tracking issue stays open indefinitely and must be closed by hand.

Eight automated issues accumulated this way and were closed manually on 2026-08-23: #2725, #2652, #2462, #2460, #1499, #1500, #1502, #2461.

Why the workflow cannot close anything today

Get-CodeScanningAlerts.ps1 fetches with state=open, so alerts.json contains only live alerts. Every action in the workflow - create, edit, comment - sits inside a single loop over that file:

done < <(jq -c '.[]' alerts.json)

A per-item loop can only act on rules that are present. A fixed or dismissed alert simply disappears from the input, so the workflow never observes its absence. Closing requires a set difference over what is missing, which this shape cannot express. The gap is structural, not a missing branch in the loop body.

Proposed fix

Add a reconciliation step after the loop:

  1. Collect the rule IDs present in alerts.json.
  2. List open issues whose body contains the automation:security-scan: marker.
  3. Parse each issue's rule ID from its marker comment.
  4. Close issues whose rule ID is absent from the live set, with a comment naming the run that observed the alert as no longer open.

The guard is the hard part

An unguarded reconciliation pass is a mass mutation with a fail-open failure mode: any run where alerts.json is empty, truncated, or malformed would close every open alert issue at once.

Emptiness cannot be the guard - zero open alerts is a legitimate and reachable state. The guard must be artifact validity: abort before closing anything unless the file parses as a JSON array.

Note that needs: [gh-code-scanning] does not cover this. It blocks on job failure, but not on a job that succeeds while producing a bad artifact. The serialization defect filed alongside this issue is exactly that case: the step succeeded and wrote syntactically valid JSON of the wrong shape. The artifact-upload step also carries if: always(), so artifact existence is not evidence that the scan succeeded.

Two related defects in the same step

Deduplication only sees open issues. The lookup uses --state open. If an issue is closed while its alert is still open, the next run files a duplicate instead of reopening. Once a close path exists, reopen-if-closed becomes the correct behavior; otherwise the two mechanisms will fight.

The update branch overwrites human edits. gh issue edit --title --body --add-label "automated,needs-triage" rewrites the entire body weekly and re-adds needs-triage to issues someone has already triaged. The weekly delta already goes in the comment the step posts; the body rewrite should be dropped or confined to a generated region.

Sequencing

The serialization fix should land first and separately. It is a one-word repair to a currently-red workflow and should not sit behind review of a mass-mutation feature.

Acceptance criteria

  • Issues whose alerts are no longer open are closed automatically, with a comment citing the observing run
  • Reconciliation aborts without closing anything when alerts.json is missing or does not parse as a JSON array
  • Zero open alerts is handled as a valid state, distinct from a malformed artifact
  • Deduplication finds closed issues and reopens rather than duplicating
  • Weekly updates no longer overwrite human-edited titles and bodies, and no longer re-add needs-triage unconditionally
  • Reviewed and validated by a qualified human reviewer

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

enhancementNew feature or requestpriority-3Medium priority, standard queuesecuritySecurity-related changes or concernstech-debtworkflowsGitHub Actions workflows

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions