mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
feat(release): validate client build artifacts
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
/** Release family discovery, publish order, tag naming, and the bump judgements. */
|
||||
|
||||
import { resolve } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { dirname, join, resolve } from 'node:path'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { officialClientBuildEnvironment, writeClientBuildRecord } from '../client-build-environment.ts'
|
||||
import { releaseFamily, type ReleaseMember } from './families.ts'
|
||||
import { compareVersions, nextVendorVersion, reachesPayload } from './bump.ts'
|
||||
|
||||
@@ -16,6 +19,27 @@ function member(directory: string, name: string, manifest: Record<string, unknow
|
||||
return { directory, name, version: '0.0.1', manifest }
|
||||
}
|
||||
|
||||
const roots: string[] = []
|
||||
|
||||
function write(path: string, content: string): void {
|
||||
mkdirSync(dirname(path), { recursive: true })
|
||||
writeFileSync(path, content)
|
||||
}
|
||||
|
||||
function buildFixture(environment: Record<string, string>): string {
|
||||
const root = mkdtempSync(join(tmpdir(), 'dsh-release-build-'))
|
||||
roots.push(root)
|
||||
write(join(root, 'apps/web/dist/index.html'), '<main></main>')
|
||||
write(join(root, 'packages/client/example/lib/client.js'), 'module.exports = {}\n')
|
||||
writeClientBuildRecord(root, environment)
|
||||
return root
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true })
|
||||
vi.unstubAllEnvs()
|
||||
})
|
||||
|
||||
describe('release families', () => {
|
||||
it('excludes private experimental packages from the dsh release', () => {
|
||||
const members = releaseFamily('dsh').members(resolve(import.meta.dirname, '../..'))
|
||||
@@ -57,6 +81,23 @@ describe('release families', () => {
|
||||
expect(() => { vendor.verifyVersions([{ ...members[0]!, version: 'latest' }]) }).toThrow(/unpublishable version/)
|
||||
})
|
||||
|
||||
it('requires a current official client build only for dsh artifacts', () => {
|
||||
const dsh = releaseFamily('dsh')
|
||||
const vendor = releaseFamily('vendor')
|
||||
const officialEnvironment = officialClientBuildEnvironment(resolve(import.meta.dirname, '../..'))
|
||||
vi.stubEnv('DSH_CLIENT_COMMIT_HASH', officialEnvironment.DSH_CLIENT_COMMIT_HASH)
|
||||
const official = buildFixture(officialEnvironment)
|
||||
const defaultBuild = buildFixture({})
|
||||
|
||||
expect(() => { dsh.verifyBuildArtifacts(official) }).not.toThrow()
|
||||
expect(() => { dsh.verifyBuildArtifacts(defaultBuild) }).toThrow(/DSH_CLIENT_TITLE/)
|
||||
expect(() => { dsh.verifyBuildArtifacts(join(defaultBuild, 'missing')) }).toThrow(/record.*missing/)
|
||||
expect(() => { vendor.verifyBuildArtifacts(join(defaultBuild, 'missing')) }).not.toThrow()
|
||||
|
||||
write(join(official, 'packages/client/example/lib/client.js'), 'module.exports = { changed: true }\n')
|
||||
expect(() => { dsh.verifyBuildArtifacts(official) }).toThrow(/artifacts differ/)
|
||||
})
|
||||
|
||||
it('publishes a dependency before its consumer, and orders ties by name', () => {
|
||||
const dsh = releaseFamily('dsh')
|
||||
const members = [
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
import { globSync, readFileSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import {
|
||||
officialClientBuildEnvironment,
|
||||
readClientBuildRecord,
|
||||
} from '../client-build-environment.ts'
|
||||
import { validateTarballPayload } from '../publication-payload.ts'
|
||||
|
||||
/**
|
||||
@@ -111,6 +115,13 @@ export abstract class ReleaseFamily {
|
||||
/** Git tag prefix this family publishes from. */
|
||||
abstract readonly tagPrefix: string
|
||||
|
||||
/**
|
||||
* Assert that built artifacts match this release family's required profile.
|
||||
* Families without environment-selected artifacts accept every build tree.
|
||||
* @param _root - repository root containing generated artifacts.
|
||||
*/
|
||||
verifyBuildArtifacts(_root: string): void {}
|
||||
|
||||
/**
|
||||
* Discover this family's members.
|
||||
* @param root - repository root.
|
||||
@@ -311,6 +322,11 @@ class DshFamily extends ReleaseFamily {
|
||||
readonly patterns = ['packages/!(experimental)/*/package.json', 'apps/*/package.json'] as const
|
||||
readonly tagPrefix = 'dsh-v'
|
||||
|
||||
/** Require current artifacts from a complete official client build. */
|
||||
override verifyBuildArtifacts(root: string): void {
|
||||
readClientBuildRecord(root, officialClientBuildEnvironment(root))
|
||||
}
|
||||
|
||||
/**
|
||||
* Require one version across the family, the way a single tag can name it.
|
||||
* @param members - this family's members.
|
||||
|
||||
@@ -46,6 +46,7 @@ function main(): void {
|
||||
const root = process.cwd()
|
||||
const destination = resolve(root, values.out ?? DEFAULT_OUTPUT)
|
||||
const members = family.publishOrder(family.members(root)).order
|
||||
family.verifyBuildArtifacts(root)
|
||||
family.verifyVersions(members)
|
||||
|
||||
rmSync(destination, { recursive: true, force: true })
|
||||
|
||||
Reference in New Issue
Block a user