Skip to content

fix(api): expose worker deployment version#2212

Open
riderx wants to merge 1 commit into
mainfrom
codex/expose-api-worker-version
Open

fix(api): expose worker deployment version#2212
riderx wants to merge 1 commit into
mainfrom
codex/expose-api-worker-version

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 11, 2026

Summary (AI generated)

  • Added Cloudflare Worker version metadata binding to the API Worker environments.
  • Exposed Cloudflare deployment metadata on API responses with X-Worker-Version-Id, X-Worker-Version-Tag, and X-Worker-Version-Timestamp headers while preserving X-Worker-Source.
  • Added unit coverage for worker source/version headers.

Motivation (AI generated)

  • Production served a stale API Worker while X-Worker-Source only showed the app release version, making the stale Cloudflare deployment hard to spot from responses.
  • Cloudflare version metadata gives us the exact runtime deployment ID for fast verification after deploys.

Business Impact (AI generated)

  • Reduces time to diagnose production API deployment mismatches and stale Worker rollouts.
  • Gives support and engineering a concrete deployment identifier in every API response without changing response bodies.

Test Plan (AI generated)

  • bunx vitest run tests/worker-source-header.unit.test.ts
  • bun lint
  • bun lint:backend
  • bunx eslint tests/worker-source-header.unit.test.ts
  • bunx wrangler deploy --config cloudflare_workers/api/wrangler.jsonc --env=prod --minify --outdir dist --upload-source-maps --dry-run
  • pre-commit hook: bun run cli:build && vue-tsc --noEmit
  • GitHub Actions CI
  • CodeRabbit review

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented version metadata tracking in worker requests to enable enhanced observability and request tracing.
    • Version information is now automatically included with incoming requests for improved diagnostics.
  • Tests

    • Added unit tests to verify proper generation and propagation of worker source headers with version metadata.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

This PR adds Cloudflare Worker version metadata tracking by introducing a new CF_VERSION_METADATA binding across all environments, updating the Bindings TypeScript type, and implementing header construction that embeds version information into outgoing requests.

Changes

Worker Version Metadata Headers

Layer / File(s) Summary
Bindings Type Definition
supabase/functions/_backend/utils/cloudflare.ts
WorkerVersionMetadata is imported and added as an optional CF_VERSION_METADATA property on the exported Bindings type.
Environment Configuration
cloudflare_workers/api/wrangler.jsonc
version_metadata binding pointing to CF_VERSION_METADATA is added to prod, preprod, alpha, and local environments.
Header Construction Function
supabase/functions/_backend/utils/hono.ts
New exported buildWorkerSourceHeaders() creates a map of X-Worker-Source, X-Worker-Version-Id, X-Worker-Version-Tag, and X-Worker-Version-Timestamp headers from function name, environment, and optional version metadata.
Request Handler Integration
supabase/functions/_backend/utils/hono.ts
createHono() now calls buildWorkerSourceHeaders() and sets each returned header on the incoming request context.
Header Validation Tests
tests/worker-source-header.unit.test.ts
New Vitest suite verifies headers are populated when metadata is present and gracefully absent when unavailable.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A rabbit hops through version streams,
Metadata binds to cloudy dreams,
Headers dance with X-Worker-* grace,
From prod to local, every place,
Tracked and traced with bunny's care! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: exposing worker deployment version metadata in API responses.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description is comprehensive and covers the summary, motivation, business impact, and test plan with detailed steps, but lacks some sections from the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/expose-api-worker-version

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 11, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing codex/expose-api-worker-version (b9c875b) with main (7ecafcc)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@riderx riderx force-pushed the codex/expose-api-worker-version branch from 1e2fade to 05908c0 Compare May 11, 2026 14:48
@riderx riderx marked this pull request as ready for review May 11, 2026 14:57
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 11, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@riderx
Copy link
Copy Markdown
Member Author

riderx commented May 11, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/worker-source-header.unit.test.ts (1)

1-17: ⚡ Quick win

Use concurrent test cases to match repo test policy.

Please switch these to it.concurrent(...) (and prefer vi.stubEnv for env isolation) so this file complies with the parallel-test rule.

