mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-25 06:35:35 +00:00
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:
parent
f5cb737440
commit
c79859be43
5 changed files with 127 additions and 40 deletions
|
|
@ -6,6 +6,9 @@ import { fileURLToPath } from "url"
|
|||
|
||||
console.log("=== publishing ===\n")
|
||||
|
||||
const tag = `v${Script.version}`
|
||||
const release_commit = `release: ${tag}`
|
||||
|
||||
const pkgjsons = await Array.fromAsync(
|
||||
new Bun.Glob("**/package.json").scan({
|
||||
absolute: true,
|
||||
|
|
@ -14,6 +17,16 @@ const pkgjsons = await Array.fromAsync(
|
|||
|
||||
const extensionToml = fileURLToPath(new URL("../packages/extensions/zed/extension.toml", import.meta.url))
|
||||
|
||||
async function hasChanges() {
|
||||
return (await $`git diff --quiet && git diff --cached --quiet`.nothrow()).exitCode !== 0
|
||||
}
|
||||
|
||||
async function releaseTagReady() {
|
||||
const ref = await $`git rev-parse -q --verify refs/tags/${tag}`.nothrow()
|
||||
if (ref.exitCode !== 0) return false
|
||||
return (await $`git log -1 --format=%s refs/tags/${tag}`.text()).trim() === release_commit
|
||||
}
|
||||
|
||||
async function prepareReleaseFiles() {
|
||||
for (const file of pkgjsons) {
|
||||
let pkg = await Bun.file(file).text()
|
||||
|
|
@ -32,21 +45,24 @@ async function prepareReleaseFiles() {
|
|||
await $`./packages/sdk/js/script/build.ts`
|
||||
}
|
||||
|
||||
if (Script.release && !Script.preview) {
|
||||
await $`git fetch origin --tags`
|
||||
if (await releaseTagReady()) await $`git switch --detach refs/tags/${tag}`
|
||||
else await $`git switch --detach`
|
||||
}
|
||||
|
||||
await prepareReleaseFiles()
|
||||
|
||||
if (Script.release) {
|
||||
if (!Script.preview) {
|
||||
await $`git switch --detach`
|
||||
await $`git commit -am "release: v${Script.version}"`
|
||||
await $`git tag -f v${Script.version}`
|
||||
await $`git push origin refs/tags/v${Script.version} --force --no-verify`
|
||||
if (Script.release && !Script.preview && !(await releaseTagReady())) {
|
||||
await $`git commit -am ${release_commit}`
|
||||
if ((await $`git rev-parse -q --verify refs/tags/${tag}`.nothrow()).exitCode === 0) {
|
||||
await $`git tag -f ${tag}`
|
||||
await $`git push origin refs/tags/${tag} --force --no-verify`
|
||||
} else {
|
||||
await $`git tag ${tag}`
|
||||
await $`git push origin refs/tags/${tag} --no-verify`
|
||||
await new Promise((resolve) => setTimeout(resolve, 5_000))
|
||||
}
|
||||
|
||||
await import(`../packages/desktop/scripts/finalize-latest-json.ts`)
|
||||
await import(`../packages/desktop-electron/scripts/finalize-latest-yml.ts`)
|
||||
|
||||
await $`gh release edit v${Script.version} --draft=false --repo ${process.env.GH_REPO}`
|
||||
}
|
||||
|
||||
console.log("\n=== cli ===\n")
|
||||
|
|
@ -58,12 +74,25 @@ await import(`../packages/sdk/js/script/publish.ts`)
|
|||
console.log("\n=== plugin ===\n")
|
||||
await import(`../packages/plugin/script/publish.ts`)
|
||||
|
||||
if (Script.release) {
|
||||
await import(`../packages/desktop/scripts/finalize-latest-json.ts`)
|
||||
await import(`../packages/desktop-electron/scripts/finalize-latest-yml.ts`)
|
||||
}
|
||||
|
||||
if (Script.release && !Script.preview) {
|
||||
await $`git fetch origin`
|
||||
await $`git checkout -B dev origin/dev`
|
||||
await prepareReleaseFiles()
|
||||
await $`git commit -am "sync release versions for v${Script.version}"`
|
||||
await $`git push origin HEAD:dev --no-verify`
|
||||
if (await hasChanges()) {
|
||||
await $`git commit -am "sync release versions for v${Script.version}"`
|
||||
await $`git push origin HEAD:dev --no-verify`
|
||||
} else {
|
||||
console.log(`dev already synced for ${tag}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (Script.release) {
|
||||
await $`gh release edit ${tag} --draft=false --repo ${process.env.GH_REPO}`
|
||||
}
|
||||
|
||||
const dir = fileURLToPath(new URL("..", import.meta.url))
|
||||
|
|
|
|||
|
|
@ -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}`)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue