Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wrangler pages publish #790

Merged
merged 15 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hungry-pandas-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": patch
---

feature: Adds 'wrangler pages publish' (alias 'wrangler pages deployment create') command.
77 changes: 77 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion packages/wrangler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"cli"
],
"dependencies": {
"blake3-wasm": "^2.1.5",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you tell me why we use blake3-wasm here, and not xxhash which we already use for sites? If possible, I'd like to use xxhash everywhere, unless there's a reason I'm not aware of?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use Blake3 in Pages currently.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did come across a pure-JS implementation later on for something else, so we could swap that in, in place of the WASM, if you'd prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, so that hashes match what Pages already does internally. But since the projects published via API wouldn't be compared with "native" Pages projects, would the choice of hasher here matter? Just want to make sure we're intentional here with this choice, because changing later would invalidate all previous projects (if I'm understanding correctly)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a possible future where you can upload to an existing project, so yeah, we need to be consistent with how files are hashed today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aight, that's a good reason.

"esbuild": "0.14.34",
"miniflare": "2.4.0",
"path-to-regexp": "^6.2.0",
Expand Down Expand Up @@ -75,13 +76,15 @@
"ignore": "^5.2.0",
"ink": "^3.2.0",
"ink-select-input": "^4.2.1",
"ink-spinner": "^4.0.3",
"ink-table": "^3.0.0",
"ink-testing-library": "^2.1.0",
"ink-text-input": "^4.0.3",
"jest-fetch-mock": "^3.0.3",
"jest-websocket-mock": "^2.3.0",
"mime": "^3.0.0",
"open": "^8.4.0",
"pretty-bytes": "^6.0.0",
"prompts": "^2.4.2",
"react": "^17.0.2",
"react-error-boundary": "^3.1.4",
Expand Down Expand Up @@ -124,7 +127,7 @@
"testTimeout": 30000,
"testRegex": ".*.(test|spec)\\.[jt]sx?$",
"transformIgnorePatterns": [
"node_modules/(?!find-up|locate-path|p-locate|p-limit|yocto-queue|path-exists|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream|get-port|supports-color)"
"node_modules/(?!find-up|locate-path|p-locate|p-limit|yocto-queue|path-exists|execa|strip-final-newline|npm-run-path|path-key|onetime|mimic-fn|human-signals|is-stream|get-port|supports-color|pretty-bytes)"
],
"moduleNameMapper": {
"clipboardy": "<rootDir>/src/__tests__/helpers/clipboardy-mock.js",
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/scripts/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ async function run() {
external: [
"fsevents",
"esbuild",
"blake3-wasm",
"miniflare",
"@miniflare/core",
"selfsigned",
Expand Down
104 changes: 101 additions & 3 deletions packages/wrangler/src/__tests__/pages.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { writeFileSync } from "node:fs";
import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
import { mockConsoleMethods } from "./helpers/mock-console";
import { runInTempDir } from "./helpers/run-in-tmp";
import { runWrangler } from "./helpers/run-wrangler";
import type { Project, Deployment } from "../pages";
import type { File, FormData } from "undici";

describe("subcommand implicit help ran on incomplete command execution", () => {
describe("pages", () => {
runInTempDir();
const std = mockConsoleMethods();
function endEventLoop() {
Expand All @@ -25,6 +27,7 @@ describe("subcommand implicit help ran on incomplete command execution", () => {
wrangler pages dev [directory] [-- command] 🧑‍💻 Develop your full-stack Pages application locally
wrangler pages project ⚡️ Interact with your Pages projects
wrangler pages deployment 🚀 Interact with the deployments of a project
wrangler pages publish [directory] 🆙 Publish a directory of static assets as a Pages deployment

Flags:
-c, --config Path to .toml configuration file [string]
Expand All @@ -49,8 +52,6 @@ describe("subcommand implicit help ran on incomplete command execution", () => {
);
});

// Note that `wrangler pages functions` does nothing...

it("should display for pages:functions:build", async () => {
await expect(runWrangler("pages functions build")).rejects.toThrowError();

Expand All @@ -67,6 +68,7 @@ describe("subcommand implicit help ran on incomplete command execution", () => {
afterEach(() => {
unsetAllMocks();
});

function mockListRequest(projects: unknown[]) {
const requests = { count: 0 };
setMockResponse(
Expand Down Expand Up @@ -249,4 +251,100 @@ describe("subcommand implicit help ran on incomplete command execution", () => {
expect(requests.count).toBe(1);
});
});

describe("deployment create", () => {
let actualProcessEnvCI: string | undefined;

mockAccountId();
mockApiToken();
runInTempDir();

beforeEach(() => {
actualProcessEnvCI = process.env.CI;
process.env.CI = "true";
});

afterEach(() => {
unsetAllMocks();
process.env.CI = actualProcessEnvCI;
});

it("should be aliased with 'wrangler pages publish'", async () => {
await runWrangler("pages publish --help");
await endEventLoop();

expect(std.out).toMatchInlineSnapshot(`
"wrangler pages publish [directory]

🆙 Publish a directory of static assets as a Pages deployment

Positionals:
directory The directory of Pages Functions [string] [default: \\"functions\\"]

Flags:
-c, --config Path to .toml configuration file [string]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]
--legacy-env Use legacy environments [boolean]

Options:
--project The name of the project you want to list deployments for [string]
--branch The branch of the project you want to list deployments for [string]
--commit-hash The branch of the project you want to list deployments for [string]
--commit-message The branch of the project you want to list deployments for [string]
--commit-dirty The branch of the project you want to list deployments for [boolean]

🚧 'wrangler pages <command>' is a beta command. Please report any issues to https://github.com/cloudflare/wrangler2/issues/new/choose"
`);
});

it("should upload a directory of files", async () => {
writeFileSync("logo.png", "foobar");

setMockResponse(
"/accounts/:accountId/pages/projects/foo/file",
async ([_url, accountId], init) => {
expect(accountId).toEqual("some-account-id");
expect(init.method).toEqual("POST");
const body = init.body as FormData;
const logoPNGFile = body.get("file") as File;
expect(await logoPNGFile.text()).toEqual("foobar");
expect(logoPNGFile.name).toEqual("logo.png");

return {
id: "2082190357cfd3617ccfe04f340c6247d4b47484797840635feb491447bcd81c",
};
}
);

setMockResponse(
"/accounts/:accountId/pages/projects/foo/deployment",
async ([_url, accountId], init) => {
expect(accountId).toEqual("some-account-id");
expect(init.method).toEqual("POST");
const body = init.body as FormData;
const manifest = JSON.parse(body.get("manifest") as string);
expect(manifest).toMatchInlineSnapshot(`
Object {
"logo.png": "2082190357cfd3617ccfe04f340c6247d4b47484797840635feb491447bcd81c",
}
`);

return {
url: "https://abcxyz.foo.pages.dev/",
};
}
);

await runWrangler("pages publish . --project=foo");

// TODO: Unmounting somehow loses this output

// expect(std.out).toMatchInlineSnapshot(`
// "✨ Success! Uploaded 1 files (TIMINGS)

// ✨ Deployment complete! Take a peek over at https://abcxyz.foo.pages.dev/"
// `);
});
});
});
Loading