-
Notifications
You must be signed in to change notification settings - Fork 4
Publish prebuilt CLI binaries #259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
16a0542
a3f96b3
46e9f96
c91bacd
99460b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@proofkit/cli": patch | ||
| --- | ||
|
|
||
| Publish prebuilt CLI binaries and cut install-time runtime deps so `npx` and `pnpm dlx` flows avoid dependency build approvals. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| #!/usr/bin/env node | ||
| "use strict"; | ||
|
|
||
| const { existsSync } = require("node:fs"); | ||
| const path = require("node:path"); | ||
| const { spawnSync } = require("node:child_process"); | ||
|
|
||
| const BINARIES = { | ||
| darwin: { | ||
| arm64: "proofkit-darwin-arm64", | ||
| x64: "proofkit-darwin-x64", | ||
| }, | ||
| linux: { | ||
| arm64: "proofkit-linux-arm64", | ||
| x64: "proofkit-linux-x64", | ||
| }, | ||
| win32: { | ||
| arm64: "proofkit-windows-arm64.exe", | ||
| x64: "proofkit-windows-x64.exe", | ||
| }, | ||
| }; | ||
|
|
||
| function run(command, args) { | ||
| const result = spawnSync(command, args, { | ||
| stdio: "inherit", | ||
| env: { | ||
| ...process.env, | ||
| PROOFKIT_PKG_ROOT: path.resolve(__dirname, ".."), | ||
| }, | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| throw result.error; | ||
| } | ||
|
|
||
| if (typeof result.status === "number") { | ||
| process.exit(result.status); | ||
| } | ||
|
|
||
| process.exit(1); | ||
|
Comment on lines
+23
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserve fallback on spawn errors and propagate child signals.
Suggested patch function run(command, args) {
const result = spawnSync(command, args, {
stdio: "inherit",
env: {
...process.env,
PROOFKIT_PKG_ROOT: path.resolve(__dirname, ".."),
},
});
if (result.error) {
throw result.error;
}
if (typeof result.status === "number") {
process.exit(result.status);
}
+
+ if (result.signal) {
+ process.kill(process.pid, result.signal);
+ return;
+ }
process.exit(1);
}
if (process.env.PROOFKIT_DISABLE_BUNDLED_BINARY !== "1") {
const binaryName = BINARIES[process.platform]?.[process.arch];
if (binaryName) {
const binaryPath = path.join(__dirname, binaryName);
if (existsSync(binaryPath)) {
- run(binaryPath, process.argv.slice(2));
+ try {
+ run(binaryPath, process.argv.slice(2));
+ } catch (error) {
+ if (!["EACCES", "ENOENT", "ENOEXEC"].includes(error?.code)) {
+ throw error;
+ }
+ }
}
}
}Also applies to: 47-49 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| if (process.env.PROOFKIT_DISABLE_BUNDLED_BINARY !== "1") { | ||
| const binaryName = BINARIES[process.platform]?.[process.arch]; | ||
| if (binaryName) { | ||
| const binaryPath = path.join(__dirname, binaryName); | ||
| if (existsSync(binaryPath)) { | ||
| run(binaryPath, process.argv.slice(2)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const fallbackPath = path.join(__dirname, "..", "dist", "index.js"); | ||
| if (existsSync(fallbackPath)) { | ||
| run(process.execPath, [fallbackPath, ...process.argv.slice(2)]); | ||
| } | ||
|
|
||
| console.error(`No ProofKit executable found for ${process.platform}-${process.arch}.`); | ||
| process.exit(1); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import { spawnSync } from "node:child_process"; | ||
| import { chmodSync, existsSync, mkdirSync, readdirSync, rmSync } from "node:fs"; | ||
| import path from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
|
|
||
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
| const packageRoot = path.resolve(__dirname, ".."); | ||
| const binDir = path.join(packageRoot, "bin"); | ||
| const entrypoint = path.join(packageRoot, "src", "index.ts"); | ||
|
|
||
| const targets = [ | ||
| { target: "bun-darwin-arm64", file: "proofkit-darwin-arm64" }, | ||
| { target: "bun-darwin-x64", file: "proofkit-darwin-x64" }, | ||
| { target: "bun-linux-arm64", file: "proofkit-linux-arm64" }, | ||
| { target: "bun-linux-x64", file: "proofkit-linux-x64" }, | ||
| { target: "bun-windows-arm64", file: "proofkit-windows-arm64.exe" }, | ||
| { target: "bun-windows-x64", file: "proofkit-windows-x64.exe" }, | ||
| ]; | ||
| const validTargets = new Set(targets.map((config) => config.target)); | ||
| const requestedTargetsEnv = process.env.PROOFKIT_BINARY_TARGETS ?? ""; | ||
|
|
||
| const selectedTargets = new Set( | ||
| requestedTargetsEnv | ||
| .split(",") | ||
| .map((target) => target.trim()) | ||
| .filter(Boolean), | ||
| ); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| const filteredSelectedTargets = new Set([...selectedTargets].filter((target) => validTargets.has(target))); | ||
|
|
||
| if (selectedTargets.size > 0 && filteredSelectedTargets.size === 0) { | ||
| console.error( | ||
| `No valid binary targets in PROOFKIT_BINARY_TARGETS="${requestedTargetsEnv}". Valid targets: ${targets | ||
| .map((config) => config.target) | ||
| .join(", ")}`, | ||
| ); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| mkdirSync(binDir, { recursive: true }); | ||
| for (const file of readdirSync(binDir)) { | ||
| if (file === "proofkit.cjs") { | ||
| continue; | ||
| } | ||
| rmSync(path.join(binDir, file), { recursive: true, force: true }); | ||
| } | ||
|
|
||
| let builtCount = 0; | ||
| for (const config of targets) { | ||
| if (filteredSelectedTargets.size > 0 && !filteredSelectedTargets.has(config.target)) { | ||
| continue; | ||
| } | ||
|
|
||
| const outfile = path.join(binDir, config.file); | ||
| const result = spawnSync( | ||
| "bun", | ||
| [ | ||
| "build", | ||
| "--compile", | ||
| `--target=${config.target}`, | ||
| "--no-compile-autoload-dotenv", | ||
| "--no-compile-autoload-bunfig", | ||
| "--no-compile-autoload-tsconfig", | ||
| "--no-compile-autoload-package-json", | ||
| entrypoint, | ||
| `--outfile=${outfile}`, | ||
| ], | ||
| { | ||
| cwd: packageRoot, | ||
| stdio: "inherit", | ||
| env: process.env, | ||
| }, | ||
| ); | ||
|
|
||
| if (result.error) { | ||
| throw result.error; | ||
| } | ||
|
|
||
| if (result.status !== 0) { | ||
| process.exit(result.status ?? 1); | ||
| } | ||
|
|
||
| if (existsSync(outfile) && !outfile.endsWith(".exe")) { | ||
| chmodSync(outfile, 0o755); | ||
| } | ||
|
|
||
| builtCount += 1; | ||
| } | ||
|
|
||
| if (builtCount === 0) { | ||
| console.error( | ||
| `No binary targets selected from PROOFKIT_BINARY_TARGETS="${requestedTargetsEnv}". Valid targets: ${targets | ||
| .map((config) => config.target) | ||
| .join(", ")}`, | ||
| ); | ||
| process.exit(1); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import { spawnSync } from "node:child_process"; | ||
| import path from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
|
|
||
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
| const packageRoot = path.resolve(__dirname, ".."); | ||
| const target = `bun-${process.platform}-${process.arch}`; | ||
|
|
||
| const result = spawnSync("node", ["./scripts/build-binaries.mjs"], { | ||
| cwd: packageRoot, | ||
| stdio: "inherit", | ||
| env: { | ||
| ...process.env, | ||
| PROOFKIT_BINARY_TARGETS: target, | ||
| }, | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| throw result.error; | ||
| } | ||
|
|
||
| process.exit(result.status ?? 1); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; | ||
| import path from "node:path"; | ||
| import { fileURLToPath } from "node:url"; | ||
|
|
||
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||
| const packageRoot = path.resolve(__dirname, ".."); | ||
| const readVersion = (packagePath) => { | ||
| const packageJson = JSON.parse(readFileSync(packagePath, "utf8")); | ||
| return packageJson.version ?? "0.0.0-private"; | ||
| }; | ||
|
|
||
| const outputPath = path.join(packageRoot, "src", "generated", "package-versions.ts"); | ||
| const content = [ | ||
| `export const CLI_VERSION = ${JSON.stringify(readVersion(path.join(packageRoot, "package.json")))} as const;`, | ||
| `export const FMDAPI_VERSION = ${JSON.stringify(readVersion(path.join(packageRoot, "..", "fmdapi", "package.json")))} as const;`, | ||
| `export const BETTER_AUTH_VERSION = ${JSON.stringify( | ||
| readVersion(path.join(packageRoot, "..", "better-auth", "package.json")), | ||
| )} as const;`, | ||
| `export const WEBVIEWER_VERSION = ${JSON.stringify( | ||
| readVersion(path.join(packageRoot, "..", "webviewer", "package.json")), | ||
| )} as const;`, | ||
| `export const TYPEGEN_VERSION = ${JSON.stringify(readVersion(path.join(packageRoot, "..", "typegen", "package.json")))} as const;`, | ||
| "", | ||
| ].join("\n"); | ||
|
|
||
| mkdirSync(path.dirname(outputPath), { recursive: true }); | ||
| writeFileSync(outputPath, content, "utf8"); | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: proofsh/proofkit
Length of output: 209
🏁 Script executed:
Repository: proofsh/proofkit
Length of output: 590
🏁 Script executed:
Repository: proofsh/proofkit
Length of output: 1314
🏁 Script executed:
Repository: proofsh/proofkit
Length of output: 637
🏁 Script executed:
Repository: proofsh/proofkit
Length of output: 42
Pin
oven-sh/setup-bunto a full commit SHA in both jobs.Using
@v2is mutable and weakens release-pipeline supply-chain guarantees. Pin these references to immutable commit SHAs at lines 83 and 165.Example change
🤖 Prompt for AI Agents