desktop: add latest.json finalizer script (#15335)
This commit is contained in:
157
packages/desktop/scripts/finalize-latest-json.ts
Normal file
157
packages/desktop/scripts/finalize-latest-json.ts
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
#!/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 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
|
||||||
|
browser_download_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) throw new Error("latest.json asset not found")
|
||||||
|
|
||||||
|
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: asset.browser_download_url,
|
||||||
|
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-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-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}`)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bun
|
#!/usr/bin/env bun
|
||||||
|
|
||||||
import { $ } from "bun"
|
|
||||||
import { Script } from "@opencode-ai/script"
|
import { Script } from "@opencode-ai/script"
|
||||||
|
import { $ } from "bun"
|
||||||
import { fileURLToPath } from "url"
|
import { fileURLToPath } from "url"
|
||||||
|
|
||||||
const highlightsTemplate = `
|
const highlightsTemplate = `
|
||||||
@@ -67,6 +67,8 @@ if (Script.release) {
|
|||||||
await new Promise((resolve) => setTimeout(resolve, 5_000))
|
await new Promise((resolve) => setTimeout(resolve, 5_000))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await import(`../packages/desktop/scripts/finalize-latest-json.ts`)
|
||||||
|
|
||||||
await $`gh release edit v${Script.version} --draft=false --repo ${process.env.GH_REPO}`
|
await $`gh release edit v${Script.version} --draft=false --repo ${process.env.GH_REPO}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user