- Add a new plugin type: `publish` - Add support for multi-plugin. A plugin module can now return an object with a property for each plugin type - Uses by default [npm](https://github.com/semantic-release/npm) and [github](https://github.com/semantic-release/github) in addition of Travis for the verify condition plugin - Uses by default [npm](https://github.com/semantic-release/npm) and [github](https://github.com/semantic-release/github) for the publish plugin - `gitTag` if one can be found is passed to `generateNotes` for both `lastRelease` and `nextRelease` - `semantic-release` now verifies the plugin configuration (in the `release` property of `package.json`) and throws an error if it's invalid - `semantic-release` now verifies each plugin output and will throw an error if a plugin returns an unexpected value. BREAKING CHANGE: `githubToken`, `githubUrl` and `githubApiPathPrefix` have to be set at the [github](https://github.com/semantic-release/github) plugin level. They can be set via `GH_TOKEN`, `GH_URL` and `GH_PREFIX` environment variables. BREAKING CHANGE: the `npm` parameter is not passed to any plugin anymore. Each plugin have to read `.npmrc` if they needs to (with https://github.com/kevva/npm-conf for example).
140 lines
4.4 KiB
JavaScript
140 lines
4.4 KiB
JavaScript
import tempy from 'tempy';
|
|
import execa from 'execa';
|
|
import pMapSeries from 'p-map-series';
|
|
|
|
/**
|
|
* Commit message informations.
|
|
*
|
|
* @typedef {Object} Commit
|
|
* @property {string} branch The commit branch.
|
|
* @property {string} hash The commit hash.
|
|
* @property {string} message The commit message.
|
|
*/
|
|
|
|
/**
|
|
* Create a temporary git repository and change the current working directory to the repository root.
|
|
*
|
|
* @return {string} The path of the repository.
|
|
*/
|
|
export async function gitRepo() {
|
|
const dir = tempy.directory();
|
|
|
|
process.chdir(dir);
|
|
await execa('git', ['init']);
|
|
await gitCheckout('master');
|
|
return dir;
|
|
}
|
|
|
|
/**
|
|
* Create commits on the current git repository.
|
|
*
|
|
* @param {Array<string>} messages commit messages.
|
|
*
|
|
* @returns {Array<Commit>} The created commits, in reverse order (to match `git log` order).
|
|
*/
|
|
export async function gitCommits(messages) {
|
|
return (await pMapSeries(messages, async msg => {
|
|
const {stdout} = await execa('git', ['commit', '-m', msg, '--allow-empty', '--no-gpg-sign']);
|
|
const [, branch, hash, message] = /^\[(\w+)\(?.*?\)?(\w+)\] (.+)$/.exec(stdout);
|
|
return {branch, hash, message};
|
|
})).reverse();
|
|
}
|
|
|
|
/**
|
|
* Amend a commit (rewriting the sha) on the current git repository.
|
|
*
|
|
* @param {string} messages commit message.
|
|
*
|
|
* @returns {Array<Commit>} the created commits.
|
|
*/
|
|
export async function gitAmmendCommit(msg) {
|
|
const {stdout} = await execa('git', ['commit', '--amend', '-m', msg, '--allow-empty']);
|
|
const [, branch, hash, message] = /^\[(\w+)\(?.*?\)?(\w+)\] (.+)(.|\s)+$/.exec(stdout);
|
|
return {branch, hash, message};
|
|
}
|
|
|
|
/**
|
|
* Checkout a branch on the current git repository.
|
|
*
|
|
* @param {string} branch Branch name.
|
|
* @param {boolean} create `true` to create the branche ans switch, `false` to only switch.
|
|
*/
|
|
export async function gitCheckout(branch, create = true) {
|
|
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch]);
|
|
}
|
|
|
|
/**
|
|
* @return {string} The sha of the head commit in the current git repository.
|
|
*/
|
|
export async function gitHead() {
|
|
return (await execa('git', ['rev-parse', 'HEAD'])).stdout;
|
|
}
|
|
|
|
/**
|
|
* Create a tag on the head commit in the current git repository.
|
|
*
|
|
* @param {string} tagName The tag name to create.
|
|
* @param {string} [sha] The commit on which to create the tag. If undefined the tag is created on the last commit.
|
|
*
|
|
* @return {string} The commit sha of the created tag.
|
|
*/
|
|
export async function gitTagVersion(tagName, sha) {
|
|
await execa('git', sha ? ['tag', '-f', tagName, sha] : ['tag', tagName]);
|
|
return (await execa('git', ['rev-list', '-1', '--tags', tagName])).stdout;
|
|
}
|
|
|
|
/**
|
|
* @return {Array<string>} The list of tags from the current git repository.
|
|
*/
|
|
export async function gitTags() {
|
|
return (await execa('git', ['tag'])).stdout.split('\n').filter(tag => !!tag);
|
|
}
|
|
|
|
/**
|
|
* @return {Array<string>} The list of commit sha from the current git repository.
|
|
*/
|
|
export async function gitLog() {
|
|
return (await execa('git', ['log', '--format=format:%H'])).stdout.split('\n').filter(sha => !!sha);
|
|
}
|
|
|
|
/**
|
|
* Create a shallow clone of a git repository and change the current working directory to the cloned repository root.
|
|
* The shallow will contain a limited number of commit and no tags.
|
|
*
|
|
* @param {string} origin The path of the repository to clone.
|
|
* @param {number} [depth=1] The number of commit to clone.
|
|
* @return {string} The path of the cloned repository.
|
|
*/
|
|
export async function gitShallowClone(origin, branch = 'master', depth = 1) {
|
|
const dir = tempy.directory();
|
|
|
|
process.chdir(dir);
|
|
await execa('git', ['clone', '--no-hardlinks', '--no-tags', '-b', branch, '--depth', depth, `file://${origin}`, dir]);
|
|
return dir;
|
|
}
|
|
|
|
/**
|
|
* Create a git repo with a detached head from another git repository and change the current working directory to the new repository root.
|
|
*
|
|
* @param {string} origin The path of the repository to clone.
|
|
* @param {number} head A commit sha of the origin repo that will become the detached head of the new one.
|
|
* @return {string} The path of the new repository.
|
|
*/
|
|
export async function gitDetachedHead(origin, head) {
|
|
const dir = tempy.directory();
|
|
|
|
process.chdir(dir);
|
|
await execa('git', ['init']);
|
|
await execa('git', ['remote', 'add', 'origin', origin]);
|
|
await execa('git', ['fetch']);
|
|
await execa('git', ['checkout', head]);
|
|
return dir;
|
|
}
|
|
|
|
/**
|
|
* Pack heads and tags of the current git repository.
|
|
*/
|
|
export async function gitPackRefs() {
|
|
await execa('git', ['pack-refs', '--all']);
|
|
}
|