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 title = `feat: ${featureName}`;
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: 'Main Implementation',
57
- description: 'Default branch for feature implementation',
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
- // Convert to lowercase for conventional commits format
116
- return `feat: ${cleanName.toLowerCase()}`;
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.21.0",
3
+ "version": "0.21.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"