mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-17 12:56:41 +02:00
1a902b291c
Beta releases no longer trigger unnecessary Winget submissions, and release finalization now completes even when some build artifacts are missing.
165 lines
4.4 KiB
TypeScript
165 lines
4.4 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
import { Buffer } from "node:buffer"
|
|
import { $ } from "bun"
|
|
|
|
const { values } = parseArgs({
|
|
args: Bun.argv.slice(2),
|
|
options: {
|
|
"dry-run": { type: "boolean", default: false },
|
|
},
|
|
})
|
|
|
|
const dryRun = values["dry-run"]
|
|
|
|
import { parseArgs } from "node:util"
|
|
|
|
const repo = process.env.GH_REPO
|
|
if (!repo) throw new Error("GH_REPO is required")
|
|
|
|
const releaseId = process.env.OPENCODE_RELEASE
|
|
if (!releaseId) throw new Error("OPENCODE_RELEASE is required")
|
|
|
|
const version = process.env.OPENCODE_VERSION
|
|
if (!version) throw new Error("OPENCODE_VERSION is required")
|
|
|
|
const token = process.env.GH_TOKEN ?? process.env.GITHUB_TOKEN
|
|
if (!token) throw new Error("GH_TOKEN or GITHUB_TOKEN is required")
|
|
|
|
const apiHeaders = {
|
|
Authorization: `token ${token}`,
|
|
Accept: "application/vnd.github+json",
|
|
}
|
|
|
|
const releaseRes = await fetch(`https://api.github.com/repos/${repo}/releases/${releaseId}`, {
|
|
headers: apiHeaders,
|
|
})
|
|
|
|
if (!releaseRes.ok) {
|
|
throw new Error(`Failed to fetch release: ${releaseRes.status} ${releaseRes.statusText}`)
|
|
}
|
|
|
|
type Asset = {
|
|
name: string
|
|
url: string
|
|
}
|
|
|
|
type Release = {
|
|
tag_name?: string
|
|
assets?: Asset[]
|
|
}
|
|
|
|
const release = (await releaseRes.json()) as Release
|
|
const assets = release.assets ?? []
|
|
const assetByName = new Map(assets.map((asset) => [asset.name, asset]))
|
|
|
|
const latestAsset = assetByName.get("latest.json")
|
|
if (!latestAsset) {
|
|
console.log("latest.json not found, skipping tauri finalization")
|
|
process.exit(0)
|
|
}
|
|
|
|
const latestRes = await fetch(latestAsset.url, {
|
|
headers: {
|
|
Authorization: `token ${token}`,
|
|
Accept: "application/octet-stream",
|
|
},
|
|
})
|
|
|
|
if (!latestRes.ok) {
|
|
throw new Error(`Failed to fetch latest.json: ${latestRes.status} ${latestRes.statusText}`)
|
|
}
|
|
|
|
const latestText = new TextDecoder().decode(await latestRes.arrayBuffer())
|
|
const latest = JSON.parse(latestText)
|
|
const base = { ...latest }
|
|
delete base.platforms
|
|
|
|
const fetchSignature = async (asset: Asset) => {
|
|
const res = await fetch(asset.url, {
|
|
headers: {
|
|
Authorization: `token ${token}`,
|
|
Accept: "application/octet-stream",
|
|
},
|
|
})
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to fetch signature: ${res.status} ${res.statusText}`)
|
|
}
|
|
|
|
return Buffer.from(await res.arrayBuffer()).toString()
|
|
}
|
|
|
|
const entries: Record<string, { url: string; signature: string }> = {}
|
|
const add = (key: string, asset: Asset, signature: string) => {
|
|
if (entries[key]) return
|
|
entries[key] = {
|
|
url: `https://github.com/${repo}/releases/download/v${version}/${asset.name}`,
|
|
signature,
|
|
}
|
|
}
|
|
|
|
const targets = [
|
|
{ key: "linux-x86_64-deb", asset: "opencode-desktop-linux-amd64.deb" },
|
|
{ key: "linux-x86_64-rpm", asset: "opencode-desktop-linux-x86_64.rpm" },
|
|
{ key: "linux-aarch64-deb", asset: "opencode-desktop-linux-arm64.deb" },
|
|
{ key: "linux-aarch64-rpm", asset: "opencode-desktop-linux-aarch64.rpm" },
|
|
{ key: "windows-aarch64-nsis", asset: "opencode-desktop-windows-arm64.exe" },
|
|
{ key: "windows-x86_64-nsis", asset: "opencode-desktop-windows-x64.exe" },
|
|
{ key: "darwin-x86_64-app", asset: "opencode-desktop-darwin-x64.app.tar.gz" },
|
|
{
|
|
key: "darwin-aarch64-app",
|
|
asset: "opencode-desktop-darwin-aarch64.app.tar.gz",
|
|
},
|
|
]
|
|
|
|
for (const target of targets) {
|
|
const asset = assetByName.get(target.asset)
|
|
if (!asset) continue
|
|
|
|
const sig = assetByName.get(`${target.asset}.sig`)
|
|
if (!sig) continue
|
|
|
|
const signature = await fetchSignature(sig)
|
|
add(target.key, asset, signature)
|
|
}
|
|
|
|
const alias = (key: string, source: string) => {
|
|
if (entries[key]) return
|
|
const entry = entries[source]
|
|
if (!entry) return
|
|
entries[key] = entry
|
|
}
|
|
|
|
alias("linux-x86_64", "linux-x86_64-deb")
|
|
alias("linux-aarch64", "linux-aarch64-deb")
|
|
alias("windows-aarch64", "windows-aarch64-nsis")
|
|
alias("windows-x86_64", "windows-x86_64-nsis")
|
|
alias("darwin-x86_64", "darwin-x86_64-app")
|
|
alias("darwin-aarch64", "darwin-aarch64-app")
|
|
|
|
const platforms = Object.fromEntries(
|
|
Object.keys(entries)
|
|
.sort()
|
|
.map((key) => [key, entries[key]]),
|
|
)
|
|
const output = {
|
|
...base,
|
|
platforms,
|
|
}
|
|
|
|
const dir = process.env.RUNNER_TEMP ?? "/tmp"
|
|
const file = `${dir}/latest.json`
|
|
await Bun.write(file, JSON.stringify(output, null, 2))
|
|
|
|
const tag = release.tag_name
|
|
if (!tag) throw new Error("Release tag not found")
|
|
|
|
if (dryRun) {
|
|
console.log(`dry-run: wrote latest.json for ${tag} to ${file}`)
|
|
process.exit(0)
|
|
}
|
|
await $`gh release upload ${tag} ${file} --clobber --repo ${repo}`
|
|
|
|
console.log(`finalized latest.json for ${tag}`)
|