Skip to content

ci: add fix-dependabot-alerts automation#339

Merged
TalZaccai merged 2 commits into
mainfrom
dev/talzacc/fix-dependabot-alerts-script
Jun 2, 2026
Merged

ci: add fix-dependabot-alerts automation#339
TalZaccai merged 2 commits into
mainfrom
dev/talzacc/fix-dependabot-alerts-script

Conversation

@TalZaccai
Copy link
Copy Markdown
Contributor

Summary

Adds a custom Node remediator (tools/scripts/fix-dependabot-alerts.mjs) and a daily GitHub Actions workflow (.github/workflows/fix-dependabot-alerts.yml) that automatically opens a single PR with verified fixes for open Dependabot security alerts in typescript/.

Modeled on the equivalent automation in microsoft/TypeAgent, adapted for TypeChat's npm + workspaces layout.

This is the companion of #338, which added the missing npm ecosystem entry to dependabot.yml so Dependabot would actually surface and (where possible) auto-PR npm vulnerabilities. The current 9 open alerts are all transitive, which Dependabot can rarely fix on its own — this automation handles those cases.

How it works

  1. Reads open Dependabot alerts via REST (requires a GitHub App: DEPENDABOT_APP_ID variable + DEPENDABOT_APP_PRIVATE_KEY secret).
  2. For each alert, tries in order: (a) npm update <pkg> --package-lock-only, (b) root overrides entry.
  3. Verifies via the lockfile that every resolved instance is ≥ the advisory's first_patched_version (avoids false positives from no-op installs).
  4. Runs npm ci --ignore-scripts && npm run build && npm test after each fix; rolls back individually on failure and records a 7-day cooldown so the same broken upgrade isn't retried daily.
  5. A final clean build (rm -rf node_modules out && npm ci ...) catches transitive .d.ts breakage that the per-fix incremental build would miss.
  6. Opens a single squash PR with only the passing fixes; supersedes any older auto-PR from the same workflow.

Status taxonomy

Status Meaning Cooldown?
applied Fix verified
rolled_back Fix worked but broke build/test 7d
unfixable Could not lift version via update or override (parent semver pin) no
no_patch Advisory has no first_patched_version yet no
skipped_cooldown Recently rolled back, in cooldown window

Local validation

Ran against current 9 open alerts:

  • minimatch 3.1.3 → 3.1.5 — fixed via npm update
  • ⚠️ qs, tar, @tootallnate/once — correctly classified as unfixable: parent semver pins (e.g. express requires qs ~6.14.0) cause npm to silently ignore the root overrides entry. These need upstream parent updates and stay in Dependabot's queue.

Security notes

  • Auth tokens (GH_TOKEN, GITHUB_TOKEN, NPM_TOKEN, DEPENDABOT_APP_PRIVATE_KEY) are stripped from the env before invoking npm ci / npm run build / npm test — those steps execute code from newly-updated dependencies.
  • actions/checkout runs with persist-credentials: false so the default token isn't reachable in .git/config during dep code execution. Push uses the App token explicitly.
  • App token is re-minted before gh pr create to avoid the 1-hour expiry hitting long verification runs (lesson from fix(fix-dependabot-alerts): refresh app token before creating PR TypeAgent#2393).

Required setup before this can run

  • Create or reuse a GitHub App with Dependabot alerts: Read + Pull requests: Write + Contents: Write permissions.
  • Add repo (or org) DEPENDABOT_APP_ID variable and DEPENDABOT_APP_PRIVATE_KEY secret.

Until those are set, the workflow will fail at the ""Generate GitHub App token"" step but will not affect anything else in the repo.

Followup

Surfaced during validation: the workspace's pre-existing prepare → build-all lifecycle currently fails on a sentiment-zod TS error unrelated to this work, which is why the script (and would-be Dependabot PRs) need --ignore-scripts on npm ci. Worth a separate triage issue.


Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Adds a custom Node remediator (tools/scripts/fix-dependabot-alerts.mjs) and a daily GitHub Actions workflow (.github/workflows/fix-dependabot-alerts.yml) that:

1. Reads open Dependabot alerts via the REST API (requires a GitHub App: DEPENDABOT_APP_ID variable + DEPENDABOT_APP_PRIVATE_KEY secret).

2. For each alert, tries 'npm update <pkg> --package-lock-only' first, then falls back to a root 'overrides' entry.

3. Verifies via the lockfile that every resolved instance is >= the advisory's first_patched_version.

4. Runs 'npm ci --ignore-scripts && npm run build && npm test' to verify; rolls back on failure with a 7-day cooldown to avoid retrying broken upgrades daily.

5. Opens a single squash PR with only the passing fixes; status taxonomy distinguishes applied / rolled_back / unfixable / no_patch / cooldown.

Local validation against the current 9 open alerts: 1 of 4 packages fixed (minimatch 3.1.3 -> 3.1.5). The other 3 (qs, tar, @tootallnate/once) are correctly classified as 'unfixable' because parent semver pins (e.g. express requires qs ~6.14.0) prevent npm 'overrides' from taking effect — these need upstream parent updates.

Modeled on the equivalent automation in microsoft/TypeAgent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a daily GitHub Actions automation to remediate open Dependabot security alerts for the typescript/ npm workspace by applying lockfile-only updates / overrides, verifying via lockfile inspection plus npm ci + build/test, and opening a single PR containing only passing fixes.

Changes:

  • Introduces tools/scripts/fix-dependabot-alerts.mjs to fetch/group Dependabot alerts and attempt verified remediations with rollback + cooldown tracking.
  • Adds .github/workflows/fix-dependabot-alerts.yml to run the script on a schedule / dispatch, cache rollback state, perform a final clean verification, and create/supersede a remediation PR.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
tools/scripts/fix-dependabot-alerts.mjs Implements alert fetching, lockfile verification, update/override strategies, and rollback/cooldown tracking with build/test validation.
.github/workflows/fix-dependabot-alerts.yml Schedules and orchestrates the remediation run, final clean verification, and automated PR creation via a GitHub App token.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/scripts/fix-dependabot-alerts.mjs
Comment thread tools/scripts/fix-dependabot-alerts.mjs Outdated
Comment thread tools/scripts/fix-dependabot-alerts.mjs Outdated
Comment thread .github/workflows/fix-dependabot-alerts.yml
Four fixes for valid Copilot review findings:

1. semverGte: parseSemver now captures prerelease tags; semverGte treats a prerelease as strictly less than the corresponding release per semver. Previously 1.2.3-beta.1 was accepted as satisfying first_patched_version=1.2.3, letting a vulnerable prerelease through verification.

2. attemptOverride now pins to the exact first_patched_version (was '>=X'), preventing range overrides from silently picking up unrelated major upgrades. Also detects and preserves the existing package.json indentation (2-space in TypeChat) so override commits don't reformat the whole file.

3. buildAndTest: when tests are enabled, only 'npm test' is run (which already runs 'npm run build' as its first step). 'npm run build' is only invoked explicitly in --skip-tests mode. Halves per-fix verification time.

4. Workflow final clean verification: same change — 'npm test' only when tests enabled, 'npm run build' only when skipped.

Verified locally: semver edge cases pass (1.2.3-beta.1 < 1.2.3 now correctly rejected); dry-run still reports 4 actionable groups.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@TalZaccai TalZaccai merged commit 246f677 into main Jun 2, 2026
12 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.

3 participants