ci: auto-resolve merge conflicts in beta sync using opencode
When merging PRs into the beta branch, the sync script now attempts to automatically resolve merge conflicts using opencode before failing. This reduces manual intervention needed for beta releases when multiple PRs have overlapping changes.
This commit is contained in:
4
.github/workflows/beta.yml
vendored
4
.github/workflows/beta.yml
vendored
@@ -27,7 +27,11 @@ jobs:
|
|||||||
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
|
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
|
||||||
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
|
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
|
||||||
|
|
||||||
|
- name: Install OpenCode
|
||||||
|
run: bun i -g opencode-ai
|
||||||
|
|
||||||
- name: Sync beta branch
|
- name: Sync beta branch
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }}
|
GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }}
|
||||||
|
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
|
||||||
run: bun script/beta.ts
|
run: bun script/beta.ts
|
||||||
|
|||||||
@@ -30,6 +30,52 @@ Please resolve this issue to include this PR in the next beta release.`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function conflicts() {
|
||||||
|
const out = await $`git diff --name-only --diff-filter=U`.text().catch(() => "")
|
||||||
|
return out
|
||||||
|
.split("\n")
|
||||||
|
.map((x) => x.trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function cleanup() {
|
||||||
|
try {
|
||||||
|
await $`git merge --abort`
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
await $`git checkout -- .`
|
||||||
|
} catch {}
|
||||||
|
try {
|
||||||
|
await $`git clean -fd`
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fix(pr: PR, files: string[]) {
|
||||||
|
console.log(` Trying to auto-resolve ${files.length} conflict(s) with opencode...`)
|
||||||
|
const prompt = [
|
||||||
|
`Resolve the current git merge conflicts while merging PR #${pr.number} into the beta branch.`,
|
||||||
|
`Only touch these files: ${files.join(", ")}.`,
|
||||||
|
"Keep the merge in progress, do not abort the merge, and do not create a commit.",
|
||||||
|
"When done, leave the working tree with no unmerged files.",
|
||||||
|
].join("\n")
|
||||||
|
|
||||||
|
try {
|
||||||
|
await $`opencode run ${prompt}`
|
||||||
|
} catch (err) {
|
||||||
|
console.log(` opencode failed: ${err}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const left = await conflicts()
|
||||||
|
if (left.length > 0) {
|
||||||
|
console.log(` Conflicts remain: ${left.join(", ")}`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(" Conflicts resolved with opencode")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
console.log("Fetching open PRs with beta label...")
|
console.log("Fetching open PRs with beta label...")
|
||||||
|
|
||||||
@@ -69,19 +115,22 @@ async function main() {
|
|||||||
try {
|
try {
|
||||||
await $`git merge --no-commit --no-ff pr/${pr.number}`
|
await $`git merge --no-commit --no-ff pr/${pr.number}`
|
||||||
} catch {
|
} catch {
|
||||||
console.log(" Failed to merge (conflicts)")
|
const files = await conflicts()
|
||||||
try {
|
if (files.length > 0) {
|
||||||
await $`git merge --abort`
|
console.log(" Failed to merge (conflicts)")
|
||||||
} catch {}
|
if (!(await fix(pr, files))) {
|
||||||
try {
|
await cleanup()
|
||||||
await $`git checkout -- .`
|
failed.push({ number: pr.number, title: pr.title, reason: "Merge conflicts" })
|
||||||
} catch {}
|
await commentOnPR(pr.number, "Merge conflicts with dev branch")
|
||||||
try {
|
continue
|
||||||
await $`git clean -fd`
|
}
|
||||||
} catch {}
|
} else {
|
||||||
failed.push({ number: pr.number, title: pr.title, reason: "Merge conflicts" })
|
console.log(" Failed to merge")
|
||||||
await commentOnPR(pr.number, "Merge conflicts with dev branch")
|
await cleanup()
|
||||||
continue
|
failed.push({ number: pr.number, title: pr.title, reason: "Merge failed" })
|
||||||
|
await commentOnPR(pr.number, "Merge failed")
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user