@semantic-release/github 10.2.0 → 10.3.1
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 +64 -18
- package/lib/fail.js +17 -1
- package/lib/resolve-config.js +4 -0
- package/lib/success.js +267 -28
- package/lib/verify.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,24 +80,26 @@ When using the _GITHUB_TOKEN_, the **minimum required permissions** are:
|
|
|
80
80
|
|
|
81
81
|
### Options
|
|
82
82
|
|
|
83
|
-
| Option
|
|
84
|
-
|
|
|
85
|
-
| `githubUrl`
|
|
86
|
-
| `githubApiPathPrefix`
|
|
87
|
-
| `githubApiUrl`
|
|
88
|
-
| `proxy`
|
|
89
|
-
| `assets`
|
|
90
|
-
| `successComment`
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
83
|
+
| Option | Description | Default |
|
|
84
|
+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
85
|
+
| `githubUrl` | The GitHub server endpoint. | `GH_URL` or `GITHUB_URL` environment variable. |
|
|
86
|
+
| `githubApiPathPrefix` | The GitHub API prefix, relative to `githubUrl`. | `GH_PREFIX` or `GITHUB_PREFIX` environment variable. |
|
|
87
|
+
| `githubApiUrl` | The GitHub API endpoint. Note that this overwrites `githubApiPathPrefix`. | `GITHUB_API_URL` environment variable. |
|
|
88
|
+
| `proxy` | The proxy to use to access the GitHub API. Set to `false` to disable usage of proxy. See [proxy](#proxy). | `HTTP_PROXY` environment variable. |
|
|
89
|
+
| `assets` | An array of files to upload to the release. See [assets](#assets). | - |
|
|
90
|
+
| `successComment` | The comment to add to each issue and pull request resolved by the release. Set to `false` to disable commenting on issues and pull requests. See [successComment](#successcomment). | `:tada: This issue has been resolved in version ${nextRelease.version} :tada:\n\nThe release is available on [GitHub release](<github_release_url>)` |
|
|
91
|
+
| `successCommentCondition` | Use this as condition, when to comment on issues or pull requests. See [successCommentCondition](#successCommentCondition) | - |
|
|
92
|
+
| `failComment` | The content of the issue created when a release fails. Set to `false` to disable opening an issue when a release fails. See [failComment](#failcomment). | Friendly message with links to **semantic-release** documentation and support, with the list of errors that caused the release to fail. |
|
|
93
|
+
| `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 🚨` |
|
|
94
|
+
| `failCommentCondition` | Use this as condition, when to comment on or create an issues in case of failures. See [failCommentCondition](#failCommentCondition). | - |
|
|
95
|
+
| `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']` |
|
|
96
|
+
| `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. | - |
|
|
97
|
+
| `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}\` : "" %>']- |
|
|
98
|
+
| `addReleases` | Will add release links to the GitHub Release. Can be `false`, `"bottom"` or `"top"`. See [addReleases](#addReleases). | `false` |
|
|
99
|
+
| `draftRelease` | A boolean indicating if a GitHub Draft Release should be created instead of publishing an actual GitHub Release. | `false` |
|
|
100
|
+
| `releaseNameTemplate` | A [Lodash template](https://lodash.com/docs#template) to customize the github release's name | `<%= nextverison.name %>` |
|
|
101
|
+
| `releaseBodyTemplate` | A [Lodash template](https://lodash.com/docs#template) to customize the github release's body | `<%= nextverison.notes %>` |
|
|
102
|
+
| `discussionCategoryName` | The category name in which to create a linked discussion to the release. Set to `false` to disable creating discussion for a release. | `false` |
|
|
101
103
|
|
|
102
104
|
#### proxy
|
|
103
105
|
|
|
@@ -181,6 +183,29 @@ The `successComment` `This ${issue.pull_request ? 'pull request' : 'issue'} is i
|
|
|
181
183
|
|
|
182
184
|
> This pull request is included in version 1.0.0
|
|
183
185
|
|
|
186
|
+
#### successCommentCondition
|
|
187
|
+
|
|
188
|
+
The message for the issue comments is generated with [Lodash template](https://lodash.com/docs#template). The following variables are available:
|
|
189
|
+
|
|
190
|
+
| Parameter | Description |
|
|
191
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
192
|
+
| `branch` | `Object` with `name`, `type`, `channel`, `range` and `prerelease` properties of the branch from which the release is done. |
|
|
193
|
+
| `lastRelease` | `Object` with `version`, `channel`, `gitTag` and `gitHead` of the last release. |
|
|
194
|
+
| `nextRelease` | `Object` with `version`, `channel`, `gitTag`, `gitHead` and `notes` of the release being done. |
|
|
195
|
+
| `commits` | `Array` of commit `Object`s with `hash`, `subject`, `body` `message` and `author`. |
|
|
196
|
+
| `releases` | `Array` with a release `Object`s for each release published, with optional release data such as `name` and `url`. |
|
|
197
|
+
| `issue` | A [GitHub API Pull Request object](https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request) for pull requests related to a commit, or an `Object` with the `number` property for issues resolved via [keywords](https://help.github.com/articles/closing-issues-using-keywords) |
|
|
198
|
+
|
|
199
|
+
##### successCommentCondition example
|
|
200
|
+
|
|
201
|
+
- do not create any comments at all: set to `false` or templating: `"<% return false; %>"`
|
|
202
|
+
- to only comment on issues: `"<% return !issue.pull_request; %>"`
|
|
203
|
+
- to only comment on pull requests: `"<% return issue.pull_request; %>"`
|
|
204
|
+
- to avoid comment on PRs or issues created by Bots: `"<% return issue.user.type !== 'Bot'; %>"`
|
|
205
|
+
- you can use labels to filter issues: `"<% return issue.labels?.includes('semantic-release-relevant'); %>"`
|
|
206
|
+
|
|
207
|
+
> check the [GitHub API issue object](https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#get-an-issue) for properties which can be used for the filter
|
|
208
|
+
|
|
184
209
|
#### failComment
|
|
185
210
|
|
|
186
211
|
The message for the issue content is generated with [Lodash template](https://lodash.com/docs#template). The following variables are available:
|
|
@@ -199,6 +224,27 @@ The `failComment` `This release from branch ${branch.name} had failed due to the
|
|
|
199
224
|
> - Error message 1
|
|
200
225
|
> - Error message 2
|
|
201
226
|
|
|
227
|
+
#### failCommentCondition
|
|
228
|
+
|
|
229
|
+
The message for the issue content is generated with [Lodash template](https://lodash.com/docs#template). The following variables are available:
|
|
230
|
+
|
|
231
|
+
| Parameter | Description |
|
|
232
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
233
|
+
| `branch` | `Object` with `name`, `type`, `channel`, `range` and `prerelease` properties of the branch from which the release is done. |
|
|
234
|
+
| `lastRelease` | `Object` with `version`, `channel`, `gitTag` and `gitHead` of the last release. |
|
|
235
|
+
| `nextRelease` | `Object` with `version`, `channel`, `gitTag`, `gitHead` and `notes` of the release being done. |
|
|
236
|
+
| `commits` | `Array` of commit `Object`s with `hash`, `subject`, `body` `message` and `author`. |
|
|
237
|
+
| `releases` | `Array` with a release `Object`s for each release published, with optional release data such as `name` and `url`. |
|
|
238
|
+
| `issue` | A [GitHub API pull request object](https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request) for pull requests related to a commit, or an `Object` with the `number` property for issues resolved via [keywords](https://help.github.com/articles/closing-issues-using-keywords) |
|
|
239
|
+
|
|
240
|
+
##### failCommentCondition example
|
|
241
|
+
|
|
242
|
+
- do not create any comments at all: set to `false` or templating: `"<% return false; %>"`
|
|
243
|
+
- to only comment on main branch: `"<% return branch.name === 'main' %>"`
|
|
244
|
+
- you can use labels to filter issues, i.e. to not comment if the issue is labeled with `wip`: `"<% return !issue.labels?.includes('wip') %>"`
|
|
245
|
+
|
|
246
|
+
> check the [GitHub API Pull Request Object](https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request) for properties which can be used for the filter
|
|
247
|
+
|
|
202
248
|
#### releasedLabels
|
|
203
249
|
|
|
204
250
|
Each label name is generated with [Lodash template](https://lodash.com/docs#template). The following variables are available:
|
package/lib/fail.js
CHANGED
|
@@ -23,14 +23,21 @@ export default async function fail(pluginConfig, context, { Octokit }) {
|
|
|
23
23
|
githubApiPathPrefix,
|
|
24
24
|
githubApiUrl,
|
|
25
25
|
proxy,
|
|
26
|
-
failComment,
|
|
27
26
|
failTitle,
|
|
27
|
+
failComment,
|
|
28
|
+
failCommentCondition,
|
|
28
29
|
labels,
|
|
29
30
|
assignees,
|
|
30
31
|
} = resolveConfig(pluginConfig, context);
|
|
31
32
|
|
|
32
33
|
if (failComment === false || failTitle === false) {
|
|
33
34
|
logger.log("Skip issue creation.");
|
|
35
|
+
// TODO: use logger.warn() instead of logger.log()
|
|
36
|
+
logger.log(
|
|
37
|
+
`DEPRECATION: 'false' for 'failComment' or 'failTitle' is deprecated and will be removed in a future major version. Use 'failCommentCondition' instead.`,
|
|
38
|
+
);
|
|
39
|
+
} else if (failCommentCondition === false) {
|
|
40
|
+
logger.log("Skip issue creation.");
|
|
34
41
|
} else {
|
|
35
42
|
const octokit = new Octokit(
|
|
36
43
|
toOctokitOptions({
|
|
@@ -52,6 +59,15 @@ export default async function fail(pluginConfig, context, { Octokit }) {
|
|
|
52
59
|
: getFailComment(branch, errors);
|
|
53
60
|
const [srIssue] = await findSRIssues(octokit, failTitle, owner, repo);
|
|
54
61
|
|
|
62
|
+
const canCommentOnOrCreateIssue = failCommentCondition
|
|
63
|
+
? template(failCommentCondition)({ ...context, issue: srIssue })
|
|
64
|
+
: true;
|
|
65
|
+
|
|
66
|
+
if (!canCommentOnOrCreateIssue) {
|
|
67
|
+
logger.log("Skip commenting on or creating an issue.");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
if (srIssue) {
|
|
56
72
|
logger.log("Found existing semantic-release issue #%d.", srIssue.number);
|
|
57
73
|
const comment = { owner, repo, issue_number: srIssue.number, body };
|
package/lib/resolve-config.js
CHANGED
|
@@ -8,8 +8,10 @@ export default function resolveConfig(
|
|
|
8
8
|
proxy,
|
|
9
9
|
assets,
|
|
10
10
|
successComment,
|
|
11
|
+
successCommentCondition,
|
|
11
12
|
failTitle,
|
|
12
13
|
failComment,
|
|
14
|
+
failCommentCondition,
|
|
13
15
|
labels,
|
|
14
16
|
assignees,
|
|
15
17
|
releasedLabels,
|
|
@@ -30,10 +32,12 @@ export default function resolveConfig(
|
|
|
30
32
|
proxy: isNil(proxy) ? env.http_proxy || env.HTTP_PROXY || false : proxy,
|
|
31
33
|
assets: assets ? castArray(assets) : assets,
|
|
32
34
|
successComment,
|
|
35
|
+
successCommentCondition,
|
|
33
36
|
failTitle: isNil(failTitle)
|
|
34
37
|
? "The automated release is failing 🚨"
|
|
35
38
|
: failTitle,
|
|
36
39
|
failComment,
|
|
40
|
+
failCommentCondition,
|
|
37
41
|
labels: isNil(labels)
|
|
38
42
|
? ["semantic-release"]
|
|
39
43
|
: labels === false
|
package/lib/success.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isNil, uniqBy, template, flatten, isEmpty } from "lodash-es";
|
|
1
|
+
import { isNil, uniqBy, template, flatten, isEmpty, merge } from "lodash-es";
|
|
2
2
|
import pFilter from "p-filter";
|
|
3
3
|
import AggregateError from "aggregate-error";
|
|
4
4
|
import issueParser from "issue-parser";
|
|
@@ -29,8 +29,10 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
29
29
|
githubApiUrl,
|
|
30
30
|
proxy,
|
|
31
31
|
successComment,
|
|
32
|
-
|
|
32
|
+
successCommentCondition,
|
|
33
33
|
failTitle,
|
|
34
|
+
failComment,
|
|
35
|
+
failCommentCondition,
|
|
34
36
|
releasedLabels,
|
|
35
37
|
addReleases,
|
|
36
38
|
} = resolveConfig(pluginConfig, context);
|
|
@@ -59,6 +61,12 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
59
61
|
logger.log("No commits found in release");
|
|
60
62
|
}
|
|
61
63
|
logger.log("Skip commenting on issues and pull requests.");
|
|
64
|
+
// TODO: use logger.warn() instead of logger.log()
|
|
65
|
+
logger.log(
|
|
66
|
+
`DEPRECATION: 'false' for 'successComment' is deprecated and will be removed in a future major version. Use 'successCommentCondition' instead.`,
|
|
67
|
+
);
|
|
68
|
+
} else if (successCommentCondition === false) {
|
|
69
|
+
logger.log("Skip commenting on issues and pull requests.");
|
|
62
70
|
} else {
|
|
63
71
|
const parser = issueParser(
|
|
64
72
|
"github",
|
|
@@ -67,16 +75,9 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
67
75
|
const releaseInfos = releases.filter((release) => Boolean(release.name));
|
|
68
76
|
const shas = commits.map(({ hash }) => hash);
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const chunkSize = 100;
|
|
74
|
-
const shasChunks = [];
|
|
75
|
-
for (let i = 0; i < shas.length; i += chunkSize) {
|
|
76
|
-
const chunk = shas.slice(i, i + chunkSize);
|
|
77
|
-
shasChunks.push(chunk);
|
|
78
|
-
}
|
|
79
|
-
for (const chunk of shasChunks) {
|
|
78
|
+
// Get associatedPRs
|
|
79
|
+
const associatedPRs = await inChunks(shas, 100, async (chunk) => {
|
|
80
|
+
const responsePRs = [];
|
|
80
81
|
const { repository } = await octokit.graphql(
|
|
81
82
|
buildAssociatedPRsQuery(chunk),
|
|
82
83
|
{ owner, repo },
|
|
@@ -85,7 +86,9 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
85
86
|
(item) => item.associatedPullRequests,
|
|
86
87
|
);
|
|
87
88
|
for (const { nodes, pageInfo } of responseAssociatedPRs) {
|
|
88
|
-
|
|
89
|
+
if (nodes.length === 0) continue;
|
|
90
|
+
|
|
91
|
+
responsePRs.push(...buildIssuesOrPRsFromResponseNode(nodes, "PR"));
|
|
89
92
|
if (pageInfo.hasNextPage) {
|
|
90
93
|
let cursor = pageInfo.endCursor;
|
|
91
94
|
let hasNextPage = true;
|
|
@@ -95,7 +98,12 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
95
98
|
{ owner, repo, sha: response.commit.oid, cursor },
|
|
96
99
|
);
|
|
97
100
|
const { associatedPullRequests } = repository.commit;
|
|
98
|
-
|
|
101
|
+
responsePRs.push(
|
|
102
|
+
...buildIssuesOrPRsFromResponseNode(
|
|
103
|
+
associatedPullRequests.nodes,
|
|
104
|
+
"PR",
|
|
105
|
+
),
|
|
106
|
+
);
|
|
99
107
|
if (associatedPullRequests.pageInfo.hasNextPage) {
|
|
100
108
|
cursor = associatedPullRequests.pageInfo.endCursor;
|
|
101
109
|
} else {
|
|
@@ -104,7 +112,8 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
104
112
|
}
|
|
105
113
|
}
|
|
106
114
|
}
|
|
107
|
-
|
|
115
|
+
return responsePRs;
|
|
116
|
+
});
|
|
108
117
|
|
|
109
118
|
const uniqueAssociatedPRs = uniqBy(flatten(associatedPRs), "number");
|
|
110
119
|
|
|
@@ -137,7 +146,7 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
137
146
|
);
|
|
138
147
|
|
|
139
148
|
// Parse the release commits message and PRs body to find resolved issues/PRs via comment keyworkds
|
|
140
|
-
const
|
|
149
|
+
const parsedIssues = [
|
|
141
150
|
...prs.map((pr) => pr.body),
|
|
142
151
|
...commits.map((commit) => commit.message),
|
|
143
152
|
].reduce(
|
|
@@ -157,10 +166,42 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
157
166
|
[],
|
|
158
167
|
);
|
|
159
168
|
|
|
160
|
-
|
|
169
|
+
let issues = [];
|
|
170
|
+
|
|
171
|
+
if (!isEmpty(parsedIssues)) {
|
|
172
|
+
const uniqueParsedIssues = uniqBy(flatten(parsedIssues), "number");
|
|
173
|
+
|
|
174
|
+
// Get relatedIssues
|
|
175
|
+
issues = await inChunks(uniqueParsedIssues, 100, async (chunk) => {
|
|
176
|
+
const { repository } = await octokit.graphql(
|
|
177
|
+
buildRelatedIssuesQuery(chunk.map((issue) => issue.number)),
|
|
178
|
+
{ owner, repo },
|
|
179
|
+
);
|
|
180
|
+
const responseRelatedIssues = Object.values(repository).map(
|
|
181
|
+
(issue) => issue,
|
|
182
|
+
);
|
|
183
|
+
return buildIssuesOrPRsFromResponseNode(responseRelatedIssues);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
debug(
|
|
187
|
+
"found related issues via PRs and Commits: %O",
|
|
188
|
+
issues.map((issue) => issue.number),
|
|
189
|
+
);
|
|
190
|
+
}
|
|
161
191
|
|
|
162
192
|
await Promise.all(
|
|
163
193
|
uniqBy([...prs, ...issues], "number").map(async (issue) => {
|
|
194
|
+
const issueOrPR = issue.pull_request ? "PR" : "issue";
|
|
195
|
+
|
|
196
|
+
const canCommentOnIssue = successCommentCondition
|
|
197
|
+
? template(successCommentCondition)({ ...context, issue })
|
|
198
|
+
: true;
|
|
199
|
+
|
|
200
|
+
if (!canCommentOnIssue) {
|
|
201
|
+
logger.log(`Skip commenting on ${issueOrPR} #%d.`, issue.number);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
164
205
|
const body = successComment
|
|
165
206
|
? template(successComment)({ ...context, issue })
|
|
166
207
|
: getSuccessComment(issue, releaseInfos, nextRelease);
|
|
@@ -173,7 +214,11 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
173
214
|
"POST /repos/{owner}/{repo}/issues/{issue_number}/comments",
|
|
174
215
|
comment,
|
|
175
216
|
);
|
|
176
|
-
logger.log(
|
|
217
|
+
logger.log(
|
|
218
|
+
`Added comment to ${issueOrPR} #%d: %s`,
|
|
219
|
+
issue.number,
|
|
220
|
+
url,
|
|
221
|
+
);
|
|
177
222
|
|
|
178
223
|
if (releasedLabels) {
|
|
179
224
|
const labels = releasedLabels.map((label) =>
|
|
@@ -188,23 +233,27 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
188
233
|
data: labels,
|
|
189
234
|
},
|
|
190
235
|
);
|
|
191
|
-
logger.log(
|
|
236
|
+
logger.log(
|
|
237
|
+
`Added labels %O to ${issueOrPR} #%d`,
|
|
238
|
+
labels,
|
|
239
|
+
issue.number,
|
|
240
|
+
);
|
|
192
241
|
}
|
|
193
242
|
} catch (error) {
|
|
194
243
|
if (error.status === 403) {
|
|
195
244
|
logger.error(
|
|
196
|
-
|
|
245
|
+
`Not allowed to add a comment to the issue/PR #%d.`,
|
|
197
246
|
issue.number,
|
|
198
247
|
);
|
|
199
248
|
} else if (error.status === 404) {
|
|
200
249
|
logger.error(
|
|
201
|
-
|
|
250
|
+
`Failed to add a comment to the issue/PR #%d as it doesn't exist.`,
|
|
202
251
|
issue.number,
|
|
203
252
|
);
|
|
204
253
|
} else {
|
|
205
254
|
errors.push(error);
|
|
206
255
|
logger.error(
|
|
207
|
-
|
|
256
|
+
`Failed to add a comment to the issue/PR #%d.`,
|
|
208
257
|
issue.number,
|
|
209
258
|
);
|
|
210
259
|
// Don't throw right away and continue to update other issues
|
|
@@ -278,6 +327,100 @@ export default async function success(pluginConfig, context, { Octokit }) {
|
|
|
278
327
|
}
|
|
279
328
|
}
|
|
280
329
|
|
|
330
|
+
/**
|
|
331
|
+
* In order to speed up a function call that handles a big array of items, we split up the
|
|
332
|
+
* array in chunks and call the function for each chunk in parallel. At the end we combine the
|
|
333
|
+
* results again.
|
|
334
|
+
*
|
|
335
|
+
* @template TItem
|
|
336
|
+
* @template TCallbackResult
|
|
337
|
+
* @param {TItem[]} items
|
|
338
|
+
* @param {number} chunkSize
|
|
339
|
+
* @param {(items: TItem[]) => TCallbackResult} callback
|
|
340
|
+
* @returns TCallbackResult
|
|
341
|
+
*/
|
|
342
|
+
async function inChunks(items, chunkSize, callback) {
|
|
343
|
+
const chunkCalls = [];
|
|
344
|
+
for (let i = 0; i < items.length; i += chunkSize) {
|
|
345
|
+
chunkCalls.push(callback(items.slice(i, i + chunkSize)));
|
|
346
|
+
}
|
|
347
|
+
const results = await Promise.all(chunkCalls);
|
|
348
|
+
|
|
349
|
+
return results.flat();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Fields common accross PRs and Issue
|
|
354
|
+
*/
|
|
355
|
+
const baseFields = `
|
|
356
|
+
id
|
|
357
|
+
title
|
|
358
|
+
body
|
|
359
|
+
url
|
|
360
|
+
number
|
|
361
|
+
createdAt
|
|
362
|
+
updatedAt
|
|
363
|
+
closedAt
|
|
364
|
+
comments {
|
|
365
|
+
totalCount
|
|
366
|
+
}
|
|
367
|
+
state
|
|
368
|
+
author {
|
|
369
|
+
login
|
|
370
|
+
url
|
|
371
|
+
avatarUrl
|
|
372
|
+
__typename
|
|
373
|
+
}
|
|
374
|
+
authorAssociation
|
|
375
|
+
activeLockReason
|
|
376
|
+
labels(first: 40) {
|
|
377
|
+
nodes {
|
|
378
|
+
id
|
|
379
|
+
url
|
|
380
|
+
name
|
|
381
|
+
color
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
milestone {
|
|
385
|
+
url
|
|
386
|
+
id
|
|
387
|
+
number
|
|
388
|
+
state
|
|
389
|
+
title
|
|
390
|
+
description
|
|
391
|
+
creator {
|
|
392
|
+
login
|
|
393
|
+
url
|
|
394
|
+
avatarUrl
|
|
395
|
+
}
|
|
396
|
+
createdAt
|
|
397
|
+
closedAt
|
|
398
|
+
updatedAt
|
|
399
|
+
}
|
|
400
|
+
locked
|
|
401
|
+
`;
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Builds GraphQL query for fetching PRs/Commits related Issues to a list of commit hash (sha)
|
|
405
|
+
* @param {Array<number>} numbers
|
|
406
|
+
* @returns {string}
|
|
407
|
+
*/
|
|
408
|
+
function buildRelatedIssuesQuery(numbers) {
|
|
409
|
+
return `#graphql
|
|
410
|
+
query getRelatedIssues($owner: String!, $repo: String!) {
|
|
411
|
+
repository(owner: $owner, name: $repo) {
|
|
412
|
+
${numbers
|
|
413
|
+
.map((num) => {
|
|
414
|
+
return `issue${num}: issue(number: ${num}) {
|
|
415
|
+
${baseFields}
|
|
416
|
+
}`;
|
|
417
|
+
})
|
|
418
|
+
.join("")}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
`;
|
|
422
|
+
}
|
|
423
|
+
|
|
281
424
|
/**
|
|
282
425
|
* Builds GraphQL query for fetching associated PRs to a list of commit hash (sha)
|
|
283
426
|
* @param {Array<string>} shas
|
|
@@ -298,9 +441,20 @@ function buildAssociatedPRsQuery(shas) {
|
|
|
298
441
|
hasNextPage
|
|
299
442
|
}
|
|
300
443
|
nodes {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
444
|
+
${baseFields}
|
|
445
|
+
mergeable
|
|
446
|
+
canBeRebased
|
|
447
|
+
changedFiles
|
|
448
|
+
mergedAt
|
|
449
|
+
isDraft
|
|
450
|
+
mergedBy {
|
|
451
|
+
login
|
|
452
|
+
avatarUrl
|
|
453
|
+
url
|
|
454
|
+
}
|
|
455
|
+
commits {
|
|
456
|
+
totalCount
|
|
457
|
+
}
|
|
304
458
|
}
|
|
305
459
|
}
|
|
306
460
|
}
|
|
@@ -320,15 +474,27 @@ const loadSingleCommitAssociatedPRs = `#graphql
|
|
|
320
474
|
repository(owner: $owner, name: $repo) {
|
|
321
475
|
commit: object(oid: $sha) {
|
|
322
476
|
...on Commit {
|
|
477
|
+
oid
|
|
323
478
|
associatedPullRequests(after: $cursor, first: 100) {
|
|
324
479
|
pageInfo {
|
|
325
480
|
endCursor
|
|
326
481
|
hasNextPage
|
|
327
482
|
}
|
|
328
483
|
nodes {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
484
|
+
${baseFields}
|
|
485
|
+
mergeable
|
|
486
|
+
canBeRebased
|
|
487
|
+
changedFiles
|
|
488
|
+
mergedAt
|
|
489
|
+
isDraft
|
|
490
|
+
mergedBy {
|
|
491
|
+
login
|
|
492
|
+
avatarUrl
|
|
493
|
+
url
|
|
494
|
+
}
|
|
495
|
+
commits {
|
|
496
|
+
totalCount
|
|
497
|
+
}
|
|
332
498
|
}
|
|
333
499
|
}
|
|
334
500
|
}
|
|
@@ -336,3 +502,76 @@ const loadSingleCommitAssociatedPRs = `#graphql
|
|
|
336
502
|
}
|
|
337
503
|
}
|
|
338
504
|
`;
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Build associatedPRs or RelatedIssues object (into issue-like object with `pull_request` property) from the GraphQL repository response
|
|
508
|
+
* @param {object} responseNodes
|
|
509
|
+
* @param {"ISSUE" | "PR"} type
|
|
510
|
+
* @returns {object[]}
|
|
511
|
+
*/
|
|
512
|
+
function buildIssuesOrPRsFromResponseNode(responseNodes, type = "ISSUE") {
|
|
513
|
+
const resultArray = [];
|
|
514
|
+
for (const node of responseNodes) {
|
|
515
|
+
let baseProps = {
|
|
516
|
+
number: node.number,
|
|
517
|
+
title: node.title,
|
|
518
|
+
body: node.body,
|
|
519
|
+
labels: node.labels?.nodes.map((label) => label.name),
|
|
520
|
+
html_url: node.url,
|
|
521
|
+
created_at: node.createdAt,
|
|
522
|
+
updated_at: node.updatedAt,
|
|
523
|
+
user: {
|
|
524
|
+
login: node.author?.login,
|
|
525
|
+
html_url: node.author?.url,
|
|
526
|
+
avatar_url: node.author?.avatarUrl,
|
|
527
|
+
type: node.author?.__typename,
|
|
528
|
+
},
|
|
529
|
+
comments: node.comments?.totalCount,
|
|
530
|
+
state: node.state,
|
|
531
|
+
milestone: node.milestone
|
|
532
|
+
? {
|
|
533
|
+
url: node.milestone.url,
|
|
534
|
+
id: node.milestone.id,
|
|
535
|
+
number: node.milestone.number,
|
|
536
|
+
state: node.milestone.state,
|
|
537
|
+
title: node.milestone.title,
|
|
538
|
+
description: node.milestone.description,
|
|
539
|
+
creator: {
|
|
540
|
+
login: node.milestone.creator.login,
|
|
541
|
+
html_url: node.milestone.creator.url,
|
|
542
|
+
avatar_url: node.milestone.creator.avatarUrl,
|
|
543
|
+
},
|
|
544
|
+
created_at: node.milestone.createdAt,
|
|
545
|
+
closed_at: node.milestone.closedAt,
|
|
546
|
+
updated_at: node.milestone.updatedAt,
|
|
547
|
+
}
|
|
548
|
+
: null,
|
|
549
|
+
locked: node.locked,
|
|
550
|
+
active_lock_reason: node.activeLockReason,
|
|
551
|
+
closed_at: node.closedAt,
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
let result = baseProps;
|
|
555
|
+
|
|
556
|
+
if (type === "PR") {
|
|
557
|
+
const prProps = {
|
|
558
|
+
pull_request: true,
|
|
559
|
+
mergeable: node.mergeable,
|
|
560
|
+
rebaseable: node.canBeRebased,
|
|
561
|
+
changed_files: node.changedFiles,
|
|
562
|
+
commits: node.commits?.totalCount,
|
|
563
|
+
merged_at: node.mergedAt,
|
|
564
|
+
draft: node.isDraft,
|
|
565
|
+
merged_by: {
|
|
566
|
+
login: node.mergedBy?.login,
|
|
567
|
+
avatar_url: node.mergedBy?.avatarUrl,
|
|
568
|
+
html_url: node.mergedBy?.url,
|
|
569
|
+
},
|
|
570
|
+
};
|
|
571
|
+
result = merge(baseProps, prProps);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
resultArray.push(result);
|
|
575
|
+
}
|
|
576
|
+
return resultArray;
|
|
577
|
+
}
|
package/lib/verify.js
CHANGED
|
@@ -38,8 +38,10 @@ const VALIDATORS = {
|
|
|
38
38
|
(isPlainObject(asset) && isStringOrStringArray(asset.path)),
|
|
39
39
|
),
|
|
40
40
|
successComment: canBeDisabled(isNonEmptyString),
|
|
41
|
+
successCommentCondition: canBeDisabled(isNonEmptyString),
|
|
41
42
|
failTitle: canBeDisabled(isNonEmptyString),
|
|
42
43
|
failComment: canBeDisabled(isNonEmptyString),
|
|
44
|
+
failCommentCondition: canBeDisabled(isNonEmptyString),
|
|
43
45
|
labels: canBeDisabled(isArrayOf(isNonEmptyString)),
|
|
44
46
|
assignees: isArrayOf(isNonEmptyString),
|
|
45
47
|
releasedLabels: canBeDisabled(isArrayOf(isNonEmptyString)),
|
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": "10.
|
|
4
|
+
"version": "10.3.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Pierre Vanduynslager (https://twitter.com/@pvdlg_)",
|
|
7
7
|
"ava": {
|