@semantic-release/github 7.0.3 → 7.0.7

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
@@ -59,13 +59,16 @@ When creating the token, the **minimum required scopes** are:
59
59
  - [`repo`](https://github.com/settings/tokens/new?scopes=repo) for a private repository
60
60
  - [`public_repo`](https://github.com/settings/tokens/new?scopes=public_repo) for a public repository
61
61
 
62
+ _Note on GitHub Actions:_ You can use the default token which is provided in the secret _GITHUB_TOKEN_. However releases done with this token will NOT trigger release events to start other workflows.
63
+ If you have actions that trigger on newly created releases, please use a generated token for that and store it in your repository's secrets (any other name than GITHUB_TOKEN is fine).
64
+
62
65
  ### Environment variables
63
66
 
64
- | Variable | Description |
65
- | ------------------------------ | --------------------------------------------------------- |
66
- | `GH_TOKEN` or `GITHUB_TOKEN` | **Required.** The token used to authenticate with GitHub. |
67
- | `GH_URL` or `GITHUB_URL` | The GitHub Enterprise endpoint. |
68
- | `GH_PREFIX` or `GITHUB_PREFIX` | The GitHub Enterprise API prefix. |
67
+ | Variable | Description |
68
+ | -------------------------------------------------- | --------------------------------------------------------- |
69
+ | `GH_TOKEN` or `GITHUB_TOKEN` | **Required.** The token used to authenticate with GitHub. |
70
+ | `GITHUB_API_URL` or `GH_URL` or `GITHUB_URL` | The GitHub Enterprise endpoint. |
71
+ | `GH_PREFIX` or `GITHUB_PREFIX` | The GitHub Enterprise API prefix. |
69
72
 
70
73
  ### Options
71
74
 
package/index.js CHANGED
@@ -14,7 +14,7 @@ async function verifyConditions(pluginConfig, context) {
14
14
  // If the GitHub publish plugin is used and has `assets`, `successComment`, `failComment`, `failTitle`, `labels` or `assignees` configured, validate it now in order to prevent any release if the configuration is wrong
15
15
  if (options.publish) {
16
16
  const publishPlugin =
17
- castArray(options.publish).find(config => config.path && config.path === '@semantic-release/github') || {};
17
+ castArray(options.publish).find((config) => config.path && config.path === '@semantic-release/github') || {};
18
18
 
19
19
  pluginConfig.assets = defaultTo(pluginConfig.assets, publishPlugin.assets);
20
20
  pluginConfig.successComment = defaultTo(pluginConfig.successComment, publishPlugin.successComment);
@@ -3,8 +3,9 @@ const {isString} = require('lodash');
3
3
  const pkg = require('../../package.json');
4
4
 
5
5
  const [homepage] = pkg.homepage.split('#');
6
- const stringify = obj => (isString(obj) ? obj : inspect(obj, {breakLength: Infinity, depth: 2, maxArrayLength: 5}));
7
- const linkify = file => `${homepage}/blob/master/${file}`;
6
+ const stringify = (object) =>
7
+ isString(object) ? object : inspect(object, {breakLength: Infinity, depth: 2, maxArrayLength: 5});
8
+ const linkify = (file) => `${homepage}/blob/master/${file}`;
8
9
 
9
10
  module.exports = {
10
11
  EINVALIDASSETS: ({assets}) => ({
@@ -7,5 +7,5 @@ module.exports = async (github, title, owner, repo) => {
7
7
  q: `in:title+repo:${owner}/${repo}+type:issue+state:open+${title}`,
8
8
  });
9
9
 
10
- return issues.filter(issue => issue.body && issue.body.includes(ISSUE_ID));
10
+ return issues.filter((issue) => issue.body && issue.body.includes(ISSUE_ID));
11
11
  };
package/lib/get-client.js CHANGED
@@ -11,7 +11,7 @@ const {RETRY_CONF, RATE_LIMITS, GLOBAL_RATE_LIMIT} = require('./definitions/rate
11
11
  /**
12
12
  * Http error status for which to not retry.
13
13
  */
14
- const SKIP_RETRY_CODES = [400, 401, 403];
14
+ const SKIP_RETRY_CODES = new Set([400, 401, 403]);
15
15
 
16
16
  /**
17
17
  * Create or retrieve the throttler function for a given rate limit group.
@@ -50,7 +50,7 @@ module.exports = ({githubToken, githubUrl, githubApiPathPrefix, proxy}) => {
50
50
  try {
51
51
  return await getThrottler(limitKey, globalThrottler).wrap(request)(options);
52
52
  } catch (error) {
53
- if (SKIP_RETRY_CODES.includes(error.status)) {
53
+ if (SKIP_RETRY_CODES.has(error.status)) {
54
54
  throw new pRetry.AbortError(error);
55
55
  }
56
56
 
@@ -4,14 +4,16 @@ const GET_HELP_URL = `${HOME_URL}#get-help`;
4
4
  const USAGE_DOC_URL = `${HOME_URL}/blob/caribou/docs/usage/README.md`;
5
5
  const NEW_ISSUE_URL = `${HOME_URL}/issues/new`;
6
6
 
7
- const formatError = error => `### ${error.message}
7
+ const formatError = (error) => `### ${error.message}
8
8
 
9
- ${error.details ||
9
+ ${
10
+ error.details ||
10
11
  `Unfortunately this error doesn't have any additional information.${
11
12
  error.pluginName
12
13
  ? ` Feel free to kindly ask the author of the \`${error.pluginName}\` plugin to add more helpful information.`
13
14
  : ''
14
- }`}`;
15
+ }`
16
+ }`;
15
17
 
16
18
  module.exports = (branch, errors) => `## :rotating_light: The automated release from the \`${
17
19
  branch.name
@@ -36,7 +38,7 @@ If those don’t help, or if this issue is reporting something you think isn’t
36
38
 
37
39
  ---
38
40
 
39
- ${errors.map(formatError).join('\n\n---\n\n')}
41
+ ${errors.map((error) => formatError(error)).join('\n\n---\n\n')}
40
42
 
41
43
  ---
42
44
 
@@ -1,5 +1,5 @@
1
1
  const HOME_URL = 'https://github.com/semantic-release/semantic-release';
2
- const linkify = releaseInfo =>
2
+ const linkify = (releaseInfo) =>
3
3
  `${releaseInfo.url ? `[${releaseInfo.name}](${releaseInfo.url})` : `\`${releaseInfo.name}\``}`;
4
4
 
5
5
  module.exports = (issue, releaseInfos, nextRelease) =>
@@ -10,7 +10,7 @@ module.exports = (issue, releaseInfos, nextRelease) =>
10
10
  ? `\n\nThe release is available on${
11
11
  releaseInfos.length === 1
12
12
  ? ` ${linkify(releaseInfos[0])}`
13
- : `:\n${releaseInfos.map(releaseInfo => `- ${linkify(releaseInfo)}`).join('\n')}`
13
+ : `:\n${releaseInfos.map((releaseInfo) => `- ${linkify(releaseInfo)}`).join('\n')}`
14
14
  }`
15
15
  : ''
16
16
  }
@@ -10,7 +10,7 @@ module.exports = async ({cwd}, assets) =>
10
10
  []
11
11
  .concat(
12
12
  ...(await Promise.all(
13
- assets.map(async asset => {
13
+ assets.map(async (asset) => {
14
14
  // Wrap single glob definition in Array
15
15
  let glob = castArray(isPlainObject(asset) ? asset.path : asset);
16
16
  // TODO Temporary workaround for https://github.com/mrmlnc/fast-glob/issues/47
@@ -40,7 +40,7 @@ module.exports = async ({cwd}, assets) =>
40
40
  // - `path` of the matched file
41
41
  // - `name` based on the actual file name (to avoid assets with duplicate `name`)
42
42
  // - other properties of the original asset definition
43
- return globbed.map(file => ({...asset, path: file, name: basename(file)}));
43
+ return globbed.map((file) => ({...asset, path: file, name: basename(file)}));
44
44
  }
45
45
 
46
46
  // If asset is an Object, output an Object definition with:
@@ -60,7 +60,7 @@ module.exports = async ({cwd}, assets) =>
60
60
  // Sort with Object first, to prioritize Object definition over Strings in dedup
61
61
  ))
62
62
  )
63
- .sort(asset => (isPlainObject(asset) ? -1 : 1)),
63
+ .sort((asset) => (isPlainObject(asset) ? -1 : 1)),
64
64
  // Compare `path` property if Object definition, value itself if String
65
65
  (a, b) => path.resolve(cwd, isPlainObject(a) ? a.path : a) === path.resolve(cwd, isPlainObject(b) ? b.path : b)
66
66
  );
@@ -1,4 +1,4 @@
1
- module.exports = repositoryUrl => {
1
+ module.exports = (repositoryUrl) => {
2
2
  const [match, auth, host, path] = /^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<path>.*)$/.exec(repositoryUrl) || [];
3
3
  try {
4
4
  const [, owner, repo] = /^\/(?<owner>[^/]+)?\/?(?<repo>.+?)(?:\.git)?$/.exec(
package/lib/publish.js CHANGED
@@ -48,7 +48,7 @@ module.exports = async (pluginConfig, context) => {
48
48
  debug('globed assets: %o', globbedAssets);
49
49
 
50
50
  await Promise.all(
51
- globbedAssets.map(async asset => {
51
+ globbedAssets.map(async (asset) => {
52
52
  const filePath = isPlainObject(asset) ? asset.path : asset;
53
53
  let file;
54
54
 
@@ -16,7 +16,7 @@ module.exports = (
16
16
  {env}
17
17
  ) => ({
18
18
  githubToken: env.GH_TOKEN || env.GITHUB_TOKEN,
19
- githubUrl: githubUrl || env.GH_URL || env.GITHUB_URL,
19
+ githubUrl: githubUrl || env.GITHUB_API_URL || env.GH_URL || env.GITHUB_URL,
20
20
  githubApiPathPrefix: githubApiPathPrefix || env.GH_PREFIX || env.GITHUB_PREFIX || '',
21
21
  proxy: proxy || env.HTTP_PROXY,
22
22
  assets: assets ? castArray(assets) : assets,
package/lib/success.js CHANGED
@@ -39,11 +39,11 @@ module.exports = async (pluginConfig, context) => {
39
39
  logger.log('Skip commenting on issues and pull requests.');
40
40
  } else {
41
41
  const parser = issueParser('github', githubUrl ? {hosts: [githubUrl]} : {});
42
- const releaseInfos = releases.filter(release => Boolean(release.name));
42
+ const releaseInfos = releases.filter((release) => Boolean(release.name));
43
43
  const shas = commits.map(({hash}) => hash);
44
44
 
45
45
  const searchQueries = getSearchQueries(`repo:${owner}/${repo}+type:pr+is:merged`, shas).map(
46
- async q => (await github.search.issuesAndPullRequests({q})).data.items
46
+ async (q) => (await github.search.issuesAndPullRequests({q})).data.items
47
47
  );
48
48
 
49
49
  const prs = await pFilter(
@@ -55,24 +55,27 @@ module.exports = async (pluginConfig, context) => {
55
55
 
56
56
  debug(
57
57
  'found pull requests: %O',
58
- prs.map(pr => pr.number)
58
+ prs.map((pr) => pr.number)
59
59
  );
60
60
 
61
61
  // Parse the release commits message and PRs body to find resolved issues/PRs via comment keyworkds
62
- const issues = [...prs.map(pr => pr.body), ...commits.map(commit => commit.message)].reduce((issues, message) => {
63
- return message
64
- ? issues.concat(
65
- parser(message)
66
- .actions.close.filter(action => isNil(action.slug) || action.slug === `${owner}/${repo}`)
67
- .map(action => ({number: parseInt(action.issue, 10)}))
68
- )
69
- : issues;
70
- }, []);
62
+ const issues = [...prs.map((pr) => pr.body), ...commits.map((commit) => commit.message)].reduce(
63
+ (issues, message) => {
64
+ return message
65
+ ? issues.concat(
66
+ parser(message)
67
+ .actions.close.filter((action) => isNil(action.slug) || action.slug === `${owner}/${repo}`)
68
+ .map((action) => ({number: Number.parseInt(action.issue, 10)}))
69
+ )
70
+ : issues;
71
+ },
72
+ []
73
+ );
71
74
 
72
75
  debug('found issues via comments: %O', issues);
73
76
 
74
77
  await Promise.all(
75
- uniqBy([...prs, ...issues], 'number').map(async issue => {
78
+ uniqBy([...prs, ...issues], 'number').map(async (issue) => {
76
79
  const body = successComment
77
80
  ? template(successComment)({...context, issue})
78
81
  : getSuccessComment(issue, releaseInfos, nextRelease);
@@ -85,7 +88,7 @@ module.exports = async (pluginConfig, context) => {
85
88
  logger.log('Added comment to issue #%d: %s', issue.number, url);
86
89
 
87
90
  if (releasedLabels) {
88
- const labels = releasedLabels.map(label => template(label)(context));
91
+ const labels = releasedLabels.map((label) => template(label)(context));
89
92
  // Don’t use .issues.addLabels for GHE < 2.16 support
90
93
  // https://github.com/semantic-release/github/issues/138
91
94
  await github.request('POST /repos/:owner/:repo/issues/:number/labels', {
@@ -119,7 +122,7 @@ module.exports = async (pluginConfig, context) => {
119
122
  debug('found semantic-release issues: %O', srIssues);
120
123
 
121
124
  await Promise.all(
122
- srIssues.map(async issue => {
125
+ srIssues.map(async (issue) => {
123
126
  debug('close issue: %O', issue);
124
127
  try {
125
128
  const updateIssue = {owner, repo, issue_number: issue.number, state: 'closed'};
package/lib/verify.js CHANGED
@@ -6,16 +6,17 @@ const resolveConfig = require('./resolve-config');
6
6
  const getClient = require('./get-client');
7
7
  const getError = require('./get-error');
8
8
 
9
- const isNonEmptyString = value => isString(value) && value.trim();
10
- const isStringOrStringArray = value => isNonEmptyString(value) || (isArray(value) && value.every(isNonEmptyString));
11
- const isArrayOf = validator => array => isArray(array) && array.every(value => validator(value));
12
- const canBeDisabled = validator => value => value === false || validator(value);
9
+ const isNonEmptyString = (value) => isString(value) && value.trim();
10
+ const isStringOrStringArray = (value) =>
11
+ isNonEmptyString(value) || (isArray(value) && value.every((string) => isNonEmptyString(string)));
12
+ const isArrayOf = (validator) => (array) => isArray(array) && array.every((value) => validator(value));
13
+ const canBeDisabled = (validator) => (value) => value === false || validator(value);
13
14
 
14
15
  const VALIDATORS = {
15
- proxy: proxy =>
16
+ proxy: (proxy) =>
16
17
  isNonEmptyString(proxy) || (isPlainObject(proxy) && isNonEmptyString(proxy.host) && isNumber(proxy.port)),
17
18
  assets: isArrayOf(
18
- asset => isStringOrStringArray(asset) || (isPlainObject(asset) && isStringOrStringArray(asset.path))
19
+ (asset) => isStringOrStringArray(asset) || (isPlainObject(asset) && isStringOrStringArray(asset.path))
19
20
  ),
20
21
  successComment: canBeDisabled(isNonEmptyString),
21
22
  failTitle: canBeDisabled(isNonEmptyString),
@@ -68,6 +69,14 @@ module.exports = async (pluginConfig, context) => {
68
69
  },
69
70
  } = await github.repos.get({repo, owner});
70
71
  if (!push) {
72
+ // If authenticated as GitHub App installation, `push` will always be false.
73
+ // We send another request to check if current authentication is an installation.
74
+ // Note: we cannot check if the installation has all required permissions, it's
75
+ // up to the user to make sure it has
76
+ if (await github.request('HEAD /installation/repositories', {per_page: 1}).catch(() => false)) {
77
+ return;
78
+ }
79
+
71
80
  errors.push(getError('EGHNOPERMISSION', {owner, repo}));
72
81
  }
73
82
  } catch (error) {
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.3",
4
+ "version": "7.0.7",
5
5
  "author": "Pierre Vanduynslager (https://twitter.com/@pvdlg_)",
6
6
  "ava": {
7
7
  "files": [
@@ -16,13 +16,13 @@
16
16
  "Gregor Martynus (https://twitter.com/gr2m)"
17
17
  ],
18
18
  "dependencies": {
19
- "@octokit/rest": "^16.43.0",
19
+ "@octokit/rest": "^17.0.0",
20
20
  "@semantic-release/error": "^2.2.0",
21
21
  "aggregate-error": "^3.0.0",
22
22
  "bottleneck": "^2.18.1",
23
23
  "debug": "^4.0.0",
24
24
  "dir-glob": "^3.0.0",
25
- "fs-extra": "^8.0.0",
25
+ "fs-extra": "^9.0.0",
26
26
  "globby": "^11.0.0",
27
27
  "http-proxy-agent": "^4.0.0",
28
28
  "https-proxy-agent": "^5.0.0",
@@ -37,15 +37,15 @@
37
37
  "ava": "^3.1.0",
38
38
  "clear-module": "^4.0.0",
39
39
  "codecov": "^3.5.0",
40
- "nock": "^11.1.0",
40
+ "nock": "^12.0.0",
41
41
  "nyc": "^15.0.0",
42
42
  "proxy": "^1.0.0",
43
43
  "proxyquire": "^2.0.0",
44
44
  "semantic-release": "^17.0.0",
45
45
  "server-destroy": "^1.0.1",
46
- "sinon": "^8.0.0",
47
- "tempy": "^0.3.0",
48
- "xo": "^0.25.2"
46
+ "sinon": "^9.0.0",
47
+ "tempy": "^0.5.0",
48
+ "xo": "^0.30.0"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=10.18"
@@ -110,7 +110,8 @@
110
110
  {
111
111
  "properties": "never"
112
112
  }
113
- ]
113
+ ],
114
+ "unicorn/string-content": "off"
114
115
  }
115
116
  }
116
117
  }