also looking at this
fix(release): gate registry notification on final artifact checks
#305
6 files
+104
-14
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -50,13 +50,8 @@ jobs: | ||
| 50 | 50 | |
| 51 | 51 | - name: Validate SBOMs |
| 52 | 52 | run: | |
| 53 | # Basic validation | |
| 54 | for file in sbom/*.json; do | |
| 55 | if [ -f "$file" ]; then | |
| 56 | echo "Validating $file..." | |
| 57 | python3 -m json.tool "$file" > /dev/null && echo " ✓ Valid JSON" || echo " ✗ Invalid JSON" | |
| 58 | fi | |
| 59 | done | |
| 53 | VERSION=$(bun -p "require('./package.json').version") | |
| 54 | bun scripts/verify-sbom.ts sbom "v$VERSION" | |
| 60 | 55 | |
| 61 | 56 | - name: Generate SBOM summary |
| 62 | 57 | run: | |
| @@ -62,3 +62,16 @@ test('a registry network failure remains a visible best-effort warning', () => { | ||
| 62 | 62 | } |
| 63 | 63 | finally { rmSync(root, { recursive: true, force: true }) } |
| 64 | 64 | }) |
| 65 | ||
| 66 | test('SBOM generation validates required documents before uploading artifacts', () => { | |
| 67 | const workflow = Bun.YAML.parse(readFileSync(join(import.meta.dir, '../.github/workflows/sbom.yml'), 'utf8')) as { jobs: Record<string, Job> } | |
| 68 | const generate = workflow.jobs.generate.steps! | |
| 69 | const validation = generate.findIndex(step => step.name === 'Validate SBOMs') | |
| 70 | const upload = generate.findIndex(step => step.uses?.startsWith('actions/upload-artifact@')) | |
| 71 | expect(validation).toBeGreaterThan(-1) | |
| 72 | expect(upload).toBeGreaterThan(validation) | |
| 73 | const command = generate[validation]!.run! | |
| 74 | expect(command).toContain('bun scripts/verify-sbom.ts sbom "v$VERSION"') | |
| 75 | expect(command).toContain("require('./package.json').version") | |
| 76 | expect(command).not.toContain('||') | |
| 77 | }) | |
| @@ -32,6 +32,10 @@ test('requires all three valid documents from the matching release', () => { | ||
| 32 | 32 | } |
| 33 | 33 | writeFileSync(join(directory, name), JSON.stringify(documents[name])) |
| 34 | 34 | } |
| 35 | for (const packages of [undefined, [], 'not-an-inventory']) { | |
| 36 | writeFileSync(join(directory, 'full-sbom.spdx.json'), JSON.stringify({ ...documents['full-sbom.spdx.json'], packages })) | |
| 37 | expect(() => verifySbomFiles(directory, 'v0.0.93')).toThrow('populated SPDX') | |
| 38 | } | |
| 35 | 39 | } |
| 36 | 40 | finally { |
| 37 | 41 | rmSync(directory, { recursive: true, force: true }) |