Skip to content

ci: add lint/test/format checks and deploy gate#27

Merged
nathanialhenniges merged 7 commits intomainfrom
claude/angry-gates-4be6d8
May 7, 2026
Merged

ci: add lint/test/format checks and deploy gate#27
nathanialhenniges merged 7 commits intomainfrom
claude/angry-gates-4be6d8

Conversation

@nathanialhenniges
Copy link
Copy Markdown
Member

Summary

Bring CI/CD parity with mrdemonwolf/fangdash. Before this PR, CI only ran check-types + build and deploys were manual with no gate. Now main is gated by lint/test/format/typecheck/build, and Cloudflare deploys auto-trigger on green CI with a /api/health smoke test.

Changes

CI (.github/workflows/ci.yml)

  • Mirror fangdash structure: actions/checkout@v6, oven-sh/setup-bun@v2.1.3 with bun-version-file: package.json, actions/cache@v5 for ~/.bun/install/cache.
  • Run order: install → typecheck → test → lint → format:check → build (placeholder envs preserved).
  • Drop non-blocking npm audit step (Dependabot covers vulnerability scanning).

New .github/workflows/deploy.yml

  • workflow_run trigger gated on CI success on main.
  • Concurrency group deploy with cancel-in-progress: true.
  • environment: production so env-scoped secrets resolve and the deploy shows in the Environments UI.
  • Runs bun run deploy (Alchemy → Cloudflare).
  • Smoke test: curl -fsS ${NEXT_PUBLIC_SERVER_URL}/api/health, fails the job if response does not contain "status":"ok".

Server (apps/server/src/index.ts)

  • Add GET /api/health returning { status: "ok" } for the post-deploy smoke test.

Root package.json

  • Add typecheck, lint, format, format:check scripts.
  • Add @biomejs/biome devDep (was referenced by biome.json but never installed).

Reviewer notes

  • The production GitHub Environment must hold these secrets before the first auto-deploy: CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, ALCHEMY_PASSWORD, BETTER_AUTH_SECRET, BETTER_AUTH_URL, NEXT_PUBLIC_SERVER_URL, CORS_ORIGIN, plus any wallet secrets in use.
  • NEXT_PUBLIC_SERVER_URL must point at the host that exposes /api/health (the worker, not the web app) for the smoke test to succeed.
  • First CI run may surface pre-existing biome lint/format violations against current code. If so, run bun run format + fix lint locally and follow up.

Test plan

  • Verify CI workflow runs on this PR and all steps (typecheck, test, lint, format:check, build) pass.
  • After merge, confirm Deploy workflow auto-triggers via workflow_run and the smoke test hits /api/health successfully.
  • Confirm the deploy is visible under repo → Environments → production.
  • (Negative) Push a commit that fails CI on main and confirm Deploy does NOT run.

🤖 Generated with Claude Code

Mirror fangdash CI/CD discipline before production deploys.

CI changes:
- Add bun install cache
- Run typecheck, test, lint, format:check, build (in that order)
- Drop non-blocking npm audit (Dependabot covers it)
- Add typecheck, lint, format, format:check root scripts
- Install @biomejs/biome (referenced by biome.json but missing)

New deploy.yml:
- Trigger via workflow_run gated on CI success on main
- Runs bun run deploy (Alchemy -> Cloudflare) under production environment
- Smoke test /api/health post-deploy, fails if non-ok

Server:
- Add GET /api/health for the smoke test

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Important

Review skipped

Too many files!

This PR contains 238 files, which is 88 over the limit of 150.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 547fff3d-c469-4bd4-9683-7f9901918d39

📥 Commits

