semver-ratchet 1.0.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/README.md +284 -0
- package/bin/semver-ratchet +4 -0
- package/index.js +29 -0
- package/package.json +50 -0
- package/src/cli.js +431 -0
- package/src/config.js +74 -0
- package/src/git_adapter.js +112 -0
- package/src/git_mock.js +348 -0
- package/src/git_real.js +210 -0
- package/src/version.js +340 -0
package/src/cli.js
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command-line interface for semver-ratchet.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
getVersion,
|
|
7
|
+
getCurrentBranch,
|
|
8
|
+
calculateCrc32Unsigned,
|
|
9
|
+
determineVersionBump,
|
|
10
|
+
getCompatibleVersions,
|
|
11
|
+
verifyGitHistory,
|
|
12
|
+
createGitTag,
|
|
13
|
+
pushGitTag,
|
|
14
|
+
isMainBranch,
|
|
15
|
+
parseSemver,
|
|
16
|
+
getGitAdapter,
|
|
17
|
+
} from './version.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Display the current version.
|
|
21
|
+
* @param {Object} _args - Command line arguments
|
|
22
|
+
*/
|
|
23
|
+
function cmdVersion(_args) {
|
|
24
|
+
const version = getVersion(
|
|
25
|
+
_args.defaultBump || 'patch',
|
|
26
|
+
!_args.noVerify,
|
|
27
|
+
);
|
|
28
|
+
console.log(version);
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Display the current branch name.
|
|
34
|
+
* @param {Object} _args - Command line arguments
|
|
35
|
+
*/
|
|
36
|
+
function cmdBranch(_args) {
|
|
37
|
+
const branch = getCurrentBranch();
|
|
38
|
+
console.log(branch);
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Calculate CRC32 of a string (useful for branch name hashing).
|
|
44
|
+
* @param {Object} _args - Command line arguments
|
|
45
|
+
*/
|
|
46
|
+
function cmdCrc32(_args) {
|
|
47
|
+
const value = calculateCrc32Unsigned(_args.string);
|
|
48
|
+
console.log(value);
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Validate a commit message for SemVer bump.
|
|
54
|
+
* @param {Object} _args - Command line arguments
|
|
55
|
+
*/
|
|
56
|
+
function cmdValidate(_args) {
|
|
57
|
+
const message = _args.message;
|
|
58
|
+
const messages = [message];
|
|
59
|
+
const bumpType = determineVersionBump(messages, _args.defaultBump || 'patch');
|
|
60
|
+
|
|
61
|
+
// Check for valid tags
|
|
62
|
+
if (message.toUpperCase().includes('[MAJOR]')) {
|
|
63
|
+
console.log(`Valid: ${bumpType.toUpperCase()} bump`);
|
|
64
|
+
console.log(' Tag: [MAJOR]');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
} else if (message.toUpperCase().includes('[MINOR]')) {
|
|
67
|
+
console.log(`Valid: ${bumpType.toUpperCase()} bump`);
|
|
68
|
+
console.log(' Tag: [MINOR]');
|
|
69
|
+
process.exit(0);
|
|
70
|
+
} else if (message.toUpperCase().includes('[PATCH]')) {
|
|
71
|
+
console.log(`Valid: ${bumpType.toUpperCase()} bump`);
|
|
72
|
+
console.log(' Tag: [PATCH]');
|
|
73
|
+
process.exit(0);
|
|
74
|
+
} else {
|
|
75
|
+
console.log(`Valid: ${bumpType.toUpperCase()} bump (default: ${_args.defaultBump || 'patch'})`);
|
|
76
|
+
console.log(` Tag: [${(_args.defaultBump || 'patch').toUpperCase()}] (implicit)`);
|
|
77
|
+
process.exit(0);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Compare two SemVer versions.
|
|
83
|
+
* @param {string} v1 - First version
|
|
84
|
+
* @param {string} v2 - Second version
|
|
85
|
+
* @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
86
|
+
*/
|
|
87
|
+
function compareSemver(v1, v2) {
|
|
88
|
+
const { major: m1, minor: n1, patch: p1 } = parseSemver(v1);
|
|
89
|
+
const { major: m2, minor: n2, patch: p2 } = parseSemver(v2);
|
|
90
|
+
|
|
91
|
+
if (m1 !== m2) return m1 < m2 ? -1 : 1;
|
|
92
|
+
if (n1 !== n2) return n1 < n2 ? -1 : 1;
|
|
93
|
+
if (p1 !== p2) return p1 < p2 ? -1 : 1;
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Check if version is monotonic (increasing).
|
|
99
|
+
* @param {Object} _args - Command line arguments
|
|
100
|
+
*/
|
|
101
|
+
function cmdCheckMonotonic(_args) {
|
|
102
|
+
try {
|
|
103
|
+
const currentVersion = getVersion(
|
|
104
|
+
_args.defaultBump || 'patch',
|
|
105
|
+
!_args.noVerify,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// For main branch, compare with latest tag
|
|
109
|
+
if (isMainBranch()) {
|
|
110
|
+
try {
|
|
111
|
+
const adapter = getGitAdapter();
|
|
112
|
+
const latestTag = adapter.getLatestTag();
|
|
113
|
+
|
|
114
|
+
if (latestTag) {
|
|
115
|
+
const comparison = compareSemver(currentVersion, latestTag);
|
|
116
|
+
|
|
117
|
+
if (comparison > 0) {
|
|
118
|
+
console.log(`Monotonic: ${latestTag} -> ${currentVersion}`);
|
|
119
|
+
process.exit(0);
|
|
120
|
+
} else {
|
|
121
|
+
console.log(`ERROR: Version decreased or stayed same: ${latestTag} -> ${currentVersion}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
// No tags yet, assume monotonic
|
|
126
|
+
console.log(`Monotonic: No previous tags, starting at ${currentVersion}`);
|
|
127
|
+
process.exit(0);
|
|
128
|
+
}
|
|
129
|
+
} catch {
|
|
130
|
+
// No tags yet, assume monotonic
|
|
131
|
+
console.log(`Monotonic: No previous tags, starting at ${currentVersion}`);
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
// Feature branches are always monotonic within their branch
|
|
136
|
+
console.log(`Monotonic: Feature branch version ${currentVersion}`);
|
|
137
|
+
process.exit(0);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.log(`ERROR: ${error.message}`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Display versioning information.
|
|
147
|
+
* @param {Object} _args - Command line arguments
|
|
148
|
+
*/
|
|
149
|
+
function cmdInfo(_args) {
|
|
150
|
+
const branch = getCurrentBranch();
|
|
151
|
+
const version = getVersion(
|
|
152
|
+
_args.defaultBump || 'patch',
|
|
153
|
+
!_args.noVerify,
|
|
154
|
+
);
|
|
155
|
+
const branchType = isMainBranch() ? 'main' : 'feature';
|
|
156
|
+
|
|
157
|
+
console.log(`Branch: ${branch}`);
|
|
158
|
+
console.log(`Type: ${branchType}`);
|
|
159
|
+
console.log(`Version: ${version}`);
|
|
160
|
+
console.log(`Default bump: ${_args.defaultBump || 'patch'}`);
|
|
161
|
+
|
|
162
|
+
if (!isMainBranch()) {
|
|
163
|
+
const crc32 = calculateCrc32Unsigned(branch);
|
|
164
|
+
console.log(`Branch CRC32: ${crc32}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Show compatible versions for main branch
|
|
168
|
+
if (isMainBranch()) {
|
|
169
|
+
try {
|
|
170
|
+
parseSemver(version);
|
|
171
|
+
const compatible = getCompatibleVersions(version);
|
|
172
|
+
console.log(`Compatible versions: ${compatible.join(', ')}`);
|
|
173
|
+
} catch {
|
|
174
|
+
// Not a valid semver, skip
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
process.exit(0);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Generate compatible versions in CSV format.
|
|
183
|
+
* @param {Object} _args - Command line arguments
|
|
184
|
+
*/
|
|
185
|
+
function cmdVersions(_args) {
|
|
186
|
+
try {
|
|
187
|
+
const version = getVersion(
|
|
188
|
+
_args.defaultBump || 'patch',
|
|
189
|
+
!_args.noVerify,
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
// Output as CSV
|
|
193
|
+
console.log('version,type,description');
|
|
194
|
+
|
|
195
|
+
const parts = version.split('.');
|
|
196
|
+
const major = parts[0];
|
|
197
|
+
const minor = parts[1];
|
|
198
|
+
|
|
199
|
+
console.log(`${version},full,Exact version ${version}`);
|
|
200
|
+
console.log(`${major}.${minor},minor,Compatible with ${major}.${minor}.x`);
|
|
201
|
+
console.log(`${major},major,Compatible with ${major}.x.x`);
|
|
202
|
+
|
|
203
|
+
process.exit(0);
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.log(`ERROR: ${error.message}`);
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Verify git history is sufficient for version calculation.
|
|
212
|
+
* @param {Object} _args - Command line arguments
|
|
213
|
+
*/
|
|
214
|
+
function cmdVerify(_args) {
|
|
215
|
+
try {
|
|
216
|
+
const depth = parseInt(_args.depth, 10) || 50;
|
|
217
|
+
verifyGitHistory(depth);
|
|
218
|
+
console.log('OK: Sufficient git history available');
|
|
219
|
+
process.exit(0);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
console.log(`ERROR: ${error.message}`);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Create and optionally push a Git tag for the current version.
|
|
228
|
+
* @param {Object} _args - Command line arguments
|
|
229
|
+
*/
|
|
230
|
+
function cmdTag(_args) {
|
|
231
|
+
if (!isMainBranch()) {
|
|
232
|
+
console.log('ERROR: Git tags can only be created on main branch');
|
|
233
|
+
process.exit(1);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
// Create tag (version is calculated internally)
|
|
238
|
+
createGitTag(_args.defaultBump || 'patch', _args.force);
|
|
239
|
+
|
|
240
|
+
// Push tag if requested
|
|
241
|
+
if (_args.push) {
|
|
242
|
+
pushGitTag(_args.defaultBump || 'patch', _args.remote || 'origin');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
process.exit(0);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
console.log(`ERROR: ${error.message}`);
|
|
248
|
+
process.exit(1);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Parse command line arguments.
|
|
254
|
+
* @param {string[]} argv - Command line arguments
|
|
255
|
+
* @returns {Object} Parsed arguments
|
|
256
|
+
*/
|
|
257
|
+
function parseArgs(argv) {
|
|
258
|
+
const args = {
|
|
259
|
+
command: null,
|
|
260
|
+
defaultBump: 'patch',
|
|
261
|
+
noVerify: false,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
const commands = ['version', 'branch', 'crc32', 'validate', 'check-monotonic', 'info', 'versions', 'verify', 'tag'];
|
|
265
|
+
|
|
266
|
+
let i = 2; // Skip node and script name
|
|
267
|
+
while (i < argv.length) {
|
|
268
|
+
const arg = argv[i];
|
|
269
|
+
|
|
270
|
+
// Check for commands
|
|
271
|
+
if (commands.includes(arg)) {
|
|
272
|
+
args.command = arg;
|
|
273
|
+
i++;
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Check for flags
|
|
278
|
+
if (arg === '--default-bump') {
|
|
279
|
+
args.defaultBump = argv[++i];
|
|
280
|
+
i++;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (arg === '--no-verify') {
|
|
285
|
+
args.noVerify = true;
|
|
286
|
+
i++;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (arg === '--force') {
|
|
291
|
+
args.force = true;
|
|
292
|
+
i++;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (arg === '--push') {
|
|
297
|
+
args.push = true;
|
|
298
|
+
i++;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (arg === '--remote') {
|
|
303
|
+
args.remote = argv[++i];
|
|
304
|
+
i++;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (arg === '--depth') {
|
|
309
|
+
args.depth = argv[++i];
|
|
310
|
+
i++;
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Positional arguments
|
|
315
|
+
if (args.command === 'crc32' && !args.string && !arg.startsWith('--')) {
|
|
316
|
+
args.string = arg;
|
|
317
|
+
i++;
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (args.command === 'validate' && !args.message && !arg.startsWith('--')) {
|
|
322
|
+
args.message = arg;
|
|
323
|
+
i++;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
i++;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return args;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Print usage information.
|
|
335
|
+
*/
|
|
336
|
+
function printUsage() {
|
|
337
|
+
console.log(`
|
|
338
|
+
Usage: semver-ratchet [options] <command>
|
|
339
|
+
|
|
340
|
+
Forward-only versioning for Trunk-Based Development
|
|
341
|
+
|
|
342
|
+
Commands:
|
|
343
|
+
version Get current version
|
|
344
|
+
branch Get current branch name
|
|
345
|
+
crc32 <string> Calculate CRC32 of a string
|
|
346
|
+
validate <msg> Validate commit message for SemVer bump
|
|
347
|
+
check-monotonic Check version monotonicity
|
|
348
|
+
info Display versioning information
|
|
349
|
+
versions Generate compatible versions in CSV format
|
|
350
|
+
verify Verify git history is sufficient
|
|
351
|
+
tag Create and push a Git tag for the current version
|
|
352
|
+
|
|
353
|
+
Global Options:
|
|
354
|
+
--default-bump <type> Default version bump (major|minor|patch, default: patch)
|
|
355
|
+
--no-verify Skip git history verification
|
|
356
|
+
|
|
357
|
+
Tag Command Options:
|
|
358
|
+
--force Overwrite existing tag if it exists
|
|
359
|
+
--push Push tag to remote after creating
|
|
360
|
+
--remote <name> Remote name to push to (default: origin)
|
|
361
|
+
|
|
362
|
+
Verify Command Options:
|
|
363
|
+
--depth <n> Minimum required commit depth (default: 50)
|
|
364
|
+
|
|
365
|
+
Examples:
|
|
366
|
+
semver-ratchet version
|
|
367
|
+
semver-ratchet version --default-bump minor
|
|
368
|
+
semver-ratchet validate "feat: add login [MINOR]"
|
|
369
|
+
semver-ratchet tag --push
|
|
370
|
+
semver-ratchet crc32 feature/my-branch
|
|
371
|
+
`);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Main entry point for CLI.
|
|
376
|
+
*/
|
|
377
|
+
export function main() {
|
|
378
|
+
const args = parseArgs(process.argv);
|
|
379
|
+
|
|
380
|
+
if (!args.command) {
|
|
381
|
+
printUsage();
|
|
382
|
+
process.exit(1);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
switch (args.command) {
|
|
386
|
+
case 'version':
|
|
387
|
+
cmdVersion(args);
|
|
388
|
+
break;
|
|
389
|
+
case 'branch':
|
|
390
|
+
cmdBranch(args);
|
|
391
|
+
break;
|
|
392
|
+
case 'crc32':
|
|
393
|
+
if (!args.string) {
|
|
394
|
+
console.log('ERROR: crc32 command requires a string argument');
|
|
395
|
+
process.exit(1);
|
|
396
|
+
}
|
|
397
|
+
cmdCrc32(args);
|
|
398
|
+
break;
|
|
399
|
+
case 'validate':
|
|
400
|
+
if (!args.message) {
|
|
401
|
+
console.log('ERROR: validate command requires a message argument');
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
404
|
+
cmdValidate(args);
|
|
405
|
+
break;
|
|
406
|
+
case 'check-monotonic':
|
|
407
|
+
cmdCheckMonotonic(args);
|
|
408
|
+
break;
|
|
409
|
+
case 'info':
|
|
410
|
+
cmdInfo(args);
|
|
411
|
+
break;
|
|
412
|
+
case 'versions':
|
|
413
|
+
cmdVersions(args);
|
|
414
|
+
break;
|
|
415
|
+
case 'verify':
|
|
416
|
+
cmdVerify(args);
|
|
417
|
+
break;
|
|
418
|
+
case 'tag':
|
|
419
|
+
cmdTag(args);
|
|
420
|
+
break;
|
|
421
|
+
default:
|
|
422
|
+
console.log(`Unknown command: ${args.command}`);
|
|
423
|
+
printUsage();
|
|
424
|
+
process.exit(1);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Run if called directly
|
|
429
|
+
if (process.argv[1] && process.argv[1].endsWith('cli.js')) {
|
|
430
|
+
main();
|
|
431
|
+
}
|
package/src/config.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration module for semver-ratchet.
|
|
3
|
+
*
|
|
4
|
+
* Handles all environment variable configuration:
|
|
5
|
+
* - RATCHET_GIT_PATH: Custom path to git binary
|
|
6
|
+
* - RATCHET_TRUNK_NAME: Custom name for main/trunk branch
|
|
7
|
+
* - RATCHET_DEFAULT_BUMP: Default version bump type
|
|
8
|
+
* - RATCHET_VERIFY_MINDEPTH: Minimum git history depth
|
|
9
|
+
* - RATCHET_MANUAL_VERSION: Manual version override (replaces RATCHET_OVERRIDE)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the path to the git binary.
|
|
14
|
+
* @returns {string} Path to git binary (default: 'git')
|
|
15
|
+
*/
|
|
16
|
+
export function getGitPath() {
|
|
17
|
+
return process.env.RATCHET_GIT_PATH || 'git';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get the name of the trunk/main branch.
|
|
22
|
+
* @returns {string} Name of the trunk branch (default: 'main')
|
|
23
|
+
*/
|
|
24
|
+
export function getTrunkName() {
|
|
25
|
+
return process.env.RATCHET_TRUNK_NAME || 'main';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the default version bump type.
|
|
30
|
+
* @returns {string} Default bump type: 'major', 'minor', or 'patch' (default: 'minor')
|
|
31
|
+
*/
|
|
32
|
+
export function getDefaultBump() {
|
|
33
|
+
return process.env.RATCHET_DEFAULT_BUMP || 'minor';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get the minimum git history depth for verification.
|
|
38
|
+
* @returns {number} Minimum number of commits required (default: 50)
|
|
39
|
+
*/
|
|
40
|
+
export function getVerifyMinDepth() {
|
|
41
|
+
const depthStr = process.env.RATCHET_VERIFY_MINDEPTH;
|
|
42
|
+
if (depthStr !== undefined && depthStr !== null && depthStr !== '') {
|
|
43
|
+
const depth = parseInt(depthStr, 10);
|
|
44
|
+
if (!isNaN(depth) && depth >= 0) {
|
|
45
|
+
return depth;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return 50;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get the manual version override.
|
|
53
|
+
* @returns {string|undefined} Manual version string or undefined
|
|
54
|
+
*
|
|
55
|
+
* Note: This replaces the deprecated RATCHET_OVERRIDE variable.
|
|
56
|
+
* RATCHET_OVERRIDE is still supported for backward compatibility.
|
|
57
|
+
*/
|
|
58
|
+
export function getManualVersion() {
|
|
59
|
+
// Check for new variable first
|
|
60
|
+
if (process.env.RATCHET_MANUAL_VERSION !== undefined &&
|
|
61
|
+
process.env.RATCHET_MANUAL_VERSION !== null &&
|
|
62
|
+
process.env.RATCHET_MANUAL_VERSION !== '') {
|
|
63
|
+
return process.env.RATCHET_MANUAL_VERSION;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Fallback to deprecated variable for backward compatibility
|
|
67
|
+
if (process.env.RATCHET_OVERRIDE !== undefined &&
|
|
68
|
+
process.env.RATCHET_OVERRIDE !== null &&
|
|
69
|
+
process.env.RATCHET_OVERRIDE !== '') {
|
|
70
|
+
return process.env.RATCHET_OVERRIDE;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Adapter Interface for semver-ratchet.
|
|
3
|
+
*
|
|
4
|
+
* This module defines the interface that all git adapters must implement.
|
|
5
|
+
* Both RealGitAdapter and MockGitAdapter implement this interface.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} GitAdapter
|
|
10
|
+
* @property {function(): string} getCurrentBranch - Get the current branch name
|
|
11
|
+
* @property {function(): boolean} isMainBranch - Check if current branch is main/master
|
|
12
|
+
* @property {function(): number} getGitDistance - Get number of commits from main
|
|
13
|
+
* @property {function(): string|null} getLatestTag - Get the latest SemVer tag
|
|
14
|
+
* @property {function(): string[]} getCommitMessages - Get commit messages since tag
|
|
15
|
+
* @property {function(number): boolean} verifyGitHistory - Verify enough history exists
|
|
16
|
+
* @property {function(string): boolean} tagExists - Check if a tag exists
|
|
17
|
+
* @property {function(string, boolean): boolean} createTag - Create a git tag
|
|
18
|
+
* @property {function(string, string): void} pushTag - Push a tag to remote
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Abstract base class for Git adapters.
|
|
23
|
+
* All git adapter implementations must extend this class.
|
|
24
|
+
*/
|
|
25
|
+
export class GitAdapter {
|
|
26
|
+
/**
|
|
27
|
+
* Get the current branch name.
|
|
28
|
+
* @returns {string} The branch name
|
|
29
|
+
* @throws {Error} If git operation fails
|
|
30
|
+
*/
|
|
31
|
+
getCurrentBranch() {
|
|
32
|
+
throw new Error('getCurrentBranch() must be implemented by subclass');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if current branch is main or master.
|
|
37
|
+
* @returns {boolean} True if on main/master branch
|
|
38
|
+
* @throws {Error} If git operation fails
|
|
39
|
+
*/
|
|
40
|
+
isMainBranch() {
|
|
41
|
+
throw new Error('isMainBranch() must be implemented by subclass');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the number of commits between HEAD and main branch.
|
|
46
|
+
* @returns {number} Number of commits
|
|
47
|
+
* @throws {Error} If git operation fails
|
|
48
|
+
*/
|
|
49
|
+
getGitDistance() {
|
|
50
|
+
throw new Error('getGitDistance() must be implemented by subclass');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get the latest SemVer tag on the current branch.
|
|
55
|
+
* @returns {string|null} Tag version without 'v' prefix, or null if no tags
|
|
56
|
+
* @throws {Error} If git operation fails
|
|
57
|
+
*/
|
|
58
|
+
getLatestTag() {
|
|
59
|
+
throw new Error('getLatestTag() must be implemented by subclass');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get commit messages since a specific tag or all commits.
|
|
64
|
+
* @param {string} [_sinceTag] - Optional tag to start from (without 'v' prefix)
|
|
65
|
+
* @returns {string[]} List of commit messages
|
|
66
|
+
* @throws {Error} If git operation fails
|
|
67
|
+
*/
|
|
68
|
+
getCommitMessages(_sinceTag = null) {
|
|
69
|
+
throw new Error('getCommitMessages() must be implemented by subclass');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Verify that enough git history is available.
|
|
74
|
+
* @param {number} [_fetchDepth] - Minimum number of commits required
|
|
75
|
+
* @returns {boolean} True if sufficient history exists
|
|
76
|
+
* @throws {Error} If history is insufficient
|
|
77
|
+
*/
|
|
78
|
+
verifyGitHistory(_fetchDepth = 50) {
|
|
79
|
+
throw new Error('verifyGitHistory() must be implemented by subclass');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if a tag exists for the given version.
|
|
84
|
+
* @param {string} _version - Version string (without 'v' prefix)
|
|
85
|
+
* @returns {boolean} True if tag exists
|
|
86
|
+
* @throws {Error} If git operation fails
|
|
87
|
+
*/
|
|
88
|
+
tagExists(_version) {
|
|
89
|
+
throw new Error('tagExists() must be implemented by subclass');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Create a git tag for the specified version.
|
|
94
|
+
* @param {string} _version - Version string (without 'v' prefix)
|
|
95
|
+
* @param {boolean} [_force] - If true, overwrite existing tag
|
|
96
|
+
* @returns {boolean} True if tag was created successfully
|
|
97
|
+
* @throws {Error} If git operation fails
|
|
98
|
+
*/
|
|
99
|
+
createTag(_version, _force = false) {
|
|
100
|
+
throw new Error('createTag() must be implemented by subclass');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Push a tag to the remote repository.
|
|
105
|
+
* @param {string} _version - Version string (without 'v' prefix)
|
|
106
|
+
* @param {string} [_remote] - Remote name to push to
|
|
107
|
+
* @throws {Error} If git operation fails
|
|
108
|
+
*/
|
|
109
|
+
pushTag(_version, _remote = 'origin') {
|
|
110
|
+
throw new Error('pushTag() must be implemented by subclass');
|
|
111
|
+
}
|
|
112
|
+
}
|