openpencil/tools/release/release-packages/tests/native/context.test.ts
Danila Poyarkov 1aa10a4fed
build(tools): group tools by role and gate them like the rest of the repo (#791)
Tools live under tools/<role>/<domain> (checks, generate, release, ci, dev), every tool is a workspace named @open-pencil/<domain>-tools, a shared tools/tsconfig.json backs the new check:tools gate that fixed 55 latent type errors, test:tools runs through bun --filter, the placement check is its own checks/test-homes package, and every tool resolves the repository through resolveWorkspaceRoot. Bun, Node, and mdast types live in a tools-root workspace so they never reach the app program.
2026-09-30 05:00:31 +04:00

80 lines
2.8 KiB
TypeScript

import { expect, test } from 'bun:test'
import { resolve } from 'node:path'
import { desktopBuilds, desktopTargets } from '#release/native/catalog'
import { ARTIFACT_TRANSFER_TIMEOUT_MS, releaseCommands } from '#release/native/commands'
import { createReleaseContext, releaseVersion } from '#release/native/context'
import { releasePaths } from '#release/workflow'
import type { CommandRequest } from '@open-pencil/package-artifacts-tools'
const environment = {
RELEASE_TAG: 'v0.15.0',
SOURCE_COMMIT: 'a'.repeat(40),
WORKFLOW_COMMIT: 'b'.repeat(40),
GITHUB_RUN_ID: '123',
GITHUB_RUN_ATTEMPT: '1',
FRONTEND_SHA256: 'c'.repeat(64),
GITHUB_REPOSITORY: 'open-pencil/open-pencil'
}
test('one context owns release identity and reuses existing npm paths', () => {
const root = resolve('fixture')
const context = createReleaseContext(environment, root)
expect(context.version).toBe('0.15.0')
expect(context.paths.packages).toBe(releasePaths(root).artifacts)
expect(context.paths.notes).toBe(resolve(root, 'release-notes.md'))
expect(context.identity.sourceCommit).toBe(environment.SOURCE_COMMIT)
})
test.each(['master', '--help', 'v0.15.0/other', 'v0.15.0\n', 'v0.15'])(
'rejects invalid release tag %s',
(tag) => {
expect(() => releaseVersion(tag)).toThrow()
}
)
test('matrix metadata and target validation share the same catalog', () => {
expect(desktopTargets).toEqual(desktopBuilds.map((build) => build.target))
expect(new Set(desktopTargets).size).toBe(desktopTargets.length)
for (const platform of new Set(desktopBuilds.map((build) => build.platform))) {
expect(
desktopBuilds.filter((build) => build.platform === platform && build.saveBunCache)
).toHaveLength(1)
}
})
test('command adapters delegate argument arrays and deadlines to shared tooling', async () => {
const requests: CommandRequest[] = []
const cwd = resolve('fixture')
const commands = releaseCommands(cwd, async (request) => {
requests.push(request)
return { stdout: 'output\n', stderr: '' }
})
expect(await commands.git('rev-parse', 'HEAD')).toBe('output')
expect(await commands.github(['release', 'view', 'v0.15.0'])).toBe('output\n')
await commands.github(['release', 'download', 'v0.15.0'], ARTIFACT_TRANSFER_TIMEOUT_MS)
await commands.verifySignature('asset with spaces', 'key.pub', 'asset.sig')
expect(requests).toEqual([
{ command: 'git', args: ['rev-parse', 'HEAD'], cwd, timeoutMs: 60_000 },
{ command: 'gh', args: ['release', 'view', 'v0.15.0'], cwd, timeoutMs: 60_000 },
{
command: 'gh',
args: ['release', 'download', 'v0.15.0'],
cwd,
timeoutMs: ARTIFACT_TRANSFER_TIMEOUT_MS
},
{
command: 'minisign',
args: ['-Vm', 'asset with spaces', '-p', 'key.pub', '-x', 'asset.sig'],
cwd,
output: 'inherit',
timeoutMs: 60_000
}
])
})