Skip to content

feat(dashboard): wrangler.dev.jsonc for local dev and production deploy CI#157

Merged
stylessh merged 3 commits intomainfrom
feat/dashboard-wrangler-dev-config-production-ci
Apr 18, 2026
Merged

feat(dashboard): wrangler.dev.jsonc for local dev and production deploy CI#157
stylessh merged 3 commits intomainfrom
feat/dashboard-wrangler-dev-config-production-ci

Conversation

@stylessh
Copy link
Copy Markdown
Owner

@stylessh stylessh commented Apr 18, 2026

Summary

  • Local dev: Vite/Vitest load wrangler.dev.jsonc when present (fallback to wrangler.jsonc); production vite build / vite preview still use the default Wrangler config path.
  • Repo hygiene: Remove tracked wrangler.jsonc; expand wrangler.jsonc.example and README for copying to wrangler.dev.jsonc (gitignored).
  • D1: Local migrations auto-pick wrangler.dev.jsonc when WRANGLER_CONFIG is unset.
  • CI: Add dashboard-deploy-production.yml (main + path filters) — generate wrangler.deploy.json from secrets, apply remote D1 migrations, deploy:ci.
  • Scripts: generate-wrangler-dashboard-config.mjs; deploy:ci in dashboard package.json.

GitHub setup

Repository secrets (not Environment unless you add environment: to the job): CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, DASHBOARD_PROD_* bindings. Optional variable: WRANGLER_COMPATIBILITY_DATE.

Summary by CodeRabbit

  • New Features

    • Added automated production deployment pipeline configured to trigger on repository changes and manual requests, streamlining the release process.
  • Documentation

    • Updated development setup instructions with improved guidance on managing local and production environment configurations.
  • Chores

    • Improved build and database migration scripts for better handling of development and production environments.
    • Enhanced configuration file management to cleanly separate local development and production settings.

- Use wrangler.dev.jsonc for Vite dev/Vitest; keep wrangler.jsonc for build/preview
- Gitignore dev/deploy wrangler files; remove tracked wrangler.jsonc (use example)
- Default local D1 migrations to wrangler.dev.jsonc when present
- Add generate-wrangler-dashboard-config.mjs and production GHA deploy
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

📝 Walkthrough

Walkthrough

Implements production deployment infrastructure for the dashboard worker by introducing a GitHub Actions workflow that generates deployment-specific Wrangler configurations, applies D1 migrations, and deploys to Cloudflare. Adds configuration-aware utilities for conditional Wrangler config path resolution and supporting scripts for environment variable validation and secret injection during CI builds.

Changes

Cohort / File(s) Summary
GitHub Actions Deployment
.github/workflows/dashboard-deploy-production.yml
New production deployment workflow that generates Wrangler config from GitHub Actions secrets/vars, applies D1 migrations, and deploys the dashboard worker to Cloudflare.
Dashboard Configuration & Documentation
apps/dashboard/.gitignore, apps/dashboard/README.md, apps/dashboard/wrangler.jsonc.example
Added gitignore entries for generated configs; updated README setup instructions to reference separate wrangler.dev.jsonc and wrangler.deploy.json files; added extensive documentation comments to example config.
Dashboard Build Configuration
apps/dashboard/package.json, apps/dashboard/vite.config.ts, apps/dashboard/tsconfig.json
Added deploy:ci and updated migrate:* scripts; updated Vite config to conditionally resolve Wrangler config path based on command/mode; added TypeScript include path for config resolution script.
Wrangler Config Management
apps/dashboard/wrangler.jsonc (deleted)
Removed hardcoded production Wrangler config; now generated at CI time via script.
Configuration Generation & Resolution Scripts
scripts/generate-wrangler-dashboard-config.mjs, scripts/resolve-wrangler-config-path.mts
New script to generate deployment Wrangler config from environment variables with validation; new utility module to conditionally resolve config paths for dev/serve vs. production builds.
Migration & Worktree Utilities
scripts/run-d1-migrations.mjs, scripts/link-worktree-dev-vars.mjs
Updated migration script to conditionally pass \-c config flag to Wrangler; updated worktree linking to include wrangler.dev.jsonc alongside .dev.vars.
Linting Configuration
.lintstagedrc.json
Added mts file extension to lint-staged glob pattern.

Sequence Diagram

sequenceDiagram
    actor GitHub as GitHub Actions
    participant Workflow as Dashboard Deploy Workflow
    participant ConfigGen as Config Generator
    participant Wrangler as Wrangler CLI
    participant D1 as D1 Database
    participant Cloudflare as Cloudflare Workers

    GitHub->>Workflow: Trigger on main push
    Workflow->>ConfigGen: node scripts/generate-wrangler-dashboard-config.mjs
    ConfigGen->>ConfigGen: Read secrets/vars from environment
    ConfigGen->>ConfigGen: Validate required values present
    ConfigGen->>Workflow: Write wrangler.deploy.json
    
    Workflow->>Wrangler: node scripts/run-d1-migrations.mjs<br/>DB --remote
    Wrangler->>D1: Apply migrations with -c wrangler.deploy.json
    D1->>Wrangler: Migrations applied
    
    Workflow->>Workflow: Copy wrangler.deploy.json to wrangler.jsonc
    Workflow->>Workflow: pnpm run build
    Workflow->>Wrangler: pnpm run deploy:ci<br/>(wrangler deploy --config wrangler.deploy.json)
    Wrangler->>Cloudflare: Deploy worker
    Cloudflare->>GitHub: Deployment complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: introducing wrangler.dev.jsonc for local development and setting up production deployment CI.
Description check ✅ Passed The PR description covers Summary and provides detailed changes addressing local dev, repo hygiene, D1 migrations, CI setup, and scripts, but omits the Test Plan and Screenshots 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 feat/dashboard-wrangler-dev-config-production-ci

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

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)
apps/dashboard/vite.config.ts (1)

21-36: Consider centralizing Wrangler config discovery to avoid logic drift.

The precedence logic at Line 29–34 is now duplicated with scripts/run-d1-migrations.mjs (Line 29–35). Extracting this into a shared helper would reduce future divergence risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/dashboard/vite.config.ts` around lines 21 - 36, The precedence logic in
resolveCloudflareWranglerConfigPath is duplicated in
scripts/run-d1-migrations.mjs; extract this logic into a single shared helper
(e.g., export a function like getWranglerConfigPath or resolveWranglerConfigPath
from a new util module) and replace the inline implementations in both
resolveCloudflareWranglerConfigPath (in vite.config.ts) and the script in
run-d1-migrations.mjs with imports that call the shared helper, ensuring the
helper accepts (command, mode) and uses the same
wranglerDevPath/wranglerMainPath checks so both callers share identical
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/dashboard/vite.config.ts`:
- Around line 21-36: The precedence logic in resolveCloudflareWranglerConfigPath
is duplicated in scripts/run-d1-migrations.mjs; extract this logic into a single
shared helper (e.g., export a function like getWranglerConfigPath or
resolveWranglerConfigPath from a new util module) and replace the inline
implementations in both resolveCloudflareWranglerConfigPath (in vite.config.ts)
and the script in run-d1-migrations.mjs with imports that call the shared
helper, ensuring the helper accepts (command, mode) and uses the same
wranglerDevPath/wranglerMainPath checks so both callers share identical
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 425761e4-1e35-4017-a31a-408bb6576fa4

📥 Commits

Reviewing files that changed from the base of the PR and between 9e7b26f and 1c1864f.

📒 Files selected for processing (9)
  • .github/workflows/dashboard-deploy-production.yml
  • apps/dashboard/.gitignore
  • apps/dashboard/README.md
  • apps/dashboard/package.json
  • apps/dashboard/vite.config.ts
  • apps/dashboard/wrangler.jsonc
  • apps/dashboard/wrangler.jsonc.example
  • scripts/generate-wrangler-dashboard-config.mjs
  • scripts/run-d1-migrations.mjs
💤 Files with no reviewable changes (1)
  • apps/dashboard/wrangler.jsonc

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
scripts/resolve-wrangler-config-path.mjs (1)

14-21: Prefer returning the resolved path to avoid cwd-coupling.

You check existence using rootDir, but return a relative filename. Returning the resolved match keeps behavior stable even when caller cwd differs.

♻️ Proposed refactor
 /**
  * Same resolution Vite uses for the Cloudflare plugin in dev / Vitest (`serve` + non-production).
  *
  * `@param` {{ command: string; mode: string; rootDir: string }} opts
- * `@returns` {string | undefined} Relative filename for `wrangler -c`, or undefined for default discovery.
+ * `@returns` {string | undefined} Resolved config path, or undefined for default discovery.
  */
 export function resolveWranglerConfigPath({ command, mode, rootDir }) {
   if (command !== "serve" || mode === "production") {
     return undefined;
   }
   const dev = path.join(rootDir, "wrangler.dev.jsonc");
   const main = path.join(rootDir, "wrangler.jsonc");
   if (existsSync(dev)) {
-    return "wrangler.dev.jsonc";
+    return dev;
   }
   if (existsSync(main)) {
-    return "wrangler.jsonc";
+    return main;
   }
   return undefined;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/resolve-wrangler-config-path.mjs` around lines 14 - 21, The function
currently checks for existence with the resolved paths stored in dev and main
but returns bare filenames, causing cwd coupling; change the returns to return
the resolved path variables (dev or main) instead of
"wrangler.dev.jsonc"/"wrangler.jsonc" so callers always get absolute/resolved
paths; update the branches that call existsSync(dev) and existsSync(main) to
return dev and main respectively and ensure any tests or callers expect a
resolved path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/run-d1-migrations.mjs`:
- Around line 29-33: The code calls resolveWranglerConfigPath(...) with rootDir:
process.cwd(), which is fragile because it assumes the script is invoked from
apps/dashboard; change the rootDir passed to resolveWranglerConfigPath to a
deterministic path pointing at the dashboard app (e.g., hardcode or compute a
repo-root-relative path to "apps/dashboard" instead of process.cwd()) and add a
brief inline comment referencing wrangler.dev.jsonc to document the assumption;
update the wranglerConfig assignment (resolveWranglerConfigPath) so it reliably
locates wrangler.dev.jsonc even when the script is run from other working
directories.

---

Nitpick comments:
In `@scripts/resolve-wrangler-config-path.mjs`:
- Around line 14-21: The function currently checks for existence with the
resolved paths stored in dev and main but returns bare filenames, causing cwd
coupling; change the returns to return the resolved path variables (dev or main)
instead of "wrangler.dev.jsonc"/"wrangler.jsonc" so callers always get
absolute/resolved paths; update the branches that call existsSync(dev) and
existsSync(main) to return dev and main respectively and ensure any tests or
callers expect a resolved path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 20710629-1d22-46f2-92a9-cbc8d3ef2f59

📥 Commits

Reviewing files that changed from the base of the PR and between 1c1864f and 4da3163.

📒 Files selected for processing (3)
  • apps/dashboard/vite.config.ts
  • scripts/resolve-wrangler-config-path.mjs
  • scripts/run-d1-migrations.mjs

Comment on lines +29 to +33
wranglerConfig = resolveWranglerConfigPath({
command: "serve",
mode: "development",
rootDir: process.cwd(),
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify how scripts/run-d1-migrations.mjs is invoked and which working directory is used.
# Expected: invocations either run from apps/dashboard or explicitly set working-directory.
rg -n -C3 'run-d1-migrations\.mjs|working-directory:|WRANGLER_CONFIG|deploy:ci|--local' --iglob '*.yml' --iglob '*.yaml' --iglob 'package.json'

Repository: stylessh/diffkit

Length of output: 810


🏁 Script executed:

#!/bin/bash
# Read the full context of the script around the flagged lines
cat -n scripts/run-d1-migrations.mjs | head -50

Repository: stylessh/diffkit

Length of output: 1781


🏁 Script executed:

#!/bin/bash
# Search for resolveWranglerConfigPath definition and usage
rg -n 'resolveWranglerConfigPath' --type=javascript --type=typescript -B5 -A5

Repository: stylessh/diffkit

Length of output: 94


🏁 Script executed:

#!/bin/bash
# Search for the implementation of resolveWranglerConfigPath
cat -n scripts/resolve-wrangler-config-path.mjs | head -80

Repository: stylessh/diffkit

Length of output: 977


🏁 Script executed:

#!/bin/bash
# Search for all invocations of run-d1-migrations.mjs
rg 'run-d1-migrations' -n --no-heading

Repository: stylessh/diffkit

Length of output: 513


cwd-coupling in config auto-detection is currently safe but fragile.

Line 32 uses process.cwd() to locate wrangler.dev.jsonc, which assumes the script runs from apps/dashboard. All current invocations (npm scripts in apps/dashboard/package.json and the explicit cd in paseo.json) satisfy this, but if the script is ever run from a different directory, the config won't be found. This isn't silent—Wrangler will fall back to its own discovery—but the assumption should be documented or the rootDir should be hardcoded to apps/dashboard for clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/run-d1-migrations.mjs` around lines 29 - 33, The code calls
resolveWranglerConfigPath(...) with rootDir: process.cwd(), which is fragile
because it assumes the script is invoked from apps/dashboard; change the rootDir
passed to resolveWranglerConfigPath to a deterministic path pointing at the
dashboard app (e.g., hardcode or compute a repo-root-relative path to
"apps/dashboard" instead of process.cwd()) and add a brief inline comment
referencing wrangler.dev.jsonc to document the assumption; update the
wranglerConfig assignment (resolveWranglerConfigPath) so it reliably locates
wrangler.dev.jsonc even when the script is run from other working directories.

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.

♻️ Duplicate comments (1)
scripts/run-d1-migrations.mjs (1)

29-33: ⚠️ Potential issue | 🟡 Minor

Make Wrangler root resolution deterministic (still cwd-coupled).

Line 32 still binds config auto-detection to invocation directory (process.cwd()), so local auto-pick can fail when the script is run outside apps/dashboard.

💡 Proposed fix
 import { spawnSync } from "node:child_process";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
 import { resolveWranglerConfigPath } from "./resolve-wrangler-config-path.mts";
 import {
   getSharedWranglerStatePath,
   isWorktreeCheckout,
 } from "./shared-worktree-paths.mjs";
 
 const PNPM_SCRIPT_EXT = /\.(c|m)?js$/u;
+const scriptDir = path.dirname(fileURLToPath(import.meta.url));
+const dashboardRoot = path.resolve(scriptDir, "../apps/dashboard");
@@
 if (!wranglerConfig && mode === "--local") {
   wranglerConfig = resolveWranglerConfigPath({
     command: "serve",
     mode: "development",
-    rootDir: process.cwd(),
+    rootDir: dashboardRoot,
   });
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/run-d1-migrations.mjs` around lines 29 - 33, The wrangler config root
is set using process.cwd() which makes resolution depend on the caller; change
the rootDir passed to resolveWranglerConfigPath so it is derived from the
script's own location instead of process.cwd() (compute the script directory
using fileURLToPath(import.meta.url) and path.dirname, then resolve the desired
project subpath from there) and assign that to wranglerConfig; update any
imports to include fileURLToPath from 'url' and ensure path.resolve is used when
constructing the rootDir for resolveWranglerConfigPath.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@scripts/run-d1-migrations.mjs`:
- Around line 29-33: The wrangler config root is set using process.cwd() which
makes resolution depend on the caller; change the rootDir passed to
resolveWranglerConfigPath so it is derived from the script's own location
instead of process.cwd() (compute the script directory using
fileURLToPath(import.meta.url) and path.dirname, then resolve the desired
project subpath from there) and assign that to wranglerConfig; update any
imports to include fileURLToPath from 'url' and ensure path.resolve is used when
constructing the rootDir for resolveWranglerConfigPath.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 220895e4-c7f5-4035-ad1c-e5ae2567967c

📥 Commits

Reviewing files that changed from the base of the PR and between 4da3163 and 7d7fc13.

📒 Files selected for processing (8)
  • .github/workflows/dashboard-deploy-production.yml
  • .lintstagedrc.json
  • apps/dashboard/package.json
  • apps/dashboard/tsconfig.json
  • apps/dashboard/vite.config.ts
  • scripts/link-worktree-dev-vars.mjs
  • scripts/resolve-wrangler-config-path.mts
  • scripts/run-d1-migrations.mjs
✅ Files skipped from review due to trivial changes (2)
  • .lintstagedrc.json
  • apps/dashboard/tsconfig.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/dashboard/package.json
  • .github/workflows/dashboard-deploy-production.yml
  • apps/dashboard/vite.config.ts

@stylessh stylessh merged commit cb5136d into main Apr 18, 2026
5 checks passed
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.

1 participant