Repository navigation
fix(root): publish validated iyarc-prune pull requests - #10087
zahin-mohammad wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
@claude review always |
|
Claude finished @zahin-mohammad's task in 26s —— View job Review of PR #10087The approach is sound. The workflow now owns publication, and the agent only leaves uncommitted edits plus a report. I found no blocking bugs, but there are a few things to check. Items to check
Summary: the logic reads correctly. The main follow-up is item 1 (CI not triggering on bot-created PRs) and verifying items 2 and 3 before the first manual dispatch. I did not run anything locally. This was a read-only review. |
Ticket: WAL-2232 Co-authored-by: Ralph CLI <ralph-cli@bitgo.com> Ralph: 18.12.3-bitgo.6 openrouter/openai/gpt-6.1-sol@default:high openrouter/z-ai/glm-5.3-flash@smol:low+task:medium openrouter/z-ai/glm-5.3@slow:max
Failed manual dispatch: cause and fixThe linked run failed before the pruning agent ran, not in the dependency validation or pull-request publication steps. Failed job logs show: Verified configuration: GitHub's OpenID Connect (OIDC), the login mechanism that exchanges a workflow identity for short-lived AWS credentials, used the feature-branch workflow ref. This repository uses the default subject format. The BitGoJS infrastructure entry grants model-inference access only to the protected role; role generation defaults its protected branch to This explains why the feature-branch dispatch was rejected while the previous master dispatch authenticated successfully with the same role. Access limit: the deployed AWS role policy could not be read locally ( Fixed in signed commit fcef23b543:
VerificationGitHub reports the pushed commit signature as nix shell github:NixOS/nixpkgs/e9b7fc70551fcd2e52077d58d2c3bcee2428cf8d#actionlint github:NixOS/nixpkgs/e9b7fc70551fcd2e52077d58d2c3bcee2428cf8d#shellcheck -c actionlint .github/workflows/iyarc-prune.ymlExit 0, no workflow diagnostics. Nix emitted node_modules/.bin/prettier --check .claude/agents/iyarc-prune.md .github/workflows/iyarc-prune.ymlThe existing publication harness was exercised again using the invocation already documented in the PR body. Its final output was: The branch-dispatch smoke executes the actual workflow Bash step locally: node /tmp/wal-2232-ref-smoke.cjsTemporary smoke script, not checked in; removed after useconst assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const yaml = require(path.join(process.cwd(), 'node_modules/js-yaml'));
const workflow = yaml.load(fs.readFileSync('.github/workflows/iyarc-prune.yml', 'utf8'));
const guard = workflow.jobs.prune.steps[0];
assert.equal(guard.name, 'Require master workflow ref');
for (const [name, ref, expectedStatus] of [
['master dispatch', 'refs/heads/master', 0],
['feature dispatch', 'refs/heads/codex/WAL-2232-iyarc-prune-create-pr', 1],
['tag named master', 'refs/tags/master', 1],
['similarly named branch', 'refs/heads/master-preview', 1],
['pull request ref', 'refs/pull/10087/merge', 1],
['missing ref', undefined, 1],
]) {
const env = { ...process.env };
if (ref === undefined) delete env.GITHUB_REF;
else env.GITHUB_REF = ref;
const result = spawnSync('bash', ['-e', '-o', 'pipefail', '-c', guard.run], { env, encoding: 'utf8' });
assert.equal(result.status, expectedStatus, result.stderr + result.stdout);
if (expectedStatus && ref) {
assert.match(result.stdout, /::error::Run iyarc-prune from master/);
assert.match(result.stdout, /workflow ref, not the checkout ref/);
}
console.log(`PASS ${name}: exit ${result.status}`);
if (name === 'feature dispatch') console.log(result.stdout.trim());
}
console.log('Branch dispatch smoke: 6/6 PASS');Commit-message validation also passed: node_modules/.bin/commitlint --last --verboseHosted verification blocked: attempting to dispatch the updated feature-branch guard with gh workflow run iyarc-prune.yml --repo BitGo/BitGoJS --ref codex/WAL-2232-iyarc-prune-create-prreturned: The authenticated-browser fallback also timed out while connecting to the local browser relay. No new hosted workflow run was started by this session. Local smoke verification does not prove live AWS authentication or publication. |
PR Review: #10087 — master execution readinessVerdict: NEEDS CHANGES on remote commit Summary and ticket alignmentThe workflow delegates dependency investigation and validation to the agent, checks the uncommitted edits and report, then creates a signed, non-draft dependency pull request. WAL-2232 requires the published changes to be validated and unexpected paths to fail. The defects below violate those requirements; the staged corrections stay within that scope. Confirmed findings
The staging-area correction intentionally supports ordinary staged dependency changes. Validation describes the working-tree bytes, not a separate staged snapshot. Unexpected staged source paths are rejected; a differing staged value for an allowed manifest is discarded before the publisher stages the validated working-tree value. The actual publisher smoke below includes staged package version Other integration contracts reviewedNo additional deterministic blocker was found in these pinned contracts:
No database queries or TypeScript product changes are introduced by this PR. Verification of the staged correctionsWorkflow decisions and both master event typesInvocation from the repository root: nix shell github:NixOS/nixpkgs/e9b7fc70551fcd2e52077d58d2c3bcee2428cf8d#coreutils -c node /tmp/wal-2232-master-validate.cjsActual output excerpts: The throwaway harness executes the actual workflow Bash in an isolated Git repository. GitHub query/label calls use a controlled stub; this is not token-permission verification. The long script is not checked in. Its load-bearing execution and publication-invariant assertions are: const result = run('bash', ['-e', '-o', 'pipefail', '-c', script(stepName)], env);if (test.ready) {
assert.equal(run('git', ['diff', '--cached', '--quiet', baseSha]).status, 0, test.name);
assert.equal(run('git', ['symbolic-ref', '--short', 'HEAD']).stdout.trim(), 'master', test.name);
assert.equal(run('git', ['rev-parse', 'refs/remotes/origin/master']).stdout.trim(), baseSha, test.name);
}Both focused boundary scripts failed before the fix by reaching the publication stub ( node /tmp/wal-2232-workspace-boundary.cjs
node /tmp/wal-2232-index-boundary.cjsproduced: Actual pinned publisher with concurrent conflicting master changesbun /tmp/wal-2232-publisher-smoke.tsBefore the base correction, actual output included: After correction, including a fetched advanced tracking ref and a conflicting allowed-path staged value, actual output was: This executes the unmodified pinned action's const validatedTree = git(worker, 'write-tree');
fs.writeFileSync(path.join(worker, 'package.json'), '{"resolution":99}\n');
git(worker, 'add', 'package.json');
fs.writeFileSync(path.join(worker, 'package.json'), '{"resolution":2}\n');const result = await createOrUpdateBranch(manager, 'chore(deps): smoke', 'master',
'osv-scanner-prune/smoke', 'origin', false, addPaths);
assert.equal(result.baseCommit.sha, base);
assert.equal(git(worker, 'rev-parse', result.headSha + '^'), base);
assert.equal(git(worker, 'rev-parse', result.headSha + '^{tree}'), validatedTree);
assert.equal(result.branchCommits.length, 1);Real Linux scanner and release severity gatenode /tmp/wal-2232-linux-smoke.cjsThe actual pinned Linux x86-64 scanner was downloaded, checksum-verified, and run against the current root lockfile in a container. The actual release severity-gate shell then evaluated its JSON. Output excerpt: CVSS means Common Vulnerability Scoring System. Scanner exit 1 means findings; the release gate passed because none reached the configured blocking score of 7.0. This is current-lockfile evidence, not proof of future agent dependency edits. Complete short Linux smoke script; temporary, not checked inconst assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const yaml = require(path.join(process.cwd(), 'node_modules/js-yaml'));
const workflow = yaml.load(fs.readFileSync('.github/workflows/iyarc-prune.yml', 'utf8'));
const scanner = workflow.jobs.prune.steps.find((step) => step.name === 'Install release audit scanner');
const gate = yaml.load(fs.readFileSync('.github/actions/osv-severity-gate/action.yml', 'utf8')).runs.steps[0].run;
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'wal-2232-linux-'));
fs.writeFileSync(path.join(root, 'scanner-install.sh'), scanner.run);
fs.writeFileSync(path.join(root, 'severity-gate.sh'), gate);
const archive = path.join(root, 'inputs.tar');
const packed = spawnSync('tar', ['-cf', archive, '-C', process.cwd(), 'yarn.lock', 'osv-scanner.toml', '.gitignore', 'examples/ts/http-proxy/yarn.lock', '-C', root, 'scanner-install.sh', 'severity-gate.sh'], { encoding: 'utf8' });
assert.equal(packed.status, 0, packed.stderr);
const script = `set -eu
apk add --no-cache bash curl jq git coreutils
mkdir -p /workspace /tmp/runner
cd /workspace
tar -xf -
export RUNNER_TEMP=/tmp/runner GITHUB_PATH=/tmp/github-path OSV_SCANNER_SHA256=${scanner.env.OSV_SCANNER_SHA256}
bash scanner-install.sh
export PATH=/tmp/runner/osv-scanner:$PATH
set +e
osv-scanner --config=osv-scanner.toml --format=json --output-file=/tmp/runner/osv-results.json ./
code=$?
set -e
printf 'Scanner exit: %s\n' "$code"
[ "$code" -le 1 ] || exit "$code"
if [ "$code" -eq 0 ]; then export SCAN_OUTCOME=success; else export SCAN_OUTCOME=failure; fi
export RESULTS_FILE=/tmp/runner/osv-results.json CVSS_THRESHOLD=7.0
bash severity-gate.sh
printf 'PASS pinned Linux scanner command and release severity gate\n'
`;
const result = spawnSync('docker', ['run', '--rm', '-i', '--platform', 'linux/amd64', 'alpine:3.22@sha256:2e0b81d60597f449baa56dc25d355367869d2dca4cd57e866f1e2b52af3eb55f', 'sh', '-c', script], { input: fs.readFileSync(archive), encoding: 'utf8', timeout: 240000 });
console.log(result.stdout);
console.error(result.stderr);
assert.equal(result.status, 0, result.error?.message);Syntax and formattingnix shell github:NixOS/nixpkgs/e9b7fc70551fcd2e52077d58d2c3bcee2428cf8d#actionlint github:NixOS/nixpkgs/e9b7fc70551fcd2e52077d58d2c3bcee2428cf8d#shellcheck -c actionlint .github/workflows/iyarc-prune.ymlExit 0, no workflow diagnostics. Nix emitted the previously observed node_modules/.bin/prettier --check .claude/agents/iyarc-prune.md .github/workflows/iyarc-prune.ymlRemaining prerequisites
Recommendation: do not merge current remote commit |
Description
The weekly
iyarc-pruneworkflow removes obsolete vulnerability-scan exceptions. It could finish with validated dependency edits but no commit or pull request because the agent treated a checkout onmasteras a local run. Reported failure and acceptance criteria.Give the workflow explicit ownership of publication: require successful agent completion, reject any change to the original checkout commit, check tracked and untracked files plus a nonempty validation report, preserve existing labels, skip an existing open prune pull request, then create a signed commit and a non-draft pull request against
masterwith the existing labels and assignment. Fail when publication produces no pull request URL. Workflow.Have the agent leave validated edits uncommitted and write its report to the workflow-provided temporary path. Local runs continue to leave edits for developer review. Agent instructions.
Replace the unsupported scanner severity flag with the release workflow's scanner output and severity evaluation. Audit instructions.
Install scanner version 2.3.8 before the agent runs, with a pinned SHA-256 checksum (a digest used to detect changed downloads). Scanner setup.
Issue Number
WAL-2232
Type of change
How Has This Been Tested?
VERIFIED locally: workflow syntax, formatting, commit rules, and 34 execution, publication, label, and scanner-installation cases. The decision harness executes the actual workflow Bash steps in an isolated temporary Git repository, with the GitHub command-line client replaced by a controlled stub.
Validation commands and actual output
Run from the repository root:
Exit status 0; no workflow diagnostics. The tool emitted these environment warnings:
Scanner-installation checks use a local executable fixture and stub downloads; they verify path export and rejection of download/checksum failures. Separately, the real Linux release binary matched the published checksum:
The temporary harness is at
/tmp/wal-2232-validate.cjs; it is not checked in. Its load-bearing execution and assertion excerpts are:Output excerpt:
git diff --checkand the repository commit hooks also passed.Unverified live behavior: the local harness does not exercise model inference, Linux scanner execution, GitHub token permissions, or signed publication against this repository. The repository setting Allow GitHub Actions to create and approve pull requests also needs verification:
gh api repos/BitGo/BitGoJS/actions/permissions/workflowreturned HTTP 403 (Resource not accessible by personal access token). After merge, manually dispatch the workflow and verify the resulting commit signature, pull request, labels, assignment, and required checks.Checklist