Skip to content

Commit

Permalink
fix: provide clear error messages for create-remix errors (remix-run#…
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 authored and aaronpowell committed May 10, 2022
1 parent 3173271 commit 9ad9ea7
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 70 deletions.
82 changes: 82 additions & 0 deletions packages/remix-dev/__tests__/create-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,88 @@ describe("the create command", () => {
expect(output).toContain(getOptOutOfInstallMessage("pnpm exec remix init"));
process.env.npm_user_agent = originalUserAgent;
});

describe("errors", () => {
it("identifies when a github repo is not accessible (403)", async () => {
let projectDir = await getProjectDir("repo");
await expect(() =>
run([
"create",
projectDir,
"--template",
"error-username/403",
"--no-install",
"--typescript",
])
).rejects.toMatchInlineSnapshot(
`[Error: 🚨 The template could not be verified because you do not have access to the repository. Please double check the access rights of this repo and try again.]`
);
});

it("identifies when a github repo does not exist (404)", async () => {
let projectDir = await getProjectDir("repo");
await expect(() =>
run([
"create",
projectDir,
"--template",
"error-username/404",
"--no-install",
"--typescript",
])
).rejects.toMatchInlineSnapshot(
`[Error: 🚨 The template could not be verified. Please double check that the template is a valid GitHub repository and try again.]`
);
});

it("identifies when something unknown goes wrong with the repo request (4xx)", async () => {
let projectDir = await getProjectDir("repo");
await expect(() =>
run([
"create",
projectDir,
"--template",
"error-username/400",
"--no-install",
"--typescript",
])
).rejects.toMatchInlineSnapshot(
`[Error: 🚨 The template could not be verified. The server returned a response with a 400 status. Please double check that the template is a valid GitHub repository and try again.]`
);
});

it("identifies when a remote tarball does not exist (404)", async () => {
let projectDir = await getProjectDir("remote-tarball");
await expect(() =>
run([
"create",
projectDir,
"--template",
"https://example.com/error/404/remix-stack.tar.gz",
"--no-install",
"--typescript",
])
).rejects.toMatchInlineSnapshot(
`[Error: 🚨 The template file could not be verified. Please double check the URL and try again.]`
);
});

it("identifies when a remote tarball does not exist (4xx)", async () => {
let projectDir = await getProjectDir("remote-tarball");
await expect(() =>
run([
"create",
projectDir,
"--template",
"https://example.com/error/400/remix-stack.tar.gz",
"--no-install",
"--typescript",
])
).rejects.toMatchInlineSnapshot(
`[Error: 🚨 The template file could not be verified. The server returned a response with a 400 status. Please double check the URL and try again.]`
);
});
});
});

function getSuccessMessage(projectDirectory: string) {
Expand Down
6 changes: 6 additions & 0 deletions packages/remix-dev/__tests__/github-mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ let githubHandlers: Array<RequestHandler> = [
return res(ctx.status(200));
}
),
rest.head(
`https://github.com/error-username/:status`,
async (req, res, ctx) => {
return res(ctx.status(Number(req.params.status)));
}
),
rest.head(`https://github.com/:owner/:repo`, async (req, res, ctx) => {
return res(ctx.status(200));
}),
Expand Down
6 changes: 6 additions & 0 deletions packages/remix-dev/__tests__/msw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { githubHandlers } from "./github-mocks";
type RequestHandler = Parameters<typeof setupServer>[0];

