Skip to content

Commit 1fab20e

Browse files
committed
feat: use cwd and env options passed by core
BREAKING CHANGE: require `semantic-release` >= `15.8.0`
1 parent 54bd404 commit 1fab20e

File tree

7 files changed

+403
-435
lines changed

7 files changed

+403
-435
lines changed

lib/git.js

+22-11
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ const debug = require('debug')('semantic-release:git');
44
/**
55
* Retrieve the list of files modified on the local repository.
66
*
7+
* @param {Object} [execaOpts] Options to pass to `execa`.
8+
*
79
* @return {Array<String>} Array of modified files path.
810
*/
9-
async function getModifiedFiles() {
10-
return (await execa.stdout('git', ['ls-files', '-m', '-o']))
11+
async function getModifiedFiles(execaOpts) {
12+
return (await execa.stdout('git', ['ls-files', '-m', '-o'], execaOpts))
1113
.split('\n')
1214
.map(tag => tag.trim())
1315
.filter(tag => Boolean(tag));
@@ -16,39 +18,48 @@ async function getModifiedFiles() {
1618
/**
1719
* Add a list of file to the Git index. `.gitignore` will be ignored.
1820
*
19-
* @param {Array<String>} files Array of files path to add to the index,
21+
* @param {Array<String>} files Array of files path to add to the index.
22+
* @param {Object} [execaOpts] Options to pass to `execa`.
2023
*/
21-
async function add(files) {
22-
const shell = await execa('git', ['add', '--force', '--ignore-errors'].concat(files), {reject: false});
24+
async function add(files, execaOpts) {
25+
const shell = await execa('git', ['add', '--force', '--ignore-errors'].concat(files), {...execaOpts, reject: false});
2326
debug('add file to git index', shell);
2427
}
2528

2629
/**
2730
* Commit to the local repository.
2831
*
2932
* @param {String} message Commit message.
33+
* @param {Object} [execaOpts] Options to pass to `execa`.
34+
*
3035
* @throws {Error} if the commit failed.
3136
*/
32-
async function commit(message) {
33-
await execa('git', ['commit', '-m', message]);
37+
async function commit(message, execaOpts) {
38+
await execa('git', ['commit', '-m', message], execaOpts);
3439
}
3540

3641
/**
3742
* Push to the remote repository.
3843
*
3944
* @param {String} origin The remote repository URL.
4045
* @param {String} branch The branch to push.
46+
* @param {Object} [execaOpts] Options to pass to `execa`.
47+
*
4148
* @throws {Error} if the push failed.
4249
*/
43-
async function push(origin, branch) {
44-
await execa('git', ['push', '--tags', origin, `HEAD:${branch}`]);
50+
async function push(origin, branch, execaOpts) {
51+
await execa('git', ['push', '--tags', origin, `HEAD:${branch}`], execaOpts);
4552
}
4653

4754
/**
55+
* Get the HEAD sha.
56+
*
57+
* @param {Object} [execaOpts] Options to pass to `execa`.
58+
*
4859
* @return {String} The sha of the head commit on the local repository
4960
*/
50-
async function gitHead() {
51-
return execa.stdout('git', ['rev-parse', 'HEAD']);
61+
async function gitHead(execaOpts) {
62+
return execa.stdout('git', ['rev-parse', 'HEAD'], execaOpts);
5263
}
5364

5465
module.exports = {getModifiedFiles, add, gitHead, commit, push};

lib/prepare.js

+38-21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const path = require('path');
12
const {pathExists} = require('fs-extra');
23
const {isUndefined, isPlainObject, isArray, template, castArray, uniq} = require('lodash');
34
const micromatch = require('micromatch');
@@ -8,9 +9,15 @@ const resolveConfig = require('./resolve-config');
89
const {getModifiedFiles, add, commit, push} = require('./git');
910

1011
const CHANGELOG = 'CHANGELOG.md';
11-
const PKG_JSON = 'package.json';
12-
const PKG_LOCK = 'package-lock.json';
13-
const SKW_JSON = 'npm-shrinkwrap.json';
12+
const PACKAGE_JSON = 'package.json';
13+
const PACKAGE_LOCK_JSON = 'package-lock.json';
14+
const SHRINKWRAP_JSON = 'npm-shrinkwrap.json';
15+
16+
// TODO Temporary workaround for https://github.com/kevva/dir-glob/issues/7
17+
const resolvePaths = (files, cwd) =>
18+
files.map(
19+
file => `${file.startsWith('!') ? '!' : ''}${path.resolve(cwd, file.startsWith('!') ? file.slice(1) : file)}`
20+
);
1421

1522
/**
1623
* Prepare a release commit including configurable files.
@@ -24,26 +31,33 @@ const SKW_JSON = 'npm-shrinkwrap.json';
2431
* @param {Object} context.nextRelease The next release.
2532
* @param {Object} logger Global logger.
2633
*/
27-
module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, lastRelease, nextRelease, logger}) => {
34+
module.exports = async (
35+
pluginConfig,
36+
{env, cwd, options: {branch, repositoryUrl}, lastRelease, nextRelease, logger}
37+
) => {
2838
const {message, assets} = resolveConfig(pluginConfig, logger);
2939
const patterns = [];
30-
const modifiedFiles = await getModifiedFiles();
40+
const modifiedFiles = await getModifiedFiles({env, cwd});
41+
const changelogPath = path.resolve(cwd, CHANGELOG);
42+
const pkgPath = path.resolve(cwd, PACKAGE_JSON);
43+
const pkgLockPath = path.resolve(cwd, PACKAGE_LOCK_JSON);
44+
const shrinkwrapPath = path.resolve(cwd, SHRINKWRAP_JSON);
3145

32-
if (isUndefined(assets) && (await pathExists(CHANGELOG))) {
33-
logger.log('Add %s to the release commit', CHANGELOG);
34-
patterns.push(CHANGELOG);
46+
if (isUndefined(assets) && (await pathExists(changelogPath))) {
47+
logger.log('Add %s to the release commit', changelogPath);
48+
patterns.push(changelogPath);
3549
}
36-
if (isUndefined(assets) && (await pathExists(PKG_JSON))) {
37-
logger.log('Add %s to the release commit', PKG_JSON);
38-
patterns.push(PKG_JSON);
50+
if (isUndefined(assets) && (await pathExists(pkgPath))) {
51+
logger.log('Add %s to the release commit', pkgPath);
52+
patterns.push(pkgPath);
3953
}
40-
if (isUndefined(assets) && (await pathExists(PKG_LOCK))) {
41-
logger.log('Add %s to the release commit', PKG_LOCK);
42-
patterns.push(PKG_LOCK);
54+
if (isUndefined(assets) && (await pathExists(pkgLockPath))) {
55+
logger.log('Add %s to the release commit', pkgLockPath);
56+
patterns.push(pkgLockPath);
4357
}
44-
if (isUndefined(assets) && (await pathExists(SKW_JSON))) {
45-
logger.log('Add %s to the release commit', SKW_JSON);
46-
patterns.push(SKW_JSON);
58+
if (isUndefined(assets) && (await pathExists(shrinkwrapPath))) {
59+
logger.log('Add %s to the release commit', shrinkwrapPath);
60+
patterns.push(shrinkwrapPath);
4761
}
4862

4963
patterns.push(
@@ -64,7 +78,9 @@ module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, lastRel
6478
glob[0]
6579
);
6680
}
67-
result.push(...micromatch(modifiedFiles, await dirGlob(glob), {dot: true, nonegate}));
81+
result.push(
82+
...micromatch(resolvePaths(modifiedFiles, cwd), await dirGlob(resolvePaths(glob, cwd)), {dot: true, nonegate})
83+
);
6884
return result;
6985
},
7086
[]
@@ -73,16 +89,17 @@ module.exports = async (pluginConfig, {options: {branch, repositoryUrl}, lastRel
7389

7490
if (filesToCommit.length > 0) {
7591
logger.log('Found %d file(s) to commit', filesToCommit.length);
76-
await add(filesToCommit);
92+
await add(filesToCommit, {env, cwd});
7793
debug('commited files: %o', filesToCommit);
7894
await commit(
7995
message
8096
? template(message)({branch, lastRelease, nextRelease})
81-
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`
97+
: `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}`,
98+
{env, cwd}
8299
);
83100
}
84101

85102
logger.log('Creating tag %s', nextRelease.gitTag);
86-
await push(repositoryUrl, branch);
103+
await push(repositoryUrl, branch, {env, cwd});
87104
logger.log('Prepared Git release: %s', nextRelease.gitTag);
88105
};

test/git.test.js

+43-47
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,88 @@
1+
import path from 'path';
12
import test from 'ava';
23
import {outputFile, appendFile} from 'fs-extra';
34
import {add, getModifiedFiles, commit, gitHead, push} from '../lib/git';
45
import {gitRepo, gitCommits, gitGetCommits, gitStaged, gitRemoteHead} from './helpers/git-utils';
56

6-
// Save the current working diretory
7-
const cwd = process.cwd();
8-
9-
test.afterEach.always(() => {
10-
// Restore the current working directory
11-
process.chdir(cwd);
12-
});
13-
14-
test.serial('Add file to index', async t => {
7+
test('Add file to index', async t => {
158
// Create a git repository, set the current working directory at the root of the repo
16-
await gitRepo();
9+
const {cwd} = await gitRepo();
1710
// Create files
18-
await outputFile('file1.js', '');
11+
await outputFile(path.resolve(cwd, 'file1.js'), '');
1912
// Add files and commit
20-
await add(['.']);
13+
await add(['.'], {cwd});
2114

22-
await t.deepEqual(await gitStaged(), ['file1.js']);
15+
await t.deepEqual(await gitStaged({cwd}), ['file1.js']);
2316
});
2417

25-
test.serial('Get the modified files, including files in .gitignore but including untracked ones', async t => {
18+
test('Get the modified files, including files in .gitignore but including untracked ones', async t => {
2619
// Create a git repository, set the current working directory at the root of the repo
27-
await gitRepo();
20+
const {cwd} = await gitRepo();
2821
// Create files
29-
await outputFile('file1.js', '');
30-
await outputFile('dir/file2.js', '');
31-
await outputFile('file3.js', '');
22+
await outputFile(path.resolve(cwd, 'file1.js'), '');
23+
await outputFile(path.resolve(cwd, 'dir/file2.js'), '');
24+
await outputFile(path.resolve(cwd, 'file3.js'), '');
3225
// Create .gitignore to ignore file3.js
33-
await outputFile('.gitignore', 'file.3.js');
26+
await outputFile(path.resolve(cwd, '.gitignore'), 'file.3.js');
3427
// Add files and commit
35-
await add(['.']);
36-
await commit('Test commit');
28+
await add(['.'], {cwd});
29+
await commit('Test commit', {cwd});
3730
// Update file1.js, dir/file2.js and file3.js
38-
await appendFile('file1.js', 'Test content');
39-
await appendFile('dir/file2.js', 'Test content');
40-
await appendFile('file3.js', 'Test content');
31+
await appendFile(path.resolve(cwd, 'file1.js'), 'Test content');
32+
await appendFile(path.resolve(cwd, 'dir/file2.js'), 'Test content');
33+
await appendFile(path.resolve(cwd, 'file3.js'), 'Test content');
4134
// Add untracked file
42-
await outputFile('file4.js', 'Test content');
35+
await outputFile(path.resolve(cwd, 'file4.js'), 'Test content');
4336

44-
await t.deepEqual((await getModifiedFiles()).sort(), ['file4.js', 'file3.js', 'dir/file2.js', 'file1.js'].sort());
37+
await t.deepEqual(
38+
(await getModifiedFiles({cwd})).sort(),
39+
['file4.js', 'file3.js', 'dir/file2.js', 'file1.js'].sort()
40+
);
4541
});
4642

47-
test.serial('Returns [] if there is no modified files', async t => {
43+
test('Returns [] if there is no modified files', async t => {
4844
// Create a git repository, set the current working directory at the root of the repo
49-
await gitRepo();
45+
const {cwd} = await gitRepo();
5046

51-
await t.deepEqual(await getModifiedFiles(), []);
47+
await t.deepEqual(await getModifiedFiles({cwd}), []);
5248
});
5349

54-
test.serial('Commit added files', async t => {
50+
test('Commit added files', async t => {
5551
// Create a git repository, set the current working directory at the root of the repo
56-
await gitRepo();
52+
const {cwd} = await gitRepo();
5753
// Create files
58-
await outputFile('file1.js', '');
54+
await outputFile(path.resolve(cwd, 'file1.js'), '');
5955
// Add files and commit
60-
await add(['.']);
61-
await commit('Test commit');
56+
await add(['.'], {cwd});
57+
await commit('Test commit', {cwd});
6258

63-
await t.true((await gitGetCommits()).length === 1);
59+
await t.true((await gitGetCommits(undefined, {cwd})).length === 1);
6460
});
6561

66-
test.serial('Get the last commit sha', async t => {
62+
test('Get the last commit sha', async t => {
6763
// Create a git repository, set the current working directory at the root of the repo
68-
await gitRepo();
64+
const {cwd} = await gitRepo();
6965
// Add commits to the master branch
70-
const [{hash}] = await gitCommits(['First']);
66+
const [{hash}] = await gitCommits(['First'], {cwd});
7167

72-
const result = await gitHead();
68+
const result = await gitHead({cwd});
7369

7470
t.is(result, hash);
7571
});
7672

77-
test.serial('Throw error if the last commit sha cannot be found', async t => {
73+
test('Throw error if the last commit sha cannot be found', async t => {
7874
// Create a git repository, set the current working directory at the root of the repo
79-
await gitRepo();
75+
const {cwd} = await gitRepo();
8076

81-
await t.throws(gitHead());
77+
await t.throws(gitHead({cwd}));
8278
});
8379

84-
test.serial('Push commit to remote repository', async t => {
80+
test('Push commit to remote repository', async t => {
8581
// Create a git repository with a remote, set the current working directory at the root of the repo
86-
const repo = await gitRepo(true);
87-
const [{hash}] = await gitCommits(['Test commit']);
82+
const {cwd, repositoryUrl} = await gitRepo(true);
83+
const [{hash}] = await gitCommits(['Test commit'], {cwd});
8884

89-
await push(repo, 'master');
85+
await push(repositoryUrl, 'master', {cwd});
9086

91-
t.is(await gitRemoteHead(repo), hash);
87+
t.is(await gitRemoteHead(repositoryUrl), hash, {cwd});
9288
});

0 commit comments

Comments
 (0)