@semantic-release/github 7.0.7 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,9 +3,7 @@
3
3
  [**semantic-release**](https://github.com/semantic-release/semantic-release) plugin to publish a
4
4
  [GitHub release](https://help.github.com/articles/about-releases) and comment on released Pull Requests/Issues.
5
5
 
6
- [![Travis](https://img.shields.io/travis/semantic-release/github.svg)](https://travis-ci.org/semantic-release/github)
7
- [![Codecov](https://img.shields.io/codecov/c/github/semantic-release/github.svg)](https://codecov.io/gh/semantic-release/github)
8
- [![Greenkeeper badge](https://badges.greenkeeper.io/semantic-release/github.svg)](https://greenkeeper.io/)
6
+ [![Build Status](https://github.com/semantic-release/github/workflows/Test/badge.svg)](https://github.com/semantic-release/github/actions?query=workflow%3ATest+branch%3Amaster)
9
7
 
10
8
  [![npm latest version](https://img.shields.io/npm/v/@semantic-release/github/latest.svg)](https://www.npmjs.com/package/@semantic-release/github)
11
9
  [![npm next version](https://img.shields.io/npm/v/@semantic-release/github/next.svg)](https://www.npmjs.com/package/@semantic-release/github)
@@ -83,7 +81,8 @@ If you have actions that trigger on newly created releases, please use a generat
83
81
  | `failTitle` | The title of the issue created when a release fails. Set to `false` to disable opening an issue when a release fails. | `The automated release is failing 🚨` |
84
82
  | `labels` | The [labels](https://help.github.com/articles/about-labels) to add to the issue created when a release fails. Set to `false` to not add any label. | `['semantic-release']` |
85
83
  | `assignees` | The [assignees](https://help.github.com/articles/assigning-issues-and-pull-requests-to-other-github-users) to add to the issue created when a release fails. | - |
86
- | `releasedLabels` | The [labels](https://help.github.com/articles/about-labels) to add to each issue and pull request resolved by the release. Set to `false` to not add any label. See [releasedLabels](#releasedlabels). | `['released<%= nextRelease.channel ? \` on @\${nextRelease.channel}\` : "" %>']` |
84
+ | `releasedLabels` | The [labels](https://help.github.com/articles/about-labels) to add to each issue and pull request resolved by the release. Set to `false` to not add any label. See [releasedLabels](#releasedlabels). | `['released<%= nextRelease.channel ? \` on @\${nextRelease.channel}\` : "" %>']- |
85
+ | `addReleases` | Will add release links to the GitHub Release. Can be `false`, `"bottom"` or `"top"`. See [addReleases](#addReleases). | `false` |
87
86
 
88
87
  #### proxy
89
88
 
@@ -204,3 +203,13 @@ Each label name is generated with [Lodash template](https://lodash.com/docs#temp
204
203
  The `releasedLabels` ```['released<%= nextRelease.channel ? ` on @\${nextRelease.channel}` : "" %> from <%= branch.name %>']``` will generate the label:
205
204
 
206
205
  > released on @next from branch next
206
+
207
+ #### addReleases
208
+
209
+ Add links to other releases to the GitHub release body.
210
+
211
+ Valid values for this option are `false`, `"top"` or `"bottom"`.
212
+
213
+ ##### addReleases example
214
+
215
+ See [The introducing PR](https://github.com/semantic-release/github/pull/282) for an example on how it will look.
@@ -57,6 +57,12 @@ Your configuration for the \`assignees\` option is \`${stringify(assignees)}\`.`
57
57
  )}) if defined, must be an \`Array\` of non empty \`String\`.
58
58
 
59
59
  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)}\`.`,
60
66
  }),
61
67
  EINVALIDGITHUBURL: () => ({
62
68
  message: 'The git repository URL is not a valid GitHub URL.',
@@ -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
+ }`;
@@ -1,5 +1,4 @@
1
1
  const path = require('path');
2
- const {basename} = require('path');
3
2
  const {isPlainObject, castArray, uniqWith, uniq} = require('lodash');
4
3
  const dirGlob = require('dir-glob');
5
4
  const globby = require('globby');
@@ -40,7 +39,7 @@ module.exports = async ({cwd}, assets) =>
40
39
  // - `path` of the matched file
41
40
  // - `name` based on the actual file name (to avoid assets with duplicate `name`)
42
41
  // - other properties of the original asset definition
43
- return globbed.map((file) => ({...asset, path: file, name: basename(file)}));
42
+ return globbed.map((file) => ({...asset, path: file, name: path.basename(file)}));
44
43
  }
45
44
 
46
45
  // If asset is an Object, output an Object definition with:
@@ -5,7 +5,7 @@ module.exports = (repositoryUrl) => {
5
5
  new URL(match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl).pathname
6
6
  );
7
7
  return {owner, repo};
8
- } catch (_) {
8
+ } catch {
9
9
  return {};
10
10
  }
11
11
  };
package/lib/publish.js CHANGED
@@ -1,4 +1,4 @@
1
- const {basename, extname, resolve} = require('path');
1
+ const path = require('path');
2
2
  const {stat, readFile} = require('fs-extra');
3
3
  const {isPlainObject, template} = require('lodash');
4
4
  const mime = require('mime');
@@ -21,18 +21,26 @@ module.exports = async (pluginConfig, context) => {
21
21
  const {githubToken, githubUrl, githubApiPathPrefix, proxy, assets} = resolveConfig(pluginConfig, context);
22
22
  const {owner, repo} = parseGithubUrl(repositoryUrl);
23
23
  const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy});
24
- const release = {owner, repo, tag_name: gitTag, name, body: notes, prerelease: isPrerelease(branch)};
24
+ const release = {
25
+ owner,
26
+ repo,
27
+ tag_name: gitTag,
28
+ target_commitish: branch.name,
29
+ name,
30
+ body: notes,
31
+ prerelease: isPrerelease(branch),
32
+ };
25
33
 
26
34
  debug('release object: %O', release);
27
35
 
28
36
  // When there are no assets, we publish a release directly
29
37
  if (!assets || assets.length === 0) {
30
38
  const {
31
- data: {html_url: url},
39
+ data: {html_url: url, id: releaseId},
32
40
  } = await github.repos.createRelease(release);
33
41
 
34
42
  logger.log('Published GitHub release: %s', url);
35
- return {url, name: RELEASE_NAME};
43
+ return {url, name: RELEASE_NAME, id: releaseId};
36
44
  }
37
45
 
38
46
  // We'll create a draft release, append the assets to it, and then publish it.
@@ -53,8 +61,8 @@ module.exports = async (pluginConfig, context) => {
53
61
  let file;
54
62
 
55
63
  try {
56
- file = await stat(resolve(cwd, filePath));
57
- } catch (_) {
64
+ file = await stat(path.resolve(cwd, filePath));
65
+ } catch {
58
66
  logger.error('The asset %s cannot be read, and will be ignored.', filePath);
59
67
  return;
60
68
  }
@@ -64,13 +72,13 @@ module.exports = async (pluginConfig, context) => {
64
72
  return;
65
73
  }
66
74
 
67
- const fileName = template(asset.name || basename(filePath))(context);
75
+ const fileName = template(asset.name || path.basename(filePath))(context);
68
76
  const upload = {
69
77
  url: uploadUrl,
70
- data: await readFile(resolve(cwd, filePath)),
78
+ data: await readFile(path.resolve(cwd, filePath)),
71
79
  name: fileName,
72
80
  headers: {
73
- 'content-type': mime.getType(extname(fileName)) || 'text/plain',
81
+ 'content-type': mime.getType(path.extname(fileName)) || 'text/plain',
74
82
  'content-length': file.size,
75
83
  },
76
84
  };
@@ -94,5 +102,5 @@ module.exports = async (pluginConfig, context) => {
94
102
  } = await github.repos.updateRelease({owner, repo, release_id: releaseId, draft: false});
95
103
 
96
104
  logger.log('Published GitHub release: %s', url);
97
- return {url, name: RELEASE_NAME};
105
+ return {url, name: RELEASE_NAME, id: releaseId};
98
106
  };
@@ -12,6 +12,7 @@ module.exports = (
12
12
  labels,
13
13
  assignees,
14
14
  releasedLabels,
15
+ addReleases,
15
16
  },
16
17
  {env}
17
18
  ) => ({
@@ -30,4 +31,5 @@ module.exports = (
30
31
  : releasedLabels === false
31
32
  ? false
32
33
  : castArray(releasedLabels),
34
+ addReleases: isNil(addReleases) ? false : addReleases,
33
35
  });
package/lib/success.js CHANGED
@@ -1,4 +1,4 @@
1
- const {isNil, uniqBy, template, flatten} = require('lodash');
1
+ const {isNil, uniqBy, template, flatten, isEmpty} = require('lodash');
2
2
  const pFilter = require('p-filter');
3
3
  const AggregateError = require('aggregate-error');
4
4
  const issueParser = require('issue-parser');
@@ -9,6 +9,8 @@ const getClient = require('./get-client');
9
9
  const getSearchQueries = require('./get-search-queries');
10
10
  const getSuccessComment = require('./get-success-comment');
11
11
  const findSRIssues = require('./find-sr-issues');
12
+ const {RELEASE_NAME} = require('./definitions/constants');
13
+ const getReleaseLinks = require('./get-release-links');
12
14
 
13
15
  module.exports = async (pluginConfig, context) => {
14
16
  const {
@@ -27,6 +29,7 @@ module.exports = async (pluginConfig, context) => {
27
29
  failComment,
28
30
  failTitle,
29
31
  releasedLabels,
32
+ addReleases,
30
33
  } = resolveConfig(pluginConfig, context);
31
34
 
32
35
  const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy});
@@ -140,6 +143,21 @@ module.exports = async (pluginConfig, context) => {
140
143
  );
141
144
  }
142
145
 
146
+ if (addReleases !== false && errors.length === 0) {
147
+ const ghRelease = releases.find((release) => release.name && release.name === RELEASE_NAME);
148
+ if (!isNil(ghRelease)) {
149
+ const ghRelaseId = ghRelease.id;
150
+ const additionalReleases = getReleaseLinks(releases);
151
+ if (!isEmpty(additionalReleases) && !isNil(ghRelaseId)) {
152
+ const newBody =
153
+ addReleases === 'top'
154
+ ? additionalReleases.concat('\n---\n', nextRelease.notes)
155
+ : nextRelease.notes.concat('\n---\n', additionalReleases);
156
+ await github.repos.updateRelease({owner, repo, release_id: ghRelaseId, body: newBody});
157
+ }
158
+ }
159
+ }
160
+
143
161
  if (errors.length > 0) {
144
162
  throw new AggregateError(errors);
145
163
  }
package/lib/verify.js CHANGED
@@ -7,6 +7,7 @@ const getClient = require('./get-client');
7
7
  const getError = require('./get-error');
8
8
 
9
9
  const isNonEmptyString = (value) => isString(value) && value.trim();
10
+ const oneOf = (enumArray) => (value) => enumArray.some((element) => element === value);
10
11
  const isStringOrStringArray = (value) =>
11
12
  isNonEmptyString(value) || (isArray(value) && value.every((string) => isNonEmptyString(string)));
12
13
  const isArrayOf = (validator) => (array) => isArray(array) && array.every((value) => validator(value));
@@ -24,6 +25,7 @@ const VALIDATORS = {
24
25
  labels: canBeDisabled(isArrayOf(isNonEmptyString)),
25
26
  assignees: isArrayOf(isNonEmptyString),
26
27
  releasedLabels: canBeDisabled(isArrayOf(isNonEmptyString)),
28
+ addReleases: canBeDisabled(oneOf(['bottom', 'top'])),
27
29
  };
28
30
 
29
31
  module.exports = async (pluginConfig, context) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@semantic-release/github",
3
3
  "description": "semantic-release plugin to publish a GitHub release and comment on released Pull Requests/Issues",
4
- "version": "7.0.7",
4
+ "version": "7.2.0",
5
5
  "author": "Pierre Vanduynslager (https://twitter.com/@pvdlg_)",
6
6
  "ava": {
7
7
  "files": [
@@ -16,7 +16,7 @@
16
16
  "Gregor Martynus (https://twitter.com/gr2m)"
17
17
  ],
18
18
  "dependencies": {
19
- "@octokit/rest": "^17.0.0",
19
+ "@octokit/rest": "^18.0.0",
20
20
  "@semantic-release/error": "^2.2.0",
21
21
  "aggregate-error": "^3.0.0",
22
22
  "bottleneck": "^2.18.1",
@@ -34,18 +34,18 @@
34
34
  "url-join": "^4.0.0"
35
35
  },
36
36
  "devDependencies": {
37
- "ava": "^3.1.0",
38
- "clear-module": "^4.0.0",
39
- "codecov": "^3.5.0",
40
- "nock": "^12.0.0",
41
- "nyc": "^15.0.0",
42
- "proxy": "^1.0.0",
43
- "proxyquire": "^2.0.0",
44
- "semantic-release": "^17.0.0",
45
- "server-destroy": "^1.0.1",
46
- "sinon": "^9.0.0",
47
- "tempy": "^0.5.0",
48
- "xo": "^0.30.0"
37
+ "ava": "3.13.0",
38
+ "clear-module": "4.1.1",
39
+ "codecov": "3.8.1",
40
+ "nock": "13.0.5",
41
+ "nyc": "15.1.0",
42
+ "proxy": "1.0.2",
43
+ "proxyquire": "2.1.3",
44
+ "semantic-release": "17.2.3",
45
+ "server-destroy": "1.0.1",
46
+ "sinon": "9.2.1",
47
+ "tempy": "1.0.0",
48
+ "xo": "0.34.2"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=10.18"
@@ -99,7 +99,8 @@
99
99
  "lint": "xo",
100
100
  "pretest": "npm run lint",
101
101
  "semantic-release": "semantic-release",
102
- "test": "nyc ava -v"
102
+ "test": "nyc ava -v",
103
+ "test:ci": "nyc ava -v"
103
104
  },
104
105
  "xo": {
105
106
  "prettier": true,
@@ -111,7 +112,13 @@
111
112
  "properties": "never"
112
113
  }
113
114
  ],
114
- "unicorn/string-content": "off"
115
+ "unicorn/string-content": "off",
116
+ "unicorn/no-reduce": "off"
115
117
  }
118
+ },
119
+ "renovate": {
120
+ "extends": [
121
+ "github>semantic-release/.github"
122
+ ]
116
123
  }
117
124
  }