Skip to content

Commit

Permalink
Support a WRANGLER_C3_COMMAND env var to support C3 integration tes…
Browse files Browse the repository at this point in the history
…ting (#3461)

* [wrangler] test: ensure that mocks are cleared between tests

* chore: add additional known words to spelling dictionary

* [wrangler] test: mock console logs in traverse-module-graph tests

This avoids unwanted excess logging output during tests.

* [wrangler] test: allow the C3 command to be modified via an environment variable.

`WRANGLER_C3_COMMAND` can override the command used by `wrangler init` when delegating to C3.

By default this will use `create cloudflare@2`.
If you want to test the integration between wrangler and C3 locally, you can do the following:

```sh
# Ensure both Wrangler and C3 are built
npm run build
# Run the command from the Wrangler package directory
cd packages/wrangler
# Tell Wrangler to use the local version of create-cloudflare
WRANGLER_C3_COMMAND="run create-cloudflare" npx wrangler init temp
```

This makes use of the fact we have a monorepo and npm will delegate to the local
version of a package if possible.
Since the way `wrangler init` is written, it will always use `npm` (or equivalent) to run C3, rather than `npx` (or equivalent).
Therefore we have added a `create-cloudflare` script to the Wrangler `package.json` that will work with `npm run create-cloudflare`.
But that means that you must run the `npx wrangler init` command from the `wrangler` package directory.
  • Loading branch information
petebacondarwin authored Jun 14, 2023
1 parent 03133ee commit b0bbf69
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 20 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
"execa",
"haikunate",
"haikunator",
"httplogs",
"iarna",
"isolinear",
"keyvalue",
"logfwdr",
"middlewares",
"Miniflare",
"mockpm",
"mrbbot",
"outdir",
"outfile",
Expand All @@ -37,7 +40,8 @@
"weakset",
"webassemblymemory",
"websockets",
"xxhash"
"xxhash",
"zjcompt"
],
"cSpell.ignoreWords": [
"TESTTEXTBLOBNAME",
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"check:lint": "eslint .",
"check:type": "tsc",
"clean": "rimraf wrangler-dist miniflare-dist emitted-types",
"create-cloudflare": "create-cloudflare",
"dev": "npm run clean && concurrently -c black,blue --kill-others-on-fail false 'npm run bundle -- --watch' 'npm run check:type -- --watch --preserveWatchOutput'",
"emit-types": "tsc -p tsconfig.emit.json && node -r esbuild-register scripts/emit-types.ts",
"prepublishOnly": "SOURCEMAPS=false npm run build",
Expand Down
81 changes: 73 additions & 8 deletions packages/wrangler/src/__tests__/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,70 @@ describe("init", () => {
{ stdio: "inherit" }
);
});

describe("with custom C3 command", () => {
const ORIGINAL_ENV = process.env;

beforeEach(() => {
process.env = {
...ORIGINAL_ENV,
WRANGLER_C3_COMMAND: "run create-cloudflare",
};
});

afterEach(() => {
process.env = ORIGINAL_ENV;
});

test("shows deprecation message and delegates to C3", async () => {
await runWrangler("init");

checkFiles({
items: {
"./src/index.js": false,
"./src/index.ts": false,
"./tsconfig.json": false,
"./package.json": false,
"./wrangler.toml": false,
},
});

expect(std).toMatchInlineSnapshot(`
Object {
"debug": "",
"err": "",
"info": "",
"out": "Running \`mockpm run create-cloudflare\`...",
"warn": "▲ [WARNING] The \`init\` command is no longer supported. Please use \`mockpm run create-cloudflare\` instead.
The \`init\` command will be removed in a future version.
",
}
`);

expect(execa).toHaveBeenCalledWith(
"mockpm",
["run", "create-cloudflare"],
{
stdio: "inherit",
}
);
});

it("if `-y` is used, delegate to c3 with --wrangler-defaults", async () => {
await runWrangler("init -y");

expect(execa).toHaveBeenCalledWith(
"mockpm",
["run", "create-cloudflare", "--", "--wrangler-defaults"],
{ stdio: "inherit" }
);
});
});
});

