openpencil/tools/release-packages/tests/workflow.test.ts
Danila Poyarkov c4a3dae2a4
ci: unify verified release builds (#711)
* ci: fix desktop build cache ownership

* build: centralize native release artifact validation

Reuse package command execution and npm artifact paths. Share release identity and target metadata, consume explicit Tauri artifact outputs, and reject incomplete or mixed-run artifact sets before draft publication.

* refactor: use release package aliases across directories

* ci: coordinate verified native and npm releases

Build shared frontend inputs once and keep native targets parallel. Bind their complete artifact set to immutable source and workflow revisions, verify updater signatures and attestations, and replace draft assets only after preflight and verified npm publication.

* test: group native release tests by domain
2026-09-16 21:58:38 +03:00

135 lines
4.6 KiB
TypeScript

import { describe, expect, test } from 'bun:test'
import { mkdir, readdir, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import {
buildReleasePackages,
createPublicationPlan,
packReleasePackages,
prepareReleasePackages,
releasePaths,
validatePublicationArtifacts
} from '#release/workflow'
async function createWorkspace() {
const root = join(tmpdir(), `open-pencil-release-workflow-${crypto.randomUUID()}`)
await mkdir(join(root, 'packages/library'), { recursive: true })
await mkdir(join(root, 'packages/app'), { recursive: true })
await writeFile(
join(root, 'package.json'),
JSON.stringify({ workspaces: ['packages/app', 'packages/library'] })
)
await writeFile(
join(root, 'packages/library/package.json'),
JSON.stringify({
name: '@fixture/library',
version: '1.0.0',
scripts: { build: "bun -e \"await Bun.write('../../order.txt', 'library')\"" }
})
)
await writeFile(
join(root, 'packages/app/package.json'),
JSON.stringify({
name: '@fixture/app',
version: '1.0.0',
dependencies: { '@fixture/library': 'workspace:*' },
scripts: {
build:
"bun -e \"const previous = await Bun.file('../../order.txt').text(); await Bun.write('../../order.txt', previous + ',app')\""
}
})
)
return root
}
describe('release workflow', () => {
test('uses conventional release artifact locations', () => {
expect(releasePaths('/repo')).toEqual({
root: '/repo',
artifacts: '/repo/.npm-packages',
prepared: '/repo/.publish'
})
})
test('creates a dependency-ordered publication plan from registry results', async () => {
const root = await createWorkspace()
const plan = await createPublicationPlan(
root,
async ({ manifest }) => manifest.name === '@fixture/library'
)
expect(plan.map(({ package: pkg, status }) => ({ name: pkg.manifest.name, status }))).toEqual([
{ name: '@fixture/library', status: 'published' },
{ name: '@fixture/app', status: 'unpublished' }
])
})
test('rejects incomplete or stale artifact sets before publication', () => {
const packageEntry = {
directory: 'packages/example',
manifest: { name: '@fixture/example', version: '1.0.0' }
}
expect(() =>
validatePublicationArtifacts([{ package: packageEntry, status: 'unpublished' }], new Map())
).toThrow('Missing verified package artifact for @fixture/example@1.0.0')
expect(() =>
validatePublicationArtifacts(
[{ package: packageEntry, status: 'published' }],
new Map([['@fixture/example@1.0.0', '/artifact.tgz']])
)
).not.toThrow()
expect(() =>
validatePublicationArtifacts([], new Map([['@fixture/unknown@1.0.0', '/artifact.tgz']]))
).toThrow('Unexpected package artifact for @fixture/unknown@1.0.0')
})
test('packs and validates an unpublished release artifact', async () => {
const root = join(tmpdir(), `open-pencil-release-pack-${crypto.randomUUID()}`)
await mkdir(join(root, 'packages/example/dist'), { recursive: true })
await writeFile(
join(root, 'package.json'),
JSON.stringify({ name: 'fixture', version: '1.0.0', workspaces: ['packages/example'] })
)
await writeFile(join(root, 'packages/example/dist/index.js'), 'export const ready = true\n')
await writeFile(
join(root, 'packages/example/dist/index.d.ts'),
'export declare const ready: true\n'
)
await writeFile(
join(root, 'packages/example/package.json'),
JSON.stringify({
name: '@fixture/release-package',
version: '1.0.0',
files: ['dist'],
exports: {
'.': {
types: './dist/index.d.ts',
import: './dist/index.js',
default: './dist/index.js'
}
},
publishConfig: { access: 'public' }
})
)
await prepareReleasePackages(root)
const plan = await packReleasePackages(root, async () => false)
expect(plan.map(({ package: pkg, status }) => [pkg.manifest.name, status])).toEqual([
['@fixture/release-package', 'unpublished']
])
expect(
(await readdir(releasePaths(root).artifacts)).filter((name) => name.endsWith('.tgz'))
).toHaveLength(1)
})
test('builds discovered packages in dependency order', async () => {
const root = await createWorkspace()
const packages = await buildReleasePackages(root, { output: 'capture' })
expect(packages.map(({ manifest }) => manifest.name)).toEqual([
'@fixture/library',
'@fixture/app'
])
expect(await Bun.file(join(root, 'order.txt')).text()).toBe('library,app')
})
})