edsger 0.21.0 â 0.21.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.
|
@@ -5,6 +5,19 @@
|
|
|
5
5
|
import { Octokit } from '@octokit/rest';
|
|
6
6
|
import { execSync } from 'child_process';
|
|
7
7
|
import { logInfo, logError } from '../../utils/logger.js';
|
|
8
|
+
// GitHub PR title best practice: keep under 72 characters
|
|
9
|
+
const MAX_PR_TITLE_LENGTH = 72;
|
|
10
|
+
const PR_TITLE_PREFIX = 'feat: ';
|
|
11
|
+
const MAX_FEATURE_NAME_LENGTH = MAX_PR_TITLE_LENGTH - PR_TITLE_PREFIX.length;
|
|
12
|
+
/**
|
|
13
|
+
* Truncate text to a maximum length, adding ellipsis if truncated
|
|
14
|
+
*/
|
|
15
|
+
function truncateText(text, maxLength) {
|
|
16
|
+
if (text.length <= maxLength) {
|
|
17
|
+
return text;
|
|
18
|
+
}
|
|
19
|
+
return text.slice(0, maxLength - 3) + '...';
|
|
20
|
+
}
|
|
8
21
|
/**
|
|
9
22
|
* Convert a feat/ branch name to a dev/ branch name
|
|
10
23
|
* e.g., "feat/abc123/1-database" -> "dev/abc123/1-database"
|
|
@@ -142,8 +155,9 @@ export async function createBranchPullRequest(config, devBranchName, featureName
|
|
|
142
155
|
pullRequestNumber: existingPR.number,
|
|
143
156
|
};
|
|
144
157
|
}
|
|
145
|
-
// Generate PR title and body
|
|
146
|
-
const
|
|
158
|
+
// Generate PR title and body (truncate to keep under 72 chars)
|
|
159
|
+
const truncatedName = truncateText(featureName, MAX_FEATURE_NAME_LENGTH);
|
|
160
|
+
const title = `${PR_TITLE_PREFIX}${truncatedName}`;
|
|
147
161
|
const body = `## Branch Implementation
|
|
148
162
|
|
|
149
163
|
${branchDescription}
|
|
@@ -10,6 +10,16 @@ import { prepareCustomBranchGitEnvironment, syncFeatBranchWithMain, } from '../.
|
|
|
10
10
|
import { getCurrentBranch, updateBranch, getBranches, createBranches, getBaseBranchInfo, } from '../../services/branches.js';
|
|
11
11
|
import { createBranchPullRequest, } from './branch-pr-creator.js';
|
|
12
12
|
import { getGitHubConfig } from '../../api/github.js';
|
|
13
|
+
import { getFeature } from '../../api/features/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Truncate text to a maximum length, adding ellipsis if truncated
|
|
16
|
+
*/
|
|
17
|
+
function truncateText(text, maxLength) {
|
|
18
|
+
if (text.length <= maxLength) {
|
|
19
|
+
return text;
|
|
20
|
+
}
|
|
21
|
+
return text.slice(0, maxLength - 3) + '...';
|
|
22
|
+
}
|
|
13
23
|
function userMessage(content) {
|
|
14
24
|
return {
|
|
15
25
|
type: 'user',
|
|
@@ -50,11 +60,25 @@ export const implementFeatureCode = async (options, config, checklistContext) =>
|
|
|
50
60
|
if (verbose) {
|
|
51
61
|
logInfo(`đ Creating default branch record for feature: ${featureId}`);
|
|
52
62
|
}
|
|
63
|
+
// Fetch feature info to get the feature name for branch naming
|
|
64
|
+
let featureName = 'Feature Implementation';
|
|
65
|
+
try {
|
|
66
|
+
const featureInfo = await getFeature(featureId, verbose);
|
|
67
|
+
if (featureInfo?.name) {
|
|
68
|
+
// Truncate feature name for branch display (max 100 chars)
|
|
69
|
+
featureName = truncateText(featureInfo.name, 100);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (verbose) {
|
|
74
|
+
logInfo(`Could not fetch feature name, using default: ${error}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
53
77
|
const defaultBranchName = `dev/${featureId}`;
|
|
54
78
|
const createdBranches = await createBranches({ featureId, verbose }, [
|
|
55
79
|
{
|
|
56
|
-
name:
|
|
57
|
-
description:
|
|
80
|
+
name: featureName,
|
|
81
|
+
description: `Implementation branch for: ${featureName}`,
|
|
58
82
|
branch_name: defaultBranchName,
|
|
59
83
|
status: 'pending',
|
|
60
84
|
},
|
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { Octokit } from '@octokit/rest';
|
|
6
6
|
import { execSync } from 'child_process';
|
|
7
|
+
// GitHub PR title best practice: keep under 72 characters
|
|
8
|
+
const MAX_PR_TITLE_LENGTH = 72;
|
|
9
|
+
const PR_TITLE_PREFIX = 'feat: ';
|
|
10
|
+
const MAX_FEATURE_NAME_LENGTH = MAX_PR_TITLE_LENGTH - PR_TITLE_PREFIX.length;
|
|
11
|
+
/**
|
|
12
|
+
* Truncate text to a maximum length, adding ellipsis if truncated
|
|
13
|
+
*/
|
|
14
|
+
function truncateText(text, maxLength) {
|
|
15
|
+
if (text.length <= maxLength) {
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
return text.slice(0, maxLength - 3) + '...';
|
|
19
|
+
}
|
|
7
20
|
/**
|
|
8
21
|
* Get current Git branch name
|
|
9
22
|
*/
|
|
@@ -108,12 +121,14 @@ const switchToMainBranch = (mainBranch = 'main', verbose) => {
|
|
|
108
121
|
};
|
|
109
122
|
/**
|
|
110
123
|
* Generate pull request title from feature name
|
|
124
|
+
* Truncates to keep under 72 characters (GitHub best practice)
|
|
111
125
|
*/
|
|
112
126
|
const generatePRTitle = (featureName) => {
|
|
113
127
|
// Remove feature ID prefix if present (e.g., "FEAT-123: Feature Name" -> "Feature Name")
|
|
114
128
|
const cleanName = featureName.replace(/^[A-Z]+-\d+:\s*/, '');
|
|
115
|
-
//
|
|
116
|
-
|
|
129
|
+
// Truncate to keep total title under 72 chars
|
|
130
|
+
const truncatedName = truncateText(cleanName.toLowerCase(), MAX_FEATURE_NAME_LENGTH);
|
|
131
|
+
return `${PR_TITLE_PREFIX}${truncatedName}`;
|
|
117
132
|
};
|
|
118
133
|
/**
|
|
119
134
|
* Check if a pull request already exists from head to base
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import { getFeature } from '../../api/features/index.js';
|
|
5
5
|
import { getGitHubConfig } from '../../api/github.js';
|
|
6
6
|
import { createPullRequest } from './creator.js';
|
|
7
|
-
import { logFeaturePhaseEvent } from '../../services/audit-logs.js';
|
|
8
7
|
import { getCurrentBranch, updateBranch, } from '../../services/branches.js';
|
|
9
8
|
/**
|
|
10
9
|
* Create pull request for successful feature implementation
|
|
@@ -14,33 +13,12 @@ export async function handlePullRequestCreation({ featureId, results, testingRes
|
|
|
14
13
|
if (verbose) {
|
|
15
14
|
console.log('đ Creating pull request for successful feature...');
|
|
16
15
|
}
|
|
17
|
-
// Log phase start
|
|
18
|
-
await logFeaturePhaseEvent({
|
|
19
|
-
featureId,
|
|
20
|
-
eventType: 'phase_started',
|
|
21
|
-
phase: 'pull_request',
|
|
22
|
-
result: 'info',
|
|
23
|
-
metadata: {
|
|
24
|
-
timestamp: new Date().toISOString(),
|
|
25
|
-
},
|
|
26
|
-
}, verbose);
|
|
27
16
|
// Get feature details for PR creation
|
|
28
17
|
const feature = await getFeature(featureId, verbose);
|
|
29
18
|
if (!feature) {
|
|
30
19
|
if (verbose) {
|
|
31
20
|
console.log('â ī¸ Could not fetch feature details for pull request creation');
|
|
32
21
|
}
|
|
33
|
-
// Log phase failure
|
|
34
|
-
await logFeaturePhaseEvent({
|
|
35
|
-
featureId,
|
|
36
|
-
eventType: 'phase_failed',
|
|
37
|
-
phase: 'pull_request',
|
|
38
|
-
result: 'error',
|
|
39
|
-
errorMessage: 'Could not fetch feature details',
|
|
40
|
-
metadata: {
|
|
41
|
-
timestamp: new Date().toISOString(),
|
|
42
|
-
},
|
|
43
|
-
}, verbose);
|
|
44
22
|
return false;
|
|
45
23
|
}
|
|
46
24
|
// Get current branch for the feature
|
|
@@ -59,20 +37,6 @@ export async function handlePullRequestCreation({ featureId, results, testingRes
|
|
|
59
37
|
console.log(`âšī¸ Pull request already exists: ${currentBranch.pull_request_url}`);
|
|
60
38
|
console.log('â
Skipping PR creation, using existing pull request');
|
|
61
39
|
}
|
|
62
|
-
// Log phase completion with existing PR
|
|
63
|
-
await logFeaturePhaseEvent({
|
|
64
|
-
featureId,
|
|
65
|
-
eventType: 'phase_completed',
|
|
66
|
-
phase: 'pull_request',
|
|
67
|
-
result: 'success',
|
|
68
|
-
metadata: {
|
|
69
|
-
pull_request_url: currentBranch.pull_request_url,
|
|
70
|
-
branch_id: currentBranch.id,
|
|
71
|
-
skipped: true,
|
|
72
|
-
reason: 'Pull request already exists',
|
|
73
|
-
timestamp: new Date().toISOString(),
|
|
74
|
-
},
|
|
75
|
-
}, verbose);
|
|
76
40
|
return true;
|
|
77
41
|
}
|
|
78
42
|
// Get GitHub configuration from product developer settings
|
|
@@ -85,17 +49,6 @@ export async function handlePullRequestCreation({ featureId, results, testingRes
|
|
|
85
49
|
console.log('â ī¸ GitHub configuration not found. Skipping pull request creation.');
|
|
86
50
|
console.log(` ${githubConfig.message || 'Please configure a developer with GitHub App installation in the product settings.'}`);
|
|
87
51
|
}
|
|
88
|
-
// Log phase failure
|
|
89
|
-
await logFeaturePhaseEvent({
|
|
90
|
-
featureId,
|
|
91
|
-
eventType: 'phase_failed',
|
|
92
|
-
phase: 'pull_request',
|
|
93
|
-
result: 'error',
|
|
94
|
-
errorMessage: githubConfig.message || 'GitHub configuration not found',
|
|
95
|
-
metadata: {
|
|
96
|
-
timestamp: new Date().toISOString(),
|
|
97
|
-
},
|
|
98
|
-
}, verbose);
|
|
99
52
|
return false;
|
|
100
53
|
}
|
|
101
54
|
const { token: githubToken, owner: githubOwner, repo: githubRepo, } = githubConfig;
|
|
@@ -141,19 +94,6 @@ export async function handlePullRequestCreation({ featureId, results, testingRes
|
|
|
141
94
|
}
|
|
142
95
|
}
|
|
143
96
|
}
|
|
144
|
-
// Log phase completion
|
|
145
|
-
await logFeaturePhaseEvent({
|
|
146
|
-
featureId,
|
|
147
|
-
eventType: 'phase_completed',
|
|
148
|
-
phase: 'pull_request',
|
|
149
|
-
result: 'success',
|
|
150
|
-
metadata: {
|
|
151
|
-
pull_request_url: prResult.pullRequestUrl,
|
|
152
|
-
pull_request_number: prResult.pullRequestNumber,
|
|
153
|
-
branch_id: currentBranch?.id,
|
|
154
|
-
timestamp: new Date().toISOString(),
|
|
155
|
-
},
|
|
156
|
-
}, verbose);
|
|
157
97
|
if (verbose) {
|
|
158
98
|
console.log(`â
Pull request created${currentBranch ? ' and branch updated' : ''}`);
|
|
159
99
|
}
|
|
@@ -163,17 +103,6 @@ export async function handlePullRequestCreation({ featureId, results, testingRes
|
|
|
163
103
|
if (verbose) {
|
|
164
104
|
console.log(`â ī¸ Pull request creation failed: ${prResult.error}`);
|
|
165
105
|
}
|
|
166
|
-
// Log phase failure
|
|
167
|
-
await logFeaturePhaseEvent({
|
|
168
|
-
featureId,
|
|
169
|
-
eventType: 'phase_failed',
|
|
170
|
-
phase: 'pull_request',
|
|
171
|
-
result: 'error',
|
|
172
|
-
errorMessage: prResult.error,
|
|
173
|
-
metadata: {
|
|
174
|
-
timestamp: new Date().toISOString(),
|
|
175
|
-
},
|
|
176
|
-
}, verbose);
|
|
177
106
|
return false;
|
|
178
107
|
}
|
|
179
108
|
}
|