diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f160b417..57f3abb9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -58,6 +58,7 @@ jobs: ./script/publish.ts env: OPENCODE_BUMP: ${{ inputs.bump }} + OPENCODE_TAG: latest GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} AUR_KEY: ${{ secrets.AUR_KEY }} NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 711af3d4..a331462e 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -30,7 +30,5 @@ jobs: run: | ./packages/opencode/script/publish.ts env: - OPENCODE_SNAPSHOT: true - OPENCODE_TAG: ${{ github.ref_name }} GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }} NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/bun.lock b/bun.lock index f76157ca..939802a8 100644 --- a/bun.lock +++ b/bun.lock @@ -4,6 +4,7 @@ "": { "name": "opencode", "dependencies": { + "@opencode-ai/script": "workspace:*", "@opencode-ai/sdk": "workspace:*", }, "devDependencies": { @@ -209,6 +210,7 @@ "@ai-sdk/amazon-bedrock": "2.2.10", "@ai-sdk/google-vertex": "3.0.16", "@octokit/webhooks-types": "7.6.1", + "@opencode-ai/script": "workspace:*", "@parcel/watcher-win32-x64": "2.5.1", "@standard-schema/spec": "1.0.0", "@tsconfig/bun": "catalog:", @@ -233,6 +235,12 @@ "typescript": "catalog:", }, }, + "packages/script": { + "name": "@opencode-ai/script", + "devDependencies": { + "@types/bun": "catalog:", + }, + }, "packages/sdk/js": { "name": "@opencode-ai/sdk", "version": "0.15.2", @@ -830,6 +838,8 @@ "@opencode-ai/plugin": ["@opencode-ai/plugin@workspace:packages/plugin"], + "@opencode-ai/script": ["@opencode-ai/script@workspace:packages/script"], + "@opencode-ai/sdk": ["@opencode-ai/sdk@workspace:packages/sdk/js"], "@opencode-ai/slack": ["@opencode-ai/slack@workspace:packages/slack"], diff --git a/package.json b/package.json index 3da69035..14eec3cf 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "turbo": "2.5.6" }, "dependencies": { - "@opencode-ai/sdk": "workspace:*" + "@opencode-ai/sdk": "workspace:*", + "@opencode-ai/script": "workspace:*" }, "repository": { "type": "git", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index 16f643ed..a5dc4d04 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -28,7 +28,8 @@ "@types/yargs": "17.0.33", "typescript": "catalog:", "vscode-languageserver-types": "3.17.5", - "zod-to-json-schema": "3.24.5" + "zod-to-json-schema": "3.24.5", + "@opencode-ai/script": "workspace:*" }, "dependencies": { "@clack/prompts": "1.0.0-alpha.1", diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts index 4c4bc782..860147f0 100755 --- a/packages/opencode/script/build.ts +++ b/packages/opencode/script/build.ts @@ -5,6 +5,7 @@ process.chdir(dir) import { $ } from "bun" import pkg from "../package.json" +import { Script } from "@opencode-ai/script" const GOARCH: Record = { arm64: "arm64", @@ -25,12 +26,11 @@ const targets = [ await $`rm -rf dist` const binaries: Record = {} -const version = process.env["OPENCODE_VERSION"] ?? "dev" for (const [os, arch] of targets) { console.log(`building ${os}-${arch}`) const name = `${pkg.name}-${os}-${arch}` await $`mkdir -p dist/${name}/bin` - await $`CGO_ENABLED=0 GOOS=${os} GOARCH=${GOARCH[arch]} go build -ldflags="-s -w -X main.Version=${version}" -o ../opencode/dist/${name}/bin/tui ../tui/cmd/opencode/main.go` + await $`CGO_ENABLED=0 GOOS=${os} GOARCH=${GOARCH[arch]} go build -ldflags="-s -w -X main.Version=${Script.version}" -o ../opencode/dist/${name}/bin/tui ../tui/cmd/opencode/main.go` .cwd("../tui") .quiet() @@ -43,12 +43,12 @@ for (const [os, arch] of targets) { compile: { target: `bun-${os}-${arch}` as any, outfile: `dist/${name}/bin/opencode`, - execArgv: [`--user-agent=opencode/${version}`, `--env-file=""`, `--`], + execArgv: [`--user-agent=opencode/${Script.version}`, `--env-file=""`, `--`], windows: {}, }, entrypoints: ["./src/index.ts"], define: { - OPENCODE_VERSION: `'${version}'`, + OPENCODE_VERSION: `'${Script.version}'`, OPENCODE_TUI_PATH: `'../../../dist/${name}/bin/tui'`, }, }) @@ -57,7 +57,7 @@ for (const [os, arch] of targets) { JSON.stringify( { name, - version, + version: Script.version, os: [os === "windows" ? "win32" : os], cpu: [arch], }, @@ -65,7 +65,7 @@ for (const [os, arch] of targets) { 2, ), ) - binaries[name] = version + binaries[name] = Script.version } export { binaries } diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index 948dcf25..e5895635 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -1,20 +1,10 @@ #!/usr/bin/env bun +import { $ } from "bun" +import pkg from "../package.json" +import { Script } from "@opencode-ai/script" + const dir = new URL("..", import.meta.url).pathname process.chdir(dir) -import { $ } from "bun" - -import pkg from "../package.json" - -const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true" -let version = process.env["OPENCODE_VERSION"] -const tag = process.env["OPENCODE_TAG"] ?? (snapshot ? "snapshot" : "latest") -if (!version && snapshot) { - version = `0.0.0-${tag}-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}` - process.env["OPENCODE_VERSION"] = version -} -if (!version) throw new Error("OPENCODE_VERSION is required") - -console.log(`publishing ${version}`) const { binaries } = await import("./build.ts") { @@ -38,7 +28,7 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( preinstall: "node ./preinstall.mjs", postinstall: "node ./postinstall.mjs", }, - version, + version: Script.version, optionalDependencies: binaries, }, null, @@ -46,11 +36,11 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( ), ) for (const [name] of Object.entries(binaries)) { - await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${tag}` + await $`cd dist/${name} && chmod 777 -R . && bun publish --access public --tag ${Script.tag}` } -await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${tag}` +await $`cd ./dist/${pkg.name} && bun publish --access public --tag ${Script.tag}` -if (!snapshot) { +if (!Script.preview) { for (const key of Object.keys(binaries)) { await $`cd dist/${key}/bin && zip -r ../../${key}.zip *` } @@ -67,7 +57,7 @@ if (!snapshot) { "# Maintainer: adam", "", "pkgname='opencode-bin'", - `pkgver=${version.split("-")[0]}`, + `pkgver=${Script.version.split("-")[0]}`, "options=('!debug' '!strip')", "pkgrel=1", "pkgdesc='The AI coding agent built for the terminal.'", @@ -78,10 +68,10 @@ if (!snapshot) { "conflicts=('opencode')", "depends=('fzf' 'ripgrep')", "", - `source_aarch64=("\${pkgname}_\${pkgver}_aarch64.zip::https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-arm64.zip")`, + `source_aarch64=("\${pkgname}_\${pkgver}_aarch64.zip::https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-arm64.zip")`, `sha256sums_aarch64=('${arm64Sha}')`, "", - `source_x86_64=("\${pkgname}_\${pkgver}_x86_64.zip::https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-x64.zip")`, + `source_x86_64=("\${pkgname}_\${pkgver}_x86_64.zip::https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-x64.zip")`, `sha256sums_x86_64=('${x64Sha}')`, "", "package() {", @@ -96,7 +86,7 @@ if (!snapshot) { "# Maintainer: adam", "", "pkgname='opencode'", - `pkgver=${version.split("-")[0]}`, + `pkgver=${Script.version.split("-")[0]}`, "options=('!debug' '!strip')", "pkgrel=1", "pkgdesc='The AI coding agent built for the terminal.'", @@ -108,7 +98,7 @@ if (!snapshot) { "depends=('fzf' 'ripgrep')", "makedepends=('git' 'bun-bin' 'go')", "", - `source=("opencode-\${pkgver}.tar.gz::https://github.com/sst/opencode/archive/v${version}.tar.gz")`, + `source=("opencode-\${pkgver}.tar.gz::https://github.com/sst/opencode/archive/v${Script.version}.tar.gz")`, `sha256sums=('SKIP')`, "", "build() {", @@ -139,7 +129,7 @@ if (!snapshot) { await Bun.file(`./dist/aur-${pkg}/PKGBUILD`).write(pkgbuild) await $`cd ./dist/aur-${pkg} && makepkg --printsrcinfo > .SRCINFO` await $`cd ./dist/aur-${pkg} && git add PKGBUILD .SRCINFO` - await $`cd ./dist/aur-${pkg} && git commit -m "Update to v${version}"` + await $`cd ./dist/aur-${pkg} && git commit -m "Update to v${Script.version}"` await $`cd ./dist/aur-${pkg} && git push` break } catch (e) { @@ -157,11 +147,11 @@ if (!snapshot) { "class Opencode < Formula", ` desc "The AI coding agent built for the terminal."`, ` homepage "https://github.com/sst/opencode"`, - ` version "${version.split("-")[0]}"`, + ` version "${Script.version.split("-")[0]}"`, "", " on_macos do", " if Hardware::CPU.intel?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-darwin-x64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-darwin-x64.zip"`, ` sha256 "${macX64Sha}"`, "", " def install", @@ -169,7 +159,7 @@ if (!snapshot) { " end", " end", " if Hardware::CPU.arm?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-darwin-arm64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-darwin-arm64.zip"`, ` sha256 "${macArm64Sha}"`, "", " def install", @@ -180,14 +170,14 @@ if (!snapshot) { "", " on_linux do", " if Hardware::CPU.intel? and Hardware::CPU.is_64_bit?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-x64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-x64.zip"`, ` sha256 "${x64Sha}"`, " def install", ' bin.install "opencode"', " end", " end", " if Hardware::CPU.arm? and Hardware::CPU.is_64_bit?", - ` url "https://github.com/sst/opencode/releases/download/v${version}/opencode-linux-arm64.zip"`, + ` url "https://github.com/sst/opencode/releases/download/v${Script.version}/opencode-linux-arm64.zip"`, ` sha256 "${arm64Sha}"`, " def install", ' bin.install "opencode"', @@ -203,6 +193,6 @@ if (!snapshot) { await $`git clone https://${process.env["GITHUB_TOKEN"]}@github.com/sst/homebrew-tap.git ./dist/homebrew-tap` await Bun.file("./dist/homebrew-tap/opencode.rb").write(homebrewFormula) await $`cd ./dist/homebrew-tap && git add opencode.rb` - await $`cd ./dist/homebrew-tap && git commit -m "Update to v${version}"` + await $`cd ./dist/homebrew-tap && git commit -m "Update to v${Script.version}"` await $`cd ./dist/homebrew-tap && git push` } diff --git a/packages/script/package.json b/packages/script/package.json new file mode 100644 index 00000000..2791305f --- /dev/null +++ b/packages/script/package.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/package", + "name": "@opencode-ai/script", + "devDependencies": { + "@types/bun": "catalog:" + }, + "exports": { + ".": "./src/index.ts" + } +} diff --git a/packages/script/src/index.ts b/packages/script/src/index.ts new file mode 100644 index 00000000..4237a76a --- /dev/null +++ b/packages/script/src/index.ts @@ -0,0 +1,35 @@ +import { $ } from "bun" + +if (process.versions.bun !== "1.3.0") { + throw new Error("This script requires bun@1.3.0") +} + +const TAG = process.env["OPENCODE_TAG"] ?? (await $`git branch --show-current`.text().then((x) => x.trim())) +const IS_PREVIEW = TAG !== "latest" +const VERSION = await (async () => { + if (IS_PREVIEW) return `0.0.0-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}` + const version = await fetch("https://registry.npmjs.org/opencode-ai/latest") + .then((res) => { + if (!res.ok) throw new Error(res.statusText) + return res.json() + }) + .then((data: any) => data.version) + const [major, minor, patch] = version.split(".").map((x: string) => Number(x) || 0) + const t = process.env["OPENCODE_BUMP"]?.toLowerCase() + if (t === "major") return `${major + 1}.0.0` + if (t === "minor") return `${major}.${minor + 1}.0` + return `${major}.${minor}.${patch + 1}` +})() + +export const Script = { + get tag() { + return TAG + }, + get version() { + return VERSION + }, + get preview() { + return IS_PREVIEW + }, +} +console.log(`opencode script`, JSON.stringify(Script, null, 2)) diff --git a/packages/script/tsconfig.json b/packages/script/tsconfig.json new file mode 100644 index 00000000..00ef1254 --- /dev/null +++ b/packages/script/tsconfig.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@tsconfig/bun/tsconfig.json", + "compilerOptions": { + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "noUncheckedIndexedAccess": false + } +} diff --git a/script/publish.ts b/script/publish.ts index 05d6df22..a4296ec4 100755 --- a/script/publish.ts +++ b/script/publish.ts @@ -2,34 +2,13 @@ import { $ } from "bun" import { createOpencode } from "@opencode-ai/sdk" -if (process.versions.bun !== "1.3.0") { - throw new Error("This script requires bun@1.3.0") -} +import { Script } from "@opencode-ai/script" const notes = [] as string[] console.log("=== publishing ===\n") -const snapshot = process.env["OPENCODE_SNAPSHOT"] === "true" -const version = await (async () => { - if (snapshot) return `0.0.0-${new Date().toISOString().slice(0, 16).replace(/[-:T]/g, "")}` - if (process.env["OPENCODE_VERSION"]) return process.env["OPENCODE_VERSION"] - const npmVersion = await fetch("https://registry.npmjs.org/opencode-ai/latest") - .then((res) => { - if (!res.ok) throw new Error(res.statusText) - return res.json() - }) - .then((data: any) => data.version) - const [major, minor, patch] = npmVersion.split(".").map((x: string) => Number(x) || 0) - const t = process.env["OPENCODE_BUMP"]?.toLowerCase() - if (t === "major") return `${major + 1}.0.0` - if (t === "minor") return `${major}.${minor + 1}.0` - return `${major}.${minor}.${patch + 1}` -})() -process.env["OPENCODE_VERSION"] = version -console.log("version:", version) - -if (!snapshot) { +if (!Script.preview) { const previous = await fetch("https://registry.npmjs.org/opencode-ai/latest") .then((res) => { if (!res.ok) throw new Error(res.statusText) @@ -98,7 +77,7 @@ const pkgjsons = await Array.fromAsync( const tree = await $`git add . && git write-tree`.text().then((x) => x.trim()) for (const file of pkgjsons) { let pkg = await Bun.file(file).text() - pkg = pkg.replaceAll(/"version": "[^"]+"/g, `"version": "${version}"`) + pkg = pkg.replaceAll(/"version": "[^"]+"/g, `"version": "${Script.version}"`) console.log("updated:", file) await Bun.file(file).write(pkg) } @@ -116,22 +95,22 @@ await import(`../packages/plugin/script/publish.ts`) const dir = new URL("..", import.meta.url).pathname process.chdir(dir) -if (!snapshot) { - await $`git commit -am "release: v${version}"` - await $`git tag v${version}` +if (!Script.preview) { + await $`git commit -am "release: v${Script.version}"` + await $`git tag v${Script.version}` await $`git fetch origin` await $`git cherry-pick HEAD..origin/dev`.nothrow() await $`git push origin HEAD --tags --no-verify --force` - await $`gh release create v${version} --title "v${version}" --notes ${notes.join("\n") ?? "No notable changes"} ./packages/opencode/dist/*.zip` + await $`gh release create v${Script.version} --title "v${Script.version}" --notes ${notes.join("\n") ?? "No notable changes"} ./packages/opencode/dist/*.zip` } -if (snapshot) { - await $`git checkout -b snapshot-${version}` - await $`git commit --allow-empty -m "Snapshot release v${version}"` - await $`git tag v${version}` - await $`git push origin v${version} --no-verify` +if (Script.preview) { + await $`git checkout -b snapshot-${Script.version}` + await $`git commit --allow-empty -m "Snapshot release v${Script.version}"` + await $`git tag v${Script.version}` + await $`git push origin v${Script.version} --no-verify` await $`git checkout dev` - await $`git branch -D snapshot-${version}` + await $`git branch -D snapshot-${Script.version}` for (const file of pkgjsons) { await $`git checkout ${tree} ${file}` }