Skip to content

Commit 90c70b6

Browse files
committed
Replaces simple process.argv[2] with a proper arg loop that handles both the positional output name and --node-binary <path> flag. Also the SEA build process no uses nodeBinary || process.execPath as the source Node binary. This is an attempt to a universal MacOS binary (ARM64 and x386).
1 parent a6aff5f commit 90c70b6

2 files changed

Lines changed: 92 additions & 13 deletions

File tree

.github/workflows/release.yml

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ jobs:
1414
fail-fast: false
1515
matrix:
1616
include:
17-
- runner: macos-latest
18-
binary: ccli-macos-arm64
1917
- runner: ubuntu-latest
2018
binary: ccli-linux-x64
2119
- runner: ubuntu-24.04-arm
@@ -53,8 +51,71 @@ jobs:
5351
name: ${{ matrix.binary }}
5452
path: dist/${{ matrix.binary }}
5553

54+
build-macos:
55+
runs-on: macos-latest
56+
name: Build ccli-macos-universal
57+
58+
steps:
59+
- uses: actions/checkout@v4
60+
61+
- uses: actions/setup-node@v4
62+
id: setup-node
63+
with:
64+
node-version: 22
65+
66+
- run: npm ci
67+
68+
# ── arm64 slice (native on macos-latest) ─────────────────────────────
69+
- name: Build arm64 slice
70+
run: node scripts/sea-build.js ccli-macos-arm64
71+
72+
- name: Smoke test arm64
73+
run: |
74+
chmod +x dist/ccli-macos-arm64
75+
./dist/ccli-macos-arm64 --version
76+
77+
# ── x64 slice (cross-build using downloaded x64 Node) ────────────────
78+
- name: Download Node x64 binary
79+
id: node-x64
80+
run: |
81+
NODE_VERSION="${{ steps.setup-node.outputs.node-version }}"
82+
TARBALL="node-v${NODE_VERSION}-darwin-x64.tar.gz"
83+
URL="https://nodejs.org/dist/v${NODE_VERSION}/${TARBALL}"
84+
echo "Downloading ${URL}"
85+
curl -fsSL "$URL" -o "$TARBALL"
86+
tar xzf "$TARBALL"
87+
NODE_X64="$(pwd)/node-v${NODE_VERSION}-darwin-x64/bin/node"
88+
echo "node_x64=${NODE_X64}" >> "$GITHUB_OUTPUT"
89+
file "$NODE_X64"
90+
91+
- name: Build x64 slice
92+
run: node scripts/sea-build.js ccli-macos-x64 --node-binary "${{ steps.node-x64.outputs.node_x64 }}"
93+
94+
- name: Smoke test x64
95+
run: |
96+
chmod +x dist/ccli-macos-x64
97+
arch -x86_64 ./dist/ccli-macos-x64 --version
98+
99+
# ── Universal binary ─────────────────────────────────────────────────
100+
- name: Create universal binary
101+
run: |
102+
lipo -create dist/ccli-macos-arm64 dist/ccli-macos-x64 -output dist/ccli-macos-universal
103+
codesign --sign - dist/ccli-macos-universal
104+
file dist/ccli-macos-universal
105+
106+
- name: Smoke test universal (arm64)
107+
run: ./dist/ccli-macos-universal --version
108+
109+
- name: Smoke test universal (x86_64)
110+
run: arch -x86_64 ./dist/ccli-macos-universal --version
111+
112+
- uses: actions/upload-artifact@v4
113+
with:
114+
name: ccli-macos-universal
115+
path: dist/ccli-macos-universal
116+
56117
release:
57-
needs: build
118+
needs: [build, build-macos]
58119
runs-on: ubuntu-latest
59120
name: Create Release
60121

