automaker / apps /server /src /services /argus /git-context.ts
Leon4gr45's picture
Upload folder using huggingface_hub (part 2)
f76cff8 verified
Raw History Blame Contribute Delete
3.64 kB
import { execGitCommand } from '@automaker/git-utils';
import { spawnProcess } from '@automaker/platform';
import { normalizeGitHubRepository } from './jules-client.js';
export interface GitDispatchContext {
repository: string;
baseBranch: string;
baseRemoteSha: string;
}
function ghEnv(): Record<string, string> {
return Object.fromEntries(
[
['PATH', process.env.PATH],
['HOME', process.env.HOME],
['GH_TOKEN', process.env.GITHUB_PAT],
].filter((entry): entry is [string, string] => Boolean(entry[1]))
);
}
export async function captureGitDispatchContext(
projectPath: string,
explicitBaseBranch?: string
): Promise<GitDispatchContext> {
let remoteUrl = '';
try {
remoteUrl = (await execGitCommand(['remote', 'get-url', 'origin'], projectPath)).trim();
} catch {
throw new Error(
'GITHUB_REMOTE_REQUIRED_FOR_JULES: Jules autonomous execution requires a canonical GitHub repository remote origin.'
);
}
const repository = normalizeGitHubRepository(remoteUrl);
if (!repository) {
throw new Error(
'GITHUB_REMOTE_REQUIRED_FOR_JULES: origin is not a canonical GitHub repository URL.'
);
}
await execGitCommand(['fetch', '--prune', 'origin'], projectPath);
let baseBranch = explicitBaseBranch || '';
if (!baseBranch)
try {
const result = await spawnProcess({
command: 'gh',
args: [
'repo',
'view',
repository,
'--json',
'defaultBranchRef',
'--jq',
'.defaultBranchRef.name',
],
cwd: projectPath,
env: ghEnv(),
});
if (result.exitCode === 0) baseBranch = result.stdout.trim();
} catch {
/* fall through to origin/HEAD */
}
if (!baseBranch)
try {
baseBranch = (
await execGitCommand(['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'], projectPath)
)
.trim()
.replace(/^origin\//, '');
} catch {
/* fail closed below */
}
if (!baseBranch)
throw new Error('GITHUB_PR_LOOKUP_FAILED: could not determine integration branch');
const baseRemoteSha = (
await execGitCommand(['rev-parse', `origin/${baseBranch}`], projectPath)
).trim();
return { repository, baseBranch, baseRemoteSha };
}
export async function verifyPullRequest(
url: string,
projectPath: string,
expected: { repository: string; baseBranch: string; branch?: string }
): Promise<{ number: number; url: string; headSha: string; branch: string }> {
const result = await spawnProcess({
command: 'gh',
args: [
'pr',
'view',
url,
'--json',
'number,url,state,baseRefName,headRefName,headRefOid,headRepositoryOwner,headRepository',
],
cwd: projectPath,
env: ghEnv(),
});
if (result.exitCode !== 0) throw new Error('GITHUB_PR_LOOKUP_FAILED');
const value = JSON.parse(result.stdout) as {
number: number;
url: string;
headRefName: string;
headRefOid: string;
state: string;
baseRefName: string;
headRepositoryOwner: { login: string };
headRepository: { name: string };
};
const repository =
`${value.headRepositoryOwner.login}/${value.headRepository.name}`.toLowerCase();
if (
value.state !== 'OPEN' ||
value.baseRefName !== expected.baseBranch ||
repository !== expected.repository.toLowerCase() ||
(expected.branch && value.headRefName !== expected.branch)
)
throw new Error('GITHUB_PR_LOOKUP_FAILED: PR identity mismatch');
return {
number: value.number,
url: value.url,
headSha: value.headRefOid,
branch: value.headRefName,
};
}