describe("deprecated behaviour is retained with --no-delegate-c3", () => {
describe("deprecated behavior is retained with --no-delegate-c3", () => {
describe("options", () => {
it("should initialize with no interactive prompts if `--yes` is used", async () => {
await runWrangler("init --yes --no-delegate-c3");
Expand Down Expand Up @@ -2787,17 +2848,21 @@ describe("init", () => {
}
`);

expect(execa).toHaveBeenCalledTimes(1);
expect(execa).toHaveBeenCalledWith(
"mockpm",
["create", "cloudflare@2"],
[
"create",
"cloudflare@2",
"existing-memory-crystal",
"--",
"--type",
"pre-existing",
"--existing-script",
"existing-memory-crystal",
],
{ stdio: "inherit" }
);
expect(execa).toHaveBeenCalledWith("git", ["--version"]);
expect(execa).toHaveBeenCalledWith("git", [
"config",
"--get",
"init.defaultBranch",
]);
});

//TODO: Tests for a case when a worker name doesn't exist - JACOB & CASS
Expand Down
5 changes: 5 additions & 0 deletions packages/wrangler/src/__tests__/jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,8 @@ jest.mock("execa", () => {
}),
};
});

afterEach(() => {
// It is important that we clear mocks between tests to avoid leakage.
jest.clearAllMocks();
});
2 changes: 2 additions & 0 deletions packages/wrangler/src/__tests__/traverse-module-graph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { mkdir, writeFile } from "fs/promises";
import path from "path";
import dedent from "ts-dedent";
import traverseModuleGraph from "../traverse-module-graph";
import { mockConsoleMethods } from "./helpers/mock-console";
import { runInTempDir } from "./helpers/run-in-tmp";
import type { ConfigModuleRuleType } from "../config";

Expand All @@ -14,6 +15,7 @@ import type { ConfigModuleRuleType } from "../config";

describe("traverse module graph", () => {
runInTempDir();
mockConsoleMethods();

it("should not detect JS without module rules", async () => {
await writeFile(
Expand Down
17 changes: 9 additions & 8 deletions packages/wrangler/src/environment-variables/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ import { logger } from "../logger";

type VariableNames =
| "CLOUDFLARE_ACCOUNT_ID"
| "CLOUDFLARE_API_TOKEN"
| "CLOUDFLARE_API_BASE_URL"
| "CLOUDFLARE_API_KEY"
| "CLOUDFLARE_API_TOKEN"
| "CLOUDFLARE_EMAIL"
| "WRANGLER_SEND_METRICS"
| "CLOUDFLARE_API_BASE_URL"
| "WRANGLER_LOG"
| "NO_CONSTELLATION_WARNING"
| "WRANGLER_API_ENVIRONMENT"
| "WRANGLER_CLIENT_ID"
| "WRANGLER_AUTH_DOMAIN"
| "WRANGLER_AUTH_URL"
| "WRANGLER_TOKEN_URL"
| "WRANGLER_REVOKE_URL"
| "WRANGLER_C3_COMMAND"
| "WRANGLER_CF_AUTHORIZATION_TOKEN"
| "NO_CONSTELLATION_WARNING";
| "WRANGLER_CLIENT_ID"
| "WRANGLER_LOG"
| "WRANGLER_REVOKE_URL"
| "WRANGLER_SEND_METRICS"
| "WRANGLER_TOKEN_URL";

type DeprecatedNames =
| "CF_ACCOUNT_ID"
Expand Down
26 changes: 26 additions & 0 deletions packages/wrangler/src/environment-variables/misc-variables.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
import { getEnvironmentVariableFactory } from "./factory";

/**
* `WRANGLER_C3_COMMAND` can override the command used by `wrangler init` when delegating to C3.
*
* By default this will use `create cloudflare@2`.
* If you want to test the integration between wrangler and C3 locally, you can do the following:
*
* ```sh
* # Ensure both Wrangler and C3 are built
* npm run build
* # Run the command from the Wrangler package directory
* cd packages/wrangler
* # Tell Wrangler to use the local version of create-cloudflare
* WRANGLER_C3_COMMAND="run create-cloudflare" npx wrangler init temp
* ```
*
* This makes use of the fact we have a monorepo and npm will delegate to the local
* version of a package if possible.
* Since the way `wrangler init` is written, it will always use `npm` (or equivalent) to run C3, rather than `npx` (or equivalent).
* Therefore we have added a `create-cloudflare` script to the Wrangler `package.json` that will work with `npm run create-cloudflare`.
* But that means that you must run the `npx wrangler init` command from the `wrangler` package directory.
*/
export const getC3CommandFromEnv = getEnvironmentVariableFactory({
variableName: "WRANGLER_C3_COMMAND",
defaultValue: () => "create cloudflare@2",
});

/**
* `WRANGLER_SEND_METRICS` can override whether we attempt to send metrics information to Sparrow.
*/
Expand Down
6 changes: 3 additions & 3 deletions packages/wrangler/src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { fetchResult } from "./cfetch";
import { fetchDashboardScript } from "./cfetch/internal";
import { readConfig } from "./config";
import { confirm, select } from "./dialogs";
import { getC3CommandFromEnv } from "./environment-variables/misc-variables";
import { initializeGit, getGitVersioon, isInsideGitRepo } from "./git-client";
import { logger } from "./logger";
import { getPackageManager } from "./package-manager";
Expand Down Expand Up @@ -202,8 +203,7 @@ export async function initHandler(args: InitArgs) {
}

const c3Arguments = [
"create",
"cloudflare@2",
...getC3CommandFromEnv().split(" "),
fromDashScriptName,
"--",
"--type",
Expand Down Expand Up @@ -252,7 +252,7 @@ export async function initHandler(args: InitArgs) {
// if a wrangler.toml file does not exist (C3 expects to scaffold *new* projects)
// and if --from-dash is not set (C3 will run wrangler to communicate with the API)
if (!fromDashScriptName) {
const c3Arguments = ["create", "cloudflare@2"];
const c3Arguments = getC3CommandFromEnv().split(" ");

if (yesFlag) {
c3Arguments.push("--", "--wrangler-defaults");
Expand Down

0 comments on commit b0bbf69

Please sign in to comment.