Reviewing files that changed from the base of the PR and between 3d096ca and 875eb5a.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (238)
  • .github/workflows/ci.yml
  • .github/workflows/deploy.yml
  • apps/docs/content/docs/getting-started/meta.json
  • apps/docs/content/docs/guide/meta.json
  • apps/docs/content/docs/meta.json
  • apps/docs/content/docs/reference/meta.json
  • apps/docs/content/docs/self-hosting/meta.json
  • apps/docs/next.config.mjs
  • apps/docs/package.json
  • apps/docs/postcss.config.mjs
  • apps/docs/source.config.ts
  • apps/docs/src/app/(home)/layout.tsx
  • apps/docs/src/app/(home)/page.tsx
  • apps/docs/src/app/docs/[[...slug]]/page.tsx
  • apps/docs/src/app/docs/layout.tsx
  • apps/docs/src/app/layout.tsx
  • apps/docs/src/components/email-preview.tsx
  • apps/docs/src/components/footer.tsx
  • apps/docs/src/components/provider.tsx
  • apps/docs/src/components/search.tsx
  • apps/docs/src/lib/layout.shared.tsx
  • apps/docs/src/lib/source.ts
  • apps/docs/src/mdx-components.tsx
  • apps/docs/tsconfig.json
  • apps/server/package.json
  • apps/server/src/index.ts
  • apps/server/tsconfig.json
  • apps/server/tsdown.config.ts
  • apps/server/wrangler.jsonc
  • apps/web/components.json
  • apps/web/next.config.ts
  • apps/web/package.json
  • apps/web/postcss.config.mjs
  • apps/web/public/favicon/site.webmanifest
  • apps/web/public/sw.js
  • apps/web/src/app/admin/account/page.tsx
  • apps/web/src/app/admin/analytics/page.tsx
  • apps/web/src/app/admin/appearance/page.tsx
  • apps/web/src/app/admin/builder/page.tsx
  • apps/web/src/app/admin/connections/page.tsx
  • apps/web/src/app/admin/error.tsx
  • apps/web/src/app/admin/forms/page.tsx
  • apps/web/src/app/admin/layout.tsx
  • apps/web/src/app/admin/loading.tsx
  • apps/web/src/app/admin/login/page.tsx
  • apps/web/src/app/admin/page.tsx
  • apps/web/src/app/admin/reset-password/layout.tsx
  • apps/web/src/app/admin/reset-password/page.tsx
  • apps/web/src/app/admin/settings/page.tsx
  • apps/web/src/app/admin/setup/layout.tsx
  • apps/web/src/app/admin/setup/page.tsx
  • apps/web/src/app/admin/social/page.tsx
  • apps/web/src/app/admin/wallet/page.tsx
  • apps/web/src/app/api/og/route.tsx
  • apps/web/src/app/error.tsx
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/manifest.ts
  • apps/web/src/app/not-found.tsx
  • apps/web/src/app/page.tsx
  • apps/web/src/app/qr/page.tsx
  • apps/web/src/app/sitemap.ts
  • apps/web/src/components/admin/analytics/countries-list.tsx
  • apps/web/src/components/admin/analytics/referrers-list.tsx
  • apps/web/src/components/admin/analytics/top-links-list.tsx
  • apps/web/src/components/admin/analytics/views-clicks-chart.tsx
  • apps/web/src/components/admin/appearance/colors-section.tsx
  • apps/web/src/components/admin/appearance/custom-css-section.tsx
  • apps/web/src/components/admin/appearance/profile-section.tsx
  • apps/web/src/components/admin/appearance/social-icon-shape-section.tsx
  • apps/web/src/components/admin/appearance/theme-presets-section.tsx
  • apps/web/src/components/admin/builder/block-edit-panel.tsx
  • apps/web/src/components/admin/builder/block-row.tsx
  • apps/web/src/components/admin/builder/builder-constants.ts
  • apps/web/src/components/admin/builder/collapsible-section.tsx
  • apps/web/src/components/admin/builder/profile-tab.tsx
  • apps/web/src/components/admin/builder/social-tab.tsx
  • apps/web/src/components/admin/confirm-dialog.tsx
  • apps/web/src/components/admin/connections/connection-detail.tsx
  • apps/web/src/components/admin/connections/connection-list-item.tsx
  • apps/web/src/components/admin/dashboard/top-links-list.tsx
  • apps/web/src/components/admin/device-frame.tsx
  • apps/web/src/components/admin/empty-state.tsx
  • apps/web/src/components/admin/form-section.tsx
  • apps/web/src/components/admin/forms/contact-detail.tsx
  • apps/web/src/components/admin/forms/contact-list-item.tsx
  • apps/web/src/components/admin/image-upload-field.tsx
  • apps/web/src/components/admin/mobile-preview-sheet.tsx
  • apps/web/src/components/admin/onboarding-tour.tsx
  • apps/web/src/components/admin/page-header.tsx
  • apps/web/src/components/admin/phone-frame.tsx
  • apps/web/src/components/admin/preview-renderer.tsx
  • apps/web/src/components/admin/section-header.tsx
  • apps/web/src/components/admin/settings/branding-section.tsx
  • apps/web/src/components/admin/settings/consent-section.tsx
  • apps/web/src/components/admin/settings/data-section.tsx
  • apps/web/src/components/admin/settings/email-section.tsx
  • apps/web/src/components/admin/settings/field-group.tsx
  • apps/web/src/components/admin/settings/linkstack-import-wizard.tsx
  • apps/web/src/components/admin/settings/mapkit-section.tsx
  • apps/web/src/components/admin/settings/migration-section.tsx
  • apps/web/src/components/admin/settings/og-preview-card.tsx
  • apps/web/src/components/admin/settings/seo-section.tsx
  • apps/web/src/components/admin/settings/vcard-section.tsx
  • apps/web/src/components/admin/settings/wallet-section.tsx
  • apps/web/src/components/admin/shared-preview.tsx
  • apps/web/src/components/admin/social/network-row.tsx
  • apps/web/src/components/admin/social/social-constants.ts
  • apps/web/src/components/admin/wallet-pass-preview.tsx
  • apps/web/src/components/loader.tsx
  • apps/web/src/components/providers.tsx
  • apps/web/src/components/public/avatar.tsx
  • apps/web/src/components/public/banner-section.tsx
  • apps/web/src/components/public/connect-block.tsx
  • apps/web/src/components/public/consent-banner.tsx
  • apps/web/src/components/public/embed-block.tsx
  • apps/web/src/components/public/footer-actions.tsx
  • apps/web/src/components/public/header-block.tsx
  • apps/web/src/components/public/link-block.tsx
  • apps/web/src/components/public/preview-context.tsx
  • apps/web/src/components/public/profile-social-icons.tsx
  • apps/web/src/components/public/public-page-content.tsx
  • apps/web/src/components/public/public-page.tsx
  • apps/web/src/components/public/shader-banner.tsx
  • apps/web/src/components/public/vcard-block.tsx
  • apps/web/src/components/theme-provider.tsx
  • apps/web/src/components/ui/badge.tsx
  • apps/web/src/components/ui/button.tsx
  • apps/web/src/components/ui/card.tsx
  • apps/web/src/components/ui/chart.tsx
  • apps/web/src/components/ui/dropdown-menu.tsx
  • apps/web/src/components/ui/input.tsx
  • apps/web/src/components/ui/label.tsx
  • apps/web/src/components/ui/progress.tsx
  • apps/web/src/components/ui/skeleton.tsx
  • apps/web/src/components/ui/sonner.tsx
  • apps/web/src/components/ui/textarea.tsx
  • apps/web/src/components/ui/theme-toggle.tsx
  • apps/web/src/components/wolf-logo.tsx
  • apps/web/src/index.css
  • apps/web/src/lib/__tests__/map-url.test.ts
  • apps/web/src/lib/auth-client.ts
  • apps/web/src/lib/format.ts
  • apps/web/src/lib/gravatar.ts
  • apps/web/src/lib/login-bg.ts
  • apps/web/src/lib/utils.ts
  • apps/web/src/middleware.ts
  • apps/web/src/utils/trpc.ts
  • apps/web/tsconfig.json
  • apps/web/wrangler.jsonc
  • biome.json
  • bts.jsonc
  • data/social-networks.json
  • package.json
  • packages/api/package.json
  • packages/api/src/routers/analytics.ts
  • packages/api/src/routers/backup.ts
  • packages/api/src/routers/blocks.ts
  • packages/api/src/routers/contacts.ts
  • packages/api/src/routers/public.ts
  • packages/api/src/routers/settings.ts
  • packages/api/src/routers/social.ts
  • packages/api/src/routers/wallet.ts
  • packages/api/src/utils/linkstack-transformer.ts
  • packages/api/src/utils/sanitize.ts
  • packages/api/src/utils/settings.ts
  • packages/api/tsconfig.json
  • packages/auth/package.json
  • packages/auth/src/index.ts
  • packages/auth/tsconfig.json
  • packages/config/package.json
  • packages/config/tsconfig.base.json
  • packages/db/drizzle.config.ts
  • packages/db/package.json
  • packages/db/src/migrations/meta/0000_snapshot.json
  • packages/db/src/migrations/meta/0001_snapshot.json
  • packages/db/src/migrations/meta/0002_snapshot.json
  • packages/db/src/migrations/meta/0003_snapshot.json
  • packages/db/src/migrations/meta/0004_snapshot.json
  • packages/db/src/migrations/meta/0005_snapshot.json
  • packages/db/src/migrations/meta/0006_snapshot.json
  • packages/db/src/migrations/meta/_journal.json
  • packages/db/src/schema/analytics.ts
  • packages/db/src/schema/auth.ts
  • packages/db/src/schema/blocks.ts
  • packages/db/src/schema/contacts.ts
  • packages/db/src/schema/settings.ts
  • packages/db/tsconfig.json
  • packages/email/package.json
  • packages/email/src/service.ts
  • packages/email/src/templates/contact-notification.tsx
  • packages/email/tsconfig.json
  • packages/env/env.d.ts
  • packages/env/package.json
  • packages/env/src/web.ts
  • packages/env/tsconfig.json
  • packages/infra/alchemy.run.ts
  • packages/infra/package.json
  • packages/ui/package.json
  • packages/ui/src/banner-presets.ts
  • packages/ui/src/components/avatar.tsx
  • packages/ui/src/components/badge.tsx
  • packages/ui/src/components/button.tsx
  • packages/ui/src/components/card.tsx
  • packages/ui/src/components/checkbox.tsx
  • packages/ui/src/components/dialog.tsx
  • packages/ui/src/components/dropdown-menu.tsx
  • packages/ui/src/components/form-field.tsx
  • packages/ui/src/components/icon-button.tsx
  • packages/ui/src/components/input.tsx
  • packages/ui/src/components/label.tsx
  • packages/ui/src/components/select.tsx
  • packages/ui/src/components/separator.tsx
  • packages/ui/src/components/sheet.tsx
  • packages/ui/src/components/skeleton.tsx
  • packages/ui/src/components/switch.tsx
  • packages/ui/src/components/tabs.tsx
  • packages/ui/src/components/textarea.tsx
  • packages/ui/src/components/toast.tsx
  • packages/ui/src/components/tooltip.tsx
  • packages/ui/src/index.ts
  • packages/ui/src/social-brands.ts
  • packages/ui/src/themes.ts
  • packages/ui/src/utils.ts
  • packages/ui/tsconfig.json
  • packages/validators/package.json
  • packages/validators/src/__tests__/block-configs.test.ts
  • packages/validators/src/analytics.ts
  • packages/validators/src/blocks.ts
  • packages/validators/src/contacts.ts
  • packages/validators/src/index.ts
  • packages/validators/src/links.ts
  • packages/validators/src/settings.ts
  • packages/validators/tsconfig.json
  • scripts/check-social-icons.mjs
  • scripts/factory-reset.ts
  • scripts/reset-password.ts
  • tsconfig.json
  • turbo.json

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/angry-gates-4be6d8

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

nathanialhenniges and others added 6 commits May 7, 2026 02:00
- Migrate biome.json to v2 schema (ignore -> includes, organizeImports -> assist)
- Demote pre-existing rule violations (a11y, noNonNullAssertion, noImgElement,
  noArrayIndexKey, etc.) to "warn" so CI can enforce on new code without
  blocking on legacy debt; followup work to address them
- Disable biome on .css files (Tailwind directives are not parsed)
- Auto-format all 236 files with biome (tab indent, double quotes, semicolons)
- Pin @vitejs/plugin-react@^5 (v6 imports vite/internal which Vite 7 does not export)
- Refresh bun.lock for newly added @biomejs/biome devDep

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e6d8

# Conflicts:
#	apps/web/src/app/admin/appearance/page.tsx
#	apps/web/src/app/admin/settings/page.tsx
#	apps/web/src/components/public/public-page.tsx
#	apps/web/src/lib/login-bg.ts
#	packages/api/src/routers/settings.ts
…e6d8

# Conflicts:
#	apps/docs/package.json
#	apps/server/package.json
#	apps/web/package.json
#	apps/web/src/app/admin/account/page.tsx
#	apps/web/src/app/admin/appearance/page.tsx
#	apps/web/src/components/public/public-page-content.tsx
#	bun.lock
#	packages/api/package.json
#	packages/auth/package.json
#	packages/auth/src/index.ts
#	packages/db/package.json
#	packages/email/package.json
#	packages/env/package.json
#	packages/infra/package.json
#	packages/ui/package.json
#	packages/validators/package.json
…e6d8

# Conflicts:
#	apps/docs/content/docs/guide/meta.json
…xcludes

- Use optional chaining for selectedConnection/selectedContact in useEffect
  deps; Next 16 build's tsc was rejecting nullable.id/.isRead access
- Exclude apps/docs/out, .next build artifacts from biome
@nathanialhenniges nathanialhenniges merged commit 486c551 into main May 7, 2026
3 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