fix(release): make publish reruns safe

Reuse the existing draft release and tagged snapshot, skip already-published packages on retry, and sync dev before undrafting so release reruns stop rewriting history and can recover cleanly from partial failures.
This commit is contained in:
Kit Langton
2026-04-17 22:18:33 -04:00
parent f5cb737440
commit c79859be43
5 changed files with 127 additions and 40 deletions
+29 -5
View File
@@ -5,6 +5,33 @@ import { $ } from "bun"
const output = [`version=${Script.version}`]
const sha = process.env.GITHUB_SHA ?? (await $`git rev-parse HEAD`.text()).trim()
const repo = process.env.GH_REPO
async function releaseView() {
if (repo) return await $`gh release view v${Script.version} --json tagName,databaseId --repo ${repo}`.json()
return await $`gh release view v${Script.version} --json tagName,databaseId`.json()
}
async function ensureRelease(notesFile?: string) {
const existing = repo
? await $`gh release view v${Script.version} --json tagName,databaseId --repo ${repo}`.nothrow()
: await $`gh release view v${Script.version} --json tagName,databaseId`.nothrow()
if (existing.exitCode === 0) return await releaseView()
if (notesFile) {
if (repo) {
await $`gh release create v${Script.version} -d --target ${sha} --title "v${Script.version}" --notes-file ${notesFile} --repo ${repo}`
return await releaseView()
}
await $`gh release create v${Script.version} -d --target ${sha} --title "v${Script.version}" --notes-file ${notesFile}`
return await releaseView()
}
if (repo) {
await $`gh release create v${Script.version} -d --target ${sha} --title "v${Script.version}" --repo ${repo}`
return await releaseView()
}
await $`gh release create v${Script.version} -d --target ${sha} --title "v${Script.version}"`
return await releaseView()
}
if (!Script.preview) {
await $`bun script/changelog.ts --to ${sha}`.cwd(process.cwd())
@@ -15,14 +42,11 @@ if (!Script.preview) {
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()
const release = await ensureRelease(notesFile)
output.push(`release=${release.databaseId}`)
output.push(`tag=${release.tagName}`)
} else if (Script.channel === "beta") {
await $`gh release create v${Script.version} -d --target ${sha} --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()
const release = await ensureRelease()
output.push(`release=${release.databaseId}`)
output.push(`tag=${release.tagName}`)
}