Skip to content

Commit dea56d8

Browse files
author
Nils Plaschke
committed
feat: add additional release links to the release
A new option `addReleases` has been added. Setting this option will add links to other releases to the Github release body. The option can be one of `false|"top"|"bottom"`. The default is `false` to be backward compatible. Closes #281
1 parent 32654fb commit dea56d8

File tree

10 files changed

+573
-4
lines changed

10 files changed

+573
-4
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,13 @@ Each label name is generated with [Lodash template](https://lodash.com/docs#temp
204204
The `releasedLabels` ```['released<%= nextRelease.channel ? ` on @\${nextRelease.channel}` : "" %> from <%= branch.name %>']``` will generate the label:
205205

206206
> released on @next from branch next
207+
208+
#### addReleases
209+
210+
Add links to other releases to the GitHub release body.
211+
212+
Valid values for this option are `false`, `"top"` or `"bottom"`.
213+
214+
##### addReleases example
215+
216+
See [The introducing PR](https://github.com/semantic-release/github/pull/282) for an example on how it will look.

lib/definitions/errors.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ Your configuration for the \`assignees\` option is \`${stringify(assignees)}\`.`
5757
)}) if defined, must be an \`Array\` of non empty \`String\`.
5858
5959
Your configuration for the \`releasedLabels\` option is \`${stringify(releasedLabels)}\`.`,
60+
}),
61+
EINVALIDADDRELEASES: ({addReleases}) => ({
62+
message: 'Invalid `addReleases` option.',
63+
details: `The [addReleases option](${linkify('README.md#options')}) if defined, must be one of \`false|top|bottom\`.
64+
65+
Your configuration for the \`addReleases\` option is \`${stringify(addReleases)}\`.`,
6066
}),
6167
EINVALIDGITHUBURL: () => ({
6268
message: 'The git repository URL is not a valid GitHub URL.',

lib/get-release-links.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const {RELEASE_NAME} = require('./definitions/constants');
2+
3+
const linkify = (releaseInfo) =>
4+
`${
5+
releaseInfo.url
6+
? releaseInfo.url.startsWith('http')
7+
? `[${releaseInfo.name}](${releaseInfo.url})`
8+
: `${releaseInfo.name}: \`${releaseInfo.url}\``
9+
: `\`${releaseInfo.name}\``
10+
}`;
11+
12+
const filterReleases = (releaseInfos) =>
13+
releaseInfos.filter((releaseInfo) => releaseInfo.name && releaseInfo.name !== RELEASE_NAME);
14+
15+
module.exports = (releaseInfos) =>
16+
`${
17+
filterReleases(releaseInfos).length > 0
18+
? `This release is also available on:\n${filterReleases(releaseInfos)
19+
.map((releaseInfo) => `- ${linkify(releaseInfo)}`)
20+
.join('\n')}`
21+
: ''
22+
}`;

lib/publish.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ module.exports = async (pluginConfig, context) => {
2828
// When there are no assets, we publish a release directly
2929
if (!assets || assets.length === 0) {
3030
const {
31-
data: {html_url: url},
31+
data: {html_url: url, id: releaseId},
3232
} = await github.repos.createRelease(release);
3333

3434
logger.log('Published GitHub release: %s', url);
35-
return {url, name: RELEASE_NAME};
35+
return {url, name: RELEASE_NAME, id: releaseId};
3636
}
3737

3838
// We'll create a draft release, append the assets to it, and then publish it.
@@ -94,5 +94,5 @@ module.exports = async (pluginConfig, context) => {
9494
} = await github.repos.updateRelease({owner, repo, release_id: releaseId, draft: false});
9595

9696
logger.log('Published GitHub release: %s', url);
97-
return {url, name: RELEASE_NAME};
97+
return {url, name: RELEASE_NAME, id: releaseId};
9898
};

lib/resolve-config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = (
1212
labels,
1313
assignees,
1414
releasedLabels,
15+
addReleases,
1516
},
1617
{env}
1718
) => ({
@@ -30,4 +31,5 @@ module.exports = (
3031
: releasedLabels === false
3132
? false
3233
: castArray(releasedLabels),
34+
addReleases: isNil(addReleases) ? false : addReleases,
3335
});

lib/success.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const {isNil, uniqBy, template, flatten} = require('lodash');
1+
const {isNil, uniqBy, template, flatten, isEmpty} = require('lodash');
22
const pFilter = require('p-filter');
33
const AggregateError = require('aggregate-error');
44
const issueParser = require('issue-parser');
@@ -9,6 +9,8 @@ const getClient = require('./get-client');
99
const getSearchQueries = require('./get-search-queries');
1010
const getSuccessComment = require('./get-success-comment');
1111
const findSRIssues = require('./find-sr-issues');
12+
const {RELEASE_NAME} = require('./definitions/constants');
13+
const getReleaseLinks = require('./get-release-links');
1214

1315
module.exports = async (pluginConfig, context) => {
1416
const {
@@ -17,6 +19,7 @@ module.exports = async (pluginConfig, context) => {
1719
nextRelease,
1820
releases,
1921
logger,
22+
notes,
2023
} = context;
2124
const {
2225
githubToken,
@@ -27,6 +30,7 @@ module.exports = async (pluginConfig, context) => {
2730
failComment,
2831
failTitle,
2932
releasedLabels,
33+
addReleases,
3034
} = resolveConfig(pluginConfig, context);
3135

3236
const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy});
@@ -140,6 +144,21 @@ module.exports = async (pluginConfig, context) => {
140144
);
141145
}
142146

147+
if (addReleases !== false && errors.length === 0) {
148+
const ghRelease = releases.find((release) => release.name && release.name === RELEASE_NAME);
149+
if (!isNil(ghRelease)) {
150+
const ghRelaseId = ghRelease.id;
151+
const additionalReleases = getReleaseLinks(releases);
152+
if (!isEmpty(additionalReleases) && !isNil(ghRelaseId)) {
153+
const newBody =
154+
addReleases === 'top'
155+
? additionalReleases.concat('\n---\n', notes)
156+
: notes.concat('\n---\n', additionalReleases);
157+
await github.repos.updateRelease({owner, repo, release_id: ghRelaseId, body: newBody});
158+
}
159+
}
160+
}
161+
143162
if (errors.length > 0) {
144163
throw new AggregateError(errors);
145164
}

lib/verify.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const getClient = require('./get-client');
77
const getError = require('./get-error');
88

99
const isNonEmptyString = (value) => isString(value) && value.trim();
10+
const oneOf = (enumArray) => (value) => enumArray.some((element) => element === value);
1011
const isStringOrStringArray = (value) =>
1112
isNonEmptyString(value) || (isArray(value) && value.every((string) => isNonEmptyString(string)));
1213
const isArrayOf = (validator) => (array) => isArray(array) && array.every((value) => validator(value));
@@ -24,6 +25,7 @@ const VALIDATORS = {
2425
labels: canBeDisabled(isArrayOf(isNonEmptyString)),
2526
assignees: isArrayOf(isNonEmptyString),
2627
releasedLabels: canBeDisabled(isArrayOf(isNonEmptyString)),
28+
addReleases: canBeDisabled(oneOf(['bottom', 'top'])),
2729
};
2830

2931
module.exports = async (pluginConfig, context) => {

test/get-release-links.test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const test = require('ava');
2+
const getReleaseLinks = require('../lib/get-release-links');
3+
const {RELEASE_NAME} = require('../lib/definitions/constants');
4+
5+
test('Comment for release with multiple releases', (t) => {
6+
const releaseInfos = [
7+
{name: RELEASE_NAME, url: 'https://github.com/release'},
8+
{name: 'Http release', url: 'https://release.com/release'},
9+
{name: 'npm release', url: 'https://npm.com/release'},
10+
];
11+
const comment = getReleaseLinks(releaseInfos);
12+
13+
t.is(
14+
comment,
15+
`This release is also available on:
16+
- [Http release](https://release.com/release)
17+
- [npm release](https://npm.com/release)`
18+
);
19+
});
20+
21+
test('Release with missing release URL', (t) => {
22+
const releaseInfos = [
23+
{name: RELEASE_NAME, url: 'https://github.com/release'},
24+
{name: 'Http release', url: 'https://release.com/release'},
25+
{name: 'npm release'},
26+
];
27+
const comment = getReleaseLinks(releaseInfos);
28+
29+
t.is(
30+
comment,
31+
`This release is also available on:
32+
- [Http release](https://release.com/release)
33+
- \`npm release\``
34+
);
35+
});
36+
37+
test('Release with one release', (t) => {
38+
const releaseInfos = [
39+
{name: RELEASE_NAME, url: 'https://github.com/release'},
40+
{name: 'Http release', url: 'https://release.com/release'},
41+
];
42+
const comment = getReleaseLinks(releaseInfos);
43+
44+
t.is(
45+
comment,
46+
`This release is also available on:
47+
- [Http release](https://release.com/release)`
48+
);
49+
});
50+
51+
test('Release with non http releases', (t) => {
52+
const releaseInfos = [{name: 'S3', url: 's3://my-bucket/release-asset'}];
53+
const comment = getReleaseLinks(releaseInfos);
54+
55+
t.is(
56+
comment,
57+
`This release is also available on:
58+
- S3: \`s3://my-bucket/release-asset\``
59+
);
60+
});
61+
62+
test('Release with only github release', (t) => {
63+
const releaseInfos = [{name: RELEASE_NAME, url: 'https://github.com/release'}];
64+
const comment = getReleaseLinks(releaseInfos);
65+
66+
t.is(comment, '');
67+
});
68+
69+
test('Comment with no release object', (t) => {
70+
const releaseInfos = [];
71+
const comment = getReleaseLinks(releaseInfos);
72+
73+
t.is(comment, '');
74+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy