Skip to content

Commit

Permalink
[added] support for GitHub releases
Browse files Browse the repository at this point in the history
Also added `--notes` option allowing custom release and tag messages
  • Loading branch information
AlexKVal committed Aug 9, 2015
1 parent 36e32c4 commit 150378e
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 15 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ E.g.:
}
```

#### GitHub releases

If you want this script to publish github releases,
you can generate token https://github.com/settings/tokens for it
and set `env.GITHUB_TOKEN` to it like this:
```sh
> GITHUB_TOKEN="xxxxxxxxxxxx" && release-script patch
```
or through your shell scripts
```sh
export GITHUB_TOKEN="xxxxxxxxxxxx"
```
You can set a custom message for release via `--notes` CLI option:
```
> release patch --notes "This is small fix"
```


#### This script does following steps:

- ensures that git repo has no pending changes
Expand All @@ -70,6 +88,7 @@ E.g.:
- adds and commits changed `package.json` (and `CHANGELOG.md`, if used) files to git repo
- adds git tag with new version (and changelog message, if used)
- pushes changes to github repo
- if github token is present, publishes release to GitHub, named as `<repo> vx.x.x`
- releases npm package by `npm publish` command
- if `bowerRepo` field is present in the `package.json`, then it releases bower package:
- clones bower repo to local `tmpBowerRepo` temp folder. `git clone bowerRepo tmpBowerRepo`
Expand Down Expand Up @@ -128,6 +147,21 @@ you can add them just like that:
"major": "release major"
```
Also you can add it like this:
```js
"scripts": {
...
"release": "release",
```
And then you can run it like that:
```
> npm run release minor -- --preid alpha
> npm run release patch -- --notes "This is small fix"
> npm run release major -- --dry-run
etc
```
_Notice: you have to add additional `--` before any `--option`. That way additional options will get straight to `release-script`._
## License
`release-script` is licensed under the [MIT License](https://github.com/alexkval/release-script/blob/master/LICENSE).
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
},
"dependencies": {
"colors": "^1.1.2",
"request": "^2.60.0",
"semver": "^5.0.0",
"shelljs": "^0.5.1",
"yargs": "^3.15.0"
Expand Down
87 changes: 72 additions & 15 deletions src/release.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'shelljs/global';
import path from 'path';
import semver from 'semver';
import yargs from 'yargs';
import request from 'request';

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

const npmjson = JSON.parse(cat(packagePath));
const isPrivate = npmjson.private;
const devDepsNode = npmjson.devDependencies;

//------------------------------------------------------------------------------
// check if one of 'rf-changelog' or 'mt-changelog' is used by project
const devDepsNode = npmjson.devDependencies;
const isCommitsChangelogUsed = devDepsNode &&
devDepsNode['rf-changelog'] || devDepsNode['mt-changelog'];
if (isCommitsChangelogUsed && !which('changelog')) {
Expand All @@ -33,25 +34,18 @@ if (isCommitsChangelogUsed && !which('changelog')) {
const configOptions = npmjson['release-script'] || {};
const bowerRoot = path.join(repoRoot, (configOptions.bowerRoot || 'amd/'));
const tmpBowerRepo = path.join(repoRoot, (configOptions.tmpBowerRepo || 'tmp-bower-repo'));

// let bowerRepo;
// if (npmjson.bowerRepo) {
// bowerRepo = npmjson.bowerRepo;
// } else {
// let match = npmjson.repository.url.match(/^git@github\.com:(.*)\.git$/);
// match = match || npmjson.repository.url.match(/^git\+https:\/\/github\.com\/(.*)\.git$/);
// let gitUrlBase = match && match[1];
// gitUrlBase = gitUrlBase || npmjson.repository.url;
// bowerRepo = `[email protected]:${gitUrlBase}-bower.git`;
// }
const bowerRepo = configOptions.bowerRepo; // if it is not set, then there is no bower repo

const githubToken = process.env.GITHUB_TOKEN;


//------------------------------------------------------------------------------
// command line options
const yargsConf = yargs
.usage('Usage: $0 <version> [--preid <identifier>]')
.example('$0 minor --preid beta', 'Release with minor version bump with pre-release tag')
.example('$0 major', 'Release with major version bump')
.example('$0 major --notes "This is new cool version"', 'Add a custom message to release')
.example('$0 major --dry-run', 'Release dry run with patch version bump')
.example('$0 --preid beta', 'Release same version with pre-release bump')
.command('patch', 'Release patch')
Expand All @@ -73,6 +67,11 @@ const yargsConf = yargs
demand: false,
default: false,
describe: 'Increased debug output'
})
.option('notes', {
demand: false,
default: false,
describe: 'A custom message for release. Overrides [rf|mt]changelog message'
});

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

let notesForRelease = argv.notes;


//------------------------------------------------------------------------------
// functions
Expand All @@ -114,6 +115,20 @@ function safeRun(command) {
}
}

