Skip to content

Commit 24ea2ee

Browse files
jedwards1211babblebey
andauthoredAug 14, 2024··
fix: compare only <owner>/<repo> when checking for rename (#886)
* fix: ignore protocol mismatch when checking if repository is renamed * fix: compare repositoryUrl to git_url instead of clone_url * fix: include values of repositoryUrl and git_url in EMISMATCHGITHUBURL * chore: fix format * fix: fix git repo check and tests * test: fix mock git_urls * test: add EMISMATCHGITHUBURL tests * chore: format code * fix: mistake that would cause error if run in github action * test: remove comment about repeat calls * refactor: code cleanup * fix: check for rename even when authenticated as a GitHub App installation * test: test rename check for GitHub installation * fix: switch back to clone_url, test a lot of URL formats --------- Co-authored-by: Olabode Lawal-Shittabey <babblebey@gmail.com>
1 parent 4adf13d commit 24ea2ee

File tree

6 files changed

+502
-87
lines changed

6 files changed

+502
-87
lines changed
 

‎lib/definitions/errors.js

+13
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,19 @@ By default the \`repositoryUrl\` option is retrieved from the \`repository\` pro
139139
};
140140
}
141141

142+
export function EMISMATCHGITHUBURL({ repositoryUrl, clone_url }) {
143+
return {
144+
message: "The git repository URL mismatches the GitHub URL.",
145+
details: `The **semantic-release** \`repositoryUrl\` option must have the same repository name and owner as the GitHub repo.
146+
147+
Your configuration for the \`repositoryUrl\` option is \`${stringify(repositoryUrl)}\` and the \`clone_url\` of your GitHub repo is \`${stringify(clone_url)}\`.
148+
149+
By default the \`repositoryUrl\` option is retrieved from the \`repository\` property of your \`package.json\` or the [git origin url](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) of the repository cloned by your CI environment.
150+
151+
Note: If you have recently changed your GitHub repository name or owner, update the value in **semantic-release** \`repositoryUrl\` option and the \`repository\` property of your \`package.json\` respectively to match the new GitHub URL.`,
152+
};
153+
}
154+
142155
export function EINVALIDPROXY({ proxy }) {
143156
return {
144157
message: "Invalid `proxy` option.",

‎lib/verify.js

+17-18
Original file line numberDiff line numberDiff line change
@@ -103,35 +103,34 @@ export default async function verify(pluginConfig, context, { Octokit }) {
103103
proxy,
104104
}),
105105
);
106-
107-
// https://github.com/semantic-release/github/issues/182
108-
// Do not check for permissions in GitHub actions, as the provided token is an installation access token.
109-
// octokit.request("GET /repos/{owner}/{repo}", {repo, owner}) does not return the "permissions" key in that case.
110-
// But GitHub Actions have all permissions required for @semantic-release/github to work
111-
if (env.GITHUB_ACTION) {
112-
return;
113-
}
114-
115106
try {
116107
const {
117-
data: {
118-
permissions: { push },
119-
},
108+
data: { permissions, clone_url },
120109
} = await octokit.request("GET /repos/{owner}/{repo}", { repo, owner });
121-
if (!push) {
110+
// Verify if Repository Name wasn't changed
111+
const parsedCloneUrl = parseGithubUrl(clone_url);
112+
if (owner !== parsedCloneUrl.owner || repo !== parsedCloneUrl.repo) {
113+
errors.push(
114+
getError("EMISMATCHGITHUBURL", { repositoryUrl, clone_url }),
115+
);
116+
}
117+
118+
// https://github.com/semantic-release/github/issues/182
119+
// Do not check for permissions in GitHub actions, as the provided token is an installation access token.
120+
// octokit.request("GET /repos/{owner}/{repo}", {repo, owner}) does not return the "permissions" key in that case.
121+
// But GitHub Actions have all permissions required for @semantic-release/github to work
122+
if (!env.GITHUB_ACTION && !permissions?.push) {
122123
// If authenticated as GitHub App installation, `push` will always be false.
123124
// We send another request to check if current authentication is an installation.
124125
// Note: we cannot check if the installation has all required permissions, it's
125126
// up to the user to make sure it has
126127
if (
127-
await octokit
128+
!(await octokit
128129
.request("HEAD /installation/repositories", { per_page: 1 })
129-
.catch(() => false)
130+
.catch(() => false))
130131
) {
131-
return;
132+
errors.push(getError("EGHNOPERMISSION", { owner, repo }));
132133
}
133-
134-
errors.push(getError("EGHNOPERMISSION", { owner, repo }));
135134
}
136135
} catch (error) {
137136
if (error.status === 401) {

‎test/fail.test.js

+4
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ test("Open a new issue with the list of errors and custom title and comment", as
115115
.sandbox()
116116
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
117117
full_name: `${owner}/${repo}`,
118+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
118119
})
119120
.getOnce(
120121
`https://api.github.local/search/issues?q=${encodeURIComponent(
@@ -182,6 +183,7 @@ test("Open a new issue with assignees and the list of errors", async (t) => {
182183
.sandbox()
183184
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
184185
full_name: `${owner}/${repo}`,
186+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
185187
})
186188
.getOnce(
187189
`https://api.github.local/search/issues?q=${encodeURIComponent(
@@ -254,6 +256,7 @@ test("Open a new issue without labels and the list of errors", async (t) => {
254256
.sandbox()
255257
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
256258
full_name: `${owner}/${repo}`,
259+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
257260
})
258261
.getOnce(
259262
`https://api.github.local/search/issues?q=${encodeURIComponent(
@@ -330,6 +333,7 @@ test("Update the first existing issue with the list of errors", async (t) => {
330333
.sandbox()
331334
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
332335
full_name: `${owner}/${repo}`,
336+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
333337
})
334338
.getOnce(
335339
`https://api.github.local/search/issues?q=${encodeURIComponent(

‎test/integration.test.js

+31-11
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ test("Verify GitHub auth", async (t) => {
2727
const fetch = fetchMock
2828
.sandbox()
2929
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
30-
permissions: { push: true },
30+
permissions: {
31+
push: true,
32+
},
33+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
3134
});
3235

3336
await t.notThrowsAsync(
@@ -56,8 +59,11 @@ test("Verify GitHub auth with publish options", async (t) => {
5659
};
5760
const fetch = fetchMock
5861
.sandbox()
59-
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
60-
permissions: { push: true },
62+
.get(`https://api.github.local/repos/${owner}/${repo}`, {
63+
permissions: {
64+
push: true,
65+
},
66+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
6167
});
6268

6369
await t.notThrowsAsync(
@@ -94,7 +100,10 @@ test("Verify GitHub auth and assets config", async (t) => {
94100
const fetch = fetchMock
95101
.sandbox()
96102
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
97-
permissions: { push: true },
103+
permissions: {
104+
push: true,
105+
},
106+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
98107
});
99108

100109
await t.notThrowsAsync(
@@ -197,7 +206,10 @@ test("Publish a release with an array of assets", async (t) => {
197206
const fetch = fetchMock
198207
.sandbox()
199208
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
200-
permissions: { push: true },
209+
permissions: {
210+
push: true,
211+
},
212+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
201213
})
202214
.postOnce(
203215
`https://api.github.local/repos/${owner}/${repo}/releases`,
@@ -289,7 +301,10 @@ test("Publish a release with release information in assets", async (t) => {
289301
const fetch = fetchMock
290302
.sandbox()
291303
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
292-
permissions: { push: true },
304+
permissions: {
305+
push: true,
306+
},
307+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
293308
})
294309
.postOnce(
295310
`https://api.github.local/repos/${owner}/${repo}/releases`,
@@ -359,7 +374,10 @@ test("Update a release", async (t) => {
359374
const fetch = fetchMock
360375
.sandbox()
361376
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
362-
permissions: { push: true },
377+
permissions: {
378+
push: true,
379+
},
380+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
363381
})
364382
.getOnce(
365383
`https://api.github.local/repos/${owner}/${repo}/releases/tags/${nextRelease.gitTag}`,
@@ -426,9 +444,9 @@ test("Comment and add labels on PR included in the releases", async (t) => {
426444
{
427445
permissions: { push: true },
428446
full_name: `${owner}/${repo}`,
447+
clone_url: `htttps://api.github.local/${owner}/${repo}.git`,
429448
},
430449
{
431-
// TODO: why do we call the same endpoint twice?
432450
repeat: 2,
433451
},
434452
)
@@ -529,10 +547,9 @@ test("Open a new issue with the list of errors", async (t) => {
529547
{
530548
permissions: { push: true },
531549
full_name: `${owner}/${repo}`,
550+
clone_url: `htttps://api.github.local/${owner}/${repo}.git`,
532551
},
533-
{
534-
repeat: 2,
535-
},
552+
{ repeat: 2 },
536553
)
537554
.getOnce(
538555
`https://api.github.local/search/issues?q=${encodeURIComponent(
@@ -625,6 +642,7 @@ test("Verify, release and notify success", async (t) => {
625642
{
626643
permissions: { push: true },
627644
full_name: `${owner}/${repo}`,
645+
clone_url: `htttps://api.github.local/${owner}/${repo}.git`,
628646
},
629647
{
630648
repeat: 2,
@@ -785,6 +803,7 @@ test("Verify, update release and notify success", async (t) => {
785803
{
786804
permissions: { push: true },
787805
full_name: `${owner}/${repo}`,
806+
clone_url: `htttps://api.github.local/${owner}/${repo}.git`,
788807
},
789808
{
790809
repeat: 2,
@@ -917,6 +936,7 @@ test("Verify and notify failure", async (t) => {
917936
{
918937
permissions: { push: true },
919938
full_name: `${owner}/${repo}`,
939+
clone_url: `htttps://api.github.local/${owner}/${repo}.git`,
920940
},
921941
{
922942
repeat: 2,

‎test/success.test.js

+21
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ test("Add comment and labels to PRs associated with release commits and issues s
5757
.sandbox()
5858
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
5959
full_name: `${redirectedOwner}/${redirectedRepo}`,
60+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
6061
})
6162
.postOnce("https://api.github.local/graphql", {
6263
data: {
@@ -418,6 +419,7 @@ test("Make multiple search queries if necessary", async (t) => {
418419
.sandbox()
419420
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
420421
full_name: `${owner}/${repo}`,
422+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
421423
})
422424
.post("https://api.github.local/graphql", {
423425
data: {
@@ -662,6 +664,7 @@ test("Do not add comment and labels for unrelated PR returned by search (compare
662664
.sandbox()
663665
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
664666
full_name: `${owner}/${repo}`,
667+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
665668
})
666669
.postOnce("https://api.github.local/graphql", {
667670
data: {
@@ -764,6 +767,7 @@ test("Do not add comment and labels if no PR is associated with release commits"
764767
.sandbox()
765768
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
766769
full_name: `${owner}/${repo}`,
770+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
767771
})
768772
.postOnce("https://api.github.local/graphql", {
769773
data: {
@@ -826,6 +830,7 @@ test("Do not add comment and labels if no commits is found for release", async (
826830
.sandbox()
827831
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
828832
full_name: `${owner}/${repo}`,
833+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
829834
})
830835
.getOnce(
831836
`https://api.github.local/search/issues?q=${encodeURIComponent(
@@ -885,6 +890,7 @@ test("Do not add comment and labels to PR/issues from other repo", async (t) =>
885890
.sandbox()
886891
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
887892
full_name: `${owner}/${repo}`,
893+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
888894
})
889895
.postOnce("https://api.github.local/graphql", {
890896
data: {
@@ -985,6 +991,7 @@ test("Ignore missing and forbidden issues/PRs", async (t) => {
985991
.sandbox()
986992
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
987993
full_name: `${owner}/${repo}`,
994+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
988995
})
989996
.postOnce("https://api.github.local/graphql", {
990997
data: {
@@ -1154,6 +1161,7 @@ test("Add custom comment and labels", async (t) => {
11541161
.sandbox()
11551162
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
11561163
full_name: `${owner}/${repo}`,
1164+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
11571165
})
11581166
.postOnce("https://api.github.local/graphql", {
11591167
data: {
@@ -1249,6 +1257,7 @@ test("Add custom label", async (t) => {
12491257
.sandbox()
12501258
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
12511259
full_name: `${owner}/${repo}`,
1260+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
12521261
})
12531262
.postOnce("https://api.github.local/graphql", {
12541263
data: {
@@ -1339,6 +1348,7 @@ test("Comment on issue/PR without ading a label", async (t) => {
13391348
.sandbox()
13401349
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
13411350
full_name: `${owner}/${repo}`,
1351+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
13421352
})
13431353
.postOnce("https://api.github.local/graphql", {
13441354
data: {
@@ -1432,6 +1442,7 @@ test("Editing the release to include all release links at the bottom", async (t)
14321442
.sandbox()
14331443
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
14341444
full_name: `${owner}/${repo}`,
1445+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
14351446
})
14361447
.postOnce("https://api.github.local/graphql", {
14371448
data: {
@@ -1536,6 +1547,7 @@ test("Editing the release to include all release links at the top", async (t) =>
15361547
.sandbox()
15371548
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
15381549
full_name: `${owner}/${repo}`,
1550+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
15391551
})
15401552
.postOnce("https://api.github.local/graphql", {
15411553
data: {
@@ -1637,6 +1649,7 @@ test("Editing the release to include all release links with no additional releas
16371649
.sandbox()
16381650
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
16391651
full_name: `${owner}/${repo}`,
1652+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
16401653
})
16411654
.postOnce("https://api.github.local/graphql", {
16421655
data: {
@@ -1727,6 +1740,7 @@ test("Editing the release to include all release links with no additional releas
17271740
.sandbox()
17281741
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
17291742
full_name: `${owner}/${repo}`,
1743+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
17301744
})
17311745
.postOnce("https://api.github.local/graphql", {
17321746
data: {
@@ -1810,6 +1824,7 @@ test("Editing the release to include all release links with no releases", async
18101824
.sandbox()
18111825
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
18121826
full_name: `${owner}/${repo}`,
1827+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
18131828
})
18141829
.postOnce("https://api.github.local/graphql", {
18151830
data: {
@@ -1895,6 +1910,7 @@ test("Editing the release with no ID in the release", async (t) => {
18951910
.sandbox()
18961911
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
18971912
full_name: `${owner}/${repo}`,
1913+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
18981914
})
18991915
.postOnce("https://api.github.local/graphql", {
19001916
data: {
@@ -1985,6 +2001,7 @@ test("Ignore errors when adding comments and closing issues", async (t) => {
19852001
.sandbox()
19862002
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
19872003
full_name: `${owner}/${repo}`,
2004+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
19882005
})
19892006
.postOnce("https://api.github.local/graphql", {
19902007
data: {
@@ -2118,6 +2135,7 @@ test("Close open issues when a release is successful", async (t) => {
21182135
.sandbox()
21192136
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
21202137
full_name: `${owner}/${repo}`,
2138+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
21212139
})
21222140
.postOnce("https://api.github.local/graphql", {
21232141
data: {
@@ -2218,6 +2236,7 @@ test('Skip commention on issues/PR if "successComment" is "false"', async (t) =>
22182236
.sandbox()
22192237
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
22202238
full_name: `${owner}/${repo}`,
2239+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
22212240
})
22222241
.getOnce(
22232242
`https://api.github.local/search/issues?q=${encodeURIComponent(
@@ -2269,6 +2288,7 @@ test('Skip closing issues if "failComment" is "false"', async (t) => {
22692288
.sandbox()
22702289
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
22712290
full_name: `${owner}/${repo}`,
2291+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
22722292
})
22732293
.postOnce("https://api.github.local/graphql", {
22742294
data: {
@@ -2320,6 +2340,7 @@ test('Skip closing issues if "failTitle" is "false"', async (t) => {
23202340
.sandbox()
23212341
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
23222342
full_name: `${owner}/${repo}`,
2343+
clone_url: `https://api.github.local/${owner}/${repo}.git`,
23232344
})
23242345
.postOnce("https://api.github.local/graphql", {
23252346
data: {

‎test/verify.test.js

+416-58
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.