Skip to content

Commit eea96b4

Browse files
committed
webhook: verify base branch exists at enqueue time, fall back to default branch if not
1 parent 49e77f2 commit eea96b4

1 file changed

Lines changed: 67 additions & 2 deletions

File tree

web/github.php

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,62 @@ function buildWebhookWhitelist(array $categories): array
5252
return $whitelist;
5353
}
5454

55+
/**
56+
* Verify that the base branch exists in the repository, correct if not
57+
*
58+
* Uses `gh api repos/{owner}/{repo}/branches/{branch}` to verify existence.
59+
* If the branch doesn't exist, falls back to the repository's default branch.
60+
*
61+
* @param string $repo Owner/repo format
62+
* @param string $baseBranch The branch to verify
63+
* @return string The verified correct base branch
64+
*/
65+
function verifyAndCorrectBaseBranch(string $repo, string $baseBranch): string
66+
{
67+
if ($baseBranch === '') {
68+
return 'main';
69+
}
70+
71+
// Quick check: if branch is main/master/develop, just return it
72+
// These are common enough that we skip the API call
73+
if (in_array($baseBranch, ['main', 'master', 'develop', 'dev', 'staging'], true)) {
74+
return $baseBranch;
75+
}
76+
77+
// Verify the branch exists via GitHub API
78+
$output = [];
79+
$ret = 0;
80+
$cmd = sprintf(
81+
'gh api repos/%s/branches/%s --jq .name 2>&1',
82+
escapeshellarg($repo),
83+
escapeshellarg($baseBranch)
84+
);
85+
exec($cmd, $output, $ret);
86+
87+
if ($ret === 0 && !empty($output)) {
88+
// Branch exists, return as-is
89+
return $baseBranch;
90+
}
91+
92+
// Branch doesn't exist - get the default branch
93+
$defaultOutput = [];
94+
$defaultRet = 0;
95+
$defaultCmd = sprintf(
96+
'gh api repos/%s --jq .default_branch 2>&1',
97+
escapeshellarg($repo)
98+
);
99+
exec($defaultCmd, $defaultOutput, $defaultRet);
100+
101+
if ($defaultRet === 0 && !empty($defaultOutput)) {
102+
$defaultBranch = trim(implode("\n", $defaultOutput));
103+
error_log("github-webhook: base_branch '{$baseBranch}' not found, using default branch '{$defaultBranch}'");
104+
return $defaultBranch ?: 'main';
105+
}
106+
107+
// Couldn't determine, return original (might work anyway if gh caches it)
108+
return $baseBranch;
109+
}
110+
55111
/**
56112
* Add universal repository fields to whitelist for a specific event
57113
*/
@@ -148,16 +204,25 @@ function addUniversalRepoFields(array $whitelist): array
148204
if ($EventType === 'pull_request' && in_array($action, ['opened', 'synchronize'], true)) {
149205
$pr = $Payload['pull_request'] ?? [];
150206
$author = $pr['user'] ?? [];
207+
$authorLogin = $author['login'] ?? '';
208+
$isBot = str_ends_with($authorLogin, '[bot]');
209+
210+
// Verify the base branch actually exists in the repo
211+
// If the stored base_branch doesn't exist, use the repo's default branch
212+
$storedBaseBranch = $pr['base']['ref'] ?? '';
213+
$baseBranch = verifyAndCorrectBaseBranch($RepositoryName, $storedBaseBranch);
214+
151215
CodeReviewQueue::enqueue([
152216
'repo' => $RepositoryName,
153217
'pr_number' => (int)($pr['number'] ?? 0),
154218
'action' => $action,
155219
'head_branch' => $pr['head']['ref'] ?? '',
156-
'base_branch' => $pr['base']['ref'] ?? '',
220+
'base_branch' => $baseBranch,
157221
'pr_url' => $pr['html_url'] ?? '',
158-
'author' => $author['login'] ?? '',
222+
'author' => $authorLogin,
159223
'author_url' => $author['html_url'] ?? '',
160224
'sha' => $pr['head']['sha'] ?? '',
225+
'is_bot' => $isBot,
161226
]);
162227
}
163228

0 commit comments

Comments
 (0)