Skip to content

Commit 95a153e

Browse files
authored
Merge pull request #342 from ndycode/audit/pr6-ci-harness-realism
mirror release harness checks on push CI
2 parents fdf1b3f + 23e5431 commit 95a153e

2 files changed

Lines changed: 113 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ on:
44
push:
55
branches: [main]
66

7+
permissions:
8+
contents: read
9+
10+
concurrency:
11+
group: ci-${{ github.ref }}
12+
cancel-in-progress: true
13+
714
jobs:
815
test:
916
name: Test on Node.js ${{ matrix.node-version }}
@@ -68,6 +75,52 @@ jobs:
6875
- name: Run ESLint
6976
run: npm run lint
7077

78+
release-harness:
79+
name: Release Harness
80+
runs-on: ubuntu-latest
81+
82+
steps:
83+
- name: Checkout code
84+
uses: actions/checkout@v4
85+
86+
- name: Setup Node.js
87+
uses: actions/setup-node@v4
88+
with:
89+
node-version: 20.x
90+
cache: npm
91+
92+
- name: Install dependencies
93+
run: npm ci
94+
95+
- name: Typecheck scripts
96+
run: npm run typecheck:scripts
97+
98+
- name: Pack budget check
99+
run: npm run pack:check
100+
101+
- name: Verify vendor provenance
102+
run: npm run vendor:verify
103+
104+
scripts-windows:
105+
name: Script Typecheck (Windows)
106+
runs-on: windows-latest
107+
108+
steps:
109+
- name: Checkout code
110+
uses: actions/checkout@v4
111+
112+
- name: Setup Node.js
113+
uses: actions/setup-node@v4
114+
with:
115+
node-version: 20.x
116+
cache: npm
117+
118+
- name: Install dependencies
119+
run: npm ci
120+
121+
- name: Typecheck scripts
122+
run: npm run typecheck:scripts
123+
71124
codex-compat:
72125
name: Codex Compatibility Smoke
73126
runs-on: ubuntu-latest

test/ci-workflows.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { readFileSync } from "node:fs";
2+
import { join, resolve } from "node:path";
3+
import { describe, expect, it } from "vitest";
4+
5+
const projectRoot = resolve(process.cwd());
6+
7+
function readWorkflow(name: string): string {
8+
return readFileSync(join(projectRoot, ".github", "workflows", name), "utf-8");
9+
}
10+
11+
function extractJobBlock(workflow: string, jobName: string): string {
12+
const start = workflow.indexOf(` ${jobName}:`);
13+
if (start === -1) {
14+
throw new Error(`Missing workflow job: ${jobName}`);
15+
}
16+
const nextMatch = workflow
17+
.slice(start + 1)
18+
.match(/\n [a-z0-9][a-z0-9-]*:\n/);
19+
const end = nextMatch ? start + 1 + nextMatch.index + 1 : workflow.length;
20+
return workflow.slice(start, end);
21+
}
22+
23+
describe("CI workflow parity", () => {
24+
it("keeps push CI aligned with the PR release harness checks", () => {
25+
const ci = readWorkflow("ci.yml");
26+
const prCi = readWorkflow("pr-ci.yml");
27+
const requiredCommands = [
28+
"npm run typecheck:scripts",
29+
"npm run pack:check",
30+
"npm run vendor:verify",
31+
];
32+
33+
for (const command of requiredCommands) {
34+
expect(prCi).toContain(command);
35+
expect(ci).toContain(command);
36+
}
37+
});
38+
39+
it("keeps push CI using the same stale-run cancellation as PR CI", () => {
40+
const ci = readWorkflow("ci.yml");
41+
const prCi = readWorkflow("pr-ci.yml");
42+
43+
expect(prCi).toContain("concurrency:");
44+
expect(prCi).toContain("cancel-in-progress: true");
45+
expect(ci).toContain("concurrency:");
46+
expect(ci).toContain("cancel-in-progress: true");
47+
});
48+
49+
it("keeps Windows script typecheck coverage in push and PR CI", () => {
50+
const ci = readWorkflow("ci.yml");
51+
const prCi = readWorkflow("pr-ci.yml");
52+
const ciWindowsJob = extractJobBlock(ci, "scripts-windows");
53+
const prWindowsJob = extractJobBlock(prCi, "scripts-windows");
54+
55+
expect(ciWindowsJob).toContain("runs-on: windows-latest");
56+
expect(ciWindowsJob).toContain("npm run typecheck:scripts");
57+
expect(prWindowsJob).toContain("runs-on: windows-latest");
58+
expect(prWindowsJob).toContain("npm run typecheck:scripts");
59+
});
60+
});

0 commit comments

Comments
 (0)