Skip to content

Commit 6bcfb3e

Browse files
committed
Almost done?
1 parent ca29c32 commit 6bcfb3e

3 files changed

Lines changed: 616 additions & 76 deletions

File tree

README.md

Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
# Wrangler Version Deploy Action with Metadata
2+
3+
Deploy Cloudflare Workers using Wrangler v4's Versions API while attaching rich, commit-aware metadata to each deployment.
4+
5+
This Action:
6+
7+
- Uses `wrangler versions upload` + `wrangler versions deploy` instead of plain `wrangler deploy`.
8+
- Lets you define custom deployment messages (and an optional tag string) using templates.
9+
- Exposes the Worker Version ID and deployment URL as outputs for downstream steps.
10+
- Is designed for workflows where you build in GitHub Actions and want clean, traceable deploys in Cloudflare.
11+
+
12+
+## When to use this instead of the official Cloudflare Action
13+
+
14+
+Use this Action when:
15+
+
16+
+- You want full control over how and where your Worker is built:
17+
+ - You build in GitHub Actions (pnpm, npm, turbo, etc.) and only need Wrangler for the final upload/deploy.
18+
+- You want rich, commit-aware metadata in Cloudflare:
19+
+ - You care about seeing branch, commit, actor, and custom messages in the Cloudflare Versions UI.
20+
+ - You want stable `version_id` outputs to link deploys back to code, PRs, or changelogs.
21+
+- You’re in a monorepo:
22+
+ - You only want to build and deploy when a specific app/package directory changes.
23+
+ - You want an Action that targets a specific `config` path and doesn’t assume a single-project repo.
24+
+- You prefer an explicit upload → deploy flow:
25+
+ - You want `wrangler versions upload` + `wrangler versions deploy <versionId>` semantics instead of a generic `wrangler deploy`.
26+
+
27+
+The official Cloudflare Actions are great if:
28+
+
29+
+- You want a quick, simple deploy with minimal control.
30+
+- You’re okay with less flexibility around build steps, metadata, and monorepo layouts.
31+
+
32+
+Use this Action if you need:
33+
+
34+
+- Monorepo-friendly behavior.
35+
+- Custom build pipelines.
36+
+- Strong, composable metadata around each deployment.
37+
38+
## Features
39+
40+
- Built for Wrangler v4 and Workers Versions.
41+
- Uploads a specific Worker Version and (by default) deploys that exact version.
42+
- Customizable deployment message via `message_template`.
43+
- Optional tag string via `tag_template` (exposed as output for your own use).
44+
- Outputs:
45+
- `version_id`: The Worker Version ID that was uploaded/deployed.
46+
- `deployment_url`: Best-effort deployment URL parsed from Wrangler output.
47+
- `message`: The final rendered message.
48+
- `tag`: The final rendered tag (if any).
49+
- `only_upload` mode when you want to upload a version and deploy it separately.
50+
51+
## How it works
52+
53+
Instead of calling:
54+
55+
- `wrangler deploy` (which does not accept rich message/tag metadata),
56+
57+
this Action performs:
58+
59+
1. Collect metadata from the GitHub Actions environment:
60+
- `owner`, `repo`
61+
- `ref`, `branch`
62+
- `sha`, `short_sha`
63+
- `actor`
64+
- `run_id`, `run_number`
65+
- `commit_message`, `short_commit_message`
66+
2. Compute the deployment message:
67+
- If `message_template` is provided, render it using the metadata.
68+
- Otherwise, generate a default:
69+
- `branch@sha6: first-line-of-commit-message` (truncated to 100 chars).
70+
3. Optionally compute a tag:
71+
- If `tag_template` is provided, render it using the same metadata.
72+
- By default, no tag is generated.
73+
- Note: this tag is not currently sent directly to Cloudflare; it’s exposed as an Action output for your own use.
74+
4. Run:
75+
- `wrangler versions upload --config <config> [upload_args...] --message="<message>"`
76+
5. Parse the Worker Version ID from the upload output.
77+
6. If `only_upload` is `false` (default):
78+
- Run:
79+
- `wrangler versions deploy <versionId> -y --config <config> [deploy_args...] --message="<message>"`
80+
- Best-effort parse the deployment URL from the deploy output.
81+
7. Expose:
82+
- `version_id`, `deployment_url`, `message`, and `tag` as outputs.
83+
84+
This upload-then-deploy flow is what enables meaningful messages to show up in Cloudflare’s deployment history.
85+
86+
## Requirements
87+
88+
You must:
89+
90+
- Use Wrangler v4 (Versions API support required).
91+
- Ensure `wrangler` is available in your GitHub Actions runner:
92+
- Example:
93+
- `pnpm dlx wrangler@4 --version`
94+
- or `npx wrangler@4 --version`
95+
- or add Wrangler v4 as a dev dependency and use it from PATH.
96+
- Provide a Cloudflare API token:
97+
- With appropriate permissions for your Worker.
98+
- Passed via `secrets` to the `api_token` input.
99+
- Provide the path to your Wrangler config file via the `config` input:
100+
- Example: `wrangler.toml`
101+
- Example: `dist/server/wrangler.json`
102+
- Run this Action from (or pointing at) the correct Worker project:
103+
- Use `config` and the args inputs to ensure Wrangler targets the right project and environment.
104+
105+
This Action does NOT:
106+
107+
- Build your project.
108+
- Infer your Wrangler config automatically.
109+
- Manage `account_id` for you (Wrangler should pick that up from config/env).
110+
111+
## Inputs
112+
113+
All inputs are strings (as per GitHub Actions) unless noted; booleans are passed as `"true"` / `"false"`.
114+
115+
- `api_token` (required)
116+
- Cloudflare API token.
117+
- Recommended: `secrets.CLOUDFLARE_API_TOKEN`.
118+
- Used to set `CLOUDFLARE_API_TOKEN` for the Wrangler commands.
119+
120+
- `config` (required)
121+
- Path to the Wrangler configuration file.
122+
- Passed as:
123+
- `--config <config>`
124+
- Applied to both:
125+
- `wrangler versions upload`
126+
- `wrangler versions deploy`
127+
128+
- `upload_args` (optional)
129+
- Extra arguments for:
130+
- `wrangler versions upload`
131+
- Do NOT include `--config` here; that comes from `config`.
132+
- Example:
133+
- `--env production`
134+
- Example command shape:
135+
- `wrangler versions upload --config <config> <upload_args...> --message="<message>"`
136+
137+
- `deploy_args` (optional)
138+
- Extra arguments for:
139+
- `wrangler versions deploy`
140+
- Do NOT include `--config` here; that comes from `config`.
141+
- Example:
142+
- `--env production`
143+
- Example command shape:
144+
- `wrangler versions deploy <versionId> -y --config <config> <deploy_args...> --message="<message>"`
145+
146+
- `message_template` (optional)
147+
- Template for the deployment message.
148+
- If not provided:
149+
- A default message based on branch, SHA, and commit message is used.
150+
- The same message is applied to both upload and deploy.
151+
- Supported placeholders:
152+
- `{{owner}}`
153+
- `{{repo}}`
154+
- `{{ref}}`
155+
- `{{branch}}`
156+
- `{{sha}}`
157+
- `{{short_sha}}`
158+
- `{{actor}}`
159+
- `{{run_id}}`
160+
- `{{run_number}}`
161+
- `{{commit_message}}`
162+
- `{{short_commit_message}}`
163+
- `{{deployment_url}}` (only meaningful when used with outputs / in later steps)
164+
- `{{version_id}}` (only meaningful when used with outputs / in later steps)
165+
166+
- `tag_template` (optional)
167+
- Template for a tag/label string derived from the same metadata.
168+
- If not provided:
169+
- No tag is generated (empty output).
170+
- Note:
171+
- Tags are NOT currently pushed directly into Cloudflare by this Action.
172+
- The rendered tag is available via the `tag` output for your own usage (e.g. PR comments, releases, logs).
173+
174+
- `only_upload` (optional, default: `"false"`)
175+
- `"false"` (default):
176+
- Full flow:
177+
- `wrangler versions upload ...`
178+
- Parse `version_id` (required).
179+
- `wrangler versions deploy <versionId> -y ...`
180+
- Best-effort parse `deployment_url`.
181+
- Fail if `version_id` cannot be parsed.
182+
- `"true"`:
183+
- Upload-only flow:
184+
- `wrangler versions upload ...`
185+
- Try to parse `version_id`:
186+
- If found → set `version_id` output.
187+
- If not found → log and still succeed.
188+
- Do NOT run `versions deploy`.
189+
- Useful if:
190+
- You deploy specific versions elsewhere, or want a manual approval step.
191+
192+
## Outputs
193+
194+
- `deployment_url`
195+
- Best-effort detected URL from `wrangler versions deploy` output.
196+
- Empty when `only_upload: "true"` or when no URL can be detected.
197+
198+
- `version_id`
199+
- Worker Version ID parsed from `wrangler versions upload` output.
200+
- Required for success when `only_upload: "false"`.
201+
- Optional when `only_upload: "true"`.
202+
203+
- `message`
204+
- The final rendered deployment message used for upload (and deploy, if applicable).
205+
206+
- `tag`
207+
- The final rendered tag string, if `tag_template` was provided.
208+
- Empty if no `tag_template` is set.
209+
210+
## Usage Examples
211+
212+
### Example 1: Upload + Deploy to Production
213+
214+
Use this when you:
215+
216+
- Build your Worker in CI.
217+
- Want to upload and immediately deploy with a descriptive message.
218+
219+
```yaml
220+
name: Deploy Worker (Production)
221+
222+
on:
223+
push:
224+
branches: [main]
225+
226+
jobs:
227+
deploy:
228+
runs-on: ubuntu-latest
229+
steps:
230+
- uses: actions/checkout@v4
231+
232+
# Build your worker here
233+
# - run: pnpm install
234+
# - run: pnpm build
235+
236+
# Ensure Wrangler v4 is available
237+
- run: pnpm dlx wrangler@4 --version
238+
239+
- name: Upload + deploy via Wrangler Versions with metadata
240+
id: cf_deploy
241+
uses: your-org/wrangler-version-deploy-action-with-metadata@v1
242+
with:
243+
api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
244+
config: "dist/server/wrangler.json"
245+
upload_args: "--env production"
246+
deploy_args: "--env production"
247+
message_template: "Deployed {{repo}}@{{short_sha}} to {{branch}} by {{actor}} (run {{run_number}})"
248+
249+
- name: Report deployment
250+
run: |
251+
echo "Version ID: ${{ steps.cf_deploy.outputs.version_id }}"
252+
echo "URL: ${{ steps.cf_deploy.outputs.deployment_url }}"
253+
echo "Message: ${{ steps.cf_deploy.outputs.message }}"
254+
echo "Tag: ${{ steps.cf_deploy.outputs.tag }}"
255+
```
256+
257+
### Example 2: Only Upload (Manual / External Deploy)
258+
259+
Use this when you:
260+
261+
- Want to create a version with metadata.
262+
- Plan to deploy that `version_id` from another workflow or system.
263+
264+
```yaml
265+
name: Upload Worker Version Only
266+
267+
on:
268+
workflow_dispatch:
269+
270+
jobs:
271+
upload-version:
272+
runs-on: ubuntu-latest
273+
steps:
274+
- uses: actions/checkout@v4
275+
- run: pnpm dlx wrangler@4 --version
276+
277+
- name: Upload Worker Version with metadata (no deploy)
278+
id: cf_upload
279+
uses: your-org/wrangler-version-deploy-action-with-metadata@v1
280+
with:
281+
api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
282+
config: "wrangler.toml"
283+
upload_args: "--env staging"
284+
only_upload: "true"
285+
message_template: "Staging candidate {{repo}}@{{short_sha}} on {{branch}} (run {{run_number}})"
286+
287+
- name: Use uploaded version ID
288+
run: |
289+
echo "Uploaded version: ${{ steps.cf_upload.outputs.version_id }}"
290+
```
291+
292+
### Example 3: Custom Templates and PR Comments
293+
294+
You can combine outputs with other Actions to post deployment info back to PRs:
295+
296+
```yaml
297+
- name: Deploy with metadata
298+
id: cf_deploy
299+
uses: your-org/wrangler-version-deploy-action-with-metadata@v1
300+
with:
301+
api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
302+
config: "wrangler.toml"
303+
upload_args: "--env preview"
304+
deploy_args: "--env preview"
305+
message_template: "[preview] {{repo}}@{{short_sha}} on {{branch}} by {{actor}}"
306+
tag_template: "preview-{{short_sha}}"
307+
308+
- name: Comment on PR with deployment info
309+
if: github.event_name == 'pull_request'
310+
uses: actions/github-script@v7
311+
with:
312+
script: |
313+
const url = "${{ steps.cf_deploy.outputs.deployment_url }}";
314+
const version = "${{ steps.cf_deploy.outputs.version_id }}";
315+
const msg = "${{ steps.cf_deploy.outputs.message }}";
316+
const tag = "${{ steps.cf_deploy.outputs.tag }}";
317+
github.rest.issues.createComment({
318+
...context.repo,
319+
issue_number: context.issue.number,
320+
body: [
321+
"🚀 Preview deployment created:",
322+
url && `- URL: ${url}`,
323+
version && `- Version: ${version}`,
324+
msg && `- Message: ${msg}`,
325+
tag && `- Tag: ${tag}`,
326+
].filter(Boolean).join("\n")
327+
});
328+
```
329+
+
330+
+### Example 4: Monorepo - Deploy Only When a Folder Changes
331+
+
332+
+In a monorepo, you often want to:
333+
+
334+
+- Only run builds/deploys when a specific app/package directory changes.
335+
+- Use a config file that lives within that directory.
336+
+
337+
+This example:
338+
+
339+
+- Triggers only when files under `apps/worker-app/` change.
340+
+- Uses the Wrangler config at `apps/worker-app/wrangler.toml`.
341+
+- Builds and deploys only that app.
342+
+
343+
+```yaml
344+
+name: Deploy Worker App (Monorepo)
345+
+
346+
+on:
347+
+ push:
348+
+ branches: [main]
349+
+ paths:
350+
+ - "apps/worker-app/**"
351+
+
352+
+jobs:
353+
+ deploy-worker-app:
354+
+ runs-on: ubuntu-latest
355+
+ defaults:
356+
+ run:
357+
+ working-directory: apps/worker-app
358+
+
359+
+ steps:
360+
+ - uses: actions/checkout@v4
361+
+
362+
+ # Install and build only this app
363+
+ # - run: pnpm install
364+
+ # - run: pnpm build
365+
+
366+
+ - run: pnpm dlx wrangler@4 --version
367+
+
368+
+ - name: Upload + deploy worker-app via Versions API with metadata
369+
+ id: cf_deploy
370+
+ uses: your-org/wrangler-version-deploy-action-with-metadata@v1
371+
+ with:
372+
+ api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
373+
+ config: "apps/worker-app/wrangler.toml"
374+
+ upload_args: "--env production"
375+
+ deploy_args: "--env production"
376+
+ message_template: "worker-app: {{repo}}@{{short_sha}} on {{branch}} (run {{run_number}})"
377+
+```
378+
379+
## Notes
380+
381+
- This Action focuses on being:
382+
- Explicit about config (`config` input).
383+
- Clear about which args go to upload vs deploy.
384+
- Purpose-built for Wrangler v4’s Versions API.
385+
- If Wrangler’s output format changes:
386+
- `deployment_url` parsing is best-effort.
387+
- `version_id` parsing is based on the standard `Worker Version ID:` line.
388+
- For GitHub Marketplace:
389+
- Reference it as `your-org/wrangler-version-deploy-action-with-metadata@v1`.
390+
- Keep a `v1` tag pointing at the latest stable release.
391+
392+
If you have real Wrangler output samples and want to harden the parsing further, you can refine this Action’s internals without changing the public interface described here.

0 commit comments

Comments
 (0)