Skip to content

Commit d49ce22

Browse files
committed
feat: Do not depends on package.json and use new repositoryUrl
BREAKING CHANGE: Require semantic-release version that pass the `repositoryUrl` option BREAKING CHANGE: Return async function instead of function calling a callback
1 parent 336ba0a commit d49ce22

File tree

7 files changed

+79
-125
lines changed

7 files changed

+79
-125
lines changed

index.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
1-
const {callbackify} = require('util');
21
const verifyGithub = require('./lib/verify');
3-
const publishGit = require('./lib/publish');
2+
const publishGithub = require('./lib/publish');
43

54
let verified;
65

7-
async function verifyConditions(pluginConfig, {pkg, options: {publish}}) {
6+
async function verifyConditions(pluginConfig, {options}) {
87
// If the Github publish plugin is used and has `assets` configured, validate it now in order to prevent any release if the configuration is wrong
9-
if (publish) {
10-
const publishPlugin = (Array.isArray(publish) ? publish : [publish]).find(
8+
if (options.publish) {
9+
const publishPlugin = (Array.isArray(options.publish) ? options.publish : [options.publish]).find(
1110
config => config.path && config.path === '@semantic-release/github'
1211
);
1312
if (publishPlugin && publishPlugin.assets) {
1413
pluginConfig.assets = publishPlugin.assets;
1514
}
1615
}
1716

18-
await verifyGithub(pluginConfig, pkg);
17+
await verifyGithub(pluginConfig, options);
1918
verified = true;
2019
}
2120

22-
async function publish(pluginConfig, {pkg, nextRelease, options, logger}) {
21+
async function publish(pluginConfig, {nextRelease, options, logger}) {
2322
if (!verified) {
24-
await verifyGithub(pluginConfig, pkg);
23+
await verifyGithub(pluginConfig, options);
2524
verified = true;
2625
}
27-
await publishGit(pluginConfig, options, pkg, nextRelease, logger);
26+
await publishGithub(pluginConfig, options, nextRelease, logger);
2827
}
2928

30-
module.exports = {verifyConditions: callbackify(verifyConditions), publish: callbackify(publish)};
29+
module.exports = {verifyConditions, publish};

lib/publish.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
const {basename} = require('path');
22
const {parse} = require('url');
33
const {stat} = require('fs-extra');
4-
const gitUrlParse = require('git-url-parse');
4+
const parseGithubUrl = require('parse-github-url');
55
const GitHubApi = require('github');
66
const pEachSeries = require('p-each-series');
77
const debug = require('debug')('semantic-release:publish-github');
88
const resolveConfig = require('./resolve-config');
99

10-
module.exports = async (pluginConfig, {branch}, {repository}, {version, gitHead, gitTag, notes}, logger) => {
10+
module.exports = async (pluginConfig, {branch, repositoryUrl}, {version, gitHead, gitTag, notes}, logger) => {
1111
const {githubToken, githubUrl, githubApiPathPrefix, assets} = resolveConfig(pluginConfig);
12-
const {name: repo, owner} = gitUrlParse(repository.url);
12+
const {name: repo, owner} = parseGithubUrl(repositoryUrl);
1313
let {port, protocol, hostname: host} = githubUrl ? parse(githubUrl) : {};
1414
protocol = (protocol || '').split(':')[0] || null;
1515

lib/verify.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
const {parse} = require('url');
2-
const gitUrlParse = require('git-url-parse');
2+
const parseGithubUrl = require('parse-github-url');
33
const GitHubApi = require('github');
44
const SemanticReleaseError = require('@semantic-release/error');
55
const resolveConfig = require('./resolve-config');
66

7-
module.exports = async (pluginConfig, {name, repository}) => {
7+
module.exports = async (pluginConfig, {repositoryUrl}) => {
88
const {githubToken, githubUrl, githubApiPathPrefix, assets} = resolveConfig(pluginConfig);
99

10-
if (!name) {
11-
throw new SemanticReleaseError('No "name" found in package.json.', 'ENOPKGNAME');
12-
}
13-
14-
if (!repository || !repository.url) {
15-
throw new SemanticReleaseError('No "repository" found in package.json.', 'ENOPKGREPO');
16-
}
17-
1810
if (!githubToken) {
1911
throw new SemanticReleaseError('No github token specified.', 'ENOGHTOKEN');
2012
}
@@ -29,7 +21,14 @@ module.exports = async (pluginConfig, {name, repository}) => {
2921
}
3022
}
3123

32-
const {name: repo, owner} = gitUrlParse(repository.url);
24+
const {name: repo, owner} = parseGithubUrl(repositoryUrl);
25+
if (!owner || !repo) {
26+
throw new SemanticReleaseError(
27+
`The git repository URL ${repositoryUrl} is not a valid Github URL.`,
28+
'EINVALIDGITURL'
29+
);
30+
}
31+
3332
let {port, protocol, hostname: host} = githubUrl ? parse(githubUrl) : {};
3433
protocol = (protocol || '').split(':')[0] || null;
3534

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
"@semantic-release/error": "^2.1.0",
2020
"debug": "^3.1.0",
2121
"fs-extra": "^4.0.2",
22-
"git-url-parse": "^7.0.1",
2322
"github": "^12.0.5",
24-
"p-each-series": "^1.0.0"
23+
"p-each-series": "^1.0.0",
24+
"parse-github-url": "^1.0.1"
2525
},
2626
"devDependencies": {
2727
"ava": "^0.23.0",
@@ -34,7 +34,7 @@
3434
"nock": "^9.1.0",
3535
"nyc": "^11.2.1",
3636
"prettier": "~1.8.2",
37-
"semantic-release": "^9.1.1",
37+
"semantic-release": "^10.0.0",
3838
"sinon": "^4.0.0",
3939
"xo": "^0.18.2"
4040
},

test/integration.test.js

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {promisify} from 'util';
21
import {escape} from 'querystring';
32
import test from 'ava';
43
import {stub, match} from 'sinon';
@@ -36,14 +35,13 @@ test.serial('Verify Github auth', async t => {
3635
process.env.GITHUB_TOKEN = 'github_token';
3736
const owner = 'test_user';
3837
const repo = 'test_repo';
39-
const options = {};
40-
const pkg = {name: 'package-name', repository: {url: `git+https://othertesturl.com/${owner}/${repo}.git`}};
38+
const options = {repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`};
4139

4240
const github = authenticate({githubToken: process.env.GITHUB_TOKEN})
4341
.get(`/repos/${owner}/${repo}`)
4442
.reply(200, {permissions: {push: true}});
4543

46-
await t.notThrows(promisify(t.context.m.verifyConditions)({}, {pkg, options}));
44+
await t.notThrows(t.context.m.verifyConditions({}, {options}));
4745

4846
t.true(github.isDone());
4947
});
@@ -52,14 +50,16 @@ test.serial('Verify Github auth with publish options', async t => {
5250
process.env.GITHUB_TOKEN = 'github_token';
5351
const owner = 'test_user';
5452
const repo = 'test_repo';
55-
const options = {publish: {path: '@semantic-release/github'}};
56-
const pkg = {name: 'package-name', repository: {url: `git+https://othertesturl.com/${owner}/${repo}.git`}};
53+
const options = {
54+
publish: {path: '@semantic-release/github'},
55+
repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`,
56+
};
5757

5858
const github = authenticate({githubToken: process.env.GITHUB_TOKEN})
5959
.get(`/repos/${owner}/${repo}`)
6060
.reply(200, {permissions: {push: true}});
6161

62-
await t.notThrows(promisify(t.context.m.verifyConditions)({}, {pkg, options}));
62+
await t.notThrows(t.context.m.verifyConditions({}, {options}));
6363

6464
t.true(github.isDone());
6565
});
@@ -69,14 +69,16 @@ test.serial('Verify Github auth and assets config', async t => {
6969
const owner = 'test_user';
7070
const repo = 'test_repo';
7171
const assets = [{path: 'lib/file.js'}, 'file.js'];
72-
const options = {publish: [{path: '@semantic-release/npm'}, {path: '@semantic-release/github', assets}]};
73-
const pkg = {name: 'package-name', repository: {url: `git+https://othertesturl.com/${owner}/${repo}.git`}};
72+
const options = {
73+
publish: [{path: '@semantic-release/npm'}, {path: '@semantic-release/github', assets}],
74+
repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`,
75+
};
7476

7577
const github = authenticate({githubToken: process.env.GH_TOKEN})
7678
.get(`/repos/${owner}/${repo}`)
7779
.reply(200, {permissions: {push: true}});
7880

79-
await t.notThrows(promisify(t.context.m.verifyConditions)({}, {pkg, options}));
81+
await t.notThrows(t.context.m.verifyConditions({}, {options}));
8082

8183
t.true(github.isDone());
8284
});
@@ -86,10 +88,12 @@ test.serial('Throw SemanticReleaseError if invalid config', async t => {
8688
const owner = 'test_user';
8789
const repo = 'test_repo';
8890
const assets = [{wrongProperty: 'lib/file.js'}];
89-
const options = {publish: [{path: '@semantic-release/npm'}, {path: '@semantic-release/github', assets}]};
90-
const pkg = {name: 'package-name', repository: {url: `git+https://othertesturl.com/${owner}/${repo}.git`}};
91+
const options = {
92+
publish: [{path: '@semantic-release/npm'}, {path: '@semantic-release/github', assets}],
93+
repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`,
94+
};
9195

92-
const error = await t.throws(promisify(t.context.m.verifyConditions)({}, {pkg, options}));
96+
const error = await t.throws(t.context.m.verifyConditions({}, {options}));
9397

9498
t.true(error instanceof SemanticReleaseError);
9599
t.is(error.code, 'EINVALIDASSETS');
@@ -104,8 +108,7 @@ test.serial('Publish a release with an array of assets', async t => {
104108
{path: 'test/fixtures/upload_other.txt', name: 'other_file.txt', label: 'Other File'},
105109
];
106110
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
107-
const options = {branch: 'master'};
108-
const pkg = {name: 'package-name', repository: {url: `https://github.com/${owner}/${repo}.git`}};
111+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
109112
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
110113
const assetUrl = `https://github.com/${owner}/${repo}/releases/download/${nextRelease.version}/upload.txt`;
111114
const otherAssetUrl = `https://github.com/${owner}/${repo}/releases/download/${nextRelease.version}/other_file.txt`;
@@ -134,7 +137,7 @@ test.serial('Publish a release with an array of assets', async t => {
134137
)
135138
.reply(200, {browser_download_url: otherAssetUrl});
136139

137-
await promisify(t.context.m.publish)({githubToken, assets}, {pkg, nextRelease, options, logger: t.context.logger});
140+
await t.context.m.publish({githubToken, assets}, {nextRelease, options, logger: t.context.logger});
138141

139142
t.true(t.context.log.calledWith(match.string, releaseUrl));
140143
t.true(t.context.log.calledWith(match.string, assetUrl));
@@ -151,10 +154,10 @@ test.serial('Verify Github auth and release', async t => {
151154
'test/fixtures/upload.txt',
152155
{path: 'test/fixtures/upload_other.txt', name: 'other_file.txt', label: 'Other File'},
153156
];
154-
const pkg = {name: 'package-name', repository: {url: `https://github.com/${owner}/${repo}.git`}};
155157
const options = {
156158
publish: [{path: '@semantic-release/npm'}, {path: '@semantic-release/github', assets}],
157159
branch: 'master',
160+
repositoryUrl: `https://github.com/${owner}/${repo}.git`,
158161
};
159162
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
160163
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
@@ -185,8 +188,8 @@ test.serial('Verify Github auth and release', async t => {
185188
)
186189
.reply(200, {browser_download_url: otherAssetUrl});
187190

188-
await t.notThrows(promisify(t.context.m.verifyConditions)({}, {pkg, options}));
189-
await promisify(t.context.m.publish)({assets}, {pkg, nextRelease, options, logger: t.context.logger});
191+
await t.notThrows(t.context.m.verifyConditions({}, {options}));
192+
await t.context.m.publish({assets}, {nextRelease, options, logger: t.context.logger});
190193

191194
t.true(t.context.log.calledWith(match.string, releaseUrl));
192195
t.true(t.context.log.calledWith(match.string, assetUrl));

test/publish.test.js

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ test.serial('Publish a release', async t => {
3636
const githubToken = 'github_token';
3737
const pluginConfig = {githubToken};
3838
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
39-
const options = {branch: 'master'};
40-
const pkg = {repository: {url: `https://github.com/${owner}/${repo}.git`}};
39+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
4140
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
4241

4342
const github = authenticate({githubToken})
@@ -51,7 +50,7 @@ test.serial('Publish a release', async t => {
5150
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
5251
.reply({});
5352

54-
await publish(pluginConfig, options, pkg, nextRelease, t.context.logger);
53+
await publish(pluginConfig, options, nextRelease, t.context.logger);
5554

5655
t.true(t.context.log.calledWith(match.string, releaseUrl));
5756
t.true(github.isDone());
@@ -65,8 +64,7 @@ test.serial('Publish a release with one asset', async t => {
6564
process.env.GH_PREFIX = 'prefix';
6665
const pluginConfig = {assets: 'test/fixtures/upload.txt'};
6766
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
68-
const options = {branch: 'master'};
69-
const pkg = {repository: {url: `https://github.com/${owner}/${repo}.git`}};
67+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
7068
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
7169
const assetUrl = `https://github.com/${owner}/${repo}/releases/download/${nextRelease.version}/upload.txt`;
7270
const releaseId = 1;
@@ -90,7 +88,7 @@ test.serial('Publish a release with one asset', async t => {
9088
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
9189
.reply(200, {browser_download_url: assetUrl});
9290

93-
await publish(pluginConfig, options, pkg, nextRelease, t.context.logger);
91+
await publish(pluginConfig, options, nextRelease, t.context.logger);
9492

9593
t.true(t.context.log.calledWith(match.string, releaseUrl));
9694
t.true(t.context.log.calledWith(match.string, assetUrl));
@@ -107,8 +105,7 @@ test.serial('Publish a release with one asset and custom github url', async t =>
107105
const assets = 'test/fixtures/upload.txt';
108106
const pluginConfig = {githubUrl: process.env.GITHUB_URL, githubApiPathPrefix: process.env.GITHUB_PREFIX, assets};
109107
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
110-
const options = {branch: 'master'};
111-
const pkg = {repository: {url: `https://github.com/${owner}/${repo}.git`}};
108+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
112109
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
113110
const assetUrl = `https://github.com/${owner}/${repo}/releases/download/${nextRelease.version}/upload.txt`;
114111
const releaseId = 1;
@@ -132,7 +129,7 @@ test.serial('Publish a release with one asset and custom github url', async t =>
132129
.post(`/repos/${owner}/${repo}/releases/${releaseId}/assets?name=${escape('upload.txt')}`)
133130
.reply(200, {browser_download_url: assetUrl});
134131

135-
await publish(pluginConfig, options, pkg, nextRelease, t.context.logger);
132+
await publish(pluginConfig, options, nextRelease, t.context.logger);
136133

137134
t.true(t.context.log.calledWith(match.string, releaseUrl));
138135
t.true(t.context.log.calledWith(match.string, assetUrl));
@@ -152,8 +149,7 @@ test.serial('Publish a release with an array of assets', async t => {
152149
],
153150
};
154151
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
155-
const options = {branch: 'master'};
156-
const pkg = {repository: {url: `https://github.com/${owner}/${repo}.git`}};
152+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
157153
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
158154
const assetUrl = `https://github.com/${owner}/${repo}/releases/download/${nextRelease.version}/upload.txt`;
159155
const otherAssetUrl = `https://github.com/${owner}/${repo}/releases/download/${nextRelease.version}/other_file.txt`;
@@ -180,7 +176,7 @@ test.serial('Publish a release with an array of assets', async t => {
180176
)
181177
.reply(200, {browser_download_url: otherAssetUrl});
182178

183-
await publish(pluginConfig, options, pkg, nextRelease, t.context.logger);
179+
await publish(pluginConfig, options, nextRelease, t.context.logger);
184180

185181
t.true(t.context.log.calledWith(match.string, releaseUrl));
186182
t.true(t.context.log.calledWith(match.string, assetUrl));
@@ -198,8 +194,7 @@ test.serial('Publish a release with an array of misconfigured assets', async t =
198194
assets: ['test/fixtures', {path: 'test/fixtures/missing.txt', name: 'missing.txt', label: 'Missing File'}],
199195
};
200196
const nextRelease = {version: '1.0.0', gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
201-
const options = {branch: 'master'};
202-
const pkg = {repository: {url: `https://github.com/${owner}/${repo}.git`}};
197+
const options = {branch: 'master', repositoryUrl: `https://github.com/${owner}/${repo}.git`};
203198
const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`;
204199
const releaseId = 1;
205200

@@ -214,7 +209,7 @@ test.serial('Publish a release with an array of misconfigured assets', async t =
214209
.post(`/repos/${owner}/${repo}/git/refs`, {ref: `refs/tags/${nextRelease.gitTag}`, sha: nextRelease.gitHead})
215210
.reply({});
216211

217-
await publish(pluginConfig, options, pkg, nextRelease, t.context.logger);
212+
await publish(pluginConfig, options, nextRelease, t.context.logger);
218213

219214
t.true(t.context.log.calledWith(match.string, releaseUrl));
220215
t.true(t.context.error.calledWith(match.string, 'test/fixtures/missing.txt'));

0 commit comments

Comments
 (0)