@@ -86,14 +147,14 @@ jobs:
86147
- name: Download release binaries
87148
run: |
88149
base="https://github.com/seabearDEV/codexCLI/releases/download/${GITHUB_REF_NAME}"
89-
for bin in ccli-macos-arm64 ccli-linux-x64 ccli-linux-arm64; do
150+
for bin in ccli-macos-universal ccli-linux-x64 ccli-linux-arm64; do
90151
curl -fsSL "$base/$bin" -o "$bin"
91152
done
92153
93154
- name: Compute SHA256 checksums
94155
id: sha
95156
run: |
96-
echo "macos_arm64=$(sha256sum ccli-macos-arm64 | awk '{print $1}')" >> "$GITHUB_OUTPUT"
157+
echo "macos_universal=$(sha256sum ccli-macos-universal | awk '{print $1}')" >> "$GITHUB_OUTPUT"
97158
echo "linux_x64=$(sha256sum ccli-linux-x64 | awk '{print $1}')" >> "$GITHUB_OUTPUT"
98159
echo "linux_arm64=$(sha256sum ccli-linux-arm64 | awk '{print $1}')" >> "$GITHUB_OUTPUT"
99160
@@ -107,7 +168,7 @@ jobs:
107168
- name: Generate formula
108169
env:
109170
CCLI_VERSION: ${{ steps.version.outputs.version }}
110-
SHA_MACOS_ARM64: ${{ steps.sha.outputs.macos_arm64 }}
171+
SHA_MACOS_UNIVERSAL: ${{ steps.sha.outputs.macos_universal }}
111172
SHA_LINUX_X64: ${{ steps.sha.outputs.linux_x64 }}
112173
SHA_LINUX_ARM64: ${{ steps.sha.outputs.linux_arm64 }}
113174
run: |
@@ -125,8 +186,8 @@ jobs:
125186
end
126187
127188
on_macos do
128-
url "https://github.com/seabearDEV/codexCLI/releases/download/v$CCLI_VERSION/ccli-macos-arm64"
129-
sha256 "$SHA_MACOS_ARM64"
189+
url "https://github.com/seabearDEV/codexCLI/releases/download/v$CCLI_VERSION/ccli-macos-universal"
190+
sha256 "$SHA_MACOS_UNIVERSAL"
130191
end
131192
132193
on_linux do

scripts/sea-build.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
/**
44
* Build a Node SEA (Single Executable Application) binary for the current platform.
55
*
6-
* Usage: node scripts/sea-build.js [output-name]
6+
* Usage: node scripts/sea-build.js [output-name] [--node-binary <path>]
77
* output-name defaults to ccli-{platform}-{arch} (e.g. ccli-darwin-arm64)
8+
* --node-binary path to the Node binary to use as the SEA shell (defaults to process.execPath)
89
*/
910

1011
const { execFileSync } = require('child_process');
@@ -18,10 +19,26 @@ const DIST = path.join(ROOT, 'dist');
1819
const platform = os.platform(); // darwin | linux | win32
1920
const arch = os.arch(); // arm64 | x64
2021

21-
// Resolve output binary name
22+
// ── Parse arguments ──────────────────────────────────────────────────────────
23+
let outputName = null;
24+
let nodeBinary = null;
25+
26+
const args = process.argv.slice(2);
27+
for (let i = 0; i < args.length; i++) {
28+
if (args[i] === '--node-binary') {
29+
nodeBinary = args[++i];
30+
if (!nodeBinary) {
31+
console.error('Error: --node-binary requires a path argument');
32+
process.exit(1);
33+
}
34+
} else if (!outputName) {
35+
outputName = args[i];
36+
}
37+
}
38+
2239
const platformName = platform === 'darwin' ? 'macos' : platform === 'win32' ? 'win' : platform;
2340
const defaultName = `ccli-${platformName}-${arch}`;
24-
let outputName = process.argv[2] || defaultName;
41+
outputName = outputName || defaultName;
2542

2643
// Ensure Windows binaries have .exe
2744
if (platform === 'win32' && !outputName.endsWith('.exe')) {
@@ -75,11 +92,12 @@ async function main() {
7592

7693
// ── 4. Copy node binary ───────────────────────────────────────────────────
7794
console.log('\n=== Step 4: Copy node binary ===');
78-
fs.copyFileSync(process.execPath, BINARY);
95+
const sourceNode = nodeBinary || process.execPath;
96+
fs.copyFileSync(sourceNode, BINARY);
7997
if (platform !== 'win32') {
8098
fs.chmodSync(BINARY, 0o755);
8199
}
82-
console.log(`Copied ${process.execPath}${BINARY}`);
100+
console.log(`Copied ${sourceNode}${BINARY}`);
83101

84102
// ── 5. Inject blob with postject ──────────────────────────────────────────
85103
console.log('\n=== Step 5: Inject SEA blob ===');

0 commit comments

Comments
 (0)