Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions .github/workflows/cloudflare-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
PREVIEW_URL: ${{ needs.preview-candidate.outputs.deployment-url }}
PREVIEW_NOTE: ${{ needs.preview-candidate.outputs.preview-note }}
RELEASE_PREFIX: ${{ fromJSON(needs.quality.outputs.deployment-policy).releasePrefix }}
Comment on lines 83 to 87
VERSION_ID: ${{ needs.preview-candidate.outputs.version-id }}
with:
Expand All @@ -96,6 +97,7 @@ jobs:
marker,
`### ${heading}`,
`- Preview: ${process.env.PREVIEW_URL}`,
...(process.env.PREVIEW_NOTE ? [`- Note: ${process.env.PREVIEW_NOTE}`] : []),
`- Cloudflare version: \`${process.env.VERSION_ID}\``,
`- Commit: \`${context.sha}\``,
].join('\n')
Expand Down
26 changes: 24 additions & 2 deletions .github/workflows/cloudflare-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ on:
value: ${{ jobs.version.outputs.version-id }}
deployment-url:
value: ${{ jobs.version.outputs.deployment-url }}
# Non-empty only when a preview produced no preview URL (Durable Object
# Workers never get one) and deployment-url fell back to the target.
preview-note:
value: ${{ jobs.version.outputs.preview-note }}
Comment on lines +48 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Sign this commit before merging

The raw object for c4996ee8cb5ef710a2adea3021817d04b9b174f4 contains no gpgsig header, so this proposed commit is unsigned and violates the repository's mandatory signing invariant. Recreate the commit with a valid signature before it is merged.

AGENTS.md reference: AGENTS.md:L52-L56

Useful? React with 👍 / 👎.


permissions:
contents: read
Expand All @@ -60,6 +64,7 @@ jobs:
outputs:
version-id: ${{ steps.metadata.outputs.version-id }}
deployment-url: ${{ steps.metadata.outputs.deployment-url }}
preview-note: ${{ steps.metadata.outputs.preview-note }}
defaults:
run:
working-directory: ${{ fromJSON(inputs.quality-policy).workingDirectory }}
Expand Down Expand Up @@ -237,21 +242,38 @@ jobs:
run: |
VERSION_ID=$(printf '%s' "$COMMAND_OUTPUT" | grep -oE '(Worker )?Version ID: +[a-f0-9-]+' | head -1 | grep -oE '[a-f0-9-]{8,}' || true)
PREVIEW_URL=$(printf '%s' "$COMMAND_OUTPUT" | grep -oE 'https://[^[:space:]]+\.workers\.dev[^[:space:]]*' | head -1 || true)
PREVIEW_NOTE=""
if [ "$OPERATION" = "preview" ]; then
DEPLOYMENT_URL="${PREVIEW_URL:-$ACTION_URL}"
if [ -z "$DEPLOYMENT_URL" ]; then
# Cloudflare does not issue preview URLs for Workers that
# implement a Durable Object, Containers included — the upload
# succeeded and the version exists at 0% traffic, there is just
# no URL that serves it. Fall back to the target URL so the
# GitHub Environment and the PR comment point somewhere real,
# and carry a note so nobody mistakes it for the preview.
DEPLOYMENT_URL="$TARGET_URL"
PREVIEW_NOTE="no preview URL: Cloudflare does not generate them for Durable Object Workers; the version is uploaded at 0% traffic and the URL above is the live target"
Comment on lines +255 to +256

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Propagate fallback notes to main-flow release notes

When a Durable Object consumer runs cloudflare-main.yml, both the single-topology deploy-candidate preview and the default preview-release job can take this fallback, but only cloudflare-pr.yml consumes preview-note. The create-releases step at lines 131-143 therefore records the live target URL as either “Candidate deployment” or “Release preview” without the warning, making the generated release notes claim that a 0%-traffic version is reachable there. Pass preview-note into create-releases and surface it or relabel the fallback URL.

AGENTS.md reference: AGENTS.md:L615-L628

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid attributing every missing URL to Durable Objects

A preview can lack a URL simply because the consumer has preview_urls disabled, even when its Worker has no Durable Objects. In that configuration this fallback still runs, but the PR comment and job summary falsely state that Cloudflare withheld the URL because this is a Durable Object Worker. Use a reason-neutral note unless the workflow can actually distinguish the Worker limitation from disabled preview URLs.

AGENTS.md reference: AGENTS.md:L620-L624

Useful? React with 👍 / 👎.

fi
else
DEPLOYMENT_URL="${TARGET_URL:-$ACTION_URL}"
fi
if [ -z "$VERSION_ID" ] || [ -z "$DEPLOYMENT_URL" ]; then
echo "::error::Cloudflare output did not contain version metadata"
exit 1
fi
echo "version-id=$VERSION_ID" >> "$GITHUB_OUTPUT"
echo "deployment-url=$DEPLOYMENT_URL" >> "$GITHUB_OUTPUT"
{
echo "version-id=$VERSION_ID"
echo "deployment-url=$DEPLOYMENT_URL"
echo "preview-note=$PREVIEW_NOTE"
} >> "$GITHUB_OUTPUT"
{
echo "### Cloudflare ${{ inputs.target }} ${{ inputs.operation }}"
echo "- Tag: \`${{ inputs.version-tag }}\`"
echo "- Version: \`$VERSION_ID\`"
echo "- URL: $DEPLOYMENT_URL"
if [ -n "$PREVIEW_NOTE" ]; then
echo "- Note: $PREVIEW_NOTE"
fi
echo "- Source: ${{ inputs.version-message }}"
} >> "$GITHUB_STEP_SUMMARY"
25 changes: 25 additions & 0 deletions tests/workflows.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,31 @@ test("Wrangler metadata arguments remain single tokens", () => {
);
});

test("preview metadata tolerates Workers without preview URLs", () => {
// Cloudflare never generates preview URLs for Workers that implement a
// Durable Object (Containers included) — `versions upload` succeeds with a
// Version ID and no URL. The metadata step must fall back to the target URL
// with an explanatory note instead of failing the preview, and the note must
// travel to the caller so cloudflare-pr.yml can surface it in the comment.
const source = fs.readFileSync(`${directory}/cloudflare-version.yml`, "utf8");
const workflow = parse(source);
const metadata = workflow.jobs.version.steps.find(
(step) => step.id === "metadata",
);
assert.match(metadata.run, /DEPLOYMENT_URL="\$TARGET_URL"/);
assert.match(metadata.run, /PREVIEW_NOTE=/);
assert.match(metadata.run, /Durable Object/);
assert.equal(
workflow.on.workflow_call.outputs["preview-note"].value,
"${{ jobs.version.outputs.preview-note }}",
);
const pr = parse(fs.readFileSync(`${directory}/cloudflare-pr.yml`, "utf8"));
const comment = pr.jobs["publish-preview"].steps.find(
(step) => step.env && step.env.PREVIEW_NOTE !== undefined,
);
assert.ok(comment, "PR comment step must receive the preview note");
});

test("Worker secrets are allowlisted, never forwarded wholesale", () => {
// toJSON(secrets) in the publish step contains every secret the caller
// inherited, the Cloudflare API token included. The allowlist is the entire
Expand Down