♻️ Proposed refactor
-import { afterEach, beforeEach, describe, expect, it } from 'vitest'
+import { afterEach, describe, expect, it, vi } from 'vitest'
 import { createHono } from '../supabase/functions/_backend/utils/hono.ts'
 import { version } from '../supabase/functions/_backend/utils/version.ts'

 describe('worker source headers', () => {
-  const originalEnvName = process.env.ENV_NAME
-
-  beforeEach(() => {
-    process.env.ENV_NAME = 'capgo_api-prod'
-  })
-
   afterEach(() => {
-    if (originalEnvName === undefined)
-      delete process.env.ENV_NAME
-    else
-      process.env.ENV_NAME = originalEnvName
+    vi.unstubAllEnvs()
   })

-  it('exposes the Cloudflare Worker deployment version when metadata is bound', async () => {
+  it.concurrent('exposes the Cloudflare Worker deployment version when metadata is bound', async () => {
+    vi.stubEnv('ENV_NAME', 'capgo_api-prod')
     const app = createHono('api', version)
     app.get('/ok', c => c.json({ status: 'ok' }))
@@
-  it('keeps the existing source header when version metadata is not available', async () => {
+  it.concurrent('keeps the existing source header when version metadata is not available', async () => {
+    vi.stubEnv('ENV_NAME', 'capgo_api-prod')
     const app = createHono('api', version)
     app.get('/ok', c => c.json({ status: 'ok' }))

As per coding guidelines, tests/**/*.test.ts: “Design all tests for parallel execution across files; use it.concurrent() instead of it() to run tests in parallel within the same file for faster CI/CD”.

Also applies to: 19-51

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/worker-source-header.unit.test.ts` around lines 1 - 17, Replace
synchronous tests and manual env manipulation with concurrent tests and vitest
env stubbing: change any it(...) calls inside the describe('worker source
headers', ...) to it.concurrent(...), remove the manual beforeEach/afterEach
that set process.env.ENV_NAME, and instead use vi.stubEnv({ ENV_NAME:
'capgo_api-prod' }) in a beforeEach (and let vi restore it automatically) so the
test harness (functions like beforeEach, afterEach, and the ENV_NAME usage)
conforms to parallel-test policy; apply the same it.concurrent and vi.stubEnv
changes for the other test cases referenced in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/worker-source-header.unit.test.ts`:
- Around line 1-17: Replace synchronous tests and manual env manipulation with
concurrent tests and vitest env stubbing: change any it(...) calls inside the
describe('worker source headers', ...) to it.concurrent(...), remove the manual
beforeEach/afterEach that set process.env.ENV_NAME, and instead use vi.stubEnv({
ENV_NAME: 'capgo_api-prod' }) in a beforeEach (and let vi restore it
automatically) so the test harness (functions like beforeEach, afterEach, and
the ENV_NAME usage) conforms to parallel-test policy; apply the same
it.concurrent and vi.stubEnv changes for the other test cases referenced in this
file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 83466d5b-c6e4-426c-b02a-5d68592e31be

📥 Commits

Reviewing files that changed from the base of the PR and between 30cedef and 05908c0.

📒 Files selected for processing (4)
  • cloudflare_workers/api/wrangler.jsonc
  • supabase/functions/_backend/utils/cloudflare.ts
  • supabase/functions/_backend/utils/hono.ts
  • tests/worker-source-header.unit.test.ts

@riderx riderx force-pushed the codex/expose-api-worker-version branch from 05908c0 to b9c875b Compare May 11, 2026 15:06
@sonarqubecloud
Copy link
Copy Markdown

@albercr3
Copy link
Copy Markdown

P2: Expose the new worker-version response headers through CORS as well.

createHono() now adds X-Worker-Version-Id, X-Worker-Version-Tag, and X-Worker-Version-Timestamp to every response, but the shared useCors config still only sets allowed request headers/methods and does not include exposeHeaders. Browser clients calling api.capgo.app cross-origin will receive the headers on the wire, but fetch(...).headers.get('x-worker-version-id') stays null unless the response includes Access-Control-Expose-Headers for these names (and probably the existing X-Worker-Source).

If the intent is for the dashboard/support tooling to verify stale Worker deployments from API responses, this needs to be added in useCors and covered with the header unit test by issuing a request with an Origin header and asserting access-control-expose-headers includes the worker headers.

Copy link
Copy Markdown

@KCDaemon KCDaemon left a comment

Choose a reason for hiding this comment

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

I rechecked the latest head (b9c875b) and the CORS exposure gap is still present. createHono() now emits X-Worker-Source, X-Worker-Version-Id, X-Worker-Version-Tag, and X-Worker-Version-Timestamp, but useCors still has no exposeHeaders, so browser clients on the dashboard/support side will not be able to read these response headers with fetch(...).headers.get(...) on cross-origin API responses.

This makes the new deployment-version metadata much less useful in the main client path: the headers are on the wire, but hidden from browser JavaScript unless Access-Control-Expose-Headers includes the worker headers. The current unit tests only make same-origin-style app.fetch() requests without an Origin header, so they do not catch this.

git diff --check origin/main...origin/pr-2212 passes locally and CI is green, but I would keep this blocked until useCors exposes the worker headers and a regression covers an Origin request asserting access-control-expose-headers contains them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants