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

feat: add support for publishing workers with r2 bucket bindings #452

Merged
merged 2 commits into from
Feb 13, 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
11 changes: 11 additions & 0 deletions .changeset/purple-planes-hug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"wrangler": patch
---

feat: add support for publishing workers with r2 bucket bindings

This change adds the ability to define bindings in your `wrangler.toml` file
for R2 buckets. These buckets will then be available in the environment
passed to the worker at runtime.

Closes #365
9 changes: 8 additions & 1 deletion packages/wrangler/src/__tests__/dev.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ function renderDev({
initialMode = "local",
jsxFactory,
jsxFragment,
bindings = {},
bindings = {
kv_namespaces: [],
vars: {},
durable_objects: { bindings: [] },
r2_buckets: [],
wasm_modules: {},
unsafe: [],
},
public: publicDir,
assetPaths,
compatibilityDate,
Expand Down
29 changes: 29 additions & 0 deletions packages/wrangler/src/__tests__/publish.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,35 @@ export default{
});
});

describe("r2 bucket bindings", () => {
it("should support r2 bucket bindings", async () => {
writeWranglerToml({
r2_buckets: [{ binding: "FOO", bucket_name: "foo-bucket" }],
});
writeWorkerSource();
mockSubDomainRequest();
mockUploadWorkerRequest({
expectedBindings: [
{ bucket_name: "foo-bucket", name: "FOO", type: "r2_bucket" },
],
});

await runWrangler("publish index.js");
expect(std.out).toMatchInlineSnapshot(`
"Uploaded
test-name
(TIMINGS)
Deployed
test-name
(TIMINGS)

test-name.test-sub-domain.workers.dev"
`);
expect(std.err).toMatchInlineSnapshot(`""`);
expect(std.warn).toMatchInlineSnapshot(`""`);
});
});

describe("unsafe bindings", () => {
it("should warn if using unsafe bindings", async () => {
writeWranglerToml({
Expand Down
9 changes: 9 additions & 0 deletions packages/wrangler/src/api/form_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface WorkerMetadata {
class_name: string;
script_name?: string;
}
| { type: "r2_bucket"; name: string; bucket_name: string }
)[];
}

Expand Down Expand Up @@ -82,6 +83,14 @@ export function toFormData(worker: CfWorkerInit): FormData {
}
);

bindings.r2_buckets?.forEach(({ binding, bucket_name }) => {
metadataBindings.push({
name: binding,
type: "r2_bucket",
bucket_name,
});
});

Object.entries(bindings.vars || {})?.forEach(([key, value]) => {
if (typeof value === "string") {
metadataBindings.push({ name: key, type: "plain_text", text: value });
Expand Down
16 changes: 11 additions & 5 deletions packages/wrangler/src/api/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ interface CfDurableObject {
script_name?: string;
}

interface CfR2Bucket {
binding: string;
bucket_name: string;
}

interface CfUnsafeBinding {
name: string;
type: string;
Expand Down Expand Up @@ -134,11 +139,12 @@ export interface CfWorkerInit {
* All the bindings
*/
bindings: {
vars?: CfVars;
kv_namespaces?: CfKvNamespace[];
wasm_modules?: CfWasmModuleBindings;
durable_objects?: { bindings: CfDurableObject[] };
unsafe?: CfUnsafeBinding[];
vars: CfVars | undefined;
kv_namespaces: CfKvNamespace[] | undefined;
wasm_modules: CfWasmModuleBindings | undefined;
durable_objects: { bindings: CfDurableObject[] } | undefined;
r2_buckets: CfR2Bucket[] | undefined;
unsafe: CfUnsafeBinding[] | undefined;
};
migrations: undefined | CfDurableObjectMigrations;
compatibility_date: string | undefined;
Expand Down
37 changes: 36 additions & 1 deletion packages/wrangler/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,15 @@ export type Config = {
preview_id?: string;
}[];

r2_buckets?: {
/** The binding name used to refer to the R2 bucket in the worker. */
binding: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

really dislike "binding" bah. I'll make some noise about it later.

/** The name of this R2 bucket at the edge. */
bucket_name: string;
/** The preview name of this R2 bucket at the edge. */
preview_bucket_name?: string;
}[];

/**
* A list of services that your worker should be bound to.
* NB: these are not inherited, and HAVE to be duplicated across all environments.
Expand Down Expand Up @@ -570,7 +579,7 @@ export function normaliseAndValidateEnvironmentsConfig(config: Config) {
}

// Warn if there is a "required" field in the top level config that has not been specified specified in the environment.
// These required fields are `vars`, `durable_objects`, and `kv_namespaces`.
// These required fields are `vars`, `durable_objects`, `kv_namespaces`, and "r2_buckets".
// Each of them has different characteristics that need to be checked.

// `vars` is just an object
Expand Down Expand Up @@ -645,5 +654,31 @@ export function normaliseAndValidateEnvironmentsConfig(config: Config) {
}
}
}

// `r2_buckets` contains an array of bucket bindings
if (config.r2_buckets !== undefined) {
if (environment.r2_buckets === undefined) {
console.warn(
`In your configuration, "r2_buckets" exists at the top level, but not on "env.${envKey}".\n` +
`This is not what you probably want, since "r2_buckets" is not inherited by environments.\n` +
`Please add "r2_buckets" to "env.${envKey}".`
);
} else {
const envBindings = new Set(
environment.r2_buckets.map((r2Bucket) => r2Bucket.binding)
);
for (const bindingName of config.r2_buckets.map(
(r2Bucket) => r2Bucket.binding
)) {
if (!envBindings.has(bindingName)) {
console.warn(
`In your configuration, there is a r2_buckets with binding "${bindingName}" at the top level, but not on "env.${envKey}".\n` +
`This is not what you probably want, since "r2_buckets" is not inherited by environments.\n` +
`Please add a binding for "${bindingName}" to "env.${envKey}.r2_buckets".`
);
}
}
}
}
}
}
8 changes: 6 additions & 2 deletions packages/wrangler/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ async function readConfig(configPath?: string): Promise<Config> {
// TODO: remove this error before GA.
if ("experimental_services" in config) {
throw new Error(
`The "experimental_services" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:
`The "experimental_services" field is no longer supported. Instead, use [[unsafe.bindings]] to enable experimental features. Add this to your wrangler.toml:

${TOML.stringify({
unsafe: {
bindings: (config.experimental_services || []).map((serviceDefinition) => {
Expand Down Expand Up @@ -811,6 +811,7 @@ export async function main(argv: string[]): Promise<void> {
vars: envRootObj.vars,
wasm_modules: config.wasm_modules,
durable_objects: envRootObj.durable_objects,
r2_buckets: envRootObj.r2_buckets,
unsafe: envRootObj.unsafe?.bindings,
}}
/>
Expand Down Expand Up @@ -1307,6 +1308,9 @@ export async function main(argv: string[]): Promise<void> {
kv_namespaces: [],
vars: {},
durable_objects: { bindings: [] },
r2_buckets: [],
wasm_modules: {},
unsafe: [],
},
modules: [],
migrations: undefined,
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export default async function publish(props: Props): Promise<void> {
vars: envRootObj.vars,
wasm_modules: config.wasm_modules,
durable_objects: envRootObj.durable_objects,
r2_buckets: envRootObj.r2_buckets,
unsafe: envRootObj.unsafe?.bindings,
};

Expand Down