Skip to content

Commit 150378e

Browse files
committed
[added] support for GitHub releases
Also added `--notes` option allowing custom release and tag messages
1 parent 36e32c4 commit 150378e

File tree

3 files changed

+107
-15
lines changed

3 files changed

+107
-15
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ E.g.:
5858
}
5959
```
6060

61+
#### GitHub releases
62+
63+
If you want this script to publish github releases,
64+
you can generate token https://github.com/settings/tokens for it
65+
and set `env.GITHUB_TOKEN` to it like this:
66+
```sh
67+
> GITHUB_TOKEN="xxxxxxxxxxxx" && release-script patch
68+
```
69+
or through your shell scripts
70+
```sh
71+
export GITHUB_TOKEN="xxxxxxxxxxxx"
72+
```
73+
You can set a custom message for release via `--notes` CLI option:
74+
```
75+
> release patch --notes "This is small fix"
76+
```
77+
78+
6179
#### This script does following steps:
6280

6381
- ensures that git repo has no pending changes
@@ -70,6 +88,7 @@ E.g.:
7088
- adds and commits changed `package.json` (and `CHANGELOG.md`, if used) files to git repo
7189
- adds git tag with new version (and changelog message, if used)
7290
- pushes changes to github repo
91+
- if github token is present, publishes release to GitHub, named as `<repo> vx.x.x`
7392
- releases npm package by `npm publish` command
7493
- if `bowerRepo` field is present in the `package.json`, then it releases bower package:
7594
- clones bower repo to local `tmpBowerRepo` temp folder. `git clone bowerRepo tmpBowerRepo`
@@ -128,6 +147,21 @@ you can add them just like that:
128147
"major": "release major"
129148
```
130149
150+
Also you can add it like this:
151+
```js
152+
"scripts": {
153+
...
154+
"release": "release",
155+
```
156+
And then you can run it like that:
157+
```
158+
> npm run release minor -- --preid alpha
159+
> npm run release patch -- --notes "This is small fix"
160+
> npm run release major -- --dry-run
161+
etc
162+
```
163+
_Notice: you have to add additional `--` before any `--option`. That way additional options will get straight to `release-script`._
164+
131165
132166
## License
133167
`release-script` is licensed under the [MIT License](https://github.com/alexkval/release-script/blob/master/LICENSE).

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
},
4747
"dependencies": {
4848
"colors": "^1.1.2",
49+
"request": "^2.60.0",
4950
"semver": "^5.0.0",
5051
"shelljs": "^0.5.1",
5152
"yargs": "^3.15.0"

src/release.js

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'shelljs/global';
66
import path from 'path';
77
import semver from 'semver';
88
import yargs from 'yargs';
9+
import request from 'request';
910

1011
// do not die on errors
1112
config.fatal = false;
@@ -18,10 +19,10 @@ const changelog = path.join(repoRoot, 'CHANGELOG.md');
1819

1920
const npmjson = JSON.parse(cat(packagePath));
2021
const isPrivate = npmjson.private;
22+
const devDepsNode = npmjson.devDependencies;
2123

2224
//------------------------------------------------------------------------------
2325
// check if one of 'rf-changelog' or 'mt-changelog' is used by project
24-
const devDepsNode = npmjson.devDependencies;
2526
const isCommitsChangelogUsed = devDepsNode &&
2627
devDepsNode['rf-changelog'] || devDepsNode['mt-changelog'];
2728
if (isCommitsChangelogUsed && !which('changelog')) {
@@ -33,25 +34,18 @@ if (isCommitsChangelogUsed && !which('changelog')) {
3334
const configOptions = npmjson['release-script'] || {};
3435
const bowerRoot = path.join(repoRoot, (configOptions.bowerRoot || 'amd/'));
3536
const tmpBowerRepo = path.join(repoRoot, (configOptions.tmpBowerRepo || 'tmp-bower-repo'));
36-
37-
// let bowerRepo;
38-
// if (npmjson.bowerRepo) {
39-
// bowerRepo = npmjson.bowerRepo;
40-
// } else {
41-
// let match = npmjson.repository.url.match(/^git@github\.com:(.*)\.git$/);
42-
// match = match || npmjson.repository.url.match(/^git\+https:\/\/github\.com\/(.*)\.git$/);
43-
// let gitUrlBase = match && match[1];
44-
// gitUrlBase = gitUrlBase || npmjson.repository.url;
45-
// bowerRepo = `[email protected]:${gitUrlBase}-bower.git`;
46-
// }
4737
const bowerRepo = configOptions.bowerRepo; // if it is not set, then there is no bower repo
4838

39+
const githubToken = process.env.GITHUB_TOKEN;
40+
41+
4942
//------------------------------------------------------------------------------
5043
// command line options
5144
const yargsConf = yargs
5245
.usage('Usage: $0 <version> [--preid <identifier>]')
5346
.example('$0 minor --preid beta', 'Release with minor version bump with pre-release tag')
5447
.example('$0 major', 'Release with major version bump')
48+
.example('$0 major --notes "This is new cool version"', 'Add a custom message to release')
5549
.example('$0 major --dry-run', 'Release dry run with patch version bump')
5650
.example('$0 --preid beta', 'Release same version with pre-release bump')
5751
.command('patch', 'Release patch')
@@ -73,6 +67,11 @@ const yargsConf = yargs
7367
demand: false,
7468
default: false,
7569
describe: 'Increased debug output'
70+
})
71+
.option('notes', {
72+
demand: false,
73+
default: false,
74+
describe: 'A custom message for release. Overrides [rf|mt]changelog message'
7675
});
7776

7877
const argv = yargsConf.argv;
@@ -92,6 +91,8 @@ if (versionBumpOptions.type === undefined && versionBumpOptions.preid === undefi
9291
exit(1);
9392
}
9493

94+
let notesForRelease = argv.notes;
95+
9596

9697
//------------------------------------------------------------------------------
9798
// functions
@@ -114,6 +115,20 @@ function safeRun(command) {
114115
}
115116
}
116117

118+
/**
119+
* Npm's `package.json` 'repository.url' could be set to one of three forms:
120+
* [email protected]:<author>/<repo-name>.git
121+
* git+https://github.com/<author>/<repo-name>.git
122+
* or just <author>/<repo-name>
123+
* @returns [<author>, <repo-name>] array
124+
*/
125+
function getOwnerAndRepo(url) {
126+
let match = url.match(/^git@github\.com:(.*)\.git$/);
127+
match = match || url.match(/^git\+https:\/\/github\.com\/(.*)\.git$/);
128+
let gitUrlBase = match && match[1];
129+
return (gitUrlBase || url).split('/');
130+
}
131+
117132
function release({ type, preid }) {
118133
if (type === undefined && !preid) printErrorAndExit('Must specify version type or preid');
119134

@@ -174,10 +189,11 @@ function release({ type, preid }) {
174189
}
175190

176191
const vVersion = `v${newVersion}`;
192+
const versionAndNotes = notesForRelease = notesForRelease ? `${vVersion} ${notesForRelease}` : vVersion;
177193

178194
// generate changelog
179195
if (isCommitsChangelogUsed) {
180-
run(`changelog --title ${vVersion} --out ${changelog}`);
196+
run(`changelog --title="${versionAndNotes}" --out ${changelog}`);
181197
safeRun(`git add ${changelog}`);
182198
console.log('Generated Changelog'.cyan);
183199
}
@@ -187,14 +203,55 @@ function release({ type, preid }) {
187203
// tag and release
188204
console.log('Tagging: '.cyan + vVersion.green);
189205
if (isCommitsChangelogUsed) {
190-
safeRun(`changelog --title ${vVersion} -s | git tag -a -F - ${vVersion}`);
206+
notesForRelease = run(`changelog --title="${versionAndNotes}" -s`);
207+
safeRun(`changelog --title="${versionAndNotes}" -s | git tag -a -F - ${vVersion}`);
191208
} else {
192-
safeRun(`git tag -a --message=${vVersion} ${vVersion}`);
209+
safeRun(`git tag -a --message="${versionAndNotes}" ${vVersion}`);
193210
}
194211
safeRun('git push');
195212
safeRun('git push --tags');
196213
console.log('Tagged: '.cyan + vVersion.green);
197214

215+
// publish to GitHub
216+
if (githubToken) {
217+
console.log(`GitHub token found ${githubToken}`.green);
218+
console.log('Publishing to GitHub: '.cyan + vVersion.green);
219+
220+
if (argv.dryRun) {
221+
console.log(`[publishing to GitHub]`.grey, 'DRY RUN'.magenta);
222+
} else {
223+
const [githubOwner, githubRepo] = getOwnerAndRepo(npmjson.repository.url);
224+
225+
request({
226+
uri: `https://api.github.com/repos/${githubOwner}/${githubRepo}/releases`,
227+
method: 'POST',
228+
json: true,
229+
body: {
230+
tag_name: vVersion, // eslint-disable-line camelcase
231+
name: `${githubRepo} ${vVersion}`,
232+
body: notesForRelease,
233+
draft: false,
234+
prerelease: !!preid
235+
},
236+
headers: {
237+
'Authorization': `token ${githubToken}`,
238+
'User-Agent': 'release-script (https://github.com/alexkval/release-script)'
239+
}
240+
}, function (err, res, body) {
241+
if (err) {
242+
console.log('API request to GitHub, error has occured:'.red);
243+
console.log(err);
244+
console.log('Skip GitHub releasing'.yellow);
245+
} else if (res.statusMessage === 'Unauthorized') {
246+
console.log(`GitHub token ${githubToken} is wrong`.red);
247+
console.log('Skip GitHub releasing'.yellow);
248+
} else {
249+
console.log(`Published at ${body.html_url}`.green);
250+
}
251+
});
252+
}
253+
}
254+
198255
// npm
199256
if (isPrivate) {
200257
console.log('Package is private, skipping npm release'.yellow);

0 commit comments

Comments
 (0)