|
1 | 1 | #!/usr/bin/env bun |
2 | 2 |
|
3 | | -import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; |
| 3 | +import { chmodSync, cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; |
4 | 4 | import path from "node:path"; |
5 | 5 | import { |
6 | 6 | binaryFilenameForSpec, |
@@ -32,45 +32,66 @@ function parseArgs(argv: string[]) { |
32 | 32 | return { outputRoot, expectedPackage }; |
33 | 33 | } |
34 | 34 |
|
35 | | -const repoRoot = path.resolve(import.meta.dir, ".."); |
36 | | -const options = parseArgs(process.argv.slice(2)); |
37 | | -const spec = getHostPlatformPackageSpec(); |
38 | | -const binaryName = binaryFilenameForSpec(spec); |
39 | | -const compiledBinaryCandidates = [ |
40 | | - path.join(repoRoot, "dist", binaryName), |
41 | | - path.join(repoRoot, "dist", "hunk"), |
42 | | -]; |
43 | | -const compiledBinary = compiledBinaryCandidates.find((candidate) => existsSync(candidate)); |
44 | | -const outputRoot = path.resolve(options.outputRoot ?? releaseArtifactsDir(repoRoot)); |
45 | | -const outputDir = path.join(outputRoot, spec.packageName); |
46 | | - |
47 | | -if (options.expectedPackage && options.expectedPackage !== spec.packageName) { |
48 | | - throw new Error( |
49 | | - `Host build resolved to ${spec.packageName}, but the workflow expected ${options.expectedPackage}.`, |
50 | | - ); |
| 35 | +export interface StagePrebuiltArtifactOptions { |
| 36 | + repoRoot?: string; |
| 37 | + outputRoot?: string; |
| 38 | + expectedPackage?: string; |
51 | 39 | } |
52 | 40 |
|
53 | | -if (!compiledBinary) { |
54 | | - throw new Error( |
55 | | - `Missing compiled binary at ${compiledBinaryCandidates.join(" or ")}. Run \`bun run build:bin\` first.`, |
| 41 | +/** Stage one standalone prebuilt release artifact for the current host. */ |
| 42 | +export function stagePrebuiltArtifact(options: StagePrebuiltArtifactOptions = {}) { |
| 43 | + const repoRoot = path.resolve(options.repoRoot ?? path.resolve(import.meta.dir, "..")); |
| 44 | + const spec = getHostPlatformPackageSpec(); |
| 45 | + const binaryName = binaryFilenameForSpec(spec); |
| 46 | + const compiledBinaryCandidates = [ |
| 47 | + path.join(repoRoot, "dist", binaryName), |
| 48 | + path.join(repoRoot, "dist", "hunk"), |
| 49 | + ]; |
| 50 | + const compiledBinary = compiledBinaryCandidates.find((candidate) => existsSync(candidate)); |
| 51 | + const outputRoot = path.resolve(options.outputRoot ?? releaseArtifactsDir(repoRoot)); |
| 52 | + const outputDir = path.join(outputRoot, spec.packageName); |
| 53 | + |
| 54 | + if (options.expectedPackage && options.expectedPackage !== spec.packageName) { |
| 55 | + throw new Error( |
| 56 | + `Host build resolved to ${spec.packageName}, but the workflow expected ${options.expectedPackage}.`, |
| 57 | + ); |
| 58 | + } |
| 59 | + |
| 60 | + if (!compiledBinary) { |
| 61 | + throw new Error( |
| 62 | + `Missing compiled binary at ${compiledBinaryCandidates.join(" or ")}. Run \`bun run build:bin\` first.`, |
| 63 | + ); |
| 64 | + } |
| 65 | + |
| 66 | + rmSync(outputDir, { recursive: true, force: true }); |
| 67 | + mkdirSync(outputDir, { recursive: true }); |
| 68 | + |
| 69 | + const stagedBinary = path.join(outputDir, binaryName); |
| 70 | + cpSync(compiledBinary, stagedBinary); |
| 71 | + if (spec.os !== "windows") { |
| 72 | + chmodSync(stagedBinary, 0o755); |
| 73 | + } |
| 74 | + |
| 75 | + cpSync(path.join(repoRoot, "skills"), path.join(outputDir, "skills"), { recursive: true }); |
| 76 | + writeFileSync( |
| 77 | + path.join(outputDir, "metadata.json"), |
| 78 | + `${JSON.stringify( |
| 79 | + { |
| 80 | + packageName: spec.packageName, |
| 81 | + os: spec.os, |
| 82 | + cpu: spec.cpu, |
| 83 | + binaryName, |
| 84 | + }, |
| 85 | + null, |
| 86 | + 2, |
| 87 | + )}\n`, |
56 | 88 | ); |
57 | | -} |
58 | 89 |
|
59 | | -rmSync(outputDir, { recursive: true, force: true }); |
60 | | -mkdirSync(outputDir, { recursive: true }); |
61 | | -cpSync(compiledBinary, path.join(outputDir, binaryName)); |
62 | | -writeFileSync( |
63 | | - path.join(outputDir, "metadata.json"), |
64 | | - `${JSON.stringify( |
65 | | - { |
66 | | - packageName: spec.packageName, |
67 | | - os: spec.os, |
68 | | - cpu: spec.cpu, |
69 | | - binaryName, |
70 | | - }, |
71 | | - null, |
72 | | - 2, |
73 | | - )}\n`, |
74 | | -); |
| 90 | + return outputDir; |
| 91 | +} |
75 | 92 |
|
76 | | -console.log(`Prepared prebuilt artifact in ${outputDir}`); |
| 93 | +if (import.meta.main) { |
| 94 | + const options = parseArgs(process.argv.slice(2)); |
| 95 | + const outputDir = stagePrebuiltArtifact(options); |
| 96 | + console.log(`Prepared prebuilt artifact in ${outputDir}`); |
| 97 | +} |
0 commit comments