forked from bradymholt/npm-github-release
/
index.js
executable file
·160 lines (132 loc) · 3.99 KB
/
index.js
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env node
const childProcess = require('child_process');
const fs = require('fs');
const readline = require('readline');
const path = require('path');
const chalk = require('chalk');
const GitHubAPI = require('github');
const inquirer = require('inquirer');
const github = new GitHubAPI();
const packageInfo = require(process.env.PWD + '/package.json');
const Logger = {
info(...args) {
console.log(chalk.bold(...args));
},
success(...args) {
console.log(chalk.green.bold(...args));
},
warn(...args) {
console.log(chalk.yellow(...args));
},
error(...args) {
console.log(chalk.red(...args));
}
};
function execp(cmd) {
return new Promise((resolve, reject) => childProcess.exec(cmd, {},
(err, stdout, stderr) => err ? reject(err) : resolve({stdout, stderr})
));
}
function checkForPackageInfoRequirements() {
if (!packageInfo.repository || !packageInfo.repository.url) {
throw new Error(
'{ "repository": { "url" } } is missing in package.json.\n[Reference: https://docs.npmjs.com/files/package.json#repository]'
);
}
}
async function promptVersionType() {
return (await inquirer.prompt([
{
type: 'list',
name: 'type',
message: 'What type of release is this?',
choices: [
'patch',
'minor',
'major',
]
}
])).type;
}
async function promptGitHubToken() {
if (process.env.GITHUB_API_TOKEN) {
return process.env.GITHUB_API_TOKEN;
}
const questions = [{
type: 'input',
name: 'ghToken',
validate: (value) => value.match(/^\w+$/) || 'Please enter a valid GitHub Personal access token',
message: 'GitHub Personal access token:'
}];
Logger.warn(
'GITHUB_API_TOKEN env variable not found (set GITHUB_API_TOKEN to skip this prompt)'
);
return (await inquirer.prompt(questions)).ghToken;
}
async function promptNotes() {
return new Promise((resolve) => {
const input = [];
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question(chalk.green('Release notes (finish with Ctrl^D from newline):\n'), (answer) => {
input.push(answer);
});
rl.on('line', function (cmd) {
input.push(cmd);
});
rl.on('close', function (cmd) {
resolve(input.join('\n'));
});
});
}
async function versionAndReturnTagName(versionType, releaseNotes) {
Logger.info('Versioning package...');
await execp(`npm version ${versionType} --force --message "Release %s\n\n${releaseNotes}"`);
Logger.info('Pushing new release tag to GitHub...');
await execp('git push --follow-tags');
return (await execp('git describe --abbrev=0 --tags')).stdout.trim()
}
async function createGitHubRelease(tagName, notes) {
const [owner, repo] = packageInfo.repository.url.match(/.com\/(\w+\/\w+)/)[1].split('/');
Logger.info('Creating a new GitHub release...');
const {data} = await github.repos.createRelease({
owner,
repo,
tag_name: tagName,
name: tagName,
body: notes || ''
});
const [command, workingDir, filePath, opts] = process.argv;
if (filePath) {
Logger.info('Uploading', filePath, 'to release...');
await github.repos.uploadAsset(Object.assign({
owner,
repo,
id: data.id,
filePath,
name: filePath
}, opts ? JSON.parse(opts) : {}));
}
return data;
}
async function run() {
checkForPackageInfoRequirements();
github.authenticate({
type: 'token',
token: await promptGitHubToken()
});
const versionType = await promptVersionType();
const notes = await promptNotes();
const tagName = await versionAndReturnTagName(versionType, notes);
const output = await createGitHubRelease(tagName, notes);
Logger.success(`${tagName} released to GitHub - ${output.html_url}`);
await execp('npm publish');
const npmURL = `https://www.npmjs.com/package/${packageInfo.name}`;
Logger.success(`${tagName} released to npm - ${npmURL}`);
}
run().catch((errorMessage) => {
Logger.error('ERROR: ', errorMessage);
process.exit(1);
});