Skip to content

Commit d12aaf6

Browse files
Merge pull request #309 from BitGo/otto/ci-per-package-test-matrix
ci: make per-package test matrix respect detect-changes
2 parents 7a2b4d1 + 1d8f66b commit d12aaf6

2 files changed

Lines changed: 49 additions & 37 deletions

File tree

.github/scripts/detect-changes.mjs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,65 @@
11
#!/usr/bin/env node
2-
import { execSync } from 'child_process';
3-
import { appendFileSync } from 'fs';
2+
import { execSync } from "child_process";
3+
import { appendFileSync } from "fs";
44

5-
const ALL_PACKAGES = ['wasm-bip32', 'wasm-mps', 'wasm-utxo', 'wasm-solana', 'wasm-dot', 'wasm-ton', 'wasm-privacy-coin'];
5+
// Per-package matrix entries. Each object becomes one `matrix.include`
6+
// combination in the `test` job. The flags gate steps there:
7+
// - needs-wasm-pack: download the build artifact (wasm .js/.wasm)
8+
// - has-wasm-pack-tests: run `npm run test:wasm-pack-{node,chrome}`
9+
// Keeping the flags here (instead of a static `include:` block in the
10+
// workflow) is what actually lets `detect-changes` shrink the matrix — a
11+
// workflow `include:` entry whose `package` conflicts with the base matrix
12+
// spawns a NEW job rather than being filtered out, which previously
13+
// re-added every package on every PR.
14+
const PACKAGE_CONFIG = [
15+
{ package: "wasm-utxo", "needs-wasm-pack": true, "has-wasm-pack-tests": true },
16+
{ package: "wasm-bip32", "needs-wasm-pack": false, "has-wasm-pack-tests": false },
17+
{ package: "wasm-mps", "needs-wasm-pack": false, "has-wasm-pack-tests": false },
18+
{ package: "wasm-solana", "needs-wasm-pack": false, "has-wasm-pack-tests": false },
19+
{ package: "wasm-dot", "needs-wasm-pack": false, "has-wasm-pack-tests": false },
20+
{ package: "wasm-ton", "needs-wasm-pack": false, "has-wasm-pack-tests": false },
21+
{ package: "wasm-privacy-coin", "needs-wasm-pack": false, "has-wasm-pack-tests": false },
22+
];
623

7-
function setOutput(packages) {
8-
const value = JSON.stringify(packages);
24+
const ALL_PACKAGES = PACKAGE_CONFIG.map((p) => p.package);
25+
26+
function setOutput(entries) {
27+
const value = JSON.stringify(entries);
928
appendFileSync(process.env.GITHUB_OUTPUT, `packages=${value}\n`);
1029
console.log(`Packages to test: ${value}`);
1130
}
1231

32+
function entriesFor(pkgs) {
33+
const wanted = new Set(pkgs);
34+
return PACKAGE_CONFIG.filter((p) => wanted.has(p.package));
35+
}
36+
1337
// Non-PR events (push to master, workflow_dispatch): run everything
14-
if (process.env.GITHUB_EVENT_NAME !== 'pull_request') {
15-
setOutput(ALL_PACKAGES);
38+
if (process.env.GITHUB_EVENT_NAME !== "pull_request") {
39+
setOutput(PACKAGE_CONFIG);
1640
process.exit(0);
1741
}
1842

1943
const base = process.env.BASE_SHA;
2044
const head = process.env.HEAD_SHA;
2145

2246
const changedFiles = execSync(`git diff --name-only ${base} ${head}`)
23-
.toString().trim().split('\n').filter(Boolean);
47+
.toString()
48+
.trim()
49+
.split("\n")
50+
.filter(Boolean);
2451

2552
// Shared infrastructure changes → run all packages
26-
const sharedChanged = changedFiles.some(f =>
27-
/^(\.github\/|package\.json$|lerna\.json$|package-lock\.json$)/.test(f)
53+
const sharedChanged = changedFiles.some((f) =>
54+
/^(\.github\/|package\.json$|lerna\.json$|package-lock\.json$)/.test(f),
2855
);
2956
if (sharedChanged) {
30-
setOutput(ALL_PACKAGES);
57+
setOutput(PACKAGE_CONFIG);
3158
process.exit(0);
3259
}
3360

3461
// Per-package detection; fall back to all if nothing package-specific changed
35-
const changed = ALL_PACKAGES.filter(pkg =>
36-
changedFiles.some(f => f.startsWith(`packages/${pkg}/`))
62+
const changed = ALL_PACKAGES.filter((pkg) =>
63+
changedFiles.some((f) => f.startsWith(`packages/${pkg}/`)),
3764
);
38-
setOutput(changed.length > 0 ? changed : ALL_PACKAGES);
65+
setOutput(changed.length > 0 ? entriesFor(changed) : PACKAGE_CONFIG);

.github/workflows/build-and-test.yaml

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -155,29 +155,14 @@ jobs:
155155
strategy:
156156
fail-fast: false
157157
matrix:
158-
package: ${{ fromJson(needs.detect-changes.outputs.packages) }}
159-
include:
160-
- package: wasm-utxo
161-
needs-wasm-pack: true
162-
has-wasm-pack-tests: true
163-
- package: wasm-bip32
164-
needs-wasm-pack: false
165-
has-wasm-pack-tests: false
166-
- package: wasm-mps
167-
needs-wasm-pack: false
168-
has-wasm-pack-tests: false
169-
- package: wasm-solana
170-
needs-wasm-pack: false
171-
has-wasm-pack-tests: false
172-
- package: wasm-dot
173-
needs-wasm-pack: false
174-
has-wasm-pack-tests: false
175-
- package: wasm-ton
176-
needs-wasm-pack: false
177-
has-wasm-pack-tests: false
178-
- package: wasm-privacy-coin
179-
needs-wasm-pack: false
180-
has-wasm-pack-tests: false
158+
# `detect-changes` emits an array of objects
159+
# [{package, needs-wasm-pack, has-wasm-pack-tests}, ...] filtered to
160+
# changed packages. Using `include:` here (not a static list keyed on
161+
# `package`) is what makes the matrix actually shrink: a workflow
162+
# `include:` entry whose `package` conflicts with the base matrix
163+
# spawns a NEW job instead of being filtered, which previously
164+
# re-added every package on every PR.
165+
include: ${{ fromJson(needs.detect-changes.outputs.packages) }}
181166
steps:
182167
- uses: actions/checkout@v4
183168
with:

0 commit comments

Comments
 (0)