From 74ca560c750b0656374e8d7c1cd11085b7d90ce7 Mon Sep 17 00:00:00 2001 From: Dax Date: Mon, 7 Sep 2026 17:59:39 -0400 Subject: [PATCH] feat(cli): publish stable releases to opencode-bin on AUR (#47856) --- packages/cli/script/publish-aur.ts | 37 ++++++++++++++++++------------ script/publish.ts | 2 +- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/cli/script/publish-aur.ts b/packages/cli/script/publish-aur.ts index b2fc7723225..7157b61e43d 100644 --- a/packages/cli/script/publish-aur.ts +++ b/packages/cli/script/publish-aur.ts @@ -5,19 +5,25 @@ import { mkdir, rm } from "node:fs/promises" import path from "node:path" import { fileURLToPath } from "node:url" -if (Script.channel !== "beta") throw new Error("AUR publishing requires the beta channel") -if (!/^0\.0\.0-beta-\d+(?:\.\d+)?$/.test(Script.version)) throw new Error("Expected a beta release version") +if (Script.channel !== "beta" && Script.channel !== "latest") { + throw new Error("AUR publishing requires the beta or latest channel") +} +const beta = Script.channel === "beta" +const name = beta ? "opencode-beta" : "opencode-bin" +if (!(beta ? /^\d+\.\d+\.\d+-beta[.-]\d+(?:\.\d+)?$/ : /^\d+\.\d+\.\d+$/).test(Script.version)) { + throw new Error(`Expected a ${Script.channel} release version`) +} -const response = await fetch("https://update.opencode.ai/api/beta/cli/npm") -if (!response.ok) throw new Error(`Failed to resolve the beta release: ${response.status}`) +const response = await fetch(`https://update.opencode.ai/api/${Script.channel}/cli/npm`) +if (!response.ok) throw new Error(`Failed to resolve the ${Script.channel} release: ${response.status}`) const release: { version: string; metadata?: { package?: string } } = await response.json() -if (release.version !== Script.version) throw new Error(`The active beta release is ${release.version}`) +if (release.version !== Script.version) throw new Error(`The active ${Script.channel} release is ${release.version}`) if (release.metadata?.package !== "@opencode/cli" && release.metadata?.package !== "@opencode-ai/cli") { - throw new Error("The beta release did not identify a supported CLI package") + throw new Error("The release did not identify a supported CLI package") } const dir = fileURLToPath(new URL("..", import.meta.url)) -const outdir = path.join(dir, "dist", "aur-opencode-beta") +const outdir = path.join(dir, "dist", `aur-${name}`) const dryRun = process.argv.includes("--dry-run") const pkgver = Script.version.replaceAll("-", ".") const scope = release.metadata.package.slice(0, -"/cli".length) @@ -27,7 +33,7 @@ await rm(outdir, { recursive: true, force: true }) await mkdir(path.dirname(outdir), { recursive: true }) if (dryRun) await mkdir(outdir) if (!dryRun) { - await $`git clone ssh://aur@aur.archlinux.org/opencode-beta.git ${outdir}` + await $`git clone ${`ssh://aur@aur.archlinux.org/${name}.git`} ${outdir}` await $`git checkout -B master`.cwd(outdir) } @@ -36,7 +42,7 @@ const sources = await Promise.all( { arch: "x86_64", target: "linux-x64-baseline" }, { arch: "aarch64", target: "linux-arm64" }, ].map(async (item) => { - const filename = `opencode-beta-${pkgver}-${item.arch}.tgz` + const filename = `${name}-${pkgver}-${item.arch}.tgz` const url = `https://registry.npmjs.org/${scope}/cli-${item.target}/-/cli-${item.target}-${Script.version}.tgz` await $`curl --fail --location --retry 5 --retry-all-errors --output ${path.join(outdir, filename)} ${url}` const sha256 = new Bun.CryptoHasher("sha256") @@ -51,16 +57,16 @@ await Bun.write( path.join(outdir, "PKGBUILD"), [ "# Maintainer: Dax ", - "pkgname=opencode-beta", + `pkgname=${name}`, `pkgver=${pkgver}`, "pkgrel=1", - "pkgdesc='OpenCode V2 beta - the AI coding agent for the terminal'", + `pkgdesc='OpenCode${beta ? " V2 beta" : ""} - the AI coding agent for the terminal'`, "url='https://github.com/anomalyco/opencode'", "arch=('x86_64' 'aarch64')", "license=('MIT')", "depends=('glibc' 'gcc-libs' 'ripgrep')", - "provides=('opencode2')", - "conflicts=('opencode2')", + beta ? "provides=('opencode2')" : "provides=('opencode' 'opencode2')", + beta ? "conflicts=('opencode2')" : "conflicts=('opencode' 'opencode2')", // Stripping a compiled Bun executable can damage its embedded application. "options=('!strip' '!debug')", "source=('LICENSE')", @@ -69,13 +75,14 @@ await Bun.write( "", "package() {", ' install -Dm755 "$srcdir/package/bin/opencode2" "$pkgdir/usr/bin/opencode2"', + ...(beta ? [] : [' ln -s opencode2 "$pkgdir/usr/bin/opencode"']), ' install -Dm644 "$srcdir/LICENSE" "$pkgdir/usr/share/licenses/$pkgname/LICENSE"', "}", "", ].join("\n"), ) await Bun.write(path.join(outdir, ".SRCINFO"), await $`makepkg --printsrcinfo`.cwd(outdir).text()) -console.log(`Prepared opencode-beta ${pkgver} in ${outdir}`) +console.log(`Prepared ${name} ${pkgver} in ${outdir}`) if (dryRun) process.exit(0) await $`git add PKGBUILD .SRCINFO LICENSE`.cwd(outdir) @@ -83,5 +90,5 @@ if ((await $`git diff --cached --quiet`.cwd(outdir).nothrow()).exitCode === 0) { console.log("AUR package is already up to date") process.exit(0) } -await $`git commit -m ${`chore: update opencode-beta to ${pkgver}`}`.cwd(outdir) +await $`git commit -m ${`chore: update ${name} to ${pkgver}`}`.cwd(outdir) await $`git push origin master`.cwd(outdir) diff --git a/script/publish.ts b/script/publish.ts index b2385440c86..49e7423fe46 100755 --- a/script/publish.ts +++ b/script/publish.ts @@ -111,7 +111,7 @@ if (Script.release) { }) } -if (Script.channel === "beta" && Script.release) { +if ((Script.channel === "beta" || Script.channel === "latest") && Script.release) { console.log("\n=== AUR ===\n") await $`bun ./packages/cli/script/publish-aur.ts` }