@git.zone/cli 2.13.13 → 2.14.0
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/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/gitzone.cli.js +46 -35
- package/dist_ts/helpers.climode.d.ts +22 -0
- package/dist_ts/helpers.climode.js +158 -0
- package/dist_ts/helpers.smartconfig.d.ts +11 -0
- package/dist_ts/helpers.smartconfig.js +139 -0
- package/dist_ts/mod_commit/index.d.ts +2 -0
- package/dist_ts/mod_commit/index.js +204 -92
- package/dist_ts/mod_config/index.d.ts +7 -2
- package/dist_ts/mod_config/index.js +390 -176
- package/dist_ts/mod_format/classes.formatcontext.d.ts +11 -2
- package/dist_ts/mod_format/classes.formatcontext.js +14 -4
- package/dist_ts/mod_format/formatters/packagejson.formatter.js +1 -67
- package/dist_ts/mod_format/formatters/smartconfig.formatter.d.ts +2 -7
- package/dist_ts/mod_format/formatters/smartconfig.formatter.js +57 -93
- package/dist_ts/mod_format/index.d.ts +4 -1
- package/dist_ts/mod_format/index.js +235 -67
- package/dist_ts/mod_format/mod.plugins.d.ts +1 -2
- package/dist_ts/mod_format/mod.plugins.js +2 -3
- package/dist_ts/mod_services/index.d.ts +2 -0
- package/dist_ts/mod_services/index.js +366 -168
- package/dist_ts/mod_standard/index.d.ts +3 -1
- package/dist_ts/mod_standard/index.js +159 -59
- package/package.json +1 -1
- package/readme.hints.md +25 -32
- package/readme.md +87 -65
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/gitzone.cli.ts +50 -38
- package/ts/helpers.climode.ts +212 -0
- package/ts/helpers.smartconfig.ts +192 -0
- package/ts/mod_commit/index.ts +325 -98
- package/ts/mod_config/index.ts +490 -182
- package/ts/mod_format/classes.formatcontext.ts +20 -3
- package/ts/mod_format/formatters/packagejson.formatter.ts +0 -91
- package/ts/mod_format/formatters/smartconfig.formatter.ts +67 -94
- package/ts/mod_format/index.ts +294 -81
- package/ts/mod_format/mod.plugins.ts +0 -2
- package/ts/mod_services/index.ts +550 -183
- package/ts/mod_standard/index.ts +191 -58
package/ts/mod_commit/index.ts
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
// this file contains code to create commits in a consistent way
|
|
2
2
|
|
|
3
|
-
import * as plugins from
|
|
4
|
-
import * as paths from
|
|
5
|
-
import { logger } from
|
|
6
|
-
import * as helpers from
|
|
7
|
-
import * as ui from
|
|
8
|
-
import { ReleaseConfig } from
|
|
3
|
+
import * as plugins from "./mod.plugins.js";
|
|
4
|
+
import * as paths from "../paths.js";
|
|
5
|
+
import { logger } from "../gitzone.logging.js";
|
|
6
|
+
import * as helpers from "./mod.helpers.js";
|
|
7
|
+
import * as ui from "./mod.ui.js";
|
|
8
|
+
import { ReleaseConfig } from "../mod_config/classes.releaseconfig.js";
|
|
9
|
+
import type { ICliMode } from "../helpers.climode.js";
|
|
10
|
+
import {
|
|
11
|
+
getCliMode,
|
|
12
|
+
printJson,
|
|
13
|
+
runWithSuppressedOutput,
|
|
14
|
+
} from "../helpers.climode.js";
|
|
9
15
|
|
|
10
16
|
export const run = async (argvArg: any) => {
|
|
17
|
+
const mode = await getCliMode(argvArg);
|
|
18
|
+
const subcommand = argvArg._?.[1];
|
|
19
|
+
|
|
20
|
+
if (mode.help || subcommand === "help") {
|
|
21
|
+
showHelp(mode);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (subcommand === "recommend") {
|
|
26
|
+
await handleRecommend(mode);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (mode.json) {
|
|
31
|
+
printJson({
|
|
32
|
+
ok: false,
|
|
33
|
+
error:
|
|
34
|
+
"JSON output is only supported for the read-only recommendation flow. Use `gitzone commit recommend --json`.",
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
|
|
11
39
|
// Read commit config from .smartconfig.json
|
|
12
40
|
const smartconfigInstance = new plugins.smartconfig.Smartconfig();
|
|
13
41
|
const gitzoneConfig = smartconfigInstance.dataFor<{
|
|
@@ -15,7 +43,7 @@ export const run = async (argvArg: any) => {
|
|
|
15
43
|
alwaysTest?: boolean;
|
|
16
44
|
alwaysBuild?: boolean;
|
|
17
45
|
};
|
|
18
|
-
}>(
|
|
46
|
+
}>("@git.zone/cli", {});
|
|
19
47
|
const commitConfig = gitzoneConfig.commit || {};
|
|
20
48
|
|
|
21
49
|
// Check flags and merge with config options
|
|
@@ -27,10 +55,12 @@ export const run = async (argvArg: any) => {
|
|
|
27
55
|
if (wantsRelease) {
|
|
28
56
|
releaseConfig = await ReleaseConfig.fromCwd();
|
|
29
57
|
if (!releaseConfig.hasRegistries()) {
|
|
30
|
-
logger.log(
|
|
31
|
-
console.log(
|
|
32
|
-
console.log(
|
|
33
|
-
|
|
58
|
+
logger.log("error", "No release registries configured.");
|
|
59
|
+
console.log("");
|
|
60
|
+
console.log(
|
|
61
|
+
" Run `gitzone config add <registry-url>` to add registries.",
|
|
62
|
+
);
|
|
63
|
+
console.log("");
|
|
34
64
|
process.exit(1);
|
|
35
65
|
}
|
|
36
66
|
}
|
|
@@ -47,26 +77,26 @@ export const run = async (argvArg: any) => {
|
|
|
47
77
|
});
|
|
48
78
|
|
|
49
79
|
if (argvArg.format) {
|
|
50
|
-
const formatMod = await import(
|
|
80
|
+
const formatMod = await import("../mod_format/index.js");
|
|
51
81
|
await formatMod.run();
|
|
52
82
|
}
|
|
53
83
|
|
|
54
84
|
// Run tests early to fail fast before analysis
|
|
55
85
|
if (wantsTest) {
|
|
56
|
-
ui.printHeader(
|
|
86
|
+
ui.printHeader("🧪 Running tests...");
|
|
57
87
|
const smartshellForTest = new plugins.smartshell.Smartshell({
|
|
58
|
-
executor:
|
|
88
|
+
executor: "bash",
|
|
59
89
|
sourceFilePaths: [],
|
|
60
90
|
});
|
|
61
|
-
const testResult = await smartshellForTest.exec(
|
|
91
|
+
const testResult = await smartshellForTest.exec("pnpm test");
|
|
62
92
|
if (testResult.exitCode !== 0) {
|
|
63
|
-
logger.log(
|
|
93
|
+
logger.log("error", "Tests failed. Aborting commit.");
|
|
64
94
|
process.exit(1);
|
|
65
95
|
}
|
|
66
|
-
logger.log(
|
|
96
|
+
logger.log("success", "All tests passed.");
|
|
67
97
|
}
|
|
68
98
|
|
|
69
|
-
ui.printHeader(
|
|
99
|
+
ui.printHeader("🔍 Analyzing repository changes...");
|
|
70
100
|
|
|
71
101
|
const aidoc = new plugins.tsdoc.AiDoc();
|
|
72
102
|
await aidoc.start();
|
|
@@ -79,58 +109,63 @@ export const run = async (argvArg: any) => {
|
|
|
79
109
|
recommendedNextVersion: nextCommitObject.recommendedNextVersion,
|
|
80
110
|
recommendedNextVersionLevel: nextCommitObject.recommendedNextVersionLevel,
|
|
81
111
|
recommendedNextVersionScope: nextCommitObject.recommendedNextVersionScope,
|
|
82
|
-
recommendedNextVersionMessage:
|
|
112
|
+
recommendedNextVersionMessage:
|
|
113
|
+
nextCommitObject.recommendedNextVersionMessage,
|
|
83
114
|
});
|
|
84
115
|
|
|
85
116
|
let answerBucket: plugins.smartinteract.AnswerBucket;
|
|
86
117
|
|
|
87
118
|
// Check if -y/--yes flag is set AND version is not a breaking change
|
|
88
119
|
// Breaking changes (major version bumps) always require manual confirmation
|
|
89
|
-
const isBreakingChange =
|
|
120
|
+
const isBreakingChange =
|
|
121
|
+
nextCommitObject.recommendedNextVersionLevel === "BREAKING CHANGE";
|
|
90
122
|
const canAutoAccept = (argvArg.y || argvArg.yes) && !isBreakingChange;
|
|
91
123
|
|
|
92
124
|
if (canAutoAccept) {
|
|
93
125
|
// Auto-mode: create AnswerBucket programmatically
|
|
94
|
-
logger.log(
|
|
126
|
+
logger.log("info", "✓ Auto-accepting AI recommendations (--yes flag)");
|
|
95
127
|
|
|
96
128
|
answerBucket = new plugins.smartinteract.AnswerBucket();
|
|
97
129
|
answerBucket.addAnswer({
|
|
98
|
-
name:
|
|
130
|
+
name: "commitType",
|
|
99
131
|
value: nextCommitObject.recommendedNextVersionLevel,
|
|
100
132
|
});
|
|
101
133
|
answerBucket.addAnswer({
|
|
102
|
-
name:
|
|
134
|
+
name: "commitScope",
|
|
103
135
|
value: nextCommitObject.recommendedNextVersionScope,
|
|
104
136
|
});
|
|
105
137
|
answerBucket.addAnswer({
|
|
106
|
-
name:
|
|
138
|
+
name: "commitDescription",
|
|
107
139
|
value: nextCommitObject.recommendedNextVersionMessage,
|
|
108
140
|
});
|
|
109
141
|
answerBucket.addAnswer({
|
|
110
|
-
name:
|
|
142
|
+
name: "pushToOrigin",
|
|
111
143
|
value: !!(argvArg.p || argvArg.push), // Only push if -p flag also provided
|
|
112
144
|
});
|
|
113
145
|
answerBucket.addAnswer({
|
|
114
|
-
name:
|
|
146
|
+
name: "createRelease",
|
|
115
147
|
value: wantsRelease,
|
|
116
148
|
});
|
|
117
149
|
} else {
|
|
118
150
|
// Warn if --yes was provided but we're requiring confirmation due to breaking change
|
|
119
151
|
if (isBreakingChange && (argvArg.y || argvArg.yes)) {
|
|
120
|
-
logger.log(
|
|
152
|
+
logger.log(
|
|
153
|
+
"warn",
|
|
154
|
+
"⚠️ BREAKING CHANGE detected - manual confirmation required",
|
|
155
|
+
);
|
|
121
156
|
}
|
|
122
157
|
// Interactive mode: prompt user for input
|
|
123
158
|
const commitInteract = new plugins.smartinteract.SmartInteract();
|
|
124
159
|
commitInteract.addQuestions([
|
|
125
160
|
{
|
|
126
|
-
type:
|
|
161
|
+
type: "list",
|
|
127
162
|
name: `commitType`,
|
|
128
163
|
message: `Choose TYPE of the commit:`,
|
|
129
164
|
choices: [`fix`, `feat`, `BREAKING CHANGE`],
|
|
130
165
|
default: nextCommitObject.recommendedNextVersionLevel,
|
|
131
166
|
},
|
|
132
167
|
{
|
|
133
|
-
type:
|
|
168
|
+
type: "input",
|
|
134
169
|
name: `commitScope`,
|
|
135
170
|
message: `What is the SCOPE of the commit:`,
|
|
136
171
|
default: nextCommitObject.recommendedNextVersionScope,
|
|
@@ -142,13 +177,13 @@ export const run = async (argvArg: any) => {
|
|
|
142
177
|
default: nextCommitObject.recommendedNextVersionMessage,
|
|
143
178
|
},
|
|
144
179
|
{
|
|
145
|
-
type:
|
|
180
|
+
type: "confirm",
|
|
146
181
|
name: `pushToOrigin`,
|
|
147
182
|
message: `Do you want to push this version now?`,
|
|
148
183
|
default: true,
|
|
149
184
|
},
|
|
150
185
|
{
|
|
151
|
-
type:
|
|
186
|
+
type: "confirm",
|
|
152
187
|
name: `createRelease`,
|
|
153
188
|
message: `Do you want to publish to npm registries?`,
|
|
154
189
|
default: wantsRelease,
|
|
@@ -157,40 +192,50 @@ export const run = async (argvArg: any) => {
|
|
|
157
192
|
answerBucket = await commitInteract.runQueue();
|
|
158
193
|
}
|
|
159
194
|
const commitString = createCommitStringFromAnswerBucket(answerBucket);
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
195
|
+
const commitType = answerBucket.getAnswerFor("commitType");
|
|
196
|
+
let commitVersionType: helpers.VersionType;
|
|
197
|
+
switch (commitType) {
|
|
198
|
+
case "fix":
|
|
199
|
+
commitVersionType = "patch";
|
|
200
|
+
break;
|
|
201
|
+
case "feat":
|
|
202
|
+
commitVersionType = "minor";
|
|
203
|
+
break;
|
|
204
|
+
case "BREAKING CHANGE":
|
|
205
|
+
commitVersionType = "major";
|
|
206
|
+
break;
|
|
207
|
+
default:
|
|
208
|
+
throw new Error(`Unsupported commit type: ${commitType}`);
|
|
209
|
+
}
|
|
170
210
|
|
|
171
|
-
ui.printHeader(
|
|
211
|
+
ui.printHeader("✨ Creating Semantic Commit");
|
|
172
212
|
ui.printCommitMessage(commitString);
|
|
173
213
|
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
174
|
-
executor:
|
|
214
|
+
executor: "bash",
|
|
175
215
|
sourceFilePaths: [],
|
|
176
216
|
});
|
|
177
217
|
|
|
178
218
|
// Load release config if user wants to release (interactively selected)
|
|
179
|
-
if (answerBucket.getAnswerFor(
|
|
219
|
+
if (answerBucket.getAnswerFor("createRelease") && !releaseConfig) {
|
|
180
220
|
releaseConfig = await ReleaseConfig.fromCwd();
|
|
181
221
|
if (!releaseConfig.hasRegistries()) {
|
|
182
|
-
logger.log(
|
|
183
|
-
console.log(
|
|
184
|
-
console.log(
|
|
185
|
-
|
|
222
|
+
logger.log("error", "No release registries configured.");
|
|
223
|
+
console.log("");
|
|
224
|
+
console.log(
|
|
225
|
+
" Run `gitzone config add <registry-url>` to add registries.",
|
|
226
|
+
);
|
|
227
|
+
console.log("");
|
|
186
228
|
process.exit(1);
|
|
187
229
|
}
|
|
188
230
|
}
|
|
189
231
|
|
|
190
232
|
// Determine total steps based on options
|
|
191
233
|
// Note: test runs early (like format) so not counted in numbered steps
|
|
192
|
-
const willPush =
|
|
193
|
-
|
|
234
|
+
const willPush =
|
|
235
|
+
answerBucket.getAnswerFor("pushToOrigin") && !(process.env.CI === "true");
|
|
236
|
+
const willRelease =
|
|
237
|
+
answerBucket.getAnswerFor("createRelease") &&
|
|
238
|
+
releaseConfig?.hasRegistries();
|
|
194
239
|
let totalSteps = 5; // Base steps: commitinfo, changelog, staging, commit, version
|
|
195
240
|
if (wantsBuild) totalSteps += 2; // build step + verification step
|
|
196
241
|
if (willPush) totalSteps++;
|
|
@@ -199,96 +244,156 @@ export const run = async (argvArg: any) => {
|
|
|
199
244
|
|
|
200
245
|
// Step 1: Baking commitinfo
|
|
201
246
|
currentStep++;
|
|
202
|
-
ui.printStep(
|
|
247
|
+
ui.printStep(
|
|
248
|
+
currentStep,
|
|
249
|
+
totalSteps,
|
|
250
|
+
"🔧 Baking commit info into code",
|
|
251
|
+
"in-progress",
|
|
252
|
+
);
|
|
203
253
|
const commitInfo = new plugins.commitinfo.CommitInfo(
|
|
204
254
|
paths.cwd,
|
|
205
255
|
commitVersionType,
|
|
206
256
|
);
|
|
207
257
|
await commitInfo.writeIntoPotentialDirs();
|
|
208
|
-
ui.printStep(
|
|
258
|
+
ui.printStep(
|
|
259
|
+
currentStep,
|
|
260
|
+
totalSteps,
|
|
261
|
+
"🔧 Baking commit info into code",
|
|
262
|
+
"done",
|
|
263
|
+
);
|
|
209
264
|
|
|
210
265
|
// Step 2: Writing changelog
|
|
211
266
|
currentStep++;
|
|
212
|
-
ui.printStep(
|
|
213
|
-
|
|
267
|
+
ui.printStep(
|
|
268
|
+
currentStep,
|
|
269
|
+
totalSteps,
|
|
270
|
+
"📄 Generating changelog.md",
|
|
271
|
+
"in-progress",
|
|
272
|
+
);
|
|
273
|
+
let changelog = nextCommitObject.changelog || "# Changelog\n";
|
|
214
274
|
changelog = changelog.replaceAll(
|
|
215
|
-
|
|
275
|
+
"{{nextVersion}}",
|
|
216
276
|
(await commitInfo.getNextPlannedVersion()).versionString,
|
|
217
277
|
);
|
|
218
278
|
changelog = changelog.replaceAll(
|
|
219
|
-
|
|
220
|
-
`${await answerBucket.getAnswerFor(
|
|
279
|
+
"{{nextVersionScope}}",
|
|
280
|
+
`${await answerBucket.getAnswerFor("commitType")}(${await answerBucket.getAnswerFor("commitScope")})`,
|
|
221
281
|
);
|
|
222
282
|
changelog = changelog.replaceAll(
|
|
223
|
-
|
|
283
|
+
"{{nextVersionMessage}}",
|
|
224
284
|
nextCommitObject.recommendedNextVersionMessage,
|
|
225
285
|
);
|
|
226
286
|
if (nextCommitObject.recommendedNextVersionDetails?.length > 0) {
|
|
227
287
|
changelog = changelog.replaceAll(
|
|
228
|
-
|
|
229
|
-
|
|
288
|
+
"{{nextVersionDetails}}",
|
|
289
|
+
"- " + nextCommitObject.recommendedNextVersionDetails.join("\n- "),
|
|
230
290
|
);
|
|
231
291
|
} else {
|
|
232
|
-
changelog = changelog.replaceAll(
|
|
292
|
+
changelog = changelog.replaceAll("\n{{nextVersionDetails}}", "");
|
|
233
293
|
}
|
|
234
294
|
|
|
235
295
|
await plugins.smartfs
|
|
236
296
|
.file(plugins.path.join(paths.cwd, `changelog.md`))
|
|
237
|
-
.encoding(
|
|
297
|
+
.encoding("utf8")
|
|
238
298
|
.write(changelog);
|
|
239
|
-
ui.printStep(currentStep, totalSteps,
|
|
299
|
+
ui.printStep(currentStep, totalSteps, "📄 Generating changelog.md", "done");
|
|
240
300
|
|
|
241
301
|
// Step 3: Staging files
|
|
242
302
|
currentStep++;
|
|
243
|
-
ui.printStep(currentStep, totalSteps,
|
|
303
|
+
ui.printStep(currentStep, totalSteps, "📦 Staging files", "in-progress");
|
|
244
304
|
await smartshellInstance.exec(`git add -A`);
|
|
245
|
-
ui.printStep(currentStep, totalSteps,
|
|
305
|
+
ui.printStep(currentStep, totalSteps, "📦 Staging files", "done");
|
|
246
306
|
|
|
247
307
|
// Step 4: Creating commit
|
|
248
308
|
currentStep++;
|
|
249
|
-
ui.printStep(
|
|
309
|
+
ui.printStep(
|
|
310
|
+
currentStep,
|
|
311
|
+
totalSteps,
|
|
312
|
+
"💾 Creating git commit",
|
|
313
|
+
"in-progress",
|
|
314
|
+
);
|
|
250
315
|
await smartshellInstance.exec(`git commit -m "${commitString}"`);
|
|
251
|
-
ui.printStep(currentStep, totalSteps,
|
|
316
|
+
ui.printStep(currentStep, totalSteps, "💾 Creating git commit", "done");
|
|
252
317
|
|
|
253
318
|
// Step 5: Bumping version
|
|
254
319
|
currentStep++;
|
|
255
320
|
const projectType = await helpers.detectProjectType();
|
|
256
|
-
const newVersion = await helpers.bumpProjectVersion(
|
|
321
|
+
const newVersion = await helpers.bumpProjectVersion(
|
|
322
|
+
projectType,
|
|
323
|
+
commitVersionType,
|
|
324
|
+
currentStep,
|
|
325
|
+
totalSteps,
|
|
326
|
+
);
|
|
257
327
|
|
|
258
328
|
// Step 6: Run build (optional)
|
|
259
329
|
if (wantsBuild) {
|
|
260
330
|
currentStep++;
|
|
261
|
-
ui.printStep(currentStep, totalSteps,
|
|
262
|
-
const buildResult = await smartshellInstance.exec(
|
|
331
|
+
ui.printStep(currentStep, totalSteps, "🔨 Running build", "in-progress");
|
|
332
|
+
const buildResult = await smartshellInstance.exec("pnpm build");
|
|
263
333
|
if (buildResult.exitCode !== 0) {
|
|
264
|
-
ui.printStep(currentStep, totalSteps,
|
|
265
|
-
logger.log(
|
|
334
|
+
ui.printStep(currentStep, totalSteps, "🔨 Running build", "error");
|
|
335
|
+
logger.log("error", "Build failed. Aborting release.");
|
|
266
336
|
process.exit(1);
|
|
267
337
|
}
|
|
268
|
-
ui.printStep(currentStep, totalSteps,
|
|
338
|
+
ui.printStep(currentStep, totalSteps, "🔨 Running build", "done");
|
|
269
339
|
|
|
270
340
|
// Step 7: Verify no uncommitted changes
|
|
271
341
|
currentStep++;
|
|
272
|
-
ui.printStep(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
342
|
+
ui.printStep(
|
|
343
|
+
currentStep,
|
|
344
|
+
totalSteps,
|
|
345
|
+
"🔍 Verifying clean working tree",
|
|
346
|
+
"in-progress",
|
|
347
|
+
);
|
|
348
|
+
const statusResult = await smartshellInstance.exec(
|
|
349
|
+
"git status --porcelain",
|
|
350
|
+
);
|
|
351
|
+
if (statusResult.stdout.trim() !== "") {
|
|
352
|
+
ui.printStep(
|
|
353
|
+
currentStep,
|
|
354
|
+
totalSteps,
|
|
355
|
+
"🔍 Verifying clean working tree",
|
|
356
|
+
"error",
|
|
357
|
+
);
|
|
358
|
+
logger.log(
|
|
359
|
+
"error",
|
|
360
|
+
"Build produced uncommitted changes. This usually means build output is not gitignored.",
|
|
361
|
+
);
|
|
362
|
+
logger.log("error", "Uncommitted files:");
|
|
278
363
|
console.log(statusResult.stdout);
|
|
279
|
-
logger.log(
|
|
364
|
+
logger.log(
|
|
365
|
+
"error",
|
|
366
|
+
"Aborting release. Please ensure build artifacts are in .gitignore",
|
|
367
|
+
);
|
|
280
368
|
process.exit(1);
|
|
281
369
|
}
|
|
282
|
-
ui.printStep(
|
|
370
|
+
ui.printStep(
|
|
371
|
+
currentStep,
|
|
372
|
+
totalSteps,
|
|
373
|
+
"🔍 Verifying clean working tree",
|
|
374
|
+
"done",
|
|
375
|
+
);
|
|
283
376
|
}
|
|
284
377
|
|
|
285
378
|
// Step: Push to remote (optional)
|
|
286
379
|
const currentBranch = await helpers.detectCurrentBranch();
|
|
287
380
|
if (willPush) {
|
|
288
381
|
currentStep++;
|
|
289
|
-
ui.printStep(
|
|
290
|
-
|
|
291
|
-
|
|
382
|
+
ui.printStep(
|
|
383
|
+
currentStep,
|
|
384
|
+
totalSteps,
|
|
385
|
+
`🚀 Pushing to origin/${currentBranch}`,
|
|
386
|
+
"in-progress",
|
|
387
|
+
);
|
|
388
|
+
await smartshellInstance.exec(
|
|
389
|
+
`git push origin ${currentBranch} --follow-tags`,
|
|
390
|
+
);
|
|
391
|
+
ui.printStep(
|
|
392
|
+
currentStep,
|
|
393
|
+
totalSteps,
|
|
394
|
+
`🚀 Pushing to origin/${currentBranch}`,
|
|
395
|
+
"done",
|
|
396
|
+
);
|
|
292
397
|
}
|
|
293
398
|
|
|
294
399
|
// Step 7: Publish to npm registries (optional)
|
|
@@ -296,51 +401,173 @@ export const run = async (argvArg: any) => {
|
|
|
296
401
|
if (willRelease && releaseConfig) {
|
|
297
402
|
currentStep++;
|
|
298
403
|
const registries = releaseConfig.getRegistries();
|
|
299
|
-
ui.printStep(
|
|
404
|
+
ui.printStep(
|
|
405
|
+
currentStep,
|
|
406
|
+
totalSteps,
|
|
407
|
+
`📦 Publishing to ${registries.length} registr${registries.length === 1 ? "y" : "ies"}`,
|
|
408
|
+
"in-progress",
|
|
409
|
+
);
|
|
300
410
|
|
|
301
411
|
const accessLevel = releaseConfig.getAccessLevel();
|
|
302
412
|
for (const registry of registries) {
|
|
303
413
|
try {
|
|
304
|
-
await smartshellInstance.exec(
|
|
414
|
+
await smartshellInstance.exec(
|
|
415
|
+
`npm publish --registry=${registry} --access=${accessLevel}`,
|
|
416
|
+
);
|
|
305
417
|
releasedRegistries.push(registry);
|
|
306
418
|
} catch (error) {
|
|
307
|
-
logger.log(
|
|
419
|
+
logger.log("error", `Failed to publish to ${registry}: ${error}`);
|
|
308
420
|
}
|
|
309
421
|
}
|
|
310
422
|
|
|
311
423
|
if (releasedRegistries.length === registries.length) {
|
|
312
|
-
ui.printStep(
|
|
424
|
+
ui.printStep(
|
|
425
|
+
currentStep,
|
|
426
|
+
totalSteps,
|
|
427
|
+
`📦 Publishing to ${registries.length} registr${registries.length === 1 ? "y" : "ies"}`,
|
|
428
|
+
"done",
|
|
429
|
+
);
|
|
313
430
|
} else {
|
|
314
|
-
ui.printStep(
|
|
431
|
+
ui.printStep(
|
|
432
|
+
currentStep,
|
|
433
|
+
totalSteps,
|
|
434
|
+
`📦 Publishing to ${registries.length} registr${registries.length === 1 ? "y" : "ies"}`,
|
|
435
|
+
"error",
|
|
436
|
+
);
|
|
315
437
|
}
|
|
316
438
|
}
|
|
317
439
|
|
|
318
|
-
console.log(
|
|
440
|
+
console.log(""); // Add spacing before summary
|
|
319
441
|
|
|
320
442
|
// Get commit SHA for summary
|
|
321
|
-
const commitShaResult = await smartshellInstance.exec(
|
|
443
|
+
const commitShaResult = await smartshellInstance.exec(
|
|
444
|
+
"git rev-parse --short HEAD",
|
|
445
|
+
);
|
|
322
446
|
const commitSha = commitShaResult.stdout.trim();
|
|
323
447
|
|
|
324
448
|
// Print final summary
|
|
325
449
|
ui.printSummary({
|
|
326
450
|
projectType,
|
|
327
451
|
branch: currentBranch,
|
|
328
|
-
commitType: answerBucket.getAnswerFor(
|
|
329
|
-
commitScope: answerBucket.getAnswerFor(
|
|
330
|
-
commitMessage: answerBucket.getAnswerFor(
|
|
452
|
+
commitType: answerBucket.getAnswerFor("commitType"),
|
|
453
|
+
commitScope: answerBucket.getAnswerFor("commitScope"),
|
|
454
|
+
commitMessage: answerBucket.getAnswerFor("commitDescription"),
|
|
331
455
|
newVersion: newVersion,
|
|
332
456
|
commitSha: commitSha,
|
|
333
457
|
pushed: willPush,
|
|
334
458
|
released: releasedRegistries.length > 0,
|
|
335
|
-
releasedRegistries:
|
|
459
|
+
releasedRegistries:
|
|
460
|
+
releasedRegistries.length > 0 ? releasedRegistries : undefined,
|
|
336
461
|
});
|
|
337
462
|
};
|
|
338
463
|
|
|
464
|
+
async function handleRecommend(mode: ICliMode): Promise<void> {
|
|
465
|
+
const recommendationBuilder = async () => {
|
|
466
|
+
const aidoc = new plugins.tsdoc.AiDoc();
|
|
467
|
+
await aidoc.start();
|
|
468
|
+
try {
|
|
469
|
+
return await aidoc.buildNextCommitObject(paths.cwd);
|
|
470
|
+
} finally {
|
|
471
|
+
await aidoc.stop();
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
const recommendation = mode.json
|
|
476
|
+
? await runWithSuppressedOutput(recommendationBuilder)
|
|
477
|
+
: await recommendationBuilder();
|
|
478
|
+
|
|
479
|
+
if (mode.json) {
|
|
480
|
+
printJson(recommendation);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
ui.printRecommendation({
|
|
485
|
+
recommendedNextVersion: recommendation.recommendedNextVersion,
|
|
486
|
+
recommendedNextVersionLevel: recommendation.recommendedNextVersionLevel,
|
|
487
|
+
recommendedNextVersionScope: recommendation.recommendedNextVersionScope,
|
|
488
|
+
recommendedNextVersionMessage: recommendation.recommendedNextVersionMessage,
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
console.log(
|
|
492
|
+
`Suggested commit: ${recommendation.recommendedNextVersionLevel}(${recommendation.recommendedNextVersionScope}): ${recommendation.recommendedNextVersionMessage}`,
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
|
|
339
496
|
const createCommitStringFromAnswerBucket = (
|
|
340
497
|
answerBucket: plugins.smartinteract.AnswerBucket,
|
|
341
498
|
) => {
|
|
342
|
-
const commitType = answerBucket.getAnswerFor(
|
|
343
|
-
const commitScope = answerBucket.getAnswerFor(
|
|
344
|
-
const commitDescription = answerBucket.getAnswerFor(
|
|
499
|
+
const commitType = answerBucket.getAnswerFor("commitType");
|
|
500
|
+
const commitScope = answerBucket.getAnswerFor("commitScope");
|
|
501
|
+
const commitDescription = answerBucket.getAnswerFor("commitDescription");
|
|
345
502
|
return `${commitType}(${commitScope}): ${commitDescription}`;
|
|
346
503
|
};
|
|
504
|
+
|
|
505
|
+
export function showHelp(mode?: ICliMode): void {
|
|
506
|
+
if (mode?.json) {
|
|
507
|
+
printJson({
|
|
508
|
+
command: "commit",
|
|
509
|
+
usage: "gitzone commit [recommend] [options]",
|
|
510
|
+
description:
|
|
511
|
+
"Creates semantic commits or emits a read-only recommendation.",
|
|
512
|
+
commands: [
|
|
513
|
+
{
|
|
514
|
+
name: "recommend",
|
|
515
|
+
description:
|
|
516
|
+
"Generate a commit recommendation without mutating the repository",
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
flags: [
|
|
520
|
+
{ flag: "-y, --yes", description: "Auto-accept AI recommendations" },
|
|
521
|
+
{ flag: "-p, --push", description: "Push to origin after commit" },
|
|
522
|
+
{ flag: "-t, --test", description: "Run tests before the commit flow" },
|
|
523
|
+
{
|
|
524
|
+
flag: "-b, --build",
|
|
525
|
+
description: "Run the build after the commit flow",
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
flag: "-r, --release",
|
|
529
|
+
description: "Publish to configured registries after push",
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
flag: "--format",
|
|
533
|
+
description: "Run gitzone format before committing",
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
flag: "--json",
|
|
537
|
+
description: "Emit JSON for `commit recommend` only",
|
|
538
|
+
},
|
|
539
|
+
],
|
|
540
|
+
examples: [
|
|
541
|
+
"gitzone commit recommend --json",
|
|
542
|
+
"gitzone commit -y",
|
|
543
|
+
"gitzone commit -ypbr",
|
|
544
|
+
],
|
|
545
|
+
});
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
console.log("");
|
|
550
|
+
console.log("Usage: gitzone commit [recommend] [options]");
|
|
551
|
+
console.log("");
|
|
552
|
+
console.log("Commands:");
|
|
553
|
+
console.log(
|
|
554
|
+
" recommend Generate a commit recommendation without mutating the repository",
|
|
555
|
+
);
|
|
556
|
+
console.log("");
|
|
557
|
+
console.log("Flags:");
|
|
558
|
+
console.log(" -y, --yes Auto-accept AI recommendations");
|
|
559
|
+
console.log(" -p, --push Push to origin after commit");
|
|
560
|
+
console.log(" -t, --test Run tests before the commit flow");
|
|
561
|
+
console.log(" -b, --build Run the build after the commit flow");
|
|
562
|
+
console.log(
|
|
563
|
+
" -r, --release Publish to configured registries after push",
|
|
564
|
+
);
|
|
565
|
+
console.log(" --format Run gitzone format before committing");
|
|
566
|
+
console.log(" --json Emit JSON for `commit recommend` only");
|
|
567
|
+
console.log("");
|
|
568
|
+
console.log("Examples:");
|
|
569
|
+
console.log(" gitzone commit recommend --json");
|
|
570
|
+
console.log(" gitzone commit -y");
|
|
571
|
+
console.log(" gitzone commit -ypbr");
|
|
572
|
+
console.log("");
|
|
573
|
+
}
|