summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2026-02-24 23:17:31 -0500
committerDax Raad <[email protected]>2026-02-24 23:17:31 -0500
commita487f11a30981f44896ac771f7ade87fba9d6092 (patch)
treea02b5992af4474a7f195190a8f206c7e8c21c9dd
parent637059a515a6afd983a8a615f90650d997a821ce (diff)
downloadopencode-a487f11a30981f44896ac771f7ade87fba9d6092.tar.gz
opencode-a487f11a30981f44896ac771f7ade87fba9d6092.zip
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.
-rw-r--r--.github/workflows/beta.yml4
-rwxr-xr-xscript/beta.ts75
2 files changed, 66 insertions, 13 deletions
diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml
index 20d2bc18d..a7106667b 100644
--- a/.github/workflows/beta.yml
+++ b/.github/workflows/beta.yml
@@ -27,7 +27,11 @@ jobs:
opencode-app-id: ${{ vars.OPENCODE_APP_ID }}
opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }}
+ - name: Install OpenCode
+ run: bun i -g opencode-ai
+
- name: Sync beta branch
env:
GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }}
+ OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
run: bun script/beta.ts
diff --git a/script/beta.ts b/script/beta.ts
index a5fb027e6..fbb121409 100755
--- a/script/beta.ts
+++ b/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() {
console.log("Fetching open PRs with beta label...")
@@ -69,19 +115,22 @@ async function main() {
try {
await $`git merge --no-commit --no-ff pr/${pr.number}`
} catch {
- console.log(" Failed to merge (conflicts)")
- try {
- await $`git merge --abort`
- } catch {}
- try {
- await $`git checkout -- .`
- } catch {}
- try {
- await $`git clean -fd`
- } catch {}
- failed.push({ number: pr.number, title: pr.title, reason: "Merge conflicts" })
- await commentOnPR(pr.number, "Merge conflicts with dev branch")
- continue
+ const files = await conflicts()
+ if (files.length > 0) {
+ console.log(" Failed to merge (conflicts)")
+ if (!(await fix(pr, files))) {
+ await cleanup()
+ failed.push({ number: pr.number, title: pr.title, reason: "Merge conflicts" })
+ await commentOnPR(pr.number, "Merge conflicts with dev branch")
+ continue
+ }
+ } else {
+ console.log(" Failed to merge")
+ await cleanup()
+ failed.push({ number: pr.number, title: pr.title, reason: "Merge failed" })
+ await commentOnPR(pr.number, "Merge failed")
+ continue
+ }
}
try {