ReviewOS

also looking at this

craft-native/craft

fix(dev): validate the pinned Zig toolchain before builds

#299
Merged glennmichael123 wants to merge codex/pinned-zig-toolchain into main
5 files +137 -14
scripts/zig.test.tsadded+51-0
Changes to scripts/zig.test.ts
@@ -0,0 +1,51 @@
1import { afterEach, expect, test } from 'bun:test'
2import { chmodSync, mkdtempSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs'
3import { tmpdir } from 'node:os'
4import { join } from 'node:path'
5import { pinnedZigVersion, resolveZig, runZig } from './zig'
6
7const roots: string[] = []
8afterEach(() => { for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }) })
9
10function fixture(version = '0.17.0-dev.1963+e00c6c439') {
11 const root = realpathSync(mkdtempSync(join(tmpdir(), 'craft-zig-toolchain-')))
12 roots.push(root)
13 mkdirSync(join(root, 'packages/zig'), { recursive: true })
14 writeFileSync(join(root, 'pantry.lock'), JSON.stringify({ workspaces: { '': { system: { 'ziglang.org': '0.17.0-dev.1963_e00c6c439' } } } }))
15 writeFileSync(join(root, 'package.json'), JSON.stringify({ version: '1.2.3' }))
16 const path = join(root, 'zig')
17 writeFileSync(path, `#!${process.execPath}\nif (process.argv[2] === 'version') console.log(${JSON.stringify(version)}); else { await Bun.write(process.env.ZIG_TEST_LOG, JSON.stringify({ cwd: process.cwd(), args: process.argv.slice(2) })); process.exit(23); }\n`)
18 chmodSync(path, 0o755)
19 return { root, path, env: { ...process.env, CRAFT_ZIG: '', CRAFT_ALLOW_UNPINNED_ZIG: '', PATH: root, ZIG_TEST_LOG: join(root, 'invocation.json') } }
20}
21
22test('accepts only the locked snapshot by default, even when PATH shadows it', () => {
23 const f = fixture('0.17.0-dev.2163+89ff10d56')
24 expect(pinnedZigVersion(f.root)).toBe('0.17.0-dev.1963+e00c6c439')
25 expect(() => resolveZig(f.root, f.env)).toThrow('version mismatch')
26 expect(() => resolveZig(f.root, f.env)).toThrow('CRAFT_ALLOW_UNPINNED_ZIG=1')
27 const pinned = fixture()
28 expect(resolveZig(f.root, { ...f.env, CRAFT_ZIG: pinned.path })).toEqual({ path: pinned.path, version: '0.17.0-dev.1963+e00c6c439', overridden: false })
29})
30
31test('requires an explicit opt-in for unpinned snapshots', () => {
32 const f = fixture('0.17.0-dev.2163+89ff10d56')
33 expect(() => resolveZig(f.root, { ...f.env, CRAFT_ALLOW_UNPINNED_ZIG: 'true' })).toThrow('version mismatch')
34 expect(resolveZig(f.root, { ...f.env, CRAFT_ALLOW_UNPINNED_ZIG: '1' }).overridden).toBe(true)
35})
36
37test('fails early for absent executables, invalid lock versions, and invalid compiler output', () => {
38 const f = fixture('not a version')
39 expect(() => resolveZig(f.root, { ...f.env, CRAFT_ZIG: join(f.root, 'missing') })).toThrow('was not found')
40 expect(() => resolveZig(f.root, f.env)).toThrow('Invalid Zig version')
41 writeFileSync(join(f.root, 'pantry.lock'), JSON.stringify({ workspaces: { '': { system: { 'ziglang.org': 'latest' } } } }))
42 expect(() => pinnedZigVersion(f.root)).toThrow('exact Zig version')
43})
44
45test('forwards arguments, core working directory, package version and compiler exit status', () => {
46 const f = fixture()
47 expect(runZig(f.root, ['--core', '--versioned', 'build', '-Doptimize=ReleaseSafe', '-Dfoo=a b'], f.env)).toBe(23)
48 expect(JSON.parse(readFileSync(f.env.ZIG_TEST_LOG, 'utf8'))).toEqual({ cwd: join(f.root, 'packages/zig'), args: ['build', '-Doptimize=ReleaseSafe', '-Dfoo=a b', '-Dversion=1.2.3'] })
49 expect(runZig(f.root, ['fmt', 'src/'], f.env)).toBe(23)
50 expect(JSON.parse(readFileSync(f.env.ZIG_TEST_LOG, 'utf8'))).toEqual({ cwd: f.root, args: ['fmt', 'src/'] })
51})