From 01602be052096582666c8b5ba409e6ab9f1f2ef6 Mon Sep 17 00:00:00 2001 From: Mark Wylde Date: Fri, 30 May 2025 21:12:47 +0100 Subject: [PATCH] Attempt to make this work --- src/entrypoints/update-comment-link.ts | 131 +++++++++++++++------- src/github/operations/branch-cleanup.ts | 140 ++++++++++++++++-------- src/github/operations/branch.ts | 47 +++++--- 3 files changed, 216 insertions(+), 102 deletions(-) diff --git a/src/entrypoints/update-comment-link.ts b/src/entrypoints/update-comment-link.ts index fb73d45..5eb4bbb 100644 --- a/src/entrypoints/update-comment-link.ts +++ b/src/entrypoints/update-comment-link.ts @@ -107,39 +107,18 @@ async function run() { const containsPRUrl = currentBody.match(prUrlPattern); if (!containsPRUrl) { - // Check if there are changes to the branch compared to the default branch - try { - const { data: comparison } = - await octokit.rest.repos.compareCommitsWithBasehead({ - owner, - repo, - basehead: `${baseBranch}...${claudeBranch}`, - }); + // Check if we're in a Gitea environment + const isGitea = + process.env.GITHUB_API_URL && + !process.env.GITHUB_API_URL.includes("api.github.com"); - // If there are changes (commits or file changes), add the PR URL - if ( - comparison.total_commits > 0 || - (comparison.files && comparison.files.length > 0) - ) { - const entityType = context.isPR ? "PR" : "Issue"; - const prTitle = encodeURIComponent( - `${entityType} #${context.entityNumber}: Changes from Claude`, - ); - const prBody = encodeURIComponent( - `This PR addresses ${entityType.toLowerCase()} #${context.entityNumber}\n\nGenerated with [Claude Code](https://claude.ai/code)`, - ); - const prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`; - prLink = `\n[Create a PR](${prUrl})`; - } - } catch (error) { - console.error("Error checking for changes in branch:", error); + if (isGitea) { + // Gitea doesn't support the /compare endpoint, use direct SHA comparison + console.log( + "Detected Gitea environment, using SHA comparison for PR link check", + ); - // For Gitea compatibility, try alternative approach try { - console.log( - "Trying alternative branch comparison for Gitea compatibility...", - ); - // Get the branch info to see if it exists and has commits const branchResponse = await octokit.rest.repos.getBranch({ owner, @@ -176,15 +155,10 @@ async function run() { `Branch ${claudeBranch} has same SHA as base, no PR link needed`, ); } - } catch (fallbackError) { - console.error( - "Fallback branch comparison also failed:", - fallbackError, - ); - // If all checks fail, still add PR link to be safe - console.log( - "Adding PR link as fallback since we can't determine branch status", - ); + } catch (error) { + console.error("Error checking branch in Gitea:", error); + // If we can't check in Gitea, add PR link to be safe + console.log("Adding PR link as fallback for Gitea"); const entityType = context.isPR ? "PR" : "Issue"; const prTitle = encodeURIComponent( `${entityType} #${context.entityNumber}: Changes from Claude`, @@ -195,6 +169,85 @@ async function run() { const prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`; prLink = `\n[Create a PR](${prUrl})`; } + } else { + // GitHub environment - use the comparison API + try { + const { data: comparison } = + await octokit.rest.repos.compareCommitsWithBasehead({ + owner, + repo, + basehead: `${baseBranch}...${claudeBranch}`, + }); + + // If there are changes (commits or file changes), add the PR URL + if ( + comparison.total_commits > 0 || + (comparison.files && comparison.files.length > 0) + ) { + const entityType = context.isPR ? "PR" : "Issue"; + const prTitle = encodeURIComponent( + `${entityType} #${context.entityNumber}: Changes from Claude`, + ); + const prBody = encodeURIComponent( + `This PR addresses ${entityType.toLowerCase()} #${context.entityNumber}\n\nGenerated with [Claude Code](https://claude.ai/code)`, + ); + const prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`; + prLink = `\n[Create a PR](${prUrl})`; + } + } catch (error) { + console.error("Error checking for changes in branch:", error); + + // Fallback to SHA comparison even on GitHub if API fails + try { + console.log( + "GitHub comparison API failed, falling back to SHA comparison", + ); + + const branchResponse = await octokit.rest.repos.getBranch({ + owner, + repo, + branch: claudeBranch, + }); + + const baseResponse = await octokit.rest.repos.getBranch({ + owner, + repo, + branch: baseBranch, + }); + + const branchSha = branchResponse.data.commit.sha; + const baseSha = baseResponse.data.commit.sha; + + // If SHAs are different, assume there are changes and add PR link + if (branchSha !== baseSha) { + const entityType = context.isPR ? "PR" : "Issue"; + const prTitle = encodeURIComponent( + `${entityType} #${context.entityNumber}: Changes from Claude`, + ); + const prBody = encodeURIComponent( + `This PR addresses ${entityType.toLowerCase()} #${context.entityNumber}\n\nGenerated with [Claude Code](https://claude.ai/code)`, + ); + const prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`; + prLink = `\n[Create a PR](${prUrl})`; + } + } catch (fallbackError) { + console.error( + "Fallback branch comparison also failed:", + fallbackError, + ); + // If all checks fail, still add PR link to be safe + console.log("Adding PR link as final fallback"); + const entityType = context.isPR ? "PR" : "Issue"; + const prTitle = encodeURIComponent( + `${entityType} #${context.entityNumber}: Changes from Claude`, + ); + const prBody = encodeURIComponent( + `This PR addresses ${entityType.toLowerCase()} #${context.entityNumber}\n\nGenerated with [Claude Code](https://claude.ai/code)`, + ); + const prUrl = `${serverUrl}/${owner}/${repo}/compare/${baseBranch}...${claudeBranch}?quick_pull=1&title=${prTitle}&body=${prBody}`; + prLink = `\n[Create a PR](${prUrl})`; + } + } } } } diff --git a/src/github/operations/branch-cleanup.ts b/src/github/operations/branch-cleanup.ts index 374a9da..c52e9a2 100644 --- a/src/github/operations/branch-cleanup.ts +++ b/src/github/operations/branch-cleanup.ts @@ -12,35 +12,18 @@ export async function checkAndDeleteEmptyBranch( let shouldDeleteBranch = false; if (claudeBranch) { - // Check if Claude made any commits to the branch - try { - const { data: comparison } = - await octokit.rest.repos.compareCommitsWithBasehead({ - owner, - repo, - basehead: `${baseBranch}...${claudeBranch}`, - }); + // Check if we're in a Gitea environment + const isGitea = + process.env.GITHUB_API_URL && + !process.env.GITHUB_API_URL.includes("api.github.com"); - // If there are no commits, mark branch for deletion - if (comparison.total_commits === 0) { - console.log( - `Branch ${claudeBranch} has no commits from Claude, will delete it`, - ); - shouldDeleteBranch = true; - } else { - // Only add branch link if there are commits - const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; - branchLink = `\n[View branch](${branchUrl})`; - } - } catch (error) { - console.error("Error checking for commits on Claude branch:", error); + if (isGitea) { + // Gitea doesn't support the /compare endpoint, use direct SHA comparison + console.log( + "Detected Gitea environment, using SHA comparison for branch check", + ); - // For Gitea compatibility, try alternative approach using branches endpoint try { - console.log( - "Trying alternative branch comparison for Gitea compatibility...", - ); - // Get the branch info to see if it exists and has commits const branchResponse = await octokit.rest.repos.getBranch({ owner, @@ -71,36 +54,101 @@ export async function checkAndDeleteEmptyBranch( ); shouldDeleteBranch = true; } - } catch (fallbackError) { - console.error("Fallback branch comparison also failed:", fallbackError); - // If all checks fail, assume the branch has commits to be safe + } catch (error) { + console.error("Error checking branch in Gitea:", error); + // If we can't check, assume the branch has commits to be safe const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; branchLink = `\n[View branch](${branchUrl})`; } + } else { + // GitHub environment - use the comparison API + try { + const { data: comparison } = + await octokit.rest.repos.compareCommitsWithBasehead({ + owner, + repo, + basehead: `${baseBranch}...${claudeBranch}`, + }); + + // If there are no commits, mark branch for deletion + if (comparison.total_commits === 0) { + console.log( + `Branch ${claudeBranch} has no commits from Claude, will delete it`, + ); + shouldDeleteBranch = true; + } else { + // Only add branch link if there are commits + const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; + branchLink = `\n[View branch](${branchUrl})`; + } + } catch (error) { + console.error("Error checking for commits on Claude branch:", error); + + // Fallback to SHA comparison even on GitHub if API fails + try { + console.log( + "GitHub comparison API failed, falling back to SHA comparison", + ); + + const branchResponse = await octokit.rest.repos.getBranch({ + owner, + repo, + branch: claudeBranch, + }); + + const baseResponse = await octokit.rest.repos.getBranch({ + owner, + repo, + branch: baseBranch, + }); + + const branchSha = branchResponse.data.commit.sha; + const baseSha = baseResponse.data.commit.sha; + + if (branchSha !== baseSha) { + const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; + branchLink = `\n[View branch](${branchUrl})`; + } else { + shouldDeleteBranch = true; + } + } catch (fallbackError) { + console.error( + "Fallback branch comparison also failed:", + fallbackError, + ); + // If all checks fail, assume the branch has commits to be safe + const branchUrl = `${GITHUB_SERVER_URL}/${owner}/${repo}/tree/${claudeBranch}`; + branchLink = `\n[View branch](${branchUrl})`; + } + } } } // Delete the branch if it has no commits if (shouldDeleteBranch && claudeBranch) { - try { - await octokit.rest.git.deleteRef({ - owner, - repo, - ref: `heads/${claudeBranch}`, - }); - console.log(`✅ Deleted empty branch: ${claudeBranch}`); - } catch (deleteError: any) { - console.error(`Failed to delete branch ${claudeBranch}:`, deleteError); - console.log(`Delete error status: ${deleteError.status}`); + // Check if we're in a Gitea environment for deletion too + const isGitea = + process.env.GITHUB_API_URL && + !process.env.GITHUB_API_URL.includes("api.github.com"); - // For Gitea, branch deletion might not be supported via API - if (deleteError.status === 405 || deleteError.status === 404) { - console.log( - "Branch deletion not supported or branch doesn't exist remotely - this is expected for Gitea", - ); + if (isGitea) { + console.log( + `Skipping branch deletion for Gitea - not reliably supported: ${claudeBranch}`, + ); + // Don't attempt deletion in Gitea as it's not reliably supported + } else { + try { + await octokit.rest.git.deleteRef({ + owner, + repo, + ref: `heads/${claudeBranch}`, + }); + console.log(`✅ Deleted empty branch: ${claudeBranch}`); + } catch (deleteError: any) { + console.error(`Failed to delete branch ${claudeBranch}:`, deleteError); + console.log(`Delete error status: ${deleteError.status}`); + // Continue even if deletion fails - this is not critical } - - // Continue even if deletion fails - this is not critical } } diff --git a/src/github/operations/branch.ts b/src/github/operations/branch.ts index b44270d..029295a 100644 --- a/src/github/operations/branch.ts +++ b/src/github/operations/branch.ts @@ -121,27 +121,40 @@ export async function setupBranch( console.log(`Current SHA: ${currentSHA}`); - // Create branch - try GitHub API first - try { - await octokits.rest.git.createRef({ - owner, - repo, - ref: `refs/heads/${newBranch}`, - sha: currentSHA, - }); + // Check if we're in a Gitea environment + const isGitea = + process.env.GITHUB_API_URL && + !process.env.GITHUB_API_URL.includes("api.github.com"); - console.log(`Successfully created branch via API: ${newBranch}`); - } catch (createRefError: any) { - // If git/refs creation fails (like in Gitea), that's expected - // Log the error details but continue - the branch will be created when we push files + if (isGitea) { + // Gitea doesn't reliably support git.createRef, skip it console.log( - `git createRef failed (expected for Gitea): ${createRefError.message}`, + `Detected Gitea environment, skipping git.createRef for branch: ${newBranch}`, ); - console.log(`Error status: ${createRefError.status}`); - console.log(`Branch ${newBranch} will be created when files are pushed`); + console.log( + `Branch ${newBranch} will be created when files are pushed via MCP server`, + ); + } else { + // GitHub environment - try to create branch via API + try { + await octokits.rest.git.createRef({ + owner, + repo, + ref: `refs/heads/${newBranch}`, + sha: currentSHA, + }); - // For Gitea, we can still proceed since the MCP server will create the branch on first push - // This is actually the preferred method for Gitea + console.log(`Successfully created branch via API: ${newBranch}`); + } catch (createRefError: any) { + // If creation fails on GitHub, log but continue + console.log( + `git createRef failed on GitHub: ${createRefError.message}`, + ); + console.log(`Error status: ${createRefError.status}`); + console.log( + `Branch ${newBranch} will be created when files are pushed`, + ); + } } console.log(`Branch setup completed for: ${newBranch}`);