refactor(landlock-run): unify workspace release (review round 1)
This commit is contained in:
@@ -15,6 +15,8 @@ const root = resolve(import.meta.dirname, '..')
|
||||
const workspaceGlobs = [
|
||||
{ dir: 'vendor', depth: 1 },
|
||||
{ dir: 'packages', depth: 2 },
|
||||
{ dir: 'native', depth: 1 },
|
||||
{ dir: 'native/landlock-run/packages', depth: 1 },
|
||||
{ dir: 'apps', depth: 1 },
|
||||
] as const
|
||||
const vendoredPackages = new Set([
|
||||
@@ -28,6 +30,11 @@ const vendoredPackages = new Set([
|
||||
'@cordisjs/plugin-hmr',
|
||||
'@cordisjs/plugin-logger-console',
|
||||
])
|
||||
const publicLandlockPackages = new Set([
|
||||
'node-addon-landlock-run',
|
||||
'node-addon-landlock-run-linux-arm64',
|
||||
'node-addon-landlock-run-linux-x64',
|
||||
])
|
||||
|
||||
const localArtifactDirs = new Set(['node_modules'])
|
||||
const appPackageFiles: Readonly<Record<string, readonly string[]>> = {
|
||||
@@ -55,6 +62,7 @@ interface PackageManifest {
|
||||
| undefined
|
||||
>
|
||||
files?: string[]
|
||||
publishConfig?: { access?: string }
|
||||
peerDependencies?: Record<string, string>
|
||||
devDependencies?: Record<string, string>
|
||||
}
|
||||
@@ -71,6 +79,8 @@ function readJson(path: string): PackageManifest {
|
||||
|
||||
const rootManifest = readJson(join(root, 'package.json'))
|
||||
const repositoryVersion = rootManifest.version
|
||||
const landlockWorkspaceManifest = readJson(join(root, 'native/landlock-run/package.json'))
|
||||
const landlockVersion = landlockWorkspaceManifest.version
|
||||
|
||||
/** Repo-relative dirs holding a package.json, walked to the configured depth. */
|
||||
function packageDirs(base: string, depth: number): string[] {
|
||||
@@ -161,8 +171,19 @@ function usesEmittedTreeDefaults(manifest: PackageManifest): boolean {
|
||||
function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
|
||||
const errors: string[] = []
|
||||
const label = manifest.name ?? dir
|
||||
const isLandlockPackageDir = dir.startsWith('native/landlock-run/packages/')
|
||||
const isPublicLandlockPackage = isLandlockPackageDir
|
||||
&& manifest.name !== undefined
|
||||
&& publicLandlockPackages.has(manifest.name)
|
||||
|
||||
if (manifest.private !== true) {
|
||||
if (isPublicLandlockPackage) {
|
||||
if (manifest.private === true) {
|
||||
errors.push(`${label}: published Landlock package must not set "private": true`)
|
||||
}
|
||||
if (manifest.publishConfig?.access !== 'public') {
|
||||
errors.push(`${label}: published Landlock package must set publishConfig.access to "public"`)
|
||||
}
|
||||
} else if (manifest.private !== true) {
|
||||
errors.push(`${label}: package.json must set "private": true`)
|
||||
}
|
||||
|
||||
@@ -187,6 +208,15 @@ function checkWorkspace({ dir, manifest }: WorkspaceManifest): string[] {
|
||||
}
|
||||
}
|
||||
|
||||
if (isLandlockPackageDir) {
|
||||
if (!isPublicLandlockPackage) {
|
||||
errors.push(`${label}: unexpected package in the public Landlock package family`)
|
||||
}
|
||||
if (manifest.version !== landlockVersion) {
|
||||
errors.push(`${label}: package.json version must match Landlock workspace version ${landlockVersion ?? '(missing)'}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (dir.startsWith('packages/') && manifest.name?.startsWith('@deepseek-ai/dsh-')) {
|
||||
const peer = manifest.peerDependencies?.cordis
|
||||
const dev = manifest.devDependencies?.cordis
|
||||
|
||||
@@ -18,10 +18,10 @@ function write(path: string, content = ''): void {
|
||||
writeFileSync(path, content)
|
||||
}
|
||||
|
||||
function addProject(root: string, path: string): void {
|
||||
function addProject(root: string, path: string, outDir = 'lib/types'): void {
|
||||
write(join(root, 'tsconfig.json'), JSON.stringify({ files: [], references: [{ path }] }))
|
||||
write(join(root, path, 'tsconfig.json'), JSON.stringify({
|
||||
compilerOptions: { composite: true, outDir: 'lib/types' },
|
||||
compilerOptions: { composite: true, outDir },
|
||||
include: ['src'],
|
||||
}))
|
||||
write(join(root, path, 'src/index.ts'), 'export {}\n')
|
||||
@@ -60,6 +60,18 @@ describe('RepositoryCleaner', () => {
|
||||
expect(existsSync(join(root, 'products/shell/lib'))).toBe(true)
|
||||
})
|
||||
|
||||
it('removes the native Landlock entry output that emits directly to lib', async () => {
|
||||
const root = fixture()
|
||||
const entry = 'native/landlock-run/packages/entry'
|
||||
addProject(root, entry, 'lib')
|
||||
write(join(root, entry, 'lib/index.js'))
|
||||
|
||||
await new RepositoryCleaner(root).clean()
|
||||
|
||||
expect(existsSync(join(root, entry, 'lib'))).toBe(false)
|
||||
expect(existsSync(join(root, entry, 'src/index.ts'))).toBe(true)
|
||||
})
|
||||
|
||||
it('refuses project outputs reached through a symlink outside the repository', async () => {
|
||||
const root = fixture()
|
||||
const externalProject = fixture()
|
||||
|
||||
@@ -114,6 +114,7 @@ export class RepositoryCleaner {
|
||||
const outputs = new Set<string>()
|
||||
const pending = [join(this.root, 'tsconfig.json')]
|
||||
const visited = new Set<string>()
|
||||
const nativeEntryOutput = join(this.root, 'native/landlock-run/packages/entry/lib')
|
||||
|
||||
while (pending.length > 0) {
|
||||
const nextConfigPath = pending.pop()
|
||||
@@ -125,10 +126,14 @@ export class RepositoryCleaner {
|
||||
const parsed = parseConfig(configPath)
|
||||
if (parsed.options.outDir !== undefined) {
|
||||
const typesDirectory = resolve(parsed.options.outDir)
|
||||
if (basename(typesDirectory) !== 'types') {
|
||||
const outputDirectory = basename(typesDirectory) === 'types'
|
||||
? dirname(typesDirectory)
|
||||
: typesDirectory === nativeEntryOutput
|
||||
? typesDirectory
|
||||
: undefined
|
||||
if (outputDirectory === undefined) {
|
||||
throw new Error(`clean: expected TypeScript outDir to end in /types: ${repositoryPath(this.root, typesDirectory)}`)
|
||||
}
|
||||
const outputDirectory = dirname(typesDirectory)
|
||||
this.assertRepositoryTarget(outputDirectory)
|
||||
outputs.add(outputDirectory)
|
||||
}
|
||||
|
||||
@@ -247,13 +247,13 @@ describe('isPermissive', () => {
|
||||
|
||||
describe('manifestPatterns', () => {
|
||||
it('derives globs from the declared members, so a new member area is read', () => {
|
||||
expect(manifestPatterns(['packages/*/*', 'tools/*'], ['packages/*'])).toEqual([
|
||||
expect(manifestPatterns(['packages/*/*', 'tools/*', 'native/landlock-run', 'native/landlock-run/packages/*'])).toEqual([
|
||||
'package.json',
|
||||
'packages/*/*/package.json',
|
||||
'tools/*/package.json',
|
||||
'examples/*/package.json',
|
||||
'native/landlock-run/package.json',
|
||||
'native/landlock-run/packages/*/package.json',
|
||||
'examples/*/package.json',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -39,10 +39,7 @@ const DEV_ONLY_AREAS = [
|
||||
'native/',
|
||||
] as const
|
||||
|
||||
/**
|
||||
* First-party packages released from sibling repositories under the project's
|
||||
* own license: reachable from workspace manifests but not third-party.
|
||||
*/
|
||||
/** First-party public native packages: reachable at runtime but not third-party. */
|
||||
const FIRST_PARTY = new Set([
|
||||
'node-addon-landlock-run',
|
||||
'node-addon-landlock-run-linux-arm64',
|
||||
@@ -119,16 +116,13 @@ function readManifest(rel: string): Manifest {
|
||||
* here, so a new member area (`tools/*`) is read the day it is declared.
|
||||
* @returns one glob per manifest-bearing location, repository-relative.
|
||||
*/
|
||||
export function manifestPatterns(rootMembers: readonly string[], nativeMembers: readonly string[]): string[] {
|
||||
export function manifestPatterns(rootMembers: readonly string[]): string[] {
|
||||
return [
|
||||
'package.json',
|
||||
...rootMembers.map(member => `${member}/package.json`),
|
||||
// The demo leaves join the workspace through `examples/package.json`, so
|
||||
// their own manifests are members of nothing and no glob above reaches them.
|
||||
'examples/*/package.json',
|
||||
// `native/landlock-run` is a nested workspace with its own lock file.
|
||||
'native/landlock-run/package.json',
|
||||
...nativeMembers.map(member => `native/landlock-run/${member}/package.json`),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -149,7 +143,7 @@ function workspaceMembers(rel: string): string[] {
|
||||
* would silently push dev-area manifests into the runtime tier.
|
||||
*/
|
||||
function loadWorkspaceManifests(): { manifests: Map<string, Manifest>; names: Set<string> } {
|
||||
const patterns = manifestPatterns(workspaceMembers('pnpm-workspace.yaml'), workspaceMembers('native/landlock-run/pnpm-workspace.yaml'))
|
||||
const patterns = manifestPatterns(workspaceMembers('pnpm-workspace.yaml'))
|
||||
const manifests = new Map<string, Manifest>()
|
||||
const names = new Set<string>()
|
||||
for (const pattern of patterns) {
|
||||
@@ -591,9 +585,9 @@ ${python.map(dep => `| [\`${dep.name}\`](${dep.repo}) | ${dep.license} | ${dep.r
|
||||
| --- | --- | --- |
|
||||
${BUILD_TIME_TOOLS.map(tool => `| [\`${tool.name}\`](${tool.repo}) | ${tool.license} | ${tool.role} |`).join('\n')}
|
||||
|
||||
## First-party sibling releases
|
||||
## First-party native packages
|
||||
|
||||
\`node-addon-landlock-run\` (and its platform packages) is released from a DeepSeek Harness sibling repository under BSD 3-Clause. It is listed here for completeness; it is first-party, not third-party.
|
||||
\`node-addon-landlock-run\` (and its platform packages) is built and released from this repository under BSD 3-Clause. It is listed here for completeness; it is first-party, not third-party.
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user