chore(release): publish beta to GitHub

This commit is contained in:
Brendonovich
2026-09-17 06:19:46 +00:00
committed by opencode-agent[bot]
Unverified
parent f28d1b44e3
commit 218534d936
2 changed files with 72 additions and 15 deletions
+51 -12
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env bun
import { Script } from "@opencode/script"
import { $ } from "bun"
import path from "node:path"
import { UpdateArtifact } from "../../../script/update-artifact"
const dryRun = process.argv.includes("--dry-run")
@@ -8,8 +10,11 @@ if (!Script.release) {
console.log("skipped desktop publication without a release")
process.exit(0)
}
const repo = process.env.GH_REPO
if (!repo) throw new Error("GH_REPO is required")
const directory = process.env.OPENCODE_DESKTOP_DIST
if (!directory) throw new Error("OPENCODE_DESKTOP_DIST is required")
const tag = `v${Script.version}`
const files = (
await Array.fromAsync(
new Bun.Glob("*.{exe,blockmap,dmg,zip,AppImage,deb,rpm,app.tar.gz}").scan({ cwd: directory, absolute: true }),
@@ -17,16 +22,24 @@ const files = (
).sort()
if (!files.length) throw new Error("No desktop release files found")
const uploaded = await UpdateArtifact.upload({ version: Script.version, files, dryRun })
const artifact = {
channel: Script.channel,
name: "desktop",
distribution: "opencode",
version: Script.version,
metadata: { files: uploaded, ...(await metadata(Script.version, uploaded)) },
if (!dryRun) {
await $`gh release upload ${tag} ${files} --clobber --repo ${repo}`
await $`bun ${path.join(import.meta.dir, "finalize-latest-json.ts")}`
await $`bun ${path.join(import.meta.dir, "finalize-latest-yml.ts")}`
}
const uploaded = await UpdateArtifact.upload({ version: Script.version, files, dryRun })
const artifacts = [
{ distribution: "github", metadata: await githubMetadata(Script.version, repo) },
{ distribution: "opencode", metadata: { files: uploaded, ...(await metadata(Script.version, uploaded)) } },
]
if (!dryRun) await $`gh release edit ${tag} --draft=false --repo ${repo}`
for (const artifact of artifacts) {
const input = { ...artifact, channel: Script.channel, name: "desktop", version: Script.version }
if (dryRun) console.log(`dry-run artifact: ${JSON.stringify(input)}`)
if (!dryRun) await UpdateArtifact.publish(input)
}
if (dryRun) console.log(`dry-run artifact: ${JSON.stringify(artifact)}`)
if (!dryRun) await UpdateArtifact.publish(artifact)
type DesktopFile = {
url: string
@@ -35,6 +48,32 @@ type DesktopFile = {
blockMapSize?: number
}
async function githubMetadata(version: string, repo: string) {
const directory = process.env.RUNNER_TEMP ?? "/tmp"
const entries = await Promise.all(
[
["desktop.yml", "latest.yml"],
["desktop-mac.yml", "latest-mac.yml"],
["desktop-linux.yml", "latest-linux.yml"],
["desktop-linux-arm64.yml", "latest-linux-arm64.yml"],
].map(async ([name, source]) => {
const file = Bun.file(`${directory}/${source}`)
if (!(await file.exists())) return undefined
return [
name,
parse(
await file.text(),
version,
(filename) => `https://github.com/${repo}/releases/download/v${version}/${encodeURIComponent(filename)}`,
),
] as const
}),
)
const manifests = Object.fromEntries(entries.filter((entry) => entry !== undefined))
if (!Object.keys(manifests).length) throw new Error("No desktop update metadata found")
return { manifests }
}
async function metadata(version: string, files: Record<string, { url: string }>) {
const directory = process.env.LATEST_YML_DIR
if (!directory) throw new Error("LATEST_YML_DIR is required")
@@ -65,7 +104,7 @@ async function metadata(version: string, files: Record<string, { url: string }>)
item.sources.map(async ([subdirectory, source]) => {
const file = Bun.file(`${directory}/${subdirectory}/${source}`)
if (!(await file.exists())) return undefined
return parse(await file.text(), version, files)
return parse(await file.text(), version, (filename) => files[filename]?.url)
}),
)
).filter((manifest) => manifest !== undefined)
@@ -81,7 +120,7 @@ async function metadata(version: string, files: Record<string, { url: string }>)
return { manifests }
}
function parse(content: string, version: string, uploaded: Record<string, { url: string }>) {
function parse(content: string, version: string, resolve: (filename: string) => string | undefined) {
const lines = content.split("\n")
const found = lines
.find((line) => line.startsWith("version:"))
@@ -100,7 +139,7 @@ function parse(content: string, version: string, uploaded: Record<string, { url:
if (value.startsWith("- url:")) {
const name = value.slice("- url:".length).trim()
const filename = name.startsWith("http") ? decodeURIComponent(new URL(name).pathname.split("/").pop()!) : name
const url = uploaded[filename]?.url
const url = resolve(filename)
if (!url) throw new Error(`Desktop update file was not uploaded: ${filename}`)
files.push({ url, sha512: "", size: 0 })
return
+21 -3
View File
@@ -1,12 +1,30 @@
#!/usr/bin/env bun
import { Script } from "@opencode/script"
import { $ } from "bun"
const output = [`version=${Script.version}`]
const sha = process.env.GITHUB_SHA ?? (await $`git rev-parse HEAD`.text()).trim()
if (!Script.preview || Script.channel === "beta") {
output.push("release=true")
output.push(`tag=v${Script.version}`)
if (!Script.preview) {
await $`bun script/changelog.ts --to ${sha}`.cwd(process.cwd())
const file = `${process.cwd()}/UPCOMING_CHANGELOG.md`
const body = await Bun.file(file)
.text()
.catch(() => "No notable changes")
const dir = process.env.RUNNER_TEMP ?? "/tmp"
const notesFile = `${dir}/opencode-release-notes.txt`
await Bun.write(notesFile, body)
await $`gh release create v${Script.version} -d --target ${sha} --title "v${Script.version}" --notes-file ${notesFile}`
const release = await $`gh release view v${Script.version} --json tagName,databaseId`.json()
output.push(`release=${release.databaseId}`)
output.push(`tag=${release.tagName}`)
} else if (Script.channel === "beta") {
await $`gh release create v${Script.version} -d --title "v${Script.version}" --repo ${process.env.GH_REPO}`
const release =
await $`gh release view v${Script.version} --json tagName,databaseId --repo ${process.env.GH_REPO}`.json()
output.push(`release=${release.databaseId}`)
output.push(`tag=${release.tagName}`)
}
output.push(`repo=${process.env.GH_REPO}`)