@sparkleideas/deployment 3.0.0-alpha.8
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/QUICK_START.md +281 -0
- package/README.md +333 -0
- package/examples/basic-release.ts +92 -0
- package/examples/dry-run.ts +70 -0
- package/examples/prerelease-workflow.ts +98 -0
- package/package.json +27 -0
- package/src/__tests__/release-manager.test.ts +72 -0
- package/src/index.ts +88 -0
- package/src/publisher.ts +273 -0
- package/src/release-manager.ts +380 -0
- package/src/types.ts +159 -0
- package/src/validator.ts +310 -0
- package/tmp.json +0 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Release Manager
|
|
3
|
+
* Handles version bumping, changelog generation, and git tagging
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { execSync, execFileSync } from 'child_process';
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Allowed git commands for security - prevents command injection
|
|
12
|
+
*/
|
|
13
|
+
const ALLOWED_GIT_COMMANDS = [
|
|
14
|
+
'git status --porcelain',
|
|
15
|
+
'git rev-parse HEAD',
|
|
16
|
+
'git log',
|
|
17
|
+
'git tag',
|
|
18
|
+
'git add',
|
|
19
|
+
'git commit',
|
|
20
|
+
'git describe',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Validate command against allowlist to prevent command injection
|
|
25
|
+
*/
|
|
26
|
+
function validateCommand(cmd: string): void {
|
|
27
|
+
// Check for shell metacharacters
|
|
28
|
+
if (/[;&|`$()<>]/.test(cmd)) {
|
|
29
|
+
throw new Error(`Invalid command: contains shell metacharacters`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Must start with an allowed command prefix
|
|
33
|
+
const isAllowed = ALLOWED_GIT_COMMANDS.some(prefix => cmd.startsWith(prefix));
|
|
34
|
+
if (!isAllowed) {
|
|
35
|
+
throw new Error(`Command not allowed: ${cmd.split(' ')[0]}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
import type {
|
|
39
|
+
ReleaseOptions,
|
|
40
|
+
ReleaseResult,
|
|
41
|
+
PackageInfo,
|
|
42
|
+
GitCommit,
|
|
43
|
+
ChangelogEntry,
|
|
44
|
+
VersionBumpType
|
|
45
|
+
} from './types.js';
|
|
46
|
+
|
|
47
|
+
export class ReleaseManager {
|
|
48
|
+
private cwd: string;
|
|
49
|
+
|
|
50
|
+
constructor(cwd: string = process.cwd()) {
|
|
51
|
+
this.cwd = cwd;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Prepare a release with version bumping, changelog, and git tagging
|
|
56
|
+
*/
|
|
57
|
+
async prepareRelease(options: ReleaseOptions = {}): Promise<ReleaseResult> {
|
|
58
|
+
const {
|
|
59
|
+
bumpType = 'patch',
|
|
60
|
+
version,
|
|
61
|
+
channel = 'latest',
|
|
62
|
+
generateChangelog = true,
|
|
63
|
+
createTag = true,
|
|
64
|
+
commit = true,
|
|
65
|
+
dryRun = false,
|
|
66
|
+
skipValidation = false,
|
|
67
|
+
tagPrefix = 'v',
|
|
68
|
+
changelogPath = 'CHANGELOG.md'
|
|
69
|
+
} = options;
|
|
70
|
+
|
|
71
|
+
const result: ReleaseResult = {
|
|
72
|
+
oldVersion: '',
|
|
73
|
+
newVersion: '',
|
|
74
|
+
success: false,
|
|
75
|
+
warnings: []
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
// Read package.json
|
|
80
|
+
const pkgPath = join(this.cwd, 'package.json');
|
|
81
|
+
if (!existsSync(pkgPath)) {
|
|
82
|
+
throw new Error('package.json not found');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const pkg: PackageInfo = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
86
|
+
result.oldVersion = pkg.version;
|
|
87
|
+
|
|
88
|
+
// Check for uncommitted changes
|
|
89
|
+
if (!skipValidation) {
|
|
90
|
+
const gitStatus = this.execCommand('git status --porcelain', true);
|
|
91
|
+
if (gitStatus && !dryRun) {
|
|
92
|
+
result.warnings?.push('Uncommitted changes detected');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Determine new version
|
|
97
|
+
result.newVersion = version || this.bumpVersion(pkg.version, bumpType, channel);
|
|
98
|
+
|
|
99
|
+
// Generate changelog if requested
|
|
100
|
+
if (generateChangelog) {
|
|
101
|
+
const commits = this.getCommitsSinceLastTag();
|
|
102
|
+
const changelogEntry = this.generateChangelogEntry(result.newVersion, commits);
|
|
103
|
+
result.changelog = this.formatChangelogEntry(changelogEntry);
|
|
104
|
+
|
|
105
|
+
if (!dryRun) {
|
|
106
|
+
this.updateChangelogFile(changelogPath, result.changelog);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Update package.json version
|
|
111
|
+
if (!dryRun) {
|
|
112
|
+
pkg.version = result.newVersion;
|
|
113
|
+
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Create git commit
|
|
117
|
+
if (commit && !dryRun) {
|
|
118
|
+
const commitMessage = `chore(release): ${result.newVersion}`;
|
|
119
|
+
|
|
120
|
+
// Stage changes
|
|
121
|
+
this.execCommand(`git add package.json ${changelogPath}`);
|
|
122
|
+
|
|
123
|
+
// Commit
|
|
124
|
+
this.execCommand(`git commit -m "${commitMessage}"`);
|
|
125
|
+
|
|
126
|
+
result.commitHash = this.execCommand('git rev-parse HEAD', true).trim();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Create git tag
|
|
130
|
+
if (createTag && !dryRun) {
|
|
131
|
+
result.tag = `${tagPrefix}${result.newVersion}`;
|
|
132
|
+
const tagMessage = `Release ${result.newVersion}`;
|
|
133
|
+
this.execCommand(`git tag -a ${result.tag} -m "${tagMessage}"`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
result.success = true;
|
|
137
|
+
return result;
|
|
138
|
+
|
|
139
|
+
} catch (error) {
|
|
140
|
+
result.error = error instanceof Error ? error.message : String(error);
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Bump version based on type
|
|
147
|
+
*/
|
|
148
|
+
private bumpVersion(
|
|
149
|
+
currentVersion: string,
|
|
150
|
+
bumpType: VersionBumpType,
|
|
151
|
+
channel: string
|
|
152
|
+
): string {
|
|
153
|
+
const versionMatch = currentVersion.match(/^(\d+)\.(\d+)\.(\d+)(?:-([a-z]+)\.(\d+))?$/);
|
|
154
|
+
|
|
155
|
+
if (!versionMatch) {
|
|
156
|
+
throw new Error(`Invalid version format: ${currentVersion}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
let [, major, minor, patch, prerelease, prereleaseNum] = versionMatch;
|
|
160
|
+
let newMajor = parseInt(major);
|
|
161
|
+
let newMinor = parseInt(minor);
|
|
162
|
+
let newPatch = parseInt(patch);
|
|
163
|
+
let newPrerelease: string | undefined = prerelease;
|
|
164
|
+
let newPrereleaseNum = prereleaseNum ? parseInt(prereleaseNum) : 0;
|
|
165
|
+
|
|
166
|
+
switch (bumpType) {
|
|
167
|
+
case 'major':
|
|
168
|
+
newMajor++;
|
|
169
|
+
newMinor = 0;
|
|
170
|
+
newPatch = 0;
|
|
171
|
+
newPrerelease = undefined;
|
|
172
|
+
break;
|
|
173
|
+
|
|
174
|
+
case 'minor':
|
|
175
|
+
newMinor++;
|
|
176
|
+
newPatch = 0;
|
|
177
|
+
newPrerelease = undefined;
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
case 'patch':
|
|
181
|
+
newPatch++;
|
|
182
|
+
newPrerelease = undefined;
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
case 'prerelease':
|
|
186
|
+
if (newPrerelease && channel === newPrerelease) {
|
|
187
|
+
newPrereleaseNum++;
|
|
188
|
+
} else {
|
|
189
|
+
newPrereleaseNum = 1;
|
|
190
|
+
newPrerelease = channel;
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let version = `${newMajor}.${newMinor}.${newPatch}`;
|
|
196
|
+
if (newPrerelease && bumpType === 'prerelease') {
|
|
197
|
+
version += `-${newPrerelease}.${newPrereleaseNum}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return version;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get git commits since last tag
|
|
205
|
+
*/
|
|
206
|
+
private getCommitsSinceLastTag(): GitCommit[] {
|
|
207
|
+
try {
|
|
208
|
+
const lastTag = this.execCommand('git describe --tags --abbrev=0', true).trim();
|
|
209
|
+
const range = `${lastTag}..HEAD`;
|
|
210
|
+
return this.parseCommits(range);
|
|
211
|
+
} catch {
|
|
212
|
+
// No tags found, get all commits
|
|
213
|
+
return this.parseCommits('');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Parse git commits
|
|
219
|
+
*/
|
|
220
|
+
private parseCommits(range: string): GitCommit[] {
|
|
221
|
+
const format = '--pretty=format:%H%n%s%n%an%n%ai%n---COMMIT---';
|
|
222
|
+
const cmd = range
|
|
223
|
+
? `git log ${range} ${format}`
|
|
224
|
+
: `git log ${format}`;
|
|
225
|
+
|
|
226
|
+
const output = this.execCommand(cmd, true);
|
|
227
|
+
const commits: GitCommit[] = [];
|
|
228
|
+
|
|
229
|
+
const commitBlocks = output.split('---COMMIT---').filter(Boolean);
|
|
230
|
+
|
|
231
|
+
for (const block of commitBlocks) {
|
|
232
|
+
const lines = block.trim().split('\n');
|
|
233
|
+
if (lines.length < 4) continue;
|
|
234
|
+
|
|
235
|
+
const [hash, message, author, date] = lines;
|
|
236
|
+
|
|
237
|
+
// Parse conventional commit format
|
|
238
|
+
const conventionalMatch = message.match(/^(\w+)(?:\(([^)]+)\))?: (.+)$/);
|
|
239
|
+
|
|
240
|
+
commits.push({
|
|
241
|
+
hash: hash.trim(),
|
|
242
|
+
message: message.trim(),
|
|
243
|
+
author: author.trim(),
|
|
244
|
+
date: date.trim(),
|
|
245
|
+
type: conventionalMatch?.[1],
|
|
246
|
+
scope: conventionalMatch?.[2],
|
|
247
|
+
breaking: message.includes('BREAKING CHANGE')
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return commits;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Generate changelog entry from commits
|
|
256
|
+
*/
|
|
257
|
+
private generateChangelogEntry(version: string, commits: GitCommit[]): ChangelogEntry {
|
|
258
|
+
const entry: ChangelogEntry = {
|
|
259
|
+
version,
|
|
260
|
+
date: new Date().toISOString().split('T')[0],
|
|
261
|
+
changes: {
|
|
262
|
+
breaking: [],
|
|
263
|
+
features: [],
|
|
264
|
+
fixes: [],
|
|
265
|
+
chore: [],
|
|
266
|
+
docs: [],
|
|
267
|
+
other: []
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
for (const commit of commits) {
|
|
272
|
+
const message = commit.scope
|
|
273
|
+
? `**${commit.scope}**: ${commit.message.split(':').slice(1).join(':').trim()}`
|
|
274
|
+
: commit.message;
|
|
275
|
+
|
|
276
|
+
if (commit.breaking) {
|
|
277
|
+
entry.changes.breaking?.push(message);
|
|
278
|
+
} else if (commit.type === 'feat') {
|
|
279
|
+
entry.changes.features?.push(message);
|
|
280
|
+
} else if (commit.type === 'fix') {
|
|
281
|
+
entry.changes.fixes?.push(message);
|
|
282
|
+
} else if (commit.type === 'chore') {
|
|
283
|
+
entry.changes.chore?.push(message);
|
|
284
|
+
} else if (commit.type === 'docs') {
|
|
285
|
+
entry.changes.docs?.push(message);
|
|
286
|
+
} else {
|
|
287
|
+
entry.changes.other?.push(message);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return entry;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Format changelog entry as markdown
|
|
296
|
+
*/
|
|
297
|
+
private formatChangelogEntry(entry: ChangelogEntry): string {
|
|
298
|
+
let markdown = `## [${entry.version}] - ${entry.date}\n\n`;
|
|
299
|
+
|
|
300
|
+
const sections = [
|
|
301
|
+
{ title: 'BREAKING CHANGES', items: entry.changes.breaking },
|
|
302
|
+
{ title: 'Features', items: entry.changes.features },
|
|
303
|
+
{ title: 'Bug Fixes', items: entry.changes.fixes },
|
|
304
|
+
{ title: 'Documentation', items: entry.changes.docs },
|
|
305
|
+
{ title: 'Chores', items: entry.changes.chore },
|
|
306
|
+
{ title: 'Other Changes', items: entry.changes.other }
|
|
307
|
+
];
|
|
308
|
+
|
|
309
|
+
for (const section of sections) {
|
|
310
|
+
if (section.items && section.items.length > 0) {
|
|
311
|
+
markdown += `### ${section.title}\n\n`;
|
|
312
|
+
for (const item of section.items) {
|
|
313
|
+
markdown += `- ${item}\n`;
|
|
314
|
+
}
|
|
315
|
+
markdown += '\n';
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return markdown;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Update CHANGELOG.md file
|
|
324
|
+
*/
|
|
325
|
+
private updateChangelogFile(path: string, newEntry: string): void {
|
|
326
|
+
const changelogPath = join(this.cwd, path);
|
|
327
|
+
let content = '';
|
|
328
|
+
|
|
329
|
+
if (existsSync(changelogPath)) {
|
|
330
|
+
content = readFileSync(changelogPath, 'utf-8');
|
|
331
|
+
|
|
332
|
+
// Insert after header
|
|
333
|
+
const headerEnd = content.indexOf('\n\n') + 2;
|
|
334
|
+
if (headerEnd > 1) {
|
|
335
|
+
content = content.slice(0, headerEnd) + newEntry + content.slice(headerEnd);
|
|
336
|
+
} else {
|
|
337
|
+
content = newEntry + '\n' + content;
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
content = `# Changelog\n\nAll notable changes to this project will be documented in this file.\n\n${newEntry}`;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
writeFileSync(changelogPath, content);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Execute command safely with validation
|
|
348
|
+
* Only allows git commands from the allowlist
|
|
349
|
+
*/
|
|
350
|
+
private execCommand(cmd: string, returnOutput = false): string {
|
|
351
|
+
// Validate command against allowlist
|
|
352
|
+
validateCommand(cmd);
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
const output = execSync(cmd, {
|
|
356
|
+
cwd: this.cwd,
|
|
357
|
+
encoding: 'utf-8',
|
|
358
|
+
stdio: returnOutput ? 'pipe' : 'inherit',
|
|
359
|
+
timeout: 30000, // 30 second timeout
|
|
360
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB buffer limit
|
|
361
|
+
});
|
|
362
|
+
return returnOutput ? output : '';
|
|
363
|
+
} catch (error) {
|
|
364
|
+
if (returnOutput && error instanceof Error) {
|
|
365
|
+
return '';
|
|
366
|
+
}
|
|
367
|
+
throw error;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Convenience function to prepare a release
|
|
374
|
+
*/
|
|
375
|
+
export async function prepareRelease(
|
|
376
|
+
options: ReleaseOptions = {}
|
|
377
|
+
): Promise<ReleaseResult> {
|
|
378
|
+
const manager = new ReleaseManager();
|
|
379
|
+
return manager.prepareRelease(options);
|
|
380
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for deployment module
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type VersionBumpType = 'major' | 'minor' | 'patch' | 'prerelease';
|
|
6
|
+
export type ReleaseChannel = 'alpha' | 'beta' | 'rc' | 'latest';
|
|
7
|
+
|
|
8
|
+
export interface ReleaseOptions {
|
|
9
|
+
/** Type of version bump */
|
|
10
|
+
bumpType?: VersionBumpType;
|
|
11
|
+
/** Specific version to set (overrides bumpType) */
|
|
12
|
+
version?: string;
|
|
13
|
+
/** Release channel/tag */
|
|
14
|
+
channel?: ReleaseChannel;
|
|
15
|
+
/** Generate changelog from git commits */
|
|
16
|
+
generateChangelog?: boolean;
|
|
17
|
+
/** Create git tag */
|
|
18
|
+
createTag?: boolean;
|
|
19
|
+
/** Commit changes */
|
|
20
|
+
commit?: boolean;
|
|
21
|
+
/** Dry run mode */
|
|
22
|
+
dryRun?: boolean;
|
|
23
|
+
/** Skip validation checks */
|
|
24
|
+
skipValidation?: boolean;
|
|
25
|
+
/** Custom git tag prefix */
|
|
26
|
+
tagPrefix?: string;
|
|
27
|
+
/** Custom changelog file path */
|
|
28
|
+
changelogPath?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ReleaseResult {
|
|
32
|
+
/** Previous version */
|
|
33
|
+
oldVersion: string;
|
|
34
|
+
/** New version */
|
|
35
|
+
newVersion: string;
|
|
36
|
+
/** Git tag name */
|
|
37
|
+
tag?: string;
|
|
38
|
+
/** Changelog content */
|
|
39
|
+
changelog?: string;
|
|
40
|
+
/** Commit hash */
|
|
41
|
+
commitHash?: string;
|
|
42
|
+
/** Success status */
|
|
43
|
+
success: boolean;
|
|
44
|
+
/** Error message if failed */
|
|
45
|
+
error?: string;
|
|
46
|
+
/** Validation warnings */
|
|
47
|
+
warnings?: string[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface PublishOptions {
|
|
51
|
+
/** npm tag (alpha, beta, latest) */
|
|
52
|
+
tag?: string;
|
|
53
|
+
/** Access level (public, restricted) */
|
|
54
|
+
access?: 'public' | 'restricted';
|
|
55
|
+
/** Dry run mode */
|
|
56
|
+
dryRun?: boolean;
|
|
57
|
+
/** Custom registry URL */
|
|
58
|
+
registry?: string;
|
|
59
|
+
/** OTP for 2FA */
|
|
60
|
+
otp?: string;
|
|
61
|
+
/** Skip build step */
|
|
62
|
+
skipBuild?: boolean;
|
|
63
|
+
/** Custom build command */
|
|
64
|
+
buildCommand?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface PublishResult {
|
|
68
|
+
/** Package name */
|
|
69
|
+
packageName: string;
|
|
70
|
+
/** Published version */
|
|
71
|
+
version: string;
|
|
72
|
+
/** npm tag */
|
|
73
|
+
tag: string;
|
|
74
|
+
/** Package tarball URL */
|
|
75
|
+
tarball?: string;
|
|
76
|
+
/** Success status */
|
|
77
|
+
success: boolean;
|
|
78
|
+
/** Error message if failed */
|
|
79
|
+
error?: string;
|
|
80
|
+
/** Publish timestamp */
|
|
81
|
+
publishedAt?: Date;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ValidationOptions {
|
|
85
|
+
/** Run linter */
|
|
86
|
+
lint?: boolean;
|
|
87
|
+
/** Run tests */
|
|
88
|
+
test?: boolean;
|
|
89
|
+
/** Run build */
|
|
90
|
+
build?: boolean;
|
|
91
|
+
/** Check dependencies */
|
|
92
|
+
checkDependencies?: boolean;
|
|
93
|
+
/** Check uncommitted changes */
|
|
94
|
+
checkGitStatus?: boolean;
|
|
95
|
+
/** Custom lint command */
|
|
96
|
+
lintCommand?: string;
|
|
97
|
+
/** Custom test command */
|
|
98
|
+
testCommand?: string;
|
|
99
|
+
/** Custom build command */
|
|
100
|
+
buildCommand?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface ValidationResult {
|
|
104
|
+
/** Overall validation success */
|
|
105
|
+
valid: boolean;
|
|
106
|
+
/** Individual check results */
|
|
107
|
+
checks: {
|
|
108
|
+
lint?: { passed: boolean; errors?: string[] };
|
|
109
|
+
test?: { passed: boolean; errors?: string[] };
|
|
110
|
+
build?: { passed: boolean; errors?: string[] };
|
|
111
|
+
dependencies?: { passed: boolean; errors?: string[] };
|
|
112
|
+
gitStatus?: { passed: boolean; errors?: string[] };
|
|
113
|
+
packageJson?: { passed: boolean; errors?: string[] };
|
|
114
|
+
};
|
|
115
|
+
/** Overall errors */
|
|
116
|
+
errors: string[];
|
|
117
|
+
/** Warnings */
|
|
118
|
+
warnings: string[];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface PackageInfo {
|
|
122
|
+
name: string;
|
|
123
|
+
version: string;
|
|
124
|
+
description?: string;
|
|
125
|
+
private?: boolean;
|
|
126
|
+
repository?: {
|
|
127
|
+
type: string;
|
|
128
|
+
url: string;
|
|
129
|
+
};
|
|
130
|
+
dependencies?: Record<string, string>;
|
|
131
|
+
devDependencies?: Record<string, string>;
|
|
132
|
+
publishConfig?: {
|
|
133
|
+
access?: string;
|
|
134
|
+
registry?: string;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface GitCommit {
|
|
139
|
+
hash: string;
|
|
140
|
+
message: string;
|
|
141
|
+
author: string;
|
|
142
|
+
date: string;
|
|
143
|
+
type?: string;
|
|
144
|
+
scope?: string;
|
|
145
|
+
breaking?: boolean;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface ChangelogEntry {
|
|
149
|
+
version: string;
|
|
150
|
+
date: string;
|
|
151
|
+
changes: {
|
|
152
|
+
breaking?: string[];
|
|
153
|
+
features?: string[];
|
|
154
|
+
fixes?: string[];
|
|
155
|
+
chore?: string[];
|
|
156
|
+
docs?: string[];
|
|
157
|
+
other?: string[];
|
|
158
|
+
};
|
|
159
|
+
}
|