diff --git a/.github/workflows/nightshift-scheduler.yaml b/.github/workflows/nightshift-scheduler.yaml new file mode 100644 index 0000000000..22a10d1201 --- /dev/null +++ b/.github/workflows/nightshift-scheduler.yaml @@ -0,0 +1,19 @@ +name: nightshift-scheduler +run-name: 'nightshift scheduler' + +on: + schedule: + - cron: '0 6 * * 1-5' # weekdays 06:00 UTC (168h cooldown gates to ~weekly) + workflow_dispatch: + inputs: + dry_run: + description: 'List tasks that would run without executing them' + required: false + default: false + type: boolean + +jobs: + schedule: + uses: BitGo/nightshift-actions/.github/workflows/nightshift-scheduler.yaml@v1 + with: + dry_run: ${{ inputs.dry_run || false }} diff --git a/.github/workflows/nightshift-task.yaml b/.github/workflows/nightshift-task.yaml new file mode 100644 index 0000000000..4088d637ab --- /dev/null +++ b/.github/workflows/nightshift-task.yaml @@ -0,0 +1,17 @@ +name: nightshift-task +run-name: 'nightshift: ${{ inputs.task_type }}' + +on: + workflow_dispatch: + inputs: + task_type: + description: 'Task type to run' + required: true + type: string + +jobs: + run: + uses: BitGo/nightshift-actions/.github/workflows/nightshift-task.yaml@v1 + with: + task_type: ${{ inputs.task_type }} + provider: bedrock diff --git a/.nightshift.yaml b/.nightshift.yaml new file mode 100644 index 0000000000..3923640717 --- /dev/null +++ b/.nightshift.yaml @@ -0,0 +1,168 @@ +max_tasks_per_run: 1 + +tasks: + enabled: + - iyarc-prune + + priorities: + iyarc-prune: 8 + + cooldowns: + iyarc-prune: '168h' + + custom: + - type: iyarc-prune + name: Audit Exclusion (.iyarc) Pruner + category: pr + cooldown: '168h' + priority: 8 + prompt: | + You are a nightshift automated maintenance agent for the BitGoJS + monorepo. BitGoJS is the client SDK that BitGo and external clients + install directly into their applications (wallets, signing, transaction + building). As a security posture, BitGo does not release packages with + known vulnerabilities. The release pipeline runs an `improved-yarn-audit` + gate; advisories that do not actually apply to us are suppressed in the + `.iyarc` ignore file at the repo root, each with a justification comment. + + Over time `.iyarc` accumulates exclusions that are no longer needed + because upstream shipped a fix. Nobody prunes them, so the suppressed + audit surface silently grows. Your job, once per cycle, is to find + exclusions that can now be safely removed, bump the relevant dependency, + prove the fix passes the release audit gate plus build/test, and open a + single pull request. Most cycles will legitimately produce NO PR — a + "nothing prunable this cycle" result is healthy and strongly preferred + over an unsafe or unverified bump. + + ## Environment notes + + - This is a Lerna + Yarn (v1, `1.22.22`) workspaces monorepo with ~116 + packages under `modules/`. Node is pinned via `.nvmrc`. + - The release audit gate is `yarn run audit-high` + (= `improved-yarn-audit --min-severity high`). It auto-reads `.iyarc` + from the repo root — no flag needed. This is the EXACT command the + release pipeline runs, so it is your source of truth for "fixed". + - IMPORTANT: nearly every entry in `.iyarc` is a TRANSITIVE dependency + (e.g. tar, minimatch, ws, form-data, protobufjs, tmp, sjcl, + sanitize-html, esbuild), pinned in the root `package.json` + `resolutions` block — NOT a direct dependency in a module + `package.json`. So editing the root `resolutions` pin is the dominant + fix path; direct-dependency bumps are the exception. + - The repo provides `yarn upgrade-dep -p -v ` (see + `scripts/upgrade-workspace-dependency.ts`). It ONLY scans module + manifests for DIRECT deps, so for a transitive dep it will print + "No packages found" and do nothing — that is expected; fall back to a + root `resolutions` edit. Also note `upgrade-dep` runs a plain + `yarn install` (full `postinstall` monorepo build) UNLESS you pass + `--ignore-scripts`; always pass `--ignore-scripts` to stay within the + runner time budget. + + ## Early exit (do this first) + + If an open PR already exists on a branch matching + `nightshift/iyarc-prune-*`, stop and report — do not open a second: + + gh pr list --state open --search "head:nightshift/iyarc-prune" + + ## Read context first + + Before changing anything, read: + 1. `.iyarc` — the full ignore list and every justification comment. + 2. The root `package.json` `resolutions` block. + 3. `scripts/upgrade-workspace-dependency.ts` (the `yarn upgrade-dep` tool). + 4. `CLAUDE.md` and `commitlint.config.js` (commit conventions). + + ## Per-exclusion evaluation + + For each `GHSA-*` entry in `.iyarc`: + + 1. Identify the affected package and the path that pulls it in. The + justification comment usually names both; confirm with `yarn why `. + 2. Determine whether a PATCHED version now exists and is reachable for us + (`yarn info versions`, the GitHub advisory's first-patched + version, registry metadata). + 3. Decide whether to attempt a fix: + - SKIP if the justification is "no upstream fix exists" / patched + range is `<0.0.0` (e.g. `sanitize-html` GHSA-rpr9-rxv7-x643, `sjcl` + GHSA-2w8x-224x-785m) UNLESS a real fix has since shipped. + - SKIP if the only available fix requires a major bump of a pinning + parent (e.g. `tar` / `minimatch` pinned by `lerna` / + `yeoman-generator`) AND that bump is incompatible. Record it under + "Still blocked" in the report. + - Otherwise, attempt the bump. + + ## Attempt a fix (per removable exclusion) + + 1. Bump compatibly: + - Transitive dep controlled by root `resolutions` (the common case): + update the pin in the root `package.json` `resolutions` block. + - Direct dependency (rare here): `yarn upgrade-dep -p + -v --ignore-scripts`. + 2. Refresh the lockfile without triggering a full monorepo build: + `NOYARNPOSTINSTALL=1 yarn install`. + 3. Remove the satisfied exclusion from `.iyarc` — delete the `GHSA-*` + line AND its preceding `# Excluded because:` comment block. + + ## Feedback loop / proof (abandon on failure) + + After each attempted fix, run the SAME gates the release pipeline runs, + in this order: + 1. Run the release gate: `yarn run audit-high`. It MUST pass with the + exclusion removed. Capture the output. + 2. Run `yarn check-deps`. It MUST pass — a `resolutions` change can break + cross-workspace version consistency. This is both a release-job step + (it runs immediately after audit in the release workflow) and a PR-CI + gate, so a failure here means the PR would be rejected anyway. + 3. Build and unit-test the affected module(s) only (keep within the + runner time budget — do NOT build/test the whole monorepo): + `yarn lerna run build --scope ` and + `yarn lerna run unit-test --scope `. + 4. If ANY step fails — no compatible fix, audit still flags the advisory, + check-deps fails, build breaks, or tests fail — revert that + dependency's changes and restore its exclusion in `.iyarc`. Never open + a PR with a red feedback loop. The full test suite still runs in PR CI + as a backstop. + + ## Commit and pull request (only if at least one exclusion was removed + with a fully green feedback loop) + + - Branch: `nightshift/iyarc-prune-YYYY-MM-DD` (use today's date). + - Conventional commit (commitlint extends `@commitlint/config-conventional`; + `deps` and `root` are valid scopes), e.g.: + `chore(deps): bump to , drop from .iyarc`. + commitlint enforces `references-empty: never`, so the commit MUST carry + an issue reference: include `Ticket: HSM-410` in the footer. + - Open a single NON-draft PR. Labels: `nightshift`, `automated`, + `dependencies`. + - Assign the PR to `gokulhost` so it does not get lost: + `gh pr edit --add-assignee gokulhost`. CODEOWNERS reviewers are + assigned automatically and separately. + - PR body must contain: + - A table of each removed exclusion: GHSA id, package, old -> new + version, the advisory it resolves. + - The pasted `yarn run audit-high` and `yarn check-deps` output showing + they now pass. + - Build/test results for the affected module(s). + - A "Still blocked" section listing every exclusion that could NOT be + removed and the reason (no upstream fix / incompatible parent pin). + + ## Output rules + + - If nothing is safely prunable this cycle, open no PR and report + "no exclusions prunable this cycle" in the job summary, including the + "Still blocked" breakdown so reviewers see what was evaluated. + - Only ever modify `.iyarc`, dependency manifests (`package.json`), + and `yarn.lock`. Do not modify product/source code. + +labels: + - nightshift + - automated + - dependencies + +pull_requests: + draft: false + branch_prefix: 'nightshift/' + labels: + - nightshift + - automated + - dependencies