From abb87eac8f9a795ead817a062c3f614c315faf05 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:08:28 -0500 Subject: [PATCH 01/16] ci --- .github/workflows/beta.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index f7180ea1ee..b941311d30 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -23,12 +23,14 @@ jobs: - name: Setup Bun uses: ./.github/actions/setup-bun - - name: Configure Git - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" + - name: Setup Git Committer + id: setup-git-committer + uses: ./.github/actions/setup-git-committer + with: + opencode-app-id: ${{ secrets.OPENCODE_APP_ID }} + opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - name: Sync beta branch env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }} run: bun script/beta.ts From ad5d495b2c360a7368671899268406b0a50a5220 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:09:27 -0500 Subject: [PATCH 02/16] ci --- .github/workflows/beta.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index b941311d30..f7ad115a29 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -27,7 +27,7 @@ jobs: id: setup-git-committer uses: ./.github/actions/setup-git-committer with: - opencode-app-id: ${{ secrets.OPENCODE_APP_ID }} + opencode-app-id: ${{ vars.OPENCODE_APP_ID }} opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - name: Sync beta branch From 5e823fd20872cef9aee1eb791abdd94666b7e74c Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:11:05 -0500 Subject: [PATCH 03/16] ci --- script/beta.ts | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index eb61540fe7..ff511d9286 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -49,24 +49,8 @@ async function main() { continue } - // Try to rebase onto current beta branch - console.log(` Attempting to rebase PR #${pr.number}...`) - const rebase = await $`git rebase beta pr-${pr.number}`.nothrow() - if (rebase.exitCode !== 0) { - console.log(` Rebase failed for PR #${pr.number} (has conflicts)`) - await $`git rebase --abort`.nothrow() - await $`git checkout beta`.nothrow() - skipped.push({ number: pr.number, reason: "Rebase failed (conflicts)" }) - continue - } - - // Move rebased commits to pr-${pr.number} branch and checkout back to beta - await $`git checkout -B pr-${pr.number}`.nothrow() - await $`git checkout beta`.nothrow() - - console.log(` Successfully rebased PR #${pr.number}`) - - // Now squash merge the rebased PR + // Try to squash merge the PR directly + console.log(` Attempting to merge PR #${pr.number}...`) const merge = await $`git merge --squash pr-${pr.number}`.nothrow() if (merge.exitCode !== 0) { console.log(` Squash merge failed for PR #${pr.number}`) From 4a4fc48ee8ee193c73c0be143a06c00c01ba5902 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:12:29 -0500 Subject: [PATCH 04/16] ci --- script/beta.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index ff511d9286..7884fd2483 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -49,9 +49,9 @@ async function main() { continue } - // Try to squash merge the PR directly + // Try to squash merge the PR directly (allow unrelated histories since beta starts fresh from dev) console.log(` Attempting to merge PR #${pr.number}...`) - const merge = await $`git merge --squash pr-${pr.number}`.nothrow() + const merge = await $`git merge --squash --allow-unrelated-histories pr-${pr.number}`.nothrow() if (merge.exitCode !== 0) { console.log(` Squash merge failed for PR #${pr.number}`) console.log(` Error: ${merge.stderr}`) From 0a0b54aa4b3ea20f45652bfc9d982922584e8448 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:15:45 -0500 Subject: [PATCH 05/16] ci --- script/beta.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/beta.ts b/script/beta.ts index 7884fd2483..a1a07ce9ab 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -100,7 +100,7 @@ async function main() { skipped.forEach((x) => console.log(` - PR #${x.number}: ${x.reason}`)) console.log("\nForce pushing beta branch...") - const push = await $`git push origin beta --force`.nothrow() + const push = await $`git push origin beta --force --no-verify`.nothrow() if (push.exitCode !== 0) { throw new Error(`Failed to push beta branch: ${push.stderr}`) } From 0d53f34c43a6e6f09a734e91b13332bcad9499da Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:20:49 -0500 Subject: [PATCH 06/16] ci --- script/beta.ts | 53 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index a1a07ce9ab..2318ad68e1 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -49,33 +49,50 @@ async function main() { continue } - // Try to squash merge the PR directly (allow unrelated histories since beta starts fresh from dev) - console.log(` Attempting to merge PR #${pr.number}...`) - const merge = await $`git merge --squash --allow-unrelated-histories pr-${pr.number}`.nothrow() - if (merge.exitCode !== 0) { - console.log(` Squash merge failed for PR #${pr.number}`) - console.log(` Error: ${merge.stderr}`) - await $`git reset --hard HEAD`.nothrow() - skipped.push({ number: pr.number, reason: `Squash merge failed: ${merge.stderr}` }) + // Get diff from PR base to PR head and apply it + console.log(` Getting diff for PR #${pr.number}...`) + const diff = await $`git diff HEAD...pr-${pr.number}`.nothrow() + if (diff.exitCode !== 0) { + console.log(` Failed to get diff for PR #${pr.number}`) + console.log(` Error: ${diff.stderr}`) + skipped.push({ number: pr.number, reason: `Failed to get diff: ${diff.stderr}` }) continue } + if (!diff.stdout.trim()) { + console.log(` No changes in PR #${pr.number}, skipping`) + skipped.push({ number: pr.number, reason: "No changes" }) + continue + } + + // Apply the diff + console.log(` Applying diff for PR #${pr.number}...`) + const apply = await Bun.spawn(["git", "apply"], { + stdin: new TextEncoder().encode(diff.stdout), + stdout: "pipe", + stderr: "pipe", + }) + const applyExit = await apply.exited + const applyStderr = await Bun.readableStreamToText(apply.stderr) + + if (applyExit !== 0) { + console.log(` Failed to apply diff for PR #${pr.number}`) + console.log(` Error: ${applyStderr}`) + await $`git checkout -- .`.nothrow() + skipped.push({ number: pr.number, reason: `Failed to apply diff: ${applyStderr}` }) + continue + } + + // Stage all changes const add = await $`git add -A`.nothrow() if (add.exitCode !== 0) { console.log(` Failed to stage changes for PR #${pr.number}`) - await $`git reset --hard HEAD`.nothrow() + await $`git checkout -- .`.nothrow() skipped.push({ number: pr.number, reason: "Failed to stage" }) continue } - const status = await $`git status --porcelain`.nothrow() - if (status.exitCode !== 0 || !status.stdout.trim()) { - console.log(` No changes to commit for PR #${pr.number}, skipping`) - await $`git reset --hard HEAD`.nothrow() - skipped.push({ number: pr.number, reason: "No changes to commit" }) - continue - } - + // Commit const commitMsg = `Apply PR #${pr.number}: ${pr.title}` const commit = await Bun.spawn(["git", "commit", "-m", commitMsg], { stdout: "pipe", stderr: "pipe" }) const commitExit = await commit.exited @@ -84,7 +101,7 @@ async function main() { if (commitExit !== 0) { console.log(` Failed to commit PR #${pr.number}`) console.log(` Error: ${commitStderr}`) - await $`git reset --hard HEAD`.nothrow() + await $`git checkout -- .`.nothrow() skipped.push({ number: pr.number, reason: `Commit failed: ${commitStderr}` }) continue } From b9e9c8c76397b6ed2b710c67499170f9951f5e0f Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:21:47 -0500 Subject: [PATCH 07/16] ci --- script/beta.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index 2318ad68e1..19b2f45640 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -49,9 +49,9 @@ async function main() { continue } - // Get diff from PR base to PR head and apply it + // Get diff from dev to PR head (PR's changes) console.log(` Getting diff for PR #${pr.number}...`) - const diff = await $`git diff HEAD...pr-${pr.number}`.nothrow() + const diff = await $`git diff dev..pr-${pr.number}`.nothrow() if (diff.exitCode !== 0) { console.log(` Failed to get diff for PR #${pr.number}`) console.log(` Error: ${diff.stderr}`) From 3f57f4913d8e6be835872bbbd42c167714103af7 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:23:19 -0500 Subject: [PATCH 08/16] ci --- script/beta.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index 19b2f45640..401ca79901 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -49,9 +49,18 @@ async function main() { continue } - // Get diff from dev to PR head (PR's changes) + // Find merge base and get diff from base to PR head (just the PR's changes) + console.log(` Finding merge base for PR #${pr.number}...`) + const mergeBaseResult = await $`git merge-base dev pr-${pr.number}`.nothrow() + if (mergeBaseResult.exitCode !== 0 || !mergeBaseResult.stdout.trim()) { + console.log(` Failed to find merge base for PR #${pr.number}`) + skipped.push({ number: pr.number, reason: "Failed to find merge base" }) + continue + } + const mergeBase = mergeBaseResult.stdout.trim() + console.log(` Getting diff for PR #${pr.number}...`) - const diff = await $`git diff dev..pr-${pr.number}`.nothrow() + const diff = await $`git diff ${mergeBase}..pr-${pr.number}`.nothrow() if (diff.exitCode !== 0) { console.log(` Failed to get diff for PR #${pr.number}`) console.log(` Error: ${diff.stderr}`) From e0b60d9f34e411ff495c4fd9891a6d92d6bb8ad8 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:25:10 -0500 Subject: [PATCH 09/16] ci --- script/beta.ts | 82 +++++++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 55 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index 401ca79901..7f51ff7936 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -2,26 +2,19 @@ interface PR { number: number - headRefName: string - headRefOid: string - createdAt: string - isDraft: boolean title: string } async function main() { console.log("Fetching open contributor PRs...") - const prsResult = - await $`gh pr list --label contributor --state open --json number,headRefName,headRefOid,createdAt,isDraft,title --limit 100`.nothrow() + const prsResult = await $`gh pr list --label contributor --state open --json number,title --limit 100`.nothrow() if (prsResult.exitCode !== 0) { throw new Error(`Failed to fetch PRs: ${prsResult.stderr}`) } - const allPRs: PR[] = JSON.parse(prsResult.stdout) - const prs = allPRs.filter((pr) => !pr.isDraft) - - console.log(`Found ${prs.length} open non-draft contributor PRs`) + const prs: PR[] = JSON.parse(prsResult.stdout) + console.log(`Found ${prs.length} open contributor PRs`) console.log("Fetching latest dev branch...") const fetchDev = await $`git fetch origin dev`.nothrow() @@ -41,43 +34,25 @@ async function main() { for (const pr of prs) { console.log(`\nProcessing PR #${pr.number}: ${pr.title}`) - // Fetch the PR - const fetchPR = await $`git fetch origin pull/${pr.number}/head:pr-${pr.number}`.nothrow() - if (fetchPR.exitCode !== 0) { - console.log(` Failed to fetch PR #${pr.number}, skipping`) - skipped.push({ number: pr.number, reason: "Failed to fetch" }) + // Get the diff from GitHub + console.log(` Getting diff...`) + const diffResult = await $`gh pr diff ${pr.number}`.nothrow() + if (diffResult.exitCode !== 0) { + console.log(` Failed to get diff`) + skipped.push({ number: pr.number, reason: `Failed to get diff: ${diffResult.stderr}` }) continue } - // Find merge base and get diff from base to PR head (just the PR's changes) - console.log(` Finding merge base for PR #${pr.number}...`) - const mergeBaseResult = await $`git merge-base dev pr-${pr.number}`.nothrow() - if (mergeBaseResult.exitCode !== 0 || !mergeBaseResult.stdout.trim()) { - console.log(` Failed to find merge base for PR #${pr.number}`) - skipped.push({ number: pr.number, reason: "Failed to find merge base" }) - continue - } - const mergeBase = mergeBaseResult.stdout.trim() - - console.log(` Getting diff for PR #${pr.number}...`) - const diff = await $`git diff ${mergeBase}..pr-${pr.number}`.nothrow() - if (diff.exitCode !== 0) { - console.log(` Failed to get diff for PR #${pr.number}`) - console.log(` Error: ${diff.stderr}`) - skipped.push({ number: pr.number, reason: `Failed to get diff: ${diff.stderr}` }) - continue - } - - if (!diff.stdout.trim()) { - console.log(` No changes in PR #${pr.number}, skipping`) + if (!diffResult.stdout.trim()) { + console.log(` No changes, skipping`) skipped.push({ number: pr.number, reason: "No changes" }) continue } - // Apply the diff - console.log(` Applying diff for PR #${pr.number}...`) - const apply = await Bun.spawn(["git", "apply"], { - stdin: new TextEncoder().encode(diff.stdout), + // Try to apply the diff + console.log(` Applying...`) + const apply = await Bun.spawn(["git", "apply", "--3way"], { + stdin: new TextEncoder().encode(diffResult.stdout), stdout: "pipe", stderr: "pipe", }) @@ -85,37 +60,34 @@ async function main() { const applyStderr = await Bun.readableStreamToText(apply.stderr) if (applyExit !== 0) { - console.log(` Failed to apply diff for PR #${pr.number}`) - console.log(` Error: ${applyStderr}`) + console.log(` Failed to apply (conflicts)`) await $`git checkout -- .`.nothrow() - skipped.push({ number: pr.number, reason: `Failed to apply diff: ${applyStderr}` }) + await $`git clean -fd`.nothrow() + skipped.push({ number: pr.number, reason: "Has conflicts" }) continue } - // Stage all changes + // Stage and commit const add = await $`git add -A`.nothrow() if (add.exitCode !== 0) { - console.log(` Failed to stage changes for PR #${pr.number}`) + console.log(` Failed to stage`) await $`git checkout -- .`.nothrow() + await $`git clean -fd`.nothrow() skipped.push({ number: pr.number, reason: "Failed to stage" }) continue } - // Commit const commitMsg = `Apply PR #${pr.number}: ${pr.title}` - const commit = await Bun.spawn(["git", "commit", "-m", commitMsg], { stdout: "pipe", stderr: "pipe" }) - const commitExit = await commit.exited - const commitStderr = await Bun.readableStreamToText(commit.stderr) - - if (commitExit !== 0) { - console.log(` Failed to commit PR #${pr.number}`) - console.log(` Error: ${commitStderr}`) + const commit = await $`git commit -m ${commitMsg}`.nothrow() + if (commit.exitCode !== 0) { + console.log(` Failed to commit`) await $`git checkout -- .`.nothrow() - skipped.push({ number: pr.number, reason: `Commit failed: ${commitStderr}` }) + await $`git clean -fd`.nothrow() + skipped.push({ number: pr.number, reason: `Commit failed: ${commit.stderr}` }) continue } - console.log(` Successfully applied PR #${pr.number}`) + console.log(` Applied successfully`) applied.push(pr.number) } From 9cf3e651ca7bb1a7e28f3590fa846cf79bffa129 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:26:55 -0500 Subject: [PATCH 10/16] ci --- script/beta.ts | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index 7f51ff7936..5cbdbfb552 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -5,6 +5,19 @@ interface PR { title: string } +interface Repo { + nameWithOwner: string +} + +interface HeadRepo { + nameWithOwner: string +} + +interface PRHead { + headRefName: string + headRepository: HeadRepo +} + async function main() { console.log("Fetching open contributor PRs...") @@ -16,6 +29,12 @@ async function main() { const prs: PR[] = JSON.parse(prsResult.stdout) console.log(`Found ${prs.length} open contributor PRs`) + const repoResult = await $`gh repo view --json nameWithOwner`.nothrow() + if (repoResult.exitCode !== 0) { + throw new Error(`Failed to fetch repo info: ${repoResult.stderr}`) + } + const repo: Repo = JSON.parse(repoResult.stdout) + console.log("Fetching latest dev branch...") const fetchDev = await $`git fetch origin dev`.nothrow() if (fetchDev.exitCode !== 0) { @@ -34,9 +53,18 @@ async function main() { for (const pr of prs) { console.log(`\nProcessing PR #${pr.number}: ${pr.title}`) - // Get the diff from GitHub + const headResult = await $`gh pr view ${pr.number} --json headRefName,headRepository`.nothrow() + if (headResult.exitCode !== 0) { + console.log(` Failed to get head info`) + skipped.push({ number: pr.number, reason: `Failed to get head info: ${headResult.stderr}` }) + continue + } + const head: PRHead = JSON.parse(headResult.stdout) + + // Get the diff from GitHub compare API console.log(` Getting diff...`) - const diffResult = await $`gh pr diff ${pr.number}`.nothrow() + const compare = `${repo.nameWithOwner}/compare/dev...${head.headRepository.nameWithOwner}:${head.headRefName}` + const diffResult = await $`gh api -H Accept:application/vnd.github.v3.diff repos/${compare}`.nothrow() if (diffResult.exitCode !== 0) { console.log(` Failed to get diff`) skipped.push({ number: pr.number, reason: `Failed to get diff: ${diffResult.stderr}` }) @@ -80,7 +108,7 @@ async function main() { const commitMsg = `Apply PR #${pr.number}: ${pr.title}` const commit = await $`git commit -m ${commitMsg}`.nothrow() if (commit.exitCode !== 0) { - console.log(` Failed to commit`) + console.log(` Failed to commit: ${commit.stderr}`) await $`git checkout -- .`.nothrow() await $`git clean -fd`.nothrow() skipped.push({ number: pr.number, reason: `Commit failed: ${commit.stderr}` }) From e4d3b961cd2217e19cd44f6b97dd92b485966afb Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:28:12 -0500 Subject: [PATCH 11/16] ci --- script/beta.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/script/beta.ts b/script/beta.ts index 5cbdbfb552..92625a8547 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -106,12 +106,17 @@ async function main() { } const commitMsg = `Apply PR #${pr.number}: ${pr.title}` - const commit = await $`git commit -m ${commitMsg}`.nothrow() - if (commit.exitCode !== 0) { - console.log(` Failed to commit: ${commit.stderr}`) + const commit = await Bun.spawn(["git", "commit", "-m", commitMsg], { + stdout: "pipe", + stderr: "pipe", + }) + const commitExit = await commit.exited + const commitStderr = await Bun.readableStreamToText(commit.stderr) + if (commitExit !== 0) { + console.log(` Failed to commit: ${commitStderr}`) await $`git checkout -- .`.nothrow() await $`git clean -fd`.nothrow() - skipped.push({ number: pr.number, reason: `Commit failed: ${commit.stderr}` }) + skipped.push({ number: pr.number, reason: `Commit failed: ${commitStderr}` }) continue } From 7fb22ab6819e6fc1486319d91f27782ad3541708 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:28:54 -0500 Subject: [PATCH 12/16] ci --- script/beta.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/script/beta.ts b/script/beta.ts index 92625a8547..f87e507547 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -66,7 +66,8 @@ async function main() { const compare = `${repo.nameWithOwner}/compare/dev...${head.headRepository.nameWithOwner}:${head.headRefName}` const diffResult = await $`gh api -H Accept:application/vnd.github.v3.diff repos/${compare}`.nothrow() if (diffResult.exitCode !== 0) { - console.log(` Failed to get diff`) + console.log(` Failed to get diff: ${diffResult.stderr}`) + console.log(` Compare: ${compare}`) skipped.push({ number: pr.number, reason: `Failed to get diff: ${diffResult.stderr}` }) continue } From 9a0132e7507ebc68511396f80757dfa90fe60276 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:35:39 -0500 Subject: [PATCH 13/16] ci --- script/beta.ts | 102 +++++++++++++++++++------------------------------ 1 file changed, 39 insertions(+), 63 deletions(-) mode change 100755 => 100644 script/beta.ts diff --git a/script/beta.ts b/script/beta.ts old mode 100755 new mode 100644 index f87e507547..7a3dfcccf4 --- a/script/beta.ts +++ b/script/beta.ts @@ -5,17 +5,10 @@ interface PR { title: string } -interface Repo { - nameWithOwner: string -} - -interface HeadRepo { - nameWithOwner: string -} - -interface PRHead { - headRefName: string - headRepository: HeadRepo +interface RunResult { + exitCode: number + stdout: string + stderr: string } async function main() { @@ -29,12 +22,6 @@ async function main() { const prs: PR[] = JSON.parse(prsResult.stdout) console.log(`Found ${prs.length} open contributor PRs`) - const repoResult = await $`gh repo view --json nameWithOwner`.nothrow() - if (repoResult.exitCode !== 0) { - throw new Error(`Failed to fetch repo info: ${repoResult.stderr}`) - } - const repo: Repo = JSON.parse(repoResult.stdout) - console.log("Fetching latest dev branch...") const fetchDev = await $`git fetch origin dev`.nothrow() if (fetchDev.exitCode !== 0) { @@ -53,53 +40,35 @@ async function main() { for (const pr of prs) { console.log(`\nProcessing PR #${pr.number}: ${pr.title}`) - const headResult = await $`gh pr view ${pr.number} --json headRefName,headRepository`.nothrow() - if (headResult.exitCode !== 0) { - console.log(` Failed to get head info`) - skipped.push({ number: pr.number, reason: `Failed to get head info: ${headResult.stderr}` }) - continue - } - const head: PRHead = JSON.parse(headResult.stdout) - - // Get the diff from GitHub compare API - console.log(` Getting diff...`) - const compare = `${repo.nameWithOwner}/compare/dev...${head.headRepository.nameWithOwner}:${head.headRefName}` - const diffResult = await $`gh api -H Accept:application/vnd.github.v3.diff repos/${compare}`.nothrow() - if (diffResult.exitCode !== 0) { - console.log(` Failed to get diff: ${diffResult.stderr}`) - console.log(` Compare: ${compare}`) - skipped.push({ number: pr.number, reason: `Failed to get diff: ${diffResult.stderr}` }) + console.log(" Fetching PR head...") + const fetch = await run(["git", "fetch", "origin", `pull/${pr.number}/head:pr/${pr.number}`]) + if (fetch.exitCode !== 0) { + console.log(` Failed to fetch PR head: ${fetch.stderr}`) + skipped.push({ number: pr.number, reason: `Fetch failed: ${fetch.stderr}` }) continue } - if (!diffResult.stdout.trim()) { - console.log(` No changes, skipping`) - skipped.push({ number: pr.number, reason: "No changes" }) - continue - } - - // Try to apply the diff - console.log(` Applying...`) - const apply = await Bun.spawn(["git", "apply", "--3way"], { - stdin: new TextEncoder().encode(diffResult.stdout), - stdout: "pipe", - stderr: "pipe", - }) - const applyExit = await apply.exited - const applyStderr = await Bun.readableStreamToText(apply.stderr) - - if (applyExit !== 0) { - console.log(` Failed to apply (conflicts)`) + console.log(" Merging...") + const merge = await run(["git", "merge", "--no-commit", "--no-ff", `pr/${pr.number}`]) + if (merge.exitCode !== 0) { + console.log(" Failed to merge (conflicts)") + await $`git merge --abort`.nothrow() await $`git checkout -- .`.nothrow() await $`git clean -fd`.nothrow() skipped.push({ number: pr.number, reason: "Has conflicts" }) continue } - // Stage and commit + const mergeHead = await $`git rev-parse -q --verify MERGE_HEAD`.nothrow() + if (mergeHead.exitCode !== 0) { + console.log(" No changes, skipping") + skipped.push({ number: pr.number, reason: "No changes" }) + continue + } + const add = await $`git add -A`.nothrow() if (add.exitCode !== 0) { - console.log(` Failed to stage`) + console.log(" Failed to stage") await $`git checkout -- .`.nothrow() await $`git clean -fd`.nothrow() skipped.push({ number: pr.number, reason: "Failed to stage" }) @@ -107,21 +76,16 @@ async function main() { } const commitMsg = `Apply PR #${pr.number}: ${pr.title}` - const commit = await Bun.spawn(["git", "commit", "-m", commitMsg], { - stdout: "pipe", - stderr: "pipe", - }) - const commitExit = await commit.exited - const commitStderr = await Bun.readableStreamToText(commit.stderr) - if (commitExit !== 0) { - console.log(` Failed to commit: ${commitStderr}`) + const commit = await run(["git", "commit", "-m", commitMsg]) + if (commit.exitCode !== 0) { + console.log(` Failed to commit: ${commit.stderr}`) await $`git checkout -- .`.nothrow() await $`git clean -fd`.nothrow() - skipped.push({ number: pr.number, reason: `Commit failed: ${commitStderr}` }) + skipped.push({ number: pr.number, reason: `Commit failed: ${commit.stderr}` }) continue } - console.log(` Applied successfully`) + console.log(" Applied successfully") applied.push(pr.number) } @@ -145,6 +109,18 @@ main().catch((err) => { process.exit(1) }) +async function run(args: string[], stdin?: Uint8Array): Promise { + const proc = Bun.spawn(args, { + stdin: stdin ?? "inherit", + stdout: "pipe", + stderr: "pipe", + }) + const exitCode = await proc.exited + const stdout = await new Response(proc.stdout).text() + const stderr = await new Response(proc.stderr).text() + return { exitCode, stdout, stderr } +} + function $(strings: TemplateStringsArray, ...values: unknown[]) { const cmd = strings.reduce((acc, str, i) => acc + str + (values[i] ?? ""), "") return { From e80a99e7bd458a68dbca2e24ee1e19c3d18f1d7f Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:36:01 -0500 Subject: [PATCH 14/16] ci --- script/beta.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 script/beta.ts diff --git a/script/beta.ts b/script/beta.ts old mode 100644 new mode 100755 From 2e005de670b53de126b08c8a0b92358815b4962f Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:38:10 -0500 Subject: [PATCH 15/16] ci --- script/beta.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/script/beta.ts b/script/beta.ts index 7a3dfcccf4..68cbd1097a 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -34,6 +34,18 @@ async function main() { throw new Error(`Failed to checkout beta branch: ${checkoutBeta.stderr}`) } + const shallow = await run(["git", "rev-parse", "--is-shallow-repository"]) + if (shallow.exitCode !== 0) { + throw new Error(`Failed to check shallow state: ${shallow.stderr}`) + } + if (shallow.stdout.trim() === "true") { + console.log("Unshallowing repository...") + const unshallow = await run(["git", "fetch", "--unshallow"]) + if (unshallow.exitCode !== 0) { + throw new Error(`Failed to unshallow repository: ${unshallow.stderr}`) + } + } + const applied: number[] = [] const skipped: Array<{ number: number; reason: string }> = [] From 1aade4b30817b8ecd2edb708737ed554879c2f28 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Fri, 30 Jan 2026 10:39:59 -0500 Subject: [PATCH 16/16] ci --- .github/workflows/beta.yml | 2 ++ script/beta.ts | 12 ------------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index f7ad115a29..b9aa498962 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -19,6 +19,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup Bun uses: ./.github/actions/setup-bun diff --git a/script/beta.ts b/script/beta.ts index 68cbd1097a..7a3dfcccf4 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -34,18 +34,6 @@ async function main() { throw new Error(`Failed to checkout beta branch: ${checkoutBeta.stderr}`) } - const shallow = await run(["git", "rev-parse", "--is-shallow-repository"]) - if (shallow.exitCode !== 0) { - throw new Error(`Failed to check shallow state: ${shallow.stderr}`) - } - if (shallow.stdout.trim() === "true") { - console.log("Unshallowing repository...") - const unshallow = await run(["git", "fetch", "--unshallow"]) - if (unshallow.exitCode !== 0) { - throw new Error(`Failed to unshallow repository: ${unshallow.stderr}`) - } - } - const applied: number[] = [] const skipped: Array<{ number: number; reason: string }> = []