Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/beta'
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdlg committed Jan 9, 2020
2 parents ceb9cca + e312747 commit 1fd1243
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 276 deletions.
8 changes: 5 additions & 3 deletions .travis.yml
Expand Up @@ -2,14 +2,16 @@ language: node_js

node_js:
- 12
- 10
- 8.16
- 10.13

# Trigger a push build on master and greenkeeper branches + PRs build on every branches
# Trigger a push build on release and greenkeeper branches + PRs build on every branches
# Avoid double build on PRs (See https://github.com/travis-ci/travis-ci/issues/1147)
branches:
only:
- master
- next
- beta
- /^\d+\.(\d+|x)(\.x)?$/
- /^greenkeeper.*$/

# Retry install on fail to avoid failing a build on network/disk/external errors
Expand Down
24 changes: 19 additions & 5 deletions README.md
Expand Up @@ -8,6 +8,7 @@

[![npm latest version](https://img.shields.io/npm/v/@semantic-release/git/latest.svg)](https://www.npmjs.com/package/@semantic-release/git)
[![npm next version](https://img.shields.io/npm/v/@semantic-release/git/next.svg)](https://www.npmjs.com/package/@semantic-release/git)
[![npm beta version](https://img.shields.io/npm/v/@semantic-release/git/beta.svg)](https://www.npmjs.com/package/@semantic-release/git)

| Step | Description |
|--------------------|------------------------------------------------------------------------------------------------------------------------------------|
Expand Down Expand Up @@ -41,6 +42,14 @@ With this example, for each release a release commit will be pushed to the remot
- a message formatted like `chore(release): <version> [skip ci]\n\n<release notes>`
- the `.js` and `.css` files in the `dist` directory, the files in the `docs` directory and the `package.json`

### Merging between semantic-release branches

This plugin will, by default, create commit messages with the keyword `[skip ci]`, so they won't trigger a new unnecessary CI build. If you are using **semantic-release** with [multiple branches](https://github.com/semantic-release/semantic-release/blob/beta/docs/usage/workflow-configuration.md), when merging a branch with a head being a release commit, a CI job will be triggered on the target branch. Depending on the CI service that might create an unexpected behavior as the head of the target branch might be ignored by the build due to the `[skip ci]` keyword.

To avoid any unexpected behavior we recommend to use the [`--no-ff` option](https://git-scm.com/docs/git-merge#Documentation/git-merge.txt---no-ff) when merging branches used by **semantic-release**.

**Note**: This concerns only merges done between two branches configured in the [`branches` option](https://github.com/semantic-release/semantic-release/blob/beta/docs/usage/configuration.md#branches).

## Configuration

### Git authentication
Expand Down Expand Up @@ -69,11 +78,16 @@ When configuring branches permission on a Git hosting service (e.g. [GitHub prot

The message for the release commit is generated with [Lodash template](https://lodash.com/docs#template). The following variables are available:

| Parameter | Description |
|---------------|-------------------------------------------------------------------------------------|
| `branch` | The branch from which the release is done. |
| `lastRelease` | `Object` with `version`, `gitTag` and `gitHead` of the last release. |
| `nextRelease` | `Object` with `version`, `gitTag`, `gitHead` and `notes` of the release being done. |
| Parameter | Description |
|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `branch` | The branch from which the release is done. |
| `branch.name` | The branch name. |
| `branch.type` | The [type of branch](https://github.com/semantic-release/semantic-release/blob/beta/docs/usage/workflow-configuration.md#branch-types). |
| `branch.channel` | The distribution channel on which to publish releases from this branch. |
| `branch.range` | The range of [semantic versions](https://semver.org) to support on this branch. |
| `branch.prerelease` | The pre-release detonation to append to [semantic versions](https://semver.org) released from this branch. |
| `lastRelease` | `Object` with `version`, `gitTag` and `gitHead` of the last release. |
| `nextRelease` | `Object` with `version`, `gitTag`, `gitHead` and `notes` of the release being done. |

**Note**: It is recommended to include `[skip ci]` in the commit message to not trigger a new build. Some CI service support the `[skip ci]` keyword only in the subject of the message.

Expand Down
17 changes: 7 additions & 10 deletions lib/git.js
Expand Up @@ -2,20 +2,17 @@ const execa = require('execa');
const debug = require('debug')('semantic-release:git');

/**
* Filter files modified on the local repository.
* Retrieve the list of files modified on the local repository.
*
* @param {Array<String>} files List of file paths to filter.
* @param {Object} [execaOpts] Options to pass to `execa`.
*
* @return {Array<String>} Array of modified files path.
*/
async function filterModifiedFiles(files, execaOpts) {
return files.length > 0
? (await execa('git', ['ls-files', '-m', '-o', ...files], execaOpts)).stdout
.split('\n')
.map(file => file.trim())
.filter(file => Boolean(file))
: [];
async function getModifiedFiles(execaOpts) {
return (await execa('git', ['ls-files', '-m', '-o'], execaOpts)).stdout
.split('\n')
.map(file => file.trim())
.filter(file => Boolean(file));
}

/**
Expand Down Expand Up @@ -65,4 +62,4 @@ async function gitHead(execaOpts) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOpts)).stdout;
}

module.exports = {filterModifiedFiles, add, gitHead, commit, push};
module.exports = {getModifiedFiles, add, gitHead, commit, push};
37 changes: 0 additions & 37 deletions lib/glob-assets.js

This file was deleted.

61 changes: 41 additions & 20 deletions lib/prepare.js
@@ -1,8 +1,10 @@
const {template} = require('lodash');
const {isPlainObject, isArray, template, castArray, uniq} = require('lodash');
const micromatch = require('micromatch');
const dirGlob = require('dir-glob');
const pReduce = require('p-reduce');
const debug = require('debug')('semantic-release:git');
const resolveConfig = require('./resolve-config');
const globAssets = require('./glob-assets.js');
const {filterModifiedFiles, add, commit, push} = require('./git');
const {getModifiedFiles, add, commit, push} = require('./git');

/**
* Prepare a release commit including configurable files.
Expand All @@ -20,32 +22,51 @@ module.exports = async (pluginConfig, context) => {
const {
env,
cwd,
options: {branch, repositoryUrl},
branch,
options: {repositoryUrl},
lastRelease,
nextRelease,
logger,
} = context;
const {message, assets} = resolveConfig(pluginConfig, logger);

if (assets && assets.length > 0) {
const globbedAssets = await globAssets(context, assets);
debug('globed assets: %o', globbedAssets);
const modifiedFiles = await getModifiedFiles({env, cwd});

const filesToCommit = await filterModifiedFiles(globbedAssets, {cwd, env});
const filesToCommit = uniq(
await pReduce(
assets.map(asset => (!isArray(asset) && isPlainObject(asset) ? asset.path : asset)),
async (result, asset) => {
const glob = castArray(asset);
let nonegate;
// Skip solo negated pattern (avoid to include every non js file with `!**/*.js`)
if (glob.length <= 1 && glob[0].startsWith('!')) {
nonegate = true;
debug(
'skipping the negated glob %o as its alone in its group and would retrieve a large amount of files ',
glob[0]
);
}

if (filesToCommit.length > 0) {
logger.log('Found %d file(s) to commit', filesToCommit.length);
await add(filesToCommit, {env, cwd});
debug('commited files: %o', filesToCommit);
await commit(
message
? template(message)({branch, lastRelease, nextRelease})
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
{env, cwd}
);
}
return [
...result,
...micromatch(modifiedFiles, await dirGlob(glob, {cwd}), {dot: true, nonegate, cwd, expand: true}),
];
},
[]
)
);

await push(repositoryUrl, branch, {env, cwd});
if (filesToCommit.length > 0) {
logger.log('Found %d file(s) to commit', filesToCommit.length);
await add(filesToCommit, {env, cwd});
debug('commited files: %o', filesToCommit);
await commit(
message
? template(message)({branch: branch.name, lastRelease, nextRelease})
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
{env, cwd}
);
await push(repositoryUrl, branch.name, {env, cwd});
logger.log('Prepared Git release: %s', nextRelease.gitTag);
}
};
14 changes: 6 additions & 8 deletions package.json
Expand Up @@ -23,9 +23,7 @@
"aggregate-error": "^3.0.0",
"debug": "^4.0.0",
"dir-glob": "^3.0.0",
"execa": "^3.2.0",
"fs-extra": "^8.0.0",
"globby": "^10.0.0",
"execa": "^4.0.0",
"lodash": "^4.17.4",
"micromatch": "^4.0.0",
"p-reduce": "^2.0.0"
Expand All @@ -35,16 +33,17 @@
"clear-module": "^4.0.0",
"codecov": "^3.0.0",
"file-url": "^3.0.0",
"fs-extra": "^8.0.0",
"get-stream": "^5.0.0",
"git-log-parser": "^1.2.0",
"nyc": "^15.0.0",
"semantic-release": "^15.0.0",
"semantic-release": "^16.0.0-beta",
"sinon": "^8.0.0",
"tempy": "^0.3.0",
"xo": "^0.25.2"
},
"engines": {
"node": ">=8.16"
"node": ">=10.13"
},
"files": [
"lib",
Expand Down Expand Up @@ -76,15 +75,14 @@
"all": true
},
"peerDependencies": {
"semantic-release": ">=15.4.0 <16.0.0"
"semantic-release": ">=16.0.0-beta <17.0.0"
},
"prettier": {
"printWidth": 120,
"trailingComma": "es5"
},
"publishConfig": {
"access": "public",
"tag": "next"
"access": "public"
},
"repository": {
"type": "git",
Expand Down
1 change: 0 additions & 1 deletion test/fixtures/files/.dotfile

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/files/upload.txt

This file was deleted.

1 change: 0 additions & 1 deletion test/fixtures/files/upload_other.txt

This file was deleted.

18 changes: 4 additions & 14 deletions test/git.test.js
@@ -1,7 +1,7 @@
import path from 'path';
import test from 'ava';
import {outputFile, appendFile} from 'fs-extra';
import {add, filterModifiedFiles, commit, gitHead, push} from '../lib/git';
import {add, getModifiedFiles, commit, gitHead, push} from '../lib/git';
import {gitRepo, gitCommits, gitGetCommits, gitStaged, gitRemoteHead} from './helpers/git-utils';

test('Add file to index', async t => {
Expand All @@ -15,7 +15,7 @@ test('Add file to index', async t => {
await t.deepEqual(await gitStaged({cwd}), ['file1.js']);
});

test('Filter modified files, including files in .gitignore and untracked ones', async t => {
test('Get the modified files, including files in .gitignore but including untracked ones', async t => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Create files
Expand All @@ -35,7 +35,7 @@ test('Filter modified files, including files in .gitignore and untracked ones',
await outputFile(path.resolve(cwd, 'file4.js'), 'Test content');

await t.deepEqual(
(await filterModifiedFiles(['file1.js', 'dir/file2.js', 'file3.js', 'file4.js'], {cwd})).sort(),
(await getModifiedFiles({cwd})).sort(),
['file1.js', 'dir/file2.js', 'file3.js', 'file4.js'].sort()
);
});
Expand All @@ -44,17 +44,7 @@ test('Returns [] if there is no modified files', async t => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();

await t.deepEqual(await filterModifiedFiles(['file1.js', 'file2.js'], {cwd}), []);
});

test('Returns [] if there is no files for which to check modification', async t => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Create files
await outputFile(path.resolve(cwd, 'file1.js'), '');
await outputFile(path.resolve(cwd, 'dir/file2.js'), '');

await t.deepEqual(await filterModifiedFiles([], {cwd}), []);
await t.deepEqual(await getModifiedFiles({cwd}), []);
});

test('Commit added files', async t => {
Expand Down

0 comments on commit 1fd1243

Please sign in to comment.