Skip to content

Commit

Permalink
feat: commit files from assets even if in they are in .gitignore
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the `.gitignore` file is now ignored when adding files to the release commit

Each files matching a glob in `assets` will now be included in the release commit. The `assets` option has now to be configured to match exactly the the files that have to be commited, independently of the `.gitignore` file.
  • Loading branch information
pvdlg authored and gr2m committed Jun 27, 2018
1 parent fede564 commit 629dfc4
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 30 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Each entry in the `assets` `Array` is globbed individually. A [glob](https://git

If a directory is configured, all the files under this directory and its children will be included.

If a file has a match in `.gitignore` it will always be excluded.
**Note**: If a file has a match in `assets` it will be included even if it also has a match in `.gitignore`.

##### `assets` examples

Expand Down
7 changes: 3 additions & 4 deletions lib/git.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@ const debug = require('debug')('semantic-release:git');
* @return {Array<String>} Array of modified files path.
*/
async function getModifiedFiles() {
return (await execa.stdout('git', ['ls-files', '-m', '-o', '--exclude-standard']))
return (await execa.stdout('git', ['ls-files', '-m', '-o']))
.split('\n')
.map(tag => tag.trim())
.filter(tag => Boolean(tag));
}

/**
* Add a list of file to the Git index.
* If on of the files is present in the .gitignore it will be silently skipped. Other files will still be added.
* Add a list of file to the Git index. `.gitignore` will be ignored.
*
* @param {Array<String>} files Array of files path to add to the index,
*/
async function add(files) {
const shell = await execa('git', ['add', '--ignore-errors'].concat(files), {reject: false});
const shell = await execa('git', ['add', '--force', '--ignore-errors'].concat(files), {reject: false});
debug('add file to git index', shell);
}

Expand Down
7 changes: 4 additions & 3 deletions test/git.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ test.serial('Add file to index', async t => {
await t.deepEqual(await gitStaged(), ['file1.js']);
});

test.serial('Get the modified files, ignoring files in .gitignore but including untracked ones', async t => {
test.serial('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
await gitRepo();
// Create files
Expand All @@ -34,13 +34,14 @@ test.serial('Get the modified files, ignoring files in .gitignore but including
// Add files and commit
await add(['.']);
await commit('Test commit');
// Update file1.js and dir/file2.js
// Update file1.js, dir/file2.js and file3.js
await appendFile('file1.js', 'Test content');
await appendFile('dir/file2.js', 'Test content');
await appendFile('file3.js', 'Test content');
// Add untracked file
await outputFile('file4.js', 'Test content');

await t.deepEqual(await getModifiedFiles(), ['file4.js', 'dir/file2.js', 'file1.js']);
await t.deepEqual((await getModifiedFiles()).sort(), ['file4.js', 'file3.js', 'dir/file2.js', 'file1.js'].sort());
});

test.serial('Returns [] if there is no modified files', async t => {
Expand Down
34 changes: 12 additions & 22 deletions test/prepare.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,13 @@ test.serial('Commit files matching the patterns in "assets"', async t => {
// Verify file2 and file1 have been commited
// file4.js is excluded as no glob matching
// file3.css is ignored due to the negative glob '!dir/*.css'
// file5.js is ignore because it's in the .gitignore
// file5.js is not ignored even if it's in the .gitignore
// file6.js and file7.css are included because dir2 is expanded
t.deepEqual(await gitCommitedFiles(), ['dir/file2.js', 'dir2/file6.js', 'dir2/file7.css', 'file1.js']);
t.deepEqual(t.context.log.args[0], ['Found %d file(s) to commit', 4]);
t.deepEqual(
(await gitCommitedFiles()).sort(),
['dir/file2.js', 'dir2/file6.js', 'dir2/file7.css', 'file1.js', 'file5.js'].sort()
);
t.deepEqual(t.context.log.args[0], ['Found %d file(s) to commit', 5]);
});

test.serial('Commit files matching the patterns in "assets" as Objects', async t => {
Expand All @@ -155,10 +158,13 @@ test.serial('Commit files matching the patterns in "assets" as Objects', async t
// Verify file2 and file1 have been commited
// file4.js is excluded as no glob matching
// file3.css is ignored due to the negative glob '!dir/*.css'
// file5.js is ignore because it's in the .gitignore
// file5.js is not ignored even if it's in the .gitignore
// file6.js and file7.css are included because dir2 is expanded
t.deepEqual(await gitCommitedFiles(), ['dir/file2.js', 'dir2/file6.js', 'dir2/file7.css', 'file1.js']);
t.deepEqual(t.context.log.args[0], ['Found %d file(s) to commit', 4]);
t.deepEqual(
(await gitCommitedFiles()).sort(),
['dir/file2.js', 'dir2/file6.js', 'dir2/file7.css', 'file1.js', 'file5.js'].sort()
);
t.deepEqual(t.context.log.args[0], ['Found %d file(s) to commit', 5]);
});

test.serial('Commit files matching the patterns in "assets" as single glob', async t => {
Expand Down Expand Up @@ -237,19 +243,3 @@ test.serial('Skip commit if there is no files to commit', async t => {
t.deepEqual(t.context.log.args[0], ['Creating tag %s', nextRelease.gitTag]);
t.deepEqual(t.context.log.args[1], ['Prepared Git release: %s', nextRelease.gitTag]);
});

test.serial('Skip commit if all the modified files are in .gitignore', async t => {
const pluginConfig = {assets: 'dist'};
const lastRelease = {};
const nextRelease = {version: '2.0.0', gitTag: 'v2.0.0'};

await outputFile('dist/files1.js', 'Test content');
await outputFile('.gitignore', 'dist/**/*');

await prepare(pluginConfig, {options: t.context.options, lastRelease, nextRelease, logger: t.context.logger});

// Verify the files that have been commited
t.deepEqual(await gitCommitedFiles(), []);
t.deepEqual(t.context.log.args[0], ['Creating tag %s', nextRelease.gitTag]);
t.deepEqual(t.context.log.args[1], ['Prepared Git release: %s', nextRelease.gitTag]);
});

0 comments on commit 629dfc4

Please sign in to comment.