/**
* Npm's `package.json` 'repository.url' could be set to one of three forms:
* [email protected]:<author>/<repo-name>.git
* git+https://github.com/<author>/<repo-name>.git
* or just <author>/<repo-name>
* @returns [<author>, <repo-name>] array
*/
function getOwnerAndRepo(url) {
let match = url.match(/^git@github\.com:(.*)\.git$/);
match = match || url.match(/^git\+https:\/\/github\.com\/(.*)\.git$/);
let gitUrlBase = match && match[1];
return (gitUrlBase || url).split('/');
}

function release({ type, preid }) {
if (type === undefined && !preid) printErrorAndExit('Must specify version type or preid');

Expand Down Expand Up @@ -174,10 +189,11 @@ function release({ type, preid }) {
}

const vVersion = `v${newVersion}`;
const versionAndNotes = notesForRelease = notesForRelease ? `${vVersion} ${notesForRelease}` : vVersion;

// generate changelog
if (isCommitsChangelogUsed) {
run(`changelog --title ${vVersion} --out ${changelog}`);
run(`changelog --title="${versionAndNotes}" --out ${changelog}`);
safeRun(`git add ${changelog}`);
console.log('Generated Changelog'.cyan);
}
Expand All @@ -187,14 +203,55 @@ function release({ type, preid }) {
// tag and release
console.log('Tagging: '.cyan + vVersion.green);
if (isCommitsChangelogUsed) {
safeRun(`changelog --title ${vVersion} -s | git tag -a -F - ${vVersion}`);
notesForRelease = run(`changelog --title="${versionAndNotes}" -s`);
safeRun(`changelog --title="${versionAndNotes}" -s | git tag -a -F - ${vVersion}`);
} else {
safeRun(`git tag -a --message=${vVersion} ${vVersion}`);
safeRun(`git tag -a --message="${versionAndNotes}" ${vVersion}`);
}
safeRun('git push');
safeRun('git push --tags');
console.log('Tagged: '.cyan + vVersion.green);

// publish to GitHub
if (githubToken) {
console.log(`GitHub token found ${githubToken}`.green);
console.log('Publishing to GitHub: '.cyan + vVersion.green);

if (argv.dryRun) {
console.log(`[publishing to GitHub]`.grey, 'DRY RUN'.magenta);
} else {
const [githubOwner, githubRepo] = getOwnerAndRepo(npmjson.repository.url);

request({
uri: `https://api.github.com/repos/${githubOwner}/${githubRepo}/releases`,
method: 'POST',
json: true,
body: {
tag_name: vVersion, // eslint-disable-line camelcase
name: `${githubRepo} ${vVersion}`,
body: notesForRelease,
draft: false,
prerelease: !!preid
},
headers: {
'Authorization': `token ${githubToken}`,
'User-Agent': 'release-script (https://github.com/alexkval/release-script)'
}
}, function (err, res, body) {
if (err) {
console.log('API request to GitHub, error has occured:'.red);
console.log(err);
console.log('Skip GitHub releasing'.yellow);
} else if (res.statusMessage === 'Unauthorized') {
console.log(`GitHub token ${githubToken} is wrong`.red);
console.log('Skip GitHub releasing'.yellow);
} else {
console.log(`Published at ${body.html_url}`.green);
}
});
}
}

// npm
if (isPrivate) {
console.log('Package is private, skipping npm release'.yellow);
Expand Down

0 comments on commit 150378e

Please sign in to comment.