@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 +8 -5
- package/index.js +1 -1
- package/lib/definitions/errors.js +3 -2
- package/lib/find-sr-issues.js +1 -1
- package/lib/get-client.js +2 -2
- package/lib/get-fail-comment.js +6 -4
- package/lib/get-success-comment.js +2 -2
- package/lib/glob-assets.js +3 -3
- package/lib/parse-github-url.js +1 -1
- package/lib/publish.js +1 -1
- package/lib/resolve-config.js +1 -1
- package/lib/success.js +18 -15
- package/lib/verify.js +15 -6
- package/package.json +9 -8
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
|
|
65
|
-
|
|
|
66
|
-
| `GH_TOKEN` or `GITHUB_TOKEN`
|
|
67
|
-
| `GH_URL` or `GITHUB_URL` | The GitHub Enterprise endpoint. |
|
|
68
|
-
| `GH_PREFIX` or `GITHUB_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 =
|
|
7
|
-
|
|
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}) => ({
|
package/lib/find-sr-issues.js
CHANGED
|
@@ -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.
|
|
53
|
+
if (SKIP_RETRY_CODES.has(error.status)) {
|
|
54
54
|
throw new pRetry.AbortError(error);
|
|
55
55
|
}
|
|
56
56
|
|
package/lib/get-fail-comment.js
CHANGED
|
@@ -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
|
-
${
|
|
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
|
}
|
package/lib/glob-assets.js
CHANGED
|
@@ -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
|
);
|
package/lib/parse-github-url.js
CHANGED
|
@@ -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
|
|
package/lib/resolve-config.js
CHANGED
|
@@ -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(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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 =
|
|
11
|
-
|
|
12
|
-
const
|
|
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.
|
|
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": "^
|
|
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": "^
|
|
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": "^
|
|
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": "^
|
|
47
|
-
"tempy": "^0.
|
|
48
|
-
"xo": "^0.
|
|
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
|
}
|