edsger 0.30.2 ā 0.30.3
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.
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
1
|
+
import { execSync, execFileSync } from 'child_process';
|
|
2
2
|
import { logInfo, logError } from '../../utils/logger.js';
|
|
3
|
+
import { buildCredentialArgs } from '../../utils/git-push.js';
|
|
3
4
|
import { getFeature } from '../../api/features/index.js';
|
|
4
5
|
import { getPullRequests, } from '../../services/pull-requests.js';
|
|
5
6
|
import { getGitHubConfig } from '../../api/github.js';
|
|
@@ -76,26 +77,26 @@ export async function fetchPRExecutionContext(featureId, verbose) {
|
|
|
76
77
|
throw new Error(`Development branch '${devBranchName}' does not exist. ` +
|
|
77
78
|
`The feature must have code on the dev branch before PR execution.`);
|
|
78
79
|
}
|
|
79
|
-
//
|
|
80
|
+
// Fetch GitHub config and data in parallel
|
|
81
|
+
const [feature, pullRequests, githubConfig] = await Promise.all([
|
|
82
|
+
getFeature(featureId, verbose),
|
|
83
|
+
getPullRequests({ featureId, verbose }),
|
|
84
|
+
getGitHubConfig(featureId, verbose),
|
|
85
|
+
]);
|
|
86
|
+
// If branch only exists on remote, fetch it (using credential helper)
|
|
80
87
|
if (!localExists && remoteExists) {
|
|
81
88
|
if (verbose) {
|
|
82
89
|
logInfo(`Fetching remote branch ${devBranchName}...`);
|
|
83
90
|
}
|
|
84
|
-
|
|
91
|
+
const credArgs = buildCredentialArgs(githubConfig.token);
|
|
92
|
+
execFileSync('git', [...credArgs, 'fetch', 'origin', devBranchName], {
|
|
85
93
|
encoding: 'utf-8',
|
|
86
94
|
stdio: 'pipe',
|
|
87
95
|
});
|
|
88
96
|
}
|
|
89
|
-
// Fetch data in parallel
|
|
90
|
-
const [feature, pullRequests] = await Promise.all([
|
|
91
|
-
getFeature(featureId, verbose),
|
|
92
|
-
getPullRequests({ featureId, verbose }),
|
|
93
|
-
]);
|
|
94
97
|
if (pullRequests.length === 0) {
|
|
95
98
|
throw new Error('No PR plan found. Run the pr-splitting phase first to create a PR plan.');
|
|
96
99
|
}
|
|
97
|
-
// Fetch GitHub config
|
|
98
|
-
const githubConfig = await getGitHubConfig(featureId, verbose);
|
|
99
100
|
if (!githubConfig.configured) {
|
|
100
101
|
throw new Error(`GitHub is not configured. ${githubConfig.message || 'Please configure GitHub integration.'}`);
|
|
101
102
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
1
|
+
import { execSync, execFileSync } from 'child_process';
|
|
2
2
|
import { logInfo, logError } from '../../utils/logger.js';
|
|
3
|
+
import { buildCredentialArgs } from '../../utils/git-push.js';
|
|
3
4
|
import { getFeature } from '../../api/features/index.js';
|
|
4
5
|
import { getProduct } from '../../api/products.js';
|
|
5
6
|
import { getBranches } from '../../services/branches.js';
|
|
@@ -82,25 +83,25 @@ export async function fetchPRSplittingContext(featureId, verbose, replaceExistin
|
|
|
82
83
|
throw new Error(`Development branch '${devBranchName}' does not exist. ` +
|
|
83
84
|
`The feature must have code on the dev branch before PR splitting.`);
|
|
84
85
|
}
|
|
85
|
-
//
|
|
86
|
+
// Fetch database data and GitHub config in parallel
|
|
87
|
+
const [feature, existing_branches, existing_pull_requests, githubConfig] = await Promise.all([
|
|
88
|
+
getFeature(featureId, verbose),
|
|
89
|
+
getBranches({ featureId, verbose }).catch(() => []),
|
|
90
|
+
getPullRequests({ featureId, verbose }).catch(() => []),
|
|
91
|
+
getGitHubConfig(featureId, verbose),
|
|
92
|
+
]);
|
|
93
|
+
// If branch only exists on remote, fetch it (using credential helper)
|
|
86
94
|
if (!localExists && remoteExists) {
|
|
87
95
|
if (verbose) {
|
|
88
96
|
logInfo(`Fetching remote branch ${devBranchName}...`);
|
|
89
97
|
}
|
|
90
|
-
|
|
98
|
+
const credArgs = buildCredentialArgs(githubConfig.token);
|
|
99
|
+
execFileSync('git', [...credArgs, 'fetch', 'origin', devBranchName], {
|
|
91
100
|
encoding: 'utf-8',
|
|
92
101
|
stdio: 'pipe',
|
|
93
102
|
});
|
|
94
103
|
}
|
|
95
|
-
// Fetch database data in parallel
|
|
96
|
-
const [feature, existing_branches, existing_pull_requests] = await Promise.all([
|
|
97
|
-
getFeature(featureId, verbose),
|
|
98
|
-
getBranches({ featureId, verbose }).catch(() => []),
|
|
99
|
-
getPullRequests({ featureId, verbose }).catch(() => []),
|
|
100
|
-
]);
|
|
101
104
|
const product = await getProduct(feature.product_id, verbose);
|
|
102
|
-
// Fetch GitHub config
|
|
103
|
-
const githubConfig = await getGitHubConfig(featureId, verbose);
|
|
104
105
|
// Detect fork status
|
|
105
106
|
let forkInfo = { isFork: false };
|
|
106
107
|
if (githubConfig.configured && githubConfig.token && githubConfig.owner && githubConfig.repo) {
|
|
@@ -67,7 +67,7 @@ export declare function branchExists(branch: string): boolean;
|
|
|
67
67
|
/**
|
|
68
68
|
* Check if a remote branch exists
|
|
69
69
|
*/
|
|
70
|
-
export declare function remoteBranchExists(branch: string): boolean;
|
|
70
|
+
export declare function remoteBranchExists(branch: string, githubToken?: string): boolean;
|
|
71
71
|
/**
|
|
72
72
|
* Options for switchToBranch
|
|
73
73
|
*/
|
|
@@ -79,6 +79,8 @@ export interface SwitchToBranchOptions {
|
|
|
79
79
|
* Set this to true to skip the remote check (useful for well-known local branches like 'main').
|
|
80
80
|
*/
|
|
81
81
|
skipRemoteCheck?: boolean;
|
|
82
|
+
/** GitHub App installation token for authenticated remote operations */
|
|
83
|
+
githubToken?: string;
|
|
82
84
|
}
|
|
83
85
|
/**
|
|
84
86
|
* Switch to a specific Git branch, creating it if it doesn't exist
|
|
@@ -99,7 +101,7 @@ export declare function switchToBranch(branch: string, verbose?: boolean, option
|
|
|
99
101
|
/**
|
|
100
102
|
* Pull latest changes from remote for a specific branch
|
|
101
103
|
*/
|
|
102
|
-
export declare function pullLatestFromBranch(branch: string, verbose?: boolean): void;
|
|
104
|
+
export declare function pullLatestFromBranch(branch: string, verbose?: boolean, githubToken?: string): void;
|
|
103
105
|
/**
|
|
104
106
|
* Switch to feature branch and rebase with main
|
|
105
107
|
* This should be called at the START of each phase
|
|
@@ -109,7 +111,7 @@ export declare function pullLatestFromBranch(branch: string, verbose?: boolean):
|
|
|
109
111
|
* @param verbose - Whether to log verbose output
|
|
110
112
|
* @returns Object containing the previous branch name
|
|
111
113
|
*/
|
|
112
|
-
export declare function switchToFeatureBranchAndRebase(featureBranch: string, baseBranch?: string, verbose?: boolean): {
|
|
114
|
+
export declare function switchToFeatureBranchAndRebase(featureBranch: string, baseBranch?: string, verbose?: boolean, githubToken?: string): {
|
|
113
115
|
previousBranch: string;
|
|
114
116
|
};
|
|
115
117
|
/**
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Git Branch Manager
|
|
3
3
|
* Shared utilities for consistent git branch management across all phases
|
|
4
4
|
*/
|
|
5
|
-
import { execSync } from 'child_process';
|
|
5
|
+
import { execSync, execFileSync } from 'child_process';
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import * as path from 'path';
|
|
8
8
|
import { Octokit } from '@octokit/rest';
|
|
9
9
|
import { logInfo, logError } from './logger.js';
|
|
10
|
-
import { gitForcePush } from './git-push.js';
|
|
10
|
+
import { gitForcePush, buildCredentialArgs } from './git-push.js';
|
|
11
11
|
/**
|
|
12
12
|
* Get current Git branch name
|
|
13
13
|
*/
|
|
@@ -225,10 +225,11 @@ export function branchExists(branch) {
|
|
|
225
225
|
/**
|
|
226
226
|
* Check if a remote branch exists
|
|
227
227
|
*/
|
|
228
|
-
export function remoteBranchExists(branch) {
|
|
228
|
+
export function remoteBranchExists(branch, githubToken) {
|
|
229
229
|
try {
|
|
230
230
|
// Fetch remote refs first to ensure we have latest info
|
|
231
|
-
|
|
231
|
+
const credArgs = buildCredentialArgs(githubToken);
|
|
232
|
+
execFileSync('git', [...credArgs, 'fetch', 'origin', '--prune'], { encoding: 'utf-8', stdio: 'pipe' });
|
|
232
233
|
execSync(`git rev-parse --verify origin/${branch}`, {
|
|
233
234
|
encoding: 'utf-8',
|
|
234
235
|
stdio: 'pipe',
|
|
@@ -280,7 +281,8 @@ export function switchToBranch(branch, verbose, options) {
|
|
|
280
281
|
// This handles multi-clone scenarios where branch was pushed from another clone
|
|
281
282
|
try {
|
|
282
283
|
// Fetch to get latest remote refs
|
|
283
|
-
|
|
284
|
+
const switchCredArgs = buildCredentialArgs(options?.githubToken);
|
|
285
|
+
execFileSync('git', [...switchCredArgs, 'fetch', 'origin'], { encoding: 'utf-8', stdio: 'pipe' });
|
|
284
286
|
// Check if remote branch exists
|
|
285
287
|
execSync(`git rev-parse --verify origin/${branch}`, {
|
|
286
288
|
encoding: 'utf-8',
|
|
@@ -317,7 +319,7 @@ export function switchToBranch(branch, verbose, options) {
|
|
|
317
319
|
/**
|
|
318
320
|
* Pull latest changes from remote for a specific branch
|
|
319
321
|
*/
|
|
320
|
-
export function pullLatestFromBranch(branch, verbose) {
|
|
322
|
+
export function pullLatestFromBranch(branch, verbose, githubToken) {
|
|
321
323
|
try {
|
|
322
324
|
// Check for uncommitted changes and reset if found
|
|
323
325
|
if (hasUncommittedChanges()) {
|
|
@@ -329,7 +331,8 @@ export function pullLatestFromBranch(branch, verbose) {
|
|
|
329
331
|
if (verbose) {
|
|
330
332
|
logInfo(`š„ Pulling latest changes from origin/${branch}...`);
|
|
331
333
|
}
|
|
332
|
-
|
|
334
|
+
const credArgs = buildCredentialArgs(githubToken);
|
|
335
|
+
execFileSync('git', [...credArgs, 'pull', 'origin', branch, '--rebase'], {
|
|
333
336
|
encoding: 'utf-8',
|
|
334
337
|
stdio: verbose ? 'inherit' : 'pipe',
|
|
335
338
|
});
|
|
@@ -350,7 +353,7 @@ export function pullLatestFromBranch(branch, verbose) {
|
|
|
350
353
|
* @param verbose - Whether to log verbose output
|
|
351
354
|
* @returns Object containing the previous branch name
|
|
352
355
|
*/
|
|
353
|
-
export function switchToFeatureBranchAndRebase(featureBranch, baseBranch = 'main', verbose) {
|
|
356
|
+
export function switchToFeatureBranchAndRebase(featureBranch, baseBranch = 'main', verbose, githubToken) {
|
|
354
357
|
const previousBranch = getCurrentBranch();
|
|
355
358
|
if (verbose) {
|
|
356
359
|
logInfo(`\nš Preparing feature branch: ${featureBranch}`);
|
|
@@ -373,7 +376,7 @@ export function switchToFeatureBranchAndRebase(featureBranch, baseBranch = 'main
|
|
|
373
376
|
if (verbose) {
|
|
374
377
|
logInfo(` Pulling latest ${baseBranch}...`);
|
|
375
378
|
}
|
|
376
|
-
pullLatestFromBranch(baseBranch, verbose);
|
|
379
|
+
pullLatestFromBranch(baseBranch, verbose, githubToken);
|
|
377
380
|
}
|
|
378
381
|
catch (error) {
|
|
379
382
|
if (verbose) {
|
|
@@ -397,7 +400,8 @@ export function switchToFeatureBranchAndRebase(featureBranch, baseBranch = 'main
|
|
|
397
400
|
resetUncommittedChanges(verbose);
|
|
398
401
|
}
|
|
399
402
|
// Fetch to get latest remote state (may have been fetched in switchToBranch, but ensures fresh data)
|
|
400
|
-
|
|
403
|
+
const credArgs = buildCredentialArgs(githubToken);
|
|
404
|
+
execFileSync('git', [...credArgs, 'fetch', 'origin'], { encoding: 'utf-8', stdio: 'pipe' });
|
|
401
405
|
// Check if remote feature branch exists
|
|
402
406
|
try {
|
|
403
407
|
execSync(`git rev-parse --verify origin/${featureBranch}`, {
|
|
@@ -459,7 +463,8 @@ export function switchToFeatureBranchAndRebase(featureBranch, baseBranch = 'main
|
|
|
459
463
|
}
|
|
460
464
|
resetUncommittedChanges(verbose);
|
|
461
465
|
}
|
|
462
|
-
|
|
466
|
+
const rebaseCredArgs = buildCredentialArgs(githubToken);
|
|
467
|
+
execFileSync('git', [...rebaseCredArgs, 'pull', 'origin', baseBranch, '--rebase'], {
|
|
463
468
|
encoding: 'utf-8',
|
|
464
469
|
stdio: verbose ? 'inherit' : 'pipe',
|
|
465
470
|
});
|
|
@@ -716,7 +721,7 @@ export async function switchToFeatureBranchAndRebaseAsync(options) {
|
|
|
716
721
|
if (verbose) {
|
|
717
722
|
logInfo(` Pulling latest ${baseBranch}...`);
|
|
718
723
|
}
|
|
719
|
-
pullLatestFromBranch(baseBranch, verbose);
|
|
724
|
+
pullLatestFromBranch(baseBranch, verbose, githubToken);
|
|
720
725
|
}
|
|
721
726
|
catch (error) {
|
|
722
727
|
if (verbose) {
|
|
@@ -739,7 +744,8 @@ export async function switchToFeatureBranchAndRebaseAsync(options) {
|
|
|
739
744
|
resetUncommittedChanges(verbose);
|
|
740
745
|
}
|
|
741
746
|
// Fetch to get latest remote state (may have been fetched in switchToBranch, but ensures fresh data)
|
|
742
|
-
|
|
747
|
+
const syncCredArgs = buildCredentialArgs(githubToken);
|
|
748
|
+
execFileSync('git', [...syncCredArgs, 'fetch', 'origin'], { encoding: 'utf-8', stdio: 'pipe' });
|
|
743
749
|
try {
|
|
744
750
|
execSync(`git rev-parse --verify origin/${featureBranch}`, {
|
|
745
751
|
encoding: 'utf-8',
|
|
@@ -802,7 +808,8 @@ export async function switchToFeatureBranchAndRebaseAsync(options) {
|
|
|
802
808
|
resetUncommittedChanges(verbose);
|
|
803
809
|
}
|
|
804
810
|
// Fetch the target branch first
|
|
805
|
-
|
|
811
|
+
const fetchCredArgs = buildCredentialArgs(githubToken);
|
|
812
|
+
execFileSync('git', [...fetchCredArgs, 'fetch', 'origin', actualRebaseTarget], {
|
|
806
813
|
encoding: 'utf-8',
|
|
807
814
|
stdio: 'pipe',
|
|
808
815
|
});
|
|
@@ -812,7 +819,7 @@ export async function switchToFeatureBranchAndRebaseAsync(options) {
|
|
|
812
819
|
// Command: git rebase --onto <new-base> <old-base>
|
|
813
820
|
// This rebases commits from <old-base>..HEAD onto <new-base>
|
|
814
821
|
// Also fetch the originalBaseBranch for the --onto reference
|
|
815
|
-
|
|
822
|
+
execFileSync('git', [...fetchCredArgs, 'fetch', 'origin', originalBaseBranch], {
|
|
816
823
|
encoding: 'utf-8',
|
|
817
824
|
stdio: 'pipe',
|
|
818
825
|
});
|