let miscHandlers: Array<RequestHandler> = [
rest.head(
"https://example.com/error/:status/remix-stack.tar.gz",
async (req, res, ctx) => {
return res(ctx.status(Number(req.params.status)));
}
),
rest.head("https://example.com/remix-stack.tar.gz", async (req, res, ctx) => {
return res(ctx.status(200));
}),
Expand Down
146 changes: 76 additions & 70 deletions packages/remix-dev/cli/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -502,69 +502,73 @@ export async function validateTemplate(input: string) {
}
case "remoteTarball": {
let spinner = ora("Validating the template file…").start();
let response;
try {
let response = await fetch(input, { method: "HEAD" });
spinner.stop();
switch (response.status) {
case 200:
return;
case 404:
throw Error(
"🚨 The template file could not be verified. Please double check " +
"the URL and try again."
);
default:
throw Error(
"🚨 The template file could not be verified. The server returned " +
`a response with a ${response.status} status. Please double ` +
"check the URL and try again."
);
}
} catch (err) {
spinner.stop();
response = await fetch(input, { method: "HEAD" });
} catch (_) {
throw Error(
"🚨 There was a problem verifying the template file. Please ensure " +
"you are connected to the internet and try again later."
);
} finally {
spinner.stop();
}

switch (response.status) {
case 200:
return;
case 404:
throw Error(
"🚨 The template file could not be verified. Please double check " +
"the URL and try again."
);
default:
throw Error(
"🚨 The template file could not be verified. The server returned " +
`a response with a ${response.status} status. Please double ` +
"check the URL and try again."
);
}
}
case "repo": {
let spinner = ora("Validating the template repo…").start();
let { url, filePath } = getRepoInfo(input);
let response;
try {
let response = await fetch(url, { method: "HEAD" });
spinner.stop();
switch (response.status) {
case 200:
return;
case 403:
throw Error(
"🚨 The template could not be verified because you do not have " +
"access to the repository. Please double check the access " +
"rights of this repo and try again."
);
case 404:
throw Error(
"🚨 The template could not be verified. Please double check that " +
"the template is a valid GitHub repository" +
(filePath && filePath !== "/"
? " and that the filepath points to a directory in the repo"
: "") +
" and try again."
);
default:
throw Error(
"🚨 The template could not be verified. The server returned a " +
`response with a ${response.status} status. Please double check ` +
"that the template is a valid GitHub repository and try again."
);
}
response = await fetch(url, { method: "HEAD" });
} catch (_) {
spinner.stop();
throw Error(
"🚨 There was a problem verifying the template. Please ensure you " +
"🚨 There was a problem fetching the template. Please ensure you " +
"are connected to the internet and try again later."
);
} finally {
spinner.stop();
}

switch (response.status) {
case 200:
return;
case 403:
throw Error(
"🚨 The template could not be verified because you do not have " +
"access to the repository. Please double check the access " +
"rights of this repo and try again."
);
case 404:
throw Error(
"🚨 The template could not be verified. Please double check that " +
"the template is a valid GitHub repository" +
(filePath && filePath !== "/"
? " and that the filepath points to a directory in the repo"
: "") +
" and try again."
);
default:
throw Error(
"🚨 The template could not be verified. The server returned a " +
`response with a ${response.status} status. Please double check ` +
"that the template is a valid GitHub repository and try again."
);
}
}
case "example":
Expand All @@ -576,34 +580,36 @@ export async function validateTemplate(input: string) {
}
let typeDir = templateType + "s";
let templateUrl = `https://github.com/remix-run/remix/tree/main/${typeDir}/${name}`;
let response;
try {
let response = await fetch(templateUrl, { method: "HEAD" });
spinner.stop();
switch (response.status) {
case 200:
return;
case 404:
throw Error(
"🚨 The template could not be verified. Please double check that " +
"the template is a valid project directory in " +
`https://github.com/remix-run/remix/tree/main/${typeDir} and ` +
"try again."
);
default:
throw Error(
"🚨 The template could not be verified. The server returned a " +
`response with a ${response.status} status. Please double ` +
"check that the template is a valid project directory in " +
`https://github.com/remix-run/remix/tree/main/${typeDir} and ` +
"try again."
);
}
response = await fetch(templateUrl, { method: "HEAD" });
} catch (_) {
spinner.stop();
throw Error(
"🚨 There was a problem verifying the template. Please ensure you are " +
"connected to the internet and try again later."
);
} finally {
spinner.stop();
}

switch (response.status) {
case 200:
return;
case 404:
throw Error(
"🚨 The template could not be verified. Please double check that " +
"the template is a valid project directory in " +
`https://github.com/remix-run/remix/tree/main/${typeDir} and ` +
"try again."
);
default:
throw Error(
"🚨 The template could not be verified. The server returned a " +
`response with a ${response.status} status. Please double ` +
"check that the template is a valid project directory in " +
`https://github.com/remix-run/remix/tree/main/${typeDir} and ` +
"try again."
);
}
}
}
Expand Down

0 comments on commit 9ad9ea7

Please sign in to comment.