@link-assistant/hive-mind 2.8.1 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/solve.pr-base-guard.lib.mjs +46 -2
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -204,6 +204,40 @@ export async function getPullRequestBaseBranch({ owner, repo, prNumber, $, log }
|
|
|
204
204
|
return baseBranch;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
async function getPullRequestBranchRange({ owner, repo, prNumber, $, log }) {
|
|
208
|
+
if (typeof $ !== 'function') {
|
|
209
|
+
throw new Error('Cannot verify pull request branches without a command runner');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const result = await ghWithRateLimitRetry(() => $`gh pr view ${prNumber} --repo ${owner}/${repo} --json baseRefName,headRefName`, {
|
|
213
|
+
label: 'gh pr view baseRefName,headRefName',
|
|
214
|
+
log,
|
|
215
|
+
});
|
|
216
|
+
if (result.code !== 0) {
|
|
217
|
+
const details = commandOutput(result) || 'unknown error';
|
|
218
|
+
throw new Error(`Could not verify pull request branches for #${prNumber}: ${details}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let branchRange;
|
|
222
|
+
try {
|
|
223
|
+
branchRange = JSON.parse(String(result.stdout || '').trim());
|
|
224
|
+
} catch {
|
|
225
|
+
throw new Error(`Could not verify pull request branches for #${prNumber}: gh returned invalid JSON`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const baseBranch = normalizeBranchName(branchRange?.baseRefName);
|
|
229
|
+
const headBranch = normalizeBranchName(branchRange?.headRefName);
|
|
230
|
+
if (!baseBranch || !headBranch) {
|
|
231
|
+
throw new Error(`Could not verify pull request branches for #${prNumber}: gh returned an empty baseRefName or headRefName`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return { baseBranch, headBranch };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function buildBaseEqualsHeadBranchMessage({ prNumber, expectedBaseBranch, currentBaseBranch }) {
|
|
238
|
+
return `Invalid --base-branch '${expectedBaseBranch}' for PR #${prNumber}: it is the pull request's head branch (the source/work branch), so it cannot also be the base branch (the target branch). The pull request currently targets '${currentBaseBranch}'. Rerun with --base-branch ${currentBaseBranch} to preserve that target, choose another target branch, or omit --base-branch to keep the existing pull request target. Manual intervention is required; no pull request changes were made.`;
|
|
239
|
+
}
|
|
240
|
+
|
|
207
241
|
export async function ensurePullRequestBaseBranch({ owner, repo, prNumber, argv = {}, log = async () => {}, formatAligned = fallbackFormatAligned, $, onMismatch = 'restore', operation = 'verify' }) {
|
|
208
242
|
const expectedBaseBranch = getExpectedPullRequestBaseBranch({ argv });
|
|
209
243
|
if (!expectedBaseBranch) {
|
|
@@ -214,7 +248,7 @@ export async function ensurePullRequestBaseBranch({ owner, repo, prNumber, argv
|
|
|
214
248
|
return { checked: false, restored: false, reason: 'missing_pull_request_context' };
|
|
215
249
|
}
|
|
216
250
|
|
|
217
|
-
const currentBaseBranch = await
|
|
251
|
+
const { baseBranch: currentBaseBranch, headBranch } = await getPullRequestBranchRange({ owner, repo, prNumber, $, log });
|
|
218
252
|
if (currentBaseBranch === expectedBaseBranch) {
|
|
219
253
|
await log(formatAligned('🎯', 'Base branch locked:', `${expectedBaseBranch} (verified)`, 2), { verbose: true });
|
|
220
254
|
return {
|
|
@@ -227,6 +261,16 @@ export async function ensurePullRequestBaseBranch({ owner, repo, prNumber, argv
|
|
|
227
261
|
|
|
228
262
|
await log(formatAligned('⚠️', 'Base branch changed:', `PR #${prNumber} targets ${currentBaseBranch}, expected ${expectedBaseBranch}`, 2), { level: 'warning' });
|
|
229
263
|
|
|
264
|
+
if (headBranch === expectedBaseBranch) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
buildBaseEqualsHeadBranchMessage({
|
|
267
|
+
prNumber,
|
|
268
|
+
expectedBaseBranch,
|
|
269
|
+
currentBaseBranch,
|
|
270
|
+
})
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
230
274
|
if (onMismatch === 'throw' || onMismatch === 'fail') {
|
|
231
275
|
throw new Error(
|
|
232
276
|
buildPullRequestBaseBranchMismatchMessage({
|
|
@@ -249,7 +293,7 @@ export async function ensurePullRequestBaseBranch({ owner, repo, prNumber, argv
|
|
|
249
293
|
throw new Error(`Could not restore pull request #${prNumber} base branch to ${expectedBaseBranch}: ${details}`);
|
|
250
294
|
}
|
|
251
295
|
|
|
252
|
-
const restoredBaseBranch = await
|
|
296
|
+
const { baseBranch: restoredBaseBranch } = await getPullRequestBranchRange({ owner, repo, prNumber, $, log });
|
|
253
297
|
if (restoredBaseBranch !== expectedBaseBranch) {
|
|
254
298
|
throw new Error(`Pull request #${prNumber} still targets ${restoredBaseBranch} after attempting to restore ${expectedBaseBranch}`);
|
|
255
299
|
}
|