Skip to content

Commit f59d20c

Browse files
committed
fix: include deleted files in release commit
BREAKING CHANGE: Require Git 2.7.1 or higher
1 parent e6af5b4 commit f59d20c

11 files changed

+97
-224
lines changed

lib/git.js

+7-10
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@ const execa = require('execa');
22
const debug = require('debug')('semantic-release:git');
33

44
/**
5-
* Filter files modified on the local repository.
5+
* Retrieve the list of files modified on the local repository.
66
*
7-
* @param {Array<String>} files List of file paths to filter.
87
* @param {Object} [execaOpts] Options to pass to `execa`.
98
*
109
* @return {Array<String>} Array of modified files path.
1110
*/
12-
async function filterModifiedFiles(files, execaOpts) {
13-
return files.length > 0
14-
? (await execa('git', ['ls-files', '-m', '-o', ...files], execaOpts)).stdout
15-
.split('\n')
16-
.map(file => file.trim())
17-
.filter(file => Boolean(file))
18-
: [];
11+
async function getModifiedFiles(execaOpts) {
12+
return (await execa('git', ['ls-files', '-m', '-o'], execaOpts)).stdout
13+
.split('\n')
14+
.map(file => file.trim())
15+
.filter(file => Boolean(file));
1916
}
2017

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

68-
module.exports = {filterModifiedFiles, add, gitHead, commit, push};
65+
module.exports = {getModifiedFiles, add, gitHead, commit, push};

lib/glob-assets.js

-37
This file was deleted.

lib/prepare.js

+38-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
const {template} = require('lodash');
1+
const {isPlainObject, isArray, template, castArray, uniq} = require('lodash');
2+
const micromatch = require('micromatch');
3+
const dirGlob = require('dir-glob');
4+
const pReduce = require('p-reduce');
25
const debug = require('debug')('semantic-release:git');
36
const resolveConfig = require('./resolve-config');
4-
const globAssets = require('./glob-assets.js');
5-
const {filterModifiedFiles, add, commit, push} = require('./git');
7+
const {getModifiedFiles, add, commit, push} = require('./git');
68

79
/**
810
* Prepare a release commit including configurable files.
@@ -28,24 +30,42 @@ module.exports = async (pluginConfig, context) => {
2830
} = context;
2931
const {message, assets} = resolveConfig(pluginConfig, logger);
3032

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

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

37-
if (filesToCommit.length > 0) {
38-
logger.log('Found %d file(s) to commit', filesToCommit.length);
39-
await add(filesToCommit, {env, cwd});
40-
debug('commited files: %o', filesToCommit);
41-
await commit(
42-
message
43-
? template(message)({branch: branch.name, lastRelease, nextRelease})
44-
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
45-
{env, cwd}
46-
);
47-
}
50+
return [
51+
...result,
52+
...micromatch(modifiedFiles, await dirGlob(glob, {cwd}), {dot: true, nonegate, cwd, expand: true}),
53+
];
54+
},
55+
[]
56+
)
57+
);
4858

59+
if (filesToCommit.length > 0) {
60+
logger.log('Found %d file(s) to commit', filesToCommit.length);
61+
await add(filesToCommit, {env, cwd});
62+
debug('commited files: %o', filesToCommit);
63+
await commit(
64+
message
65+
? template(message)({branch: branch.name, lastRelease, nextRelease})
66+
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
67+
{env, cwd}
68+
);
4969
await push(repositoryUrl, branch.name, {env, cwd});
5070
logger.log('Prepared Git release: %s', nextRelease.gitTag);
5171
}

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
"debug": "^4.0.0",
2525
"dir-glob": "^3.0.0",
2626
"execa": "^3.0.0",
27-
"fs-extra": "^8.0.0",
28-
"globby": "^10.0.0",
2927
"lodash": "^4.17.4",
3028
"micromatch": "^4.0.0",
3129
"p-reduce": "^2.0.0"
@@ -35,6 +33,7 @@
3533
"clear-module": "^4.0.0",
3634
"codecov": "^3.0.0",
3735
"file-url": "^3.0.0",
36+
"fs-extra": "^8.0.0",
3837
"get-stream": "^5.0.0",
3938
"git-log-parser": "^1.2.0",
4039
"nyc": "^14.0.0",

test/fixtures/files/.dotfile

-1
This file was deleted.

test/fixtures/files/upload.txt

-1
This file was deleted.

test/fixtures/files/upload_other.txt

-1
This file was deleted.

test/git.test.js

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import path from 'path';
22
import test from 'ava';
33
import {outputFile, appendFile} from 'fs-extra';
4-
import {add, filterModifiedFiles, commit, gitHead, push} from '../lib/git';
4+
import {add, getModifiedFiles, commit, gitHead, push} from '../lib/git';
55
import {gitRepo, gitCommits, gitGetCommits, gitStaged, gitRemoteHead} from './helpers/git-utils';
66

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

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

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

47-
await t.deepEqual(await filterModifiedFiles(['file1.js', 'file2.js'], {cwd}), []);
48-
});
49-
50-
test('Returns [] if there is no files for which to check modification', async t => {
51-
// Create a git repository, set the current working directory at the root of the repo
52-
const {cwd} = await gitRepo();
53-
// Create files
54-
await outputFile(path.resolve(cwd, 'file1.js'), '');
55-
await outputFile(path.resolve(cwd, 'dir/file2.js'), '');
56-
57-
await t.deepEqual(await filterModifiedFiles([], {cwd}), []);
47+
await t.deepEqual(await getModifiedFiles({cwd}), []);
5848
});
5949

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

test/glob-assets.test.js

-138
This file was deleted.

test/helpers/git-utils.js

+21
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,24 @@ export async function gitCommitedFiles(ref, execaOpts) {
186186
.split('\n')
187187
.filter(file => Boolean(file));
188188
}
189+
190+
/**
191+
* Add a list of file to the Git index.
192+
*
193+
* @param {Array<String>} files Array of files path to add to the index.
194+
* @param {Object} [execaOpts] Options to pass to `execa`.
195+
*/
196+
export async function gitAdd(files, execaOpts) {
197+
await execa('git', ['add', '--force', '--ignore-errors', ...files], {...execaOpts});
198+
}
199+
200+
/**
201+
* Push to the remote repository.
202+
*
203+
* @param {String} repositoryUrl The remote repository URL.
204+
* @param {String} branch The branch to push.
205+
* @param {Object} [execaOpts] Options to pass to `execa`.
206+
*/
207+
export async function gitPush(repositoryUrl, branch, execaOpts) {
208+
await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOpts);
209+
}

0 commit comments

Comments
 (0)