-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathrelease.ts
More file actions
93 lines (76 loc) · 2.98 KB
/
release.ts
File metadata and controls
93 lines (76 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { execSync } from 'node:child_process';
import { readFileSync, writeFileSync } from 'node:fs';
import path from 'node:path';
import readline from 'node:readline/promises';
import chalk from 'chalk';
import { build } from './build.ts';
import { run } from './util.ts';
const VERSION_TYPES = ['patch', 'minor', 'major'] as const;
type VersionType = (typeof VERSION_TYPES)[number];
const PACKAGE_JSON_PATH = path.join(process.cwd(), 'package.json');
export async function release(type: string): Promise<void> {
if (!VERSION_TYPES.includes(type as VersionType)) {
throw new Error(`Invalid version type: ${type}. Must be one of: ${VERSION_TYPES.join(', ')}.`);
}
const versionType = type as VersionType;
if (execSync('git status --porcelain').toString().trim()) {
throw new Error('Commit your changes before publishing.');
}
const currentBranch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
if (currentBranch !== 'master') {
throw new Error('You must be on the master branch to publish.');
}
try {
execSync('npm whoami', { stdio: 'ignore' });
} catch {
throw new Error('You are not logged in to npm. Run `npm login` before publishing.');
}
const currentVersion = getCurrentVersion();
const nextVersion = getNextVersion(versionType, currentVersion);
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const answer = await rl.question(
chalk.yellow(`current: ${currentVersion}, next: ${nextVersion} (${versionType}). Are you sure? (y/n) `)
);
rl.close();
if (answer.toLowerCase() !== 'y') {
console.log(chalk.red('Aborted.'));
return;
}
console.log(chalk.green(`Publishing version ${nextVersion}...`));
updateVersion(nextVersion);
run('npm', ['install']);
await build.lib();
run('git', ['commit', '-am', `Release ${nextVersion}`]);
run('git', ['tag', `v${nextVersion}`]);
run('git', ['push', 'origin', `v${nextVersion}`]);
run('npm', ['publish', '--access', 'public']);
run('git', ['push', 'origin', 'master']);
console.log(chalk.green(`Published ${nextVersion}.`));
}
function getCurrentVersion(): string {
const pkg = JSON.parse(readFileSync(PACKAGE_JSON_PATH, 'utf-8'));
return pkg.version;
}
function updateVersion(version: string): void {
const pkg = JSON.parse(readFileSync(PACKAGE_JSON_PATH, 'utf-8'));
pkg.version = version;
writeFileSync(PACKAGE_JSON_PATH, JSON.stringify(pkg, null, 2) + '\n');
}
function getNextVersion(type: VersionType, currentVersion: string): string {
const match = currentVersion.match(/^(\d+)\.(\d+)\.(\d+)$/);
if (!match) {
throw new Error(`Cannot parse version: ${currentVersion}`);
}
const [, majorStr, minorStr, patchStr] = match;
const major = Number(majorStr);
const minor = Number(minorStr);
const patch = Number(patchStr);
switch (type) {
case 'patch':
return `${major}.${minor}.${patch + 1}`;
case 'minor':
return `${major}.${minor + 1}.0`;
case 'major':
return `${major + 1}.0.0`;
}
}