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 55d093f + 31e84e5 commit f7d87f8
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -2,7 +2,7 @@ version: ~> 1.0

import:
- semantic-release/semantic-release:.travis/node.yml
- semantic-release/semantic-release:.travis/node-versions.yml
- semantic-release/semantic-release:.travis/node-versions.yml@beta
- semantic-release/semantic-release:.travis/semantic-release.yml
- semantic-release/semantic-release:.travis/greenkeeper.yml
- semantic-release/semantic-release:.travis/codecov.yml
10 changes: 10 additions & 0 deletions README.md
Expand Up @@ -8,6 +8,7 @@

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

| Step | Description |
|--------------------|---------------------------------------------------------------------------------------------------------|
Expand Down Expand Up @@ -60,6 +61,7 @@ With this example:
| `verifyReleaseCmd` | The shell command to execute during the verify release step. See [verifyReleaseCmd](#verifyreleasecmd). |
| `generateNotesCmd` | The shell command to execute during the generate notes step. See [generateNotesCmd](#generatenotescmd). |
| `prepareCmd` | The shell command to execute during the prepare step. See [prepareCmd](#preparecmd). |
| `addChannelCmd` | The shell command to execute during the add channel step. See [addChannelCmd](#addchannelcmd). |
| `publishCmd` | The shell command to execute during the publish step. See [publishCmd](#publishcmd). |
| `successCmd` | The shell command to execute during the success step. See [successCmd](#successcmd). |
| `failCmd` | The shell command to execute during the fail step. See [failCmd](#failcmd). |
Expand Down Expand Up @@ -110,6 +112,14 @@ Execute a shell command to verify if the release should happen.
| `stdout` | Can be used for logging. |
| `stderr` | Can be used for logging. |

## addChannelCmd

| Command property | Description |
|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `exit code` | Any non `0` code is considered as an unexpected error and will stop the `semantic-release` execution with an error. |
| `stdout` | The `release` information can be written to `stdout` as parseable JSON (for example `{"name": "Release name", "url": "http://url/release/1.0.0"}`). If the command write non parseable JSON to `stdout` no `release` information will be returned. |
| `stderr` | Can be used for logging. |

## publishCmd

| Command property | Description |
Expand Down
33 changes: 32 additions & 1 deletion index.js
Expand Up @@ -79,6 +79,27 @@ async function publish(pluginConfig, context) {
return false;
}

async function addChannel(pluginConfig, context) {
if (!isNil(pluginConfig.addChannelCmd) || !isNil(pluginConfig.cmd)) {
verifyConfig('addChannelCmd', pluginConfig);

const stdout = await exec('addChannelCmd', pluginConfig, context);

try {
return stdout ? parseJson(stdout) : undefined;
} catch (error) {
debug(stdout);
debug(error);

debug(`The command ${pluginConfig.cmd} wrote invalid JSON to stdout. The stdout content will be ignored.`);

return undefined;
}
}

return false;
}

async function success(pluginConfig, context) {
if (!isNil(pluginConfig.successCmd) || !isNil(pluginConfig.cmd)) {
verifyConfig('successCmd', pluginConfig);
Expand All @@ -95,4 +116,14 @@ async function fail(pluginConfig, context) {
}
}

module.exports = {verifyConditions, analyzeCommits, verifyRelease, generateNotes, prepare, publish, success, fail};
module.exports = {
verifyConditions,
analyzeCommits,
verifyRelease,
generateNotes,
prepare,
publish,
addChannel,
success,
fail,
};
11 changes: 5 additions & 6 deletions package.json
Expand Up @@ -14,21 +14,21 @@
"@semantic-release/error": "^2.1.0",
"aggregate-error": "^3.0.0",
"debug": "^4.0.0",
"execa": "^3.2.0",
"execa": "^4.0.0",
"lodash": "^4.17.4",
"parse-json": "^5.0.0"
},
"devDependencies": {
"ava": "^2.0.0",
"codecov": "^3.0.0",
"nyc": "^15.0.0",
"semantic-release": "^15.0.0",
"semantic-release": "^16.0.0-beta",
"sinon": "^8.0.0",
"stream-buffers": "^3.0.2",
"xo": "^0.25.0"
},
"engines": {
"node": ">=8.16"
"node": ">=10.13"
},
"files": [
"lib",
Expand Down Expand Up @@ -59,15 +59,14 @@
"all": true
},
"peerDependencies": {
"semantic-release": ">=15.9.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
86 changes: 86 additions & 0 deletions test/add-channel.test.js
@@ -0,0 +1,86 @@
import test from 'ava';
import {stub} from 'sinon';
import {WritableStreamBuffer} from 'stream-buffers';
import {addChannel} from '..';

test.beforeEach(t => {
t.context.stdout = new WritableStreamBuffer();
t.context.stderr = new WritableStreamBuffer();
// Mock logger
t.context.log = stub();
t.context.error = stub();
t.context.logger = {log: t.context.log, error: t.context.error};
});

test('Parse JSON returned by addChannel script', async t => {
const pluginConfig = {
addChannelCmd:
'./test/fixtures/echo-args.sh {\\"name\\": \\"Release name\\", \\"url\\": \\"https://host.com/release/1.0.0\\"}',
};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.deepEqual(result, {name: 'Release name', url: 'https://host.com/release/1.0.0'});
});

test('Return "undefined" if the addChannel script wrtite invalid JSON to stdout (with "publishCmd")', async t => {
const pluginConfig = {addChannelCmd: './test/fixtures/echo-args.sh invalid_json'};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.is(result, undefined);
});

test('Return "undefined" if the addChannel script wrtite invalid JSON to stdout (with "cmd")', async t => {
const pluginConfig = {cmd: './test/fixtures/echo-args.sh invalid_json'};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.is(result, undefined);
});

test('Return "undefined" if the addChannel script wrtite nothing to stdout', async t => {
const pluginConfig = {addChannelCmd: './test/fixtures/echo-args.sh'};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.is(result, undefined);
});

test('Throw "Error" if the addChannel script does not returns 0', async t => {
const pluginConfig = {addChannelCmd: 'exit 1'};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger, options: {}};

await t.throwsAsync(addChannel(pluginConfig, context), Error);
});

test('Use "cmd" if defined and "addChannelCmd" is not', async t => {
const pluginConfig = {
cmd:
'./test/fixtures/echo-args.sh {\\"name\\": \\"Release name\\", \\"url\\": \\"https://host.com/release/1.0.0\\"}',
};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.deepEqual(result, {name: 'Release name', url: 'https://host.com/release/1.0.0'});
});

test('Use "addChannelCmd" even if "cmd" is defined', async t => {
const pluginConfig = {
addChannelCmd:
'./test/fixtures/echo-args.sh {\\"name\\": \\"Release name\\", \\"url\\": \\"https://host.com/release/1.0.0\\"}',
cmd: 'exit 1',
};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.deepEqual(result, {name: 'Release name', url: 'https://host.com/release/1.0.0'});
});

test('Return "false" if neither "addChannelCmd" nor "cmd" is defined', async t => {
const pluginConfig = {};
const context = {stdout: t.context.stdout, stderr: t.context.stderr, logger: t.context.logger};

const result = await addChannel(pluginConfig, context);
t.is(result, false);
});
1 change: 1 addition & 0 deletions test/integration.test.js
Expand Up @@ -8,6 +8,7 @@ test('Skip step if neither "cmd" nor step cmd is defined', async t => {
await t.notThrowsAsync(m.generateNotes({}, {}));
await t.notThrowsAsync(m.prepare({}, {}));
await t.notThrowsAsync(m.publish({}, {}));
await t.notThrowsAsync(m.addChannel({}, {}));
await t.notThrowsAsync(m.success({}, {}));
await t.notThrowsAsync(m.fail({}, {}));
});

0 comments on commit f7d87f8

Please sign in to comment.