overhaul git setup

This commit is contained in:
Colin McDonnell
2025-12-16 18:00:22 -08:00
parent f6ac916e22
commit 1bff21f7fb
19 changed files with 514 additions and 195 deletions
+6 -5
View File
@@ -7,12 +7,12 @@ export interface AgentInfo {
url: string;
}
export interface WorkflowRunInfo {
export interface WorkflowRunFooterInfo {
owner: string;
repo: string;
runId: string;
/** optional job URL - if provided, will be used instead of building from runId */
htmlUrl?: string;
/** optional job ID - if provided, will append /job/{jobId} to the workflow run URL */
jobId?: string | undefined;
}
export interface BuildPullfrogFooterParams {
@@ -21,7 +21,7 @@ export interface BuildPullfrogFooterParams {
/** add "Using [agent](url)" link */
agent?: AgentInfo | undefined;
/** add "View workflow run" link */
workflowRun?: WorkflowRunInfo | undefined;
workflowRun?: WorkflowRunFooterInfo | undefined;
/** arbitrary custom parts (e.g., action links) */
customParts?: string[];
}
@@ -42,7 +42,8 @@ export function buildPullfrogFooter(params: BuildPullfrogFooterParams): string {
}
if (params.workflowRun) {
const url = params.workflowRun.htmlUrl ?? `https://github.com/${params.workflowRun.owner}/${params.workflowRun.repo}/actions/runs/${params.workflowRun.runId}`;
const baseUrl = `https://github.com/${params.workflowRun.owner}/${params.workflowRun.repo}/actions/runs/${params.workflowRun.runId}`;
const url = params.workflowRun.jobId ? `${baseUrl}/job/${params.workflowRun.jobId}` : baseUrl;
parts.push(`[View workflow run](${url})`);
}
+13 -47
View File
@@ -62,19 +62,19 @@ export function setupGitConfig(): void {
}
}
export type SetupGitResult = {
pushRemote: string;
};
/**
* Unified git setup: configures authentication and checks out PR branch if applicable.
* For PR events, always returns a push URL constructed from the PR's head repo.
* This works for both same-repo and fork PRs with a single code path.
* Setup git authentication for the repository.
* PR checkout is handled dynamically by the checkout_pr MCP tool.
*
* FORK PR ARCHITECTURE (handled by checkout_pr tool):
* - origin: always points to BASE REPO (where PR targets)
* - checkout_pr sets per-branch pushRemote config for fork PRs
* - diff operations use: git diff origin/<base>..HEAD
*/
export async function setupGit(ctx: Context): Promise<SetupGitResult> {
export async function setupGit(ctx: Context): Promise<void> {
const repoDir = process.cwd();
log.info("🔧 Setting up git authentication...");
log.info("🔧 setting up git authentication...");
// remove existing git auth headers that actions/checkout might have set
try {
@@ -82,47 +82,13 @@ export async function setupGit(ctx: Context): Promise<SetupGitResult> {
cwd: repoDir,
stdio: "pipe",
});
log.info("✓ Removed existing authentication headers");
log.info("✓ removed existing authentication headers");
} catch {
log.debug("No existing authentication headers to remove");
log.debug("no existing authentication headers to remove");
}
// set up origin with token (needed for fetch operations)
// authenticate origin - needed for all fetch operations including PR fetches
const originUrl = `https://x-access-token:${ctx.githubInstallationToken}@github.com/${ctx.owner}/${ctx.name}.git`;
$("git", ["remote", "set-url", "origin", originUrl], { cwd: repoDir });
log.info("✓ Updated origin URL with authentication token");
// non-PR events: stay on default branch
if (ctx.payload.event.is_pr !== true || !ctx.payload.event.issue_number) {
return { pushRemote: "origin" };
}
// PR event: fetch PR info to get branch name and head repo
const prNumber = ctx.payload.event.issue_number;
const pr = await ctx.octokit.rest.pulls.get({
owner: ctx.owner,
repo: ctx.name,
pull_number: prNumber,
});
const headRepo = pr.data.head.repo;
if (!headRepo) {
throw new Error(`PR #${prNumber} source repository was deleted`);
}
// checkout PR branch using plain git (no gh cli needed)
const branch = pr.data.head.ref;
log.info(`🌿 Checking out PR #${prNumber} (${branch})...`);
$("git", ["fetch", "--no-tags", "origin", `pull/${prNumber}/head:${branch}`], { cwd: repoDir });
$("git", ["checkout", branch], { cwd: repoDir });
log.info(`✓ Successfully checked out PR #${prNumber}`);
// unified push URL - works for both same-repo and fork PRs
const token = process.env.GITHUB_TOKEN || ctx.githubInstallationToken;
const pushUrl = `https://x-access-token:${token}@github.com/${headRepo.full_name}.git`;
const isFork = headRepo.full_name !== pr.data.base.repo.full_name;
if (isFork) {
log.info(`🍴 Fork PR detected, will push to: ${headRepo.full_name}`);
}
return { pushRemote: pushUrl };
log.info("✓ updated origin URL with authentication token");
}