diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0ce8621ef72..dbb13829459 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -195,9 +195,33 @@ jobs: path: packages/cli/dist/cli-* if-no-files-found: error - build-node-cli: + build-node-app-archive: needs: version - if: github.repository == 'anomalyco/opencode' && false # Temporarily disabled + runs-on: blacksmith-4vcpu-ubuntu-2404 + timeout-minutes: 30 + if: github.repository == 'anomalyco/opencode' + steps: + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + + - uses: ./.github/actions/setup-bun + + - name: Build app archive + run: bun packages/cli/script/build-node.ts --app-archive-only --app-archive=.cache/app-archive.bin --skip-install + env: + OPENCODE_VERSION: ${{ needs.version.outputs.version }} + OPENCODE_RELEASE: ${{ needs.version.outputs.release }} + + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: opencode-node-app-archive + path: packages/cli/.cache/app-archive.bin + if-no-files-found: error + + build-node-cli: + needs: + - version + - build-node-app-archive + if: github.repository == 'anomalyco/opencode' strategy: fail-fast: false matrix: @@ -227,8 +251,13 @@ jobs: with: node-version: "26.4.0" + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: opencode-node-app-archive + path: packages/cli/.cache + - name: Build - run: bun packages/cli/script/build-node.ts --target=${{ matrix.settings.target }} --skip-install --outdir=dist/node + run: bun packages/cli/script/build-node.ts --target=${{ matrix.settings.target }} --skip-install --outdir=dist/node --app-archive=.cache/app-archive.bin env: OPENCODE_VERSION: ${{ needs.version.outputs.version }} OPENCODE_RELEASE: ${{ needs.version.outputs.release }} @@ -543,6 +572,7 @@ jobs: - version - build-cli - sign-cli-macos + - build-node-app-archive - build-node-cli - sign-cli-windows - build-electron diff --git a/packages/cli/script/build-node.ts b/packages/cli/script/build-node.ts index 294e567d661..e283199d817 100644 --- a/packages/cli/script/build-node.ts +++ b/packages/cli/script/build-node.ts @@ -27,6 +27,9 @@ if (outdir === path.join(dir, "dist-node")) { const bundleOnly = process.argv.includes("--bundle-only") const single = process.argv.includes("--single") const skipInstall = process.argv.includes("--skip-install") +const appArchiveOnly = process.argv.includes("--app-archive-only") +const requestedArchive = process.argv.find((arg) => arg.startsWith("--app-archive="))?.slice("--app-archive=".length) +const archivePath = requestedArchive ? path.resolve(dir, requestedArchive) : undefined const requested = process.argv.find((arg) => arg.startsWith("--target="))?.slice("--target=".length) const allTargets = [ nodeTarget("linux", "arm64"), @@ -41,6 +44,14 @@ const targets = requested ? [nodeTarget(process.platform, process.arch)] : allTargets +process.chdir(dir) +if (!skipInstall) run(process.execPath, ["install", "--os=*", "--cpu=*"]) +if (appArchiveOnly) { + if (!archivePath) throw new Error("--app-archive-only requires --app-archive=") + await mkdir(path.dirname(archivePath), { recursive: true }) + await writeFile(archivePath, await buildAppArchive(Script.channel)) + process.exit(0) +} if (targets.length === 0) { if (requested === "darwin-x64") throw new Error("Node 26.4 SEA does not support macOS x64") throw new Error(`Unknown Node target: ${requested}`) @@ -48,15 +59,12 @@ if (targets.length === 0) { if (!bundleOnly && targets.some((target) => target.platform === "darwin" && target.arch === "x64")) { throw new Error("Node 26.4 SEA does not support macOS x64") } - -process.chdir(dir) -if (!skipInstall) run(process.execPath, ["install", "--os=*", "--cpu=*"]) +const appArchive = archivePath ? (await Bun.file(archivePath).text()).trim() : await buildAppArchive(Script.channel) if (!bundleOnly) await rm(outdir, { recursive: true, force: true }) const builder = !bundleOnly || targets.some((target) => target.platform === process.platform && target.arch === process.arch) ? await resolveHostNode() : undefined -const appArchive = await buildAppArchive(Script.channel) // Vite silently rewrites text imports of known asset types (.txt) to asset // URL strings when the raw-text plugin doesn't intercept them first — the