Skip to content

Commit

Permalink
fix: failing release due to renamed repository (#878)
Browse files Browse the repository at this point in the history
This introduces an extra step in the plugin `verify` lifecycle which verifies that the `repositoryUrl` and/or project package.json's `repository` field matches the project's current GitHub URL. This throws an error `EMISMATCHGITHUBURL` which confirms mismatch and suggests a fix.
  • Loading branch information
babblebey authored Jul 25, 2024
1 parent c70cfbf commit 76fdaa3
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 92 deletions.
11 changes: 11 additions & 0 deletions lib/definitions/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ By default the \`repositoryUrl\` option is retrieved from the \`repository\` pro
};
}

export function EMISMATCHGITHUBURL() {
return {
message: "The git repository URL mismatches the GitHub URL.",
details: `The **semantic-release** \`repositoryUrl\` option must match your GitHub URL with the format \`<GitHub_or_GHE_URL>/<owner>/<repo>.git\`.
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.
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.`,
};
}

export function EINVALIDPROXY({ proxy }) {
return {
message: "Invalid `proxy` option.",
Expand Down
27 changes: 27 additions & 0 deletions lib/verify.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,33 @@ export default async function verify(pluginConfig, context, { Octokit }) {
}
}

// Verify if Repository Name wasn't changed
if (
owner &&
repo &&
githubToken &&
!errors.find(({ code }) => code === "EINVALIDPROXY") &&
!errors.find(({ code }) => code === "EMISSINGREPO")
) {
const octokit = new Octokit(
toOctokitOptions({
githubToken,
githubUrl,
githubApiPathPrefix,
githubApiUrl,
proxy,
}),
);

const {
status,
data: { clone_url },
} = await octokit.request("GET /repos/{owner}/{repo}", { owner, repo });
if (status !== 200 || repositoryUrl !== clone_url) {
errors.push(getError("EMISMATCHGITHUBURL"));
}
}

if (!githubToken) {
errors.push(getError("ENOGHTOKEN", { owner, repo }));
}
Expand Down
94 changes: 67 additions & 27 deletions test/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ test("Verify GitHub auth", async (t) => {
repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`,
};

const fetch = fetchMock
.sandbox()
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
const fetch = fetchMock.sandbox().get(
`https://api.github.local/repos/${owner}/${repo}`,
{
permissions: { push: true },
});
clone_url: `git+https://othertesturl.com/${owner}/${repo}.git`,
},
{
repeat: 2,
},
);

await t.notThrowsAsync(
t.context.m.verifyConditions(
Expand All @@ -54,11 +59,16 @@ test("Verify GitHub auth with publish options", async (t) => {
publish: { path: "@semantic-release/github" },
repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`,
};
const fetch = fetchMock
.sandbox()
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
const fetch = fetchMock.sandbox().get(
`https://api.github.local/repos/${owner}/${repo}`,
{
permissions: { push: true },
});
clone_url: `git+https://othertesturl.com/${owner}/${repo}.git`,
},
{
repeat: 2,
},
);

await t.notThrowsAsync(
t.context.m.verifyConditions(
Expand Down Expand Up @@ -91,11 +101,16 @@ test("Verify GitHub auth and assets config", async (t) => {
publish: [{ path: "@semantic-release/npm" }],
repositoryUrl: `git+https://othertesturl.com/${owner}/${repo}.git`,
};
const fetch = fetchMock
.sandbox()
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
const fetch = fetchMock.sandbox().get(
`https://api.github.local/repos/${owner}/${repo}`,
{
permissions: { push: true },
});
clone_url: `git+https://othertesturl.com/${owner}/${repo}.git`,
},
{
repeat: 2,
},
);

await t.notThrowsAsync(
t.context.m.verifyConditions(
Expand Down Expand Up @@ -196,9 +211,16 @@ test("Publish a release with an array of assets", async (t) => {

const fetch = fetchMock
.sandbox()
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
permissions: { push: true },
})
.get(
`https://api.github.local/repos/${owner}/${repo}`,
{
permissions: { push: true },
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
},
)
.postOnce(
`https://api.github.local/repos/${owner}/${repo}/releases`,
{ upload_url: uploadUrl, html_url: releaseUrl, id: releaseId },
Expand Down Expand Up @@ -288,9 +310,16 @@ test("Publish a release with release information in assets", async (t) => {

const fetch = fetchMock
.sandbox()
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
permissions: { push: true },
})
.get(
`https://api.github.local/repos/${owner}/${repo}`,
{
permissions: { push: true },
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
},
)
.postOnce(
`https://api.github.local/repos/${owner}/${repo}/releases`,
{ upload_url: uploadUrl, html_url: releaseUrl, id: releaseId },
Expand Down Expand Up @@ -358,9 +387,16 @@ test("Update a release", async (t) => {

const fetch = fetchMock
.sandbox()
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
permissions: { push: true },
})
.get(
`https://api.github.local/repos/${owner}/${repo}`,
{
permissions: { push: true },
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
},
)
.getOnce(
`https://api.github.local/repos/${owner}/${repo}/releases/tags/${nextRelease.gitTag}`,
{ id: releaseId },
Expand Down Expand Up @@ -426,10 +462,10 @@ test("Comment and add labels on PR included in the releases", async (t) => {
{
permissions: { push: true },
full_name: `${owner}/${repo}`,
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
// TODO: why do we call the same endpoint twice?
repeat: 2,
repeat: 3,
},
)
.postOnce("https://api.github.local/graphql", {
Expand Down Expand Up @@ -529,9 +565,10 @@ test("Open a new issue with the list of errors", async (t) => {
{
permissions: { push: true },
full_name: `${owner}/${repo}`,
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
repeat: 3,
},
)
.getOnce(
Expand Down Expand Up @@ -625,9 +662,10 @@ test("Verify, release and notify success", async (t) => {
{
permissions: { push: true },
full_name: `${owner}/${repo}`,
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
repeat: 3,
},
)
.postOnce(
Expand Down Expand Up @@ -785,9 +823,10 @@ test("Verify, update release and notify success", async (t) => {
{
permissions: { push: true },
full_name: `${owner}/${repo}`,
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
repeat: 3,
},
)
.getOnce(
Expand Down Expand Up @@ -917,9 +956,10 @@ test("Verify and notify failure", async (t) => {
{
permissions: { push: true },
full_name: `${owner}/${repo}`,
clone_url: `https://github.com/${owner}/${repo}.git`,
},
{
repeat: 2,
repeat: 3,
},
)
.getOnce(
Expand Down
Loading

0 comments on commit 76fdaa3

Please sign in to comment.