edsger 0.21.3 ā 0.21.5
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.
|
@@ -14,7 +14,6 @@ import { markWorkflowPhaseCompleted } from '../../api/features/update-feature.js
|
|
|
14
14
|
import { logError, logInfo, logWarning } from '../../utils/logger.js';
|
|
15
15
|
import { logPhaseResult } from '../../utils/pipeline-logger.js';
|
|
16
16
|
import { runFeatureAnalysisPhase, runTechnicalDesignPhase, runBranchPlanningPhase, runCodeImplementationPhase, runFunctionalTestingPhase, runCodeRefinePhase, runCodeReviewPhase, } from './executors/phase-executor.js';
|
|
17
|
-
import { handlePullRequestCreation } from '../../phases/pull-request/handler.js';
|
|
18
17
|
/**
|
|
19
18
|
* Map workflow phase names (underscore format) to phase runner functions
|
|
20
19
|
* Note: code_refine includes built-in verification loop (similar to technical_design)
|
|
@@ -104,8 +103,6 @@ export async function runFeatureWorkflow(options, config) {
|
|
|
104
103
|
}
|
|
105
104
|
// 3. Execute each pending phase in order
|
|
106
105
|
const results = [];
|
|
107
|
-
// Check if workflow includes a pull_request phase
|
|
108
|
-
const hasPullRequestPhase = pendingPhases.some((p) => p.phase === 'pull_request');
|
|
109
106
|
for (const workflowPhase of pendingPhases) {
|
|
110
107
|
const result = await executePhase(workflowPhase.phase, options, config);
|
|
111
108
|
results.push(result);
|
|
@@ -116,37 +113,8 @@ export async function runFeatureWorkflow(options, config) {
|
|
|
116
113
|
}
|
|
117
114
|
break;
|
|
118
115
|
}
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
result.status === 'success' &&
|
|
122
|
-
!hasPullRequestPhase) {
|
|
123
|
-
if (verbose) {
|
|
124
|
-
logInfo('\nš Creating pull request for implemented code...');
|
|
125
|
-
}
|
|
126
|
-
const prCreated = await handlePullRequestCreation({
|
|
127
|
-
featureId,
|
|
128
|
-
results,
|
|
129
|
-
verbose,
|
|
130
|
-
});
|
|
131
|
-
const prResult = {
|
|
132
|
-
featureId,
|
|
133
|
-
phase: 'pull-request',
|
|
134
|
-
status: prCreated ? 'success' : 'error',
|
|
135
|
-
message: prCreated
|
|
136
|
-
? 'Pull request created successfully'
|
|
137
|
-
: 'Pull request creation failed',
|
|
138
|
-
data: {},
|
|
139
|
-
};
|
|
140
|
-
logPhaseResult(prResult, verbose);
|
|
141
|
-
results.push(prResult);
|
|
142
|
-
// If PR creation failed, stop workflow
|
|
143
|
-
if (!prCreated) {
|
|
144
|
-
if (verbose) {
|
|
145
|
-
logInfo('\nā Stopping workflow execution: pull-request failed');
|
|
146
|
-
}
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
116
|
+
// Note: PR creation is now handled within the code-implementation phase itself,
|
|
117
|
+
// so we no longer need to create it here after code_implementation succeeds.
|
|
150
118
|
}
|
|
151
119
|
if (verbose) {
|
|
152
120
|
const successCount = results.filter((r) => r.status === 'success').length;
|
|
@@ -42,6 +42,7 @@ export function devBranchToFeatBranch(devBranchName) {
|
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Push a branch to remote
|
|
45
|
+
* Falls back to force-with-lease if normal push fails (e.g., after rebase)
|
|
45
46
|
*/
|
|
46
47
|
async function pushBranch(branchName, verbose) {
|
|
47
48
|
try {
|
|
@@ -66,8 +67,27 @@ async function pushBranch(branchName, verbose) {
|
|
|
66
67
|
return { success: true };
|
|
67
68
|
}
|
|
68
69
|
catch (retryError) {
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
// If push still fails (likely non-fast-forward after rebase),
|
|
71
|
+
// use force-with-lease for safer force push
|
|
72
|
+
if (verbose) {
|
|
73
|
+
logInfo(`ā ļø Push rejected, attempting force push with lease...`);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
execSync(`git push --force-with-lease origin ${branchName}`, {
|
|
77
|
+
encoding: 'utf-8',
|
|
78
|
+
stdio: verbose ? 'inherit' : 'pipe',
|
|
79
|
+
});
|
|
80
|
+
if (verbose) {
|
|
81
|
+
logInfo(`ā
Successfully force pushed ${branchName}`);
|
|
82
|
+
}
|
|
83
|
+
return { success: true };
|
|
84
|
+
}
|
|
85
|
+
catch (forceError) {
|
|
86
|
+
const errorMessage = forceError instanceof Error
|
|
87
|
+
? forceError.message
|
|
88
|
+
: String(forceError);
|
|
89
|
+
return { success: false, error: errorMessage };
|
|
90
|
+
}
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
93
|
}
|
|
@@ -856,6 +856,7 @@ const parseImplementationResponse = (response, featureId) => {
|
|
|
856
856
|
};
|
|
857
857
|
/**
|
|
858
858
|
* Push branch to remote repository
|
|
859
|
+
* Falls back to force-with-lease if normal push fails (e.g., after rebase)
|
|
859
860
|
*/
|
|
860
861
|
async function pushToRemote(branchName, verbose) {
|
|
861
862
|
try {
|
|
@@ -883,11 +884,31 @@ async function pushToRemote(branchName, verbose) {
|
|
|
883
884
|
return { success: true };
|
|
884
885
|
}
|
|
885
886
|
catch (retryError) {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
887
|
+
// If push still fails (likely non-fast-forward after rebase),
|
|
888
|
+
// use force-with-lease for safer force push
|
|
889
|
+
// force-with-lease ensures we don't overwrite others' work by checking remote state
|
|
890
|
+
if (verbose) {
|
|
891
|
+
logInfo(`ā ļø Push rejected, attempting force push with lease...`);
|
|
892
|
+
}
|
|
893
|
+
try {
|
|
894
|
+
execSync(`git push --force-with-lease origin ${branchName}`, {
|
|
895
|
+
encoding: 'utf-8',
|
|
896
|
+
stdio: verbose ? 'inherit' : 'pipe',
|
|
897
|
+
});
|
|
898
|
+
if (verbose) {
|
|
899
|
+
logInfo(`ā
Successfully force pushed ${branchName}`);
|
|
900
|
+
}
|
|
901
|
+
return { success: true };
|
|
902
|
+
}
|
|
903
|
+
catch (forceError) {
|
|
904
|
+
const errorMessage = forceError instanceof Error
|
|
905
|
+
? forceError.message
|
|
906
|
+
: String(forceError);
|
|
907
|
+
return {
|
|
908
|
+
success: false,
|
|
909
|
+
error: errorMessage,
|
|
910
|
+
};
|
|
911
|
+
}
|
|
891
912
|
}
|
|
892
913
|
}
|
|
893
914
|
}
|
|
@@ -85,6 +85,7 @@ const switchToBranch = (branch, verbose) => {
|
|
|
85
85
|
};
|
|
86
86
|
/**
|
|
87
87
|
* Push current branch to remote
|
|
88
|
+
* Falls back to force-with-lease if normal push fails (e.g., after rebase)
|
|
88
89
|
*/
|
|
89
90
|
const pushBranch = (branch, verbose) => {
|
|
90
91
|
try {
|
|
@@ -97,7 +98,22 @@ const pushBranch = (branch, verbose) => {
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
catch (error) {
|
|
100
|
-
|
|
101
|
+
// If push fails (likely non-fast-forward after rebase),
|
|
102
|
+
// use force-with-lease for safer force push
|
|
103
|
+
if (verbose) {
|
|
104
|
+
console.log(`ā ļø Push rejected, attempting force push with lease...`);
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
execSync(`git push --force-with-lease origin ${branch}`, {
|
|
108
|
+
encoding: 'utf-8',
|
|
109
|
+
});
|
|
110
|
+
if (verbose) {
|
|
111
|
+
console.log(`ā
Successfully force pushed ${branch}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (forceError) {
|
|
115
|
+
throw new Error(`Failed to push branch: ${forceError}`);
|
|
116
|
+
}
|
|
101
117
|
}
|
|
102
118
|
};
|
|
103
119
|
/**
|