mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-22 23:53:08 +00:00
* Changes from feature/worktree-view-customization * Feature: Git sync, set-tracking, and push divergence handling (#796) * Add quick-add feature with improved workflows (#802) * Changes from feature/quick-add * feat: Clarify system prompt and improve error handling across services. Address PR Feedback * feat: Improve PR description parsing and refactor event handling * feat: Add context options to pipeline orchestrator initialization * fix: Deduplicate React and handle CJS interop for use-sync-external-store Resolve "Cannot read properties of null (reading 'useState')" errors by deduplicating React/react-dom and ensuring use-sync-external-store is bundled together with React to prevent CJS packages from resolving to different React instances. * Changes from feature/worktree-view-customization * refactor: Remove unused worktree swap and highlight props * refactor: Consolidate feature completion logic and improve thinking level defaults * feat: Increase max turn limit to 10000 - Update DEFAULT_MAX_TURNS from 1000 to 10000 in settings-helpers.ts and agent-executor.ts - Update MAX_ALLOWED_TURNS from 2000 to 10000 in settings-helpers.ts - Update UI clamping logic from 2000 to 10000 in app-store.ts - Update fallback values from 1000 to 10000 in use-settings-sync.ts - Update default value from 1000 to 10000 in DEFAULT_GLOBAL_SETTINGS - Update documentation to reflect new range: 1-10000 Allows agents to perform up to 10000 turns for complex feature execution. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * feat: Add model resolution, improve session handling, and enhance UI stability * refactor: Remove unused sync and tracking branch props from worktree components * feat: Add PR number update functionality to worktrees. Address pr feedback * feat: Optimize Gemini CLI startup and add tool result tracking * refactor: Improve error handling and simplify worktree task cleanup --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
164 lines
5.4 KiB
TypeScript
164 lines
5.4 KiB
TypeScript
/**
|
|
* POST /update-pr-number endpoint - Update the tracked PR number for a worktree
|
|
*
|
|
* Allows users to manually change which PR number is tracked for a worktree branch.
|
|
* Fetches updated PR info from GitHub when available, or updates metadata with the
|
|
* provided number only if GitHub CLI is unavailable.
|
|
*/
|
|
|
|
import type { Request, Response } from 'express';
|
|
import { getErrorMessage, logError, execAsync, execEnv, isGhCliAvailable } from '../common.js';
|
|
import { updateWorktreePRInfo } from '../../../lib/worktree-metadata.js';
|
|
import { createLogger } from '@automaker/utils';
|
|
import { validatePRState } from '@automaker/types';
|
|
|
|
const logger = createLogger('UpdatePRNumber');
|
|
|
|
export function createUpdatePRNumberHandler() {
|
|
return async (req: Request, res: Response): Promise<void> => {
|
|
try {
|
|
const { worktreePath, projectPath, prNumber } = req.body as {
|
|
worktreePath: string;
|
|
projectPath?: string;
|
|
prNumber: number;
|
|
};
|
|
|
|
if (!worktreePath) {
|
|
res.status(400).json({ success: false, error: 'worktreePath required' });
|
|
return;
|
|
}
|
|
|
|
if (
|
|
!prNumber ||
|
|
typeof prNumber !== 'number' ||
|
|
prNumber <= 0 ||
|
|
!Number.isInteger(prNumber)
|
|
) {
|
|
res.status(400).json({ success: false, error: 'prNumber must be a positive integer' });
|
|
return;
|
|
}
|
|
|
|
const effectiveProjectPath = projectPath || worktreePath;
|
|
|
|
// Get current branch name
|
|
const { stdout: branchOutput } = await execAsync('git rev-parse --abbrev-ref HEAD', {
|
|
cwd: worktreePath,
|
|
env: execEnv,
|
|
});
|
|
const branchName = branchOutput.trim();
|
|
|
|
if (!branchName || branchName === 'HEAD') {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: 'Cannot update PR number in detached HEAD state',
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Try to fetch PR info from GitHub for the given PR number
|
|
const ghCliAvailable = await isGhCliAvailable();
|
|
|
|
if (ghCliAvailable) {
|
|
try {
|
|
// Detect repository for gh CLI
|
|
let repoFlag = '';
|
|
try {
|
|
const { stdout: remotes } = await execAsync('git remote -v', {
|
|
cwd: worktreePath,
|
|
env: execEnv,
|
|
});
|
|
const lines = remotes.split(/\r?\n/);
|
|
let upstreamRepo: string | null = null;
|
|
let originOwner: string | null = null;
|
|
let originRepo: string | null = null;
|
|
|
|
for (const line of lines) {
|
|
const match =
|
|
line.match(/^(\w+)\s+.*[:/]([^/]+)\/([^/\s]+?)(?:\.git)?\s+\(fetch\)/) ||
|
|
line.match(/^(\w+)\s+git@[^:]+:([^/]+)\/([^\s]+?)(?:\.git)?\s+\(fetch\)/) ||
|
|
line.match(/^(\w+)\s+https?:\/\/[^/]+\/([^/]+)\/([^\s]+?)(?:\.git)?\s+\(fetch\)/);
|
|
|
|
if (match) {
|
|
const [, remoteName, owner, repo] = match;
|
|
if (remoteName === 'upstream') {
|
|
upstreamRepo = `${owner}/${repo}`;
|
|
} else if (remoteName === 'origin') {
|
|
originOwner = owner;
|
|
originRepo = repo;
|
|
}
|
|
}
|
|
}
|
|
|
|
const targetRepo =
|
|
upstreamRepo || (originOwner && originRepo ? `${originOwner}/${originRepo}` : null);
|
|
if (targetRepo) {
|
|
repoFlag = ` --repo "${targetRepo}"`;
|
|
}
|
|
} catch {
|
|
// Ignore remote parsing errors
|
|
}
|
|
|
|
// Fetch PR info from GitHub using the PR number
|
|
const viewCmd = `gh pr view ${prNumber}${repoFlag} --json number,title,url,state,createdAt`;
|
|
const { stdout: prOutput } = await execAsync(viewCmd, {
|
|
cwd: worktreePath,
|
|
env: execEnv,
|
|
});
|
|
|
|
const prData = JSON.parse(prOutput);
|
|
|
|
const prInfo = {
|
|
number: prData.number,
|
|
url: prData.url,
|
|
title: prData.title,
|
|
state: validatePRState(prData.state),
|
|
createdAt: prData.createdAt || new Date().toISOString(),
|
|
};
|
|
|
|
await updateWorktreePRInfo(effectiveProjectPath, branchName, prInfo);
|
|
|
|
logger.info(`Updated PR tracking to #${prNumber} for branch ${branchName}`);
|
|
|
|
res.json({
|
|
success: true,
|
|
result: {
|
|
branch: branchName,
|
|
prInfo,
|
|
},
|
|
});
|
|
return;
|
|
} catch (error) {
|
|
logger.warn(`Failed to fetch PR #${prNumber} from GitHub:`, error);
|
|
// Fall through to simple update below
|
|
}
|
|
}
|
|
|
|
// Fallback: update with just the number, preserving existing PR info structure
|
|
// or creating minimal info if no GitHub data available
|
|
const prInfo = {
|
|
number: prNumber,
|
|
url: `https://github.com/pulls/${prNumber}`,
|
|
title: `PR #${prNumber}`,
|
|
state: validatePRState('OPEN'),
|
|
createdAt: new Date().toISOString(),
|
|
};
|
|
|
|
await updateWorktreePRInfo(effectiveProjectPath, branchName, prInfo);
|
|
|
|
logger.info(`Updated PR tracking to #${prNumber} for branch ${branchName} (no GitHub data)`);
|
|
|
|
res.json({
|
|
success: true,
|
|
result: {
|
|
branch: branchName,
|
|
prInfo,
|
|
ghCliUnavailable: !ghCliAvailable,
|
|
},
|
|
});
|
|
} catch (error) {
|
|
logError(error, 'Update PR number failed');
|
|
res.status(500).json({ success: false, error: getErrorMessage(error) });
|
|
}
|
|
};
|
|
}
|