Skip to content

Commit f4c37bb

Browse files
Add --template-mode to create-cloudflare (#8708)
* Make default template-mode undefined Co-authored-by: Aaron Herres <[email protected]> * Pass template-mode to degit as mode Co-authored-by: Aaron Herres <[email protected]> * Update wording in args help output Co-authored-by: Aaron Herres <[email protected]> * Add changeset, define our change as a minor bump Co-authored-by: Aaron Herres <[email protected]> --------- Co-authored-by: Aaron Herres <[email protected]>
1 parent 511be3d commit f4c37bb

File tree

6 files changed

+80
-2
lines changed

6 files changed

+80
-2
lines changed

.changeset/solid-needles-deny.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"create-cloudflare": minor
3+
---
4+
5+
Add --template-mode argument to create-cloudflare to support templating from private repositories
6+
7+
create-cloudflare uses degit under the hood to clone template git repositories. degit will attempt to download a tar file of the HEAD of a repository if it is served up on one of several allow listed repository hosting services including GitHub. However, the tar support does not support templating from private repositories. To support that, we needed to create the ability to tell degit to use "git" mode to download the template using the user's git credentials.

packages/create-cloudflare/src/__tests__/templates.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,32 @@ describe("downloadRemoteTemplate", () => {
279279

280280
expect(spinner).not.toBeCalled();
281281
});
282+
283+
test("should call degit with a mode of undefined if not specified", async () => {
284+
const mock = mockDegit();
285+
286+
await downloadRemoteTemplate("cloudflare/workers-sdk");
287+
288+
expect(mock).toBeCalledWith("cloudflare/workers-sdk", {
289+
cache: false,
290+
verbose: false,
291+
force: true,
292+
mode: undefined,
293+
});
294+
});
295+
296+
test("should call degit with a mode of 'git' if specified", async () => {
297+
const mock = mockDegit();
298+
299+
await downloadRemoteTemplate("cloudflare/workers-sdk", "git");
300+
301+
expect(mock).toBeCalledWith("cloudflare/workers-sdk", {
302+
cache: false,
303+
verbose: false,
304+
force: true,
305+
mode: "git",
306+
});
307+
});
282308
});
283309

284310
describe("deriveCorrelatedArgs", () => {

packages/create-cloudflare/src/helpers/__tests__/args.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,22 @@ describe("Cli", () => {
125125
expect.stringContaining(`Not enough arguments following: ${arg}`),
126126
);
127127
});
128+
129+
test("parsing template-mode correctly", async () => {
130+
const result = await parseArgs(["--template-mode", "git"]);
131+
132+
assert(result.type === "default");
133+
assert(result.args.templateMode === "git");
134+
});
135+
136+
test("template-mode correctly defaults to be undefined", async () => {
137+
const result = await parseArgs([
138+
"--template",
139+
"[email protected]:user/repo",
140+
]);
141+
142+
assert(result.type === "default");
143+
expect(result.args.templateMode).toBeUndefined();
144+
});
128145
});
129146
});

packages/create-cloudflare/src/helpers/args.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,29 @@ export const cliDefinition: ArgumentsDefinition = {
199199
npm create cloudflare -- --template https://github.com/cloudflare/workers-sdk/templates/worker-r2
200200
`,
201201
},
202+
{
203+
name: "template-mode",
204+
type: "string",
205+
requiresArg: true,
206+
description: `The mechanism to use when fetching the template.
207+
208+
Can be either "git" or "tar". "tar" does not support fetching from private
209+
repositories. By default, degit will use "tar" if the template is hosted on GitHub, BitBucket, GitLab, or git.sr.ht.
210+
Otherwise, it will use "git".
211+
`,
212+
values: [
213+
{
214+
name: "git",
215+
description:
216+
"Use git to fetch the template. Supports private repositories.",
217+
},
218+
{
219+
name: "tar",
220+
description:
221+
"Use tar to fetch the template. Only supported on public repositories hosted on GitHub, BitBucket, GitLab, or git.sr.ht.",
222+
},
223+
],
224+
},
202225
{
203226
name: "accept-defaults",
204227
alias: "y",

packages/create-cloudflare/src/templates.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ export const processRemoteTemplate = async (args: Partial<C3Args>) => {
685685
.replace("/tree/main/", "/");
686686
}
687687

688-
const path = await downloadRemoteTemplate(src);
688+
const path = await downloadRemoteTemplate(src, args.templateMode);
689689
const config = inferTemplateConfig(path);
690690

691691
validateTemplate(path, config);
@@ -772,7 +772,10 @@ const inferCopyFilesDefinition = (path: string): CopyFiles => {
772772
* For convenience, `owner/repo` is also accepted.
773773
* @returns A path to a temporary directory containing the downloaded template
774774
*/
775-
export const downloadRemoteTemplate = async (src: string) => {
775+
export const downloadRemoteTemplate = async (
776+
src: string,
777+
mode?: "git" | "tar",
778+
) => {
776779
// degit runs `git clone` internally which may prompt for credentials if required
777780
// Avoid using a `spinner()` during this operation -- use updateStatus instead.
778781

@@ -783,6 +786,7 @@ export const downloadRemoteTemplate = async (src: string) => {
783786
cache: false,
784787
verbose: false,
785788
force: true,
789+
mode,
786790
});
787791

788792
const tmpDir = await mkdtemp(join(tmpdir(), "c3-template"));

packages/create-cloudflare/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type C3Args = {
1717
lang?: string;
1818
existingScript?: string;
1919
template?: string;
20+
templateMode?: "tar" | "git";
2021
acceptDefaults?: boolean;
2122
wranglerDefaults?: boolean;
2223
additionalArgs?: string[];

0 commit comments

Comments
 (0)