ci: add typecheck, lint, and format checks to PR workflow
From the PR description
Summary
- Extend the existing
ci.ymlworkflow so every PR tomainruns explicit type-check, lint, and Prettier format checks on bothfrontendandbackend. Each check is its own named step so the PR status shows exactly what fails. - Backend got a fresh ESLint setup (flat config,
@eslint/js+typescript-eslintrecommended) since it had none; both packages got a shared Prettier config. - Frontend
lintis now--max-warnings 0so warnings block CI. - Cleaned up everything the new checks flagged so the workflow lands green:
- Backend (26 errors): removed unused vars/imports/functions, killed
anytypes intabular.ts, narroweslint-disablefor the intentional control-char regex instorage.ts. - Frontend (68 warnings): removed/_-prefixed unused vars, converted ternary-as-statement patterns to
if/else, added justifiedeslint-disable-next-line react-hooks/exhaustive-depswhere existing dep arrays were deliberately narrow.
- Backend (26 errors): removed unused vars/imports/functions, killed
- The bulk of the diff is
prettier --writeformatting in its own commit so reviewers can ignore the noise.
Commits (in order)
docs: add PR CI checks design specci: add explicit typecheck, lint, and format checks on PRs- read this one carefully; it's the actual setupchore: apply prettier formatting and fix lint/type errors- the noisy diff
Design doc: docs/superpowers/specs/2026-05-19-pr-ci-checks-design.md
Test plan
- All four new CI steps pass on this PR: frontend format/lint/typecheck/build + backend format/lint/typecheck/build + drizzle migration
- Locally verified:
npm run format:check && npm run lint && npm run typecheck && npm run buildexits 0 in both packages - Once green, consider wiring branch protection to require the
Frontend checksandBackend checksstatus checks before merge
🤖 Generated with Claude Code
Our analysis
CI checks PR that swept in the AWS re-platform — read the full analysis →
Think the analysis missed something the PR description covers?
Commits in this PR (2)
| SHA | Subject | Author | Date | |
|---|---|---|---|---|
2dc27676 | Re-platform from Cloudflare/Supabase to AWS | Alex Maingot | 2026-05-14 | ↗ GitHub |
commit bodyAuth: Supabase Auth → AWS Cognito. Frontend uses amazon-cognito-identity-js
behind a supabase-shaped wrapper so existing call sites only changed import
paths. Backend uses aws-jwt-verify (CognitoJwtVerifier for real AWS,
JwtRsaVerifier with a custom HTTP fetcher for cognito-local). Signup page
now handles Cognito's email-confirmation step.
DB: Supabase PostgREST → RDS Postgres via Drizzle ORM. ~191 query sites
across 14 backend files (~8000 lines) rewritten. Drizzle schema mirrors
the original 17 tables minus the auth.uid()-based RLS helpers - access is
already enforced in lib/access.ts via service-role queries (defense in
depth note in the original schema.sql:1052). Initial migration committed
under backend/drizzle/. A new public.users table mirrors Cognito identities
(replaces the Postgres on-signup trigger).
Storage: R2 → S3 envs (S3_BUCKET_NAME, S3_ENDPOINT_URL, AWS_*). Endpoint
and forcePathStyle are conditional - set for MinIO locally, unset for real
AWS so the SDK uses the ECS task-role credential chain.
LLM: Anthropic SDK → @aws-sdk/client-bedrock-runtime for Claude only.
OpenAI and Gemini still call their providers directly. Per-user Claude
keys are dropped (Bedrock uses IAM); a migration purges existing rows and
narrows the user_api_keys.provider check constraint.
Account deletion: routes/user.ts now calls AdminDeleteUserCommand on the
Cognito User Pool plus a cascading delete on public.users.
Frontend runtime: Cloudflare Workers / OpenNext → Next.js standalone in
Docker (output: "standalone" + `node server.js`). Removes @opennextjs/
cloudflare, wrangler, @openrouter/sdk, @supabase/*.
Backend runtime: nixpacks → node:20-bookworm-slim with libreoffice +
fontconfig baked in for DOC/DOCX → PDF conversion.
Infra artifacts:
- frontend/Dockerfile, backend/Dockerfile (multi-stage, healthchecked)
- docker-compose.yml: postgres, cognito-local (ghcr.io/amaingot/cognito-local),
MinIO + minio-init for bucket bootstrap, smtp4dev, backend, frontend
- scripts/bootstrap-local.sh: pre-seeds cognito-local's clients.json so the
fork's auto-generated client id doesn't clash with the env-pinned id,
then runs Drizzle migrations
- .github/workflows/ci.yml: PR build + lint + db:migrate against a postgres
service
- .github/workflows/build-and-publish.yml: multi-arch (amd64/arm64) push to
ghcr.io/<owner>/mike-{frontend,backend} on main and v* tags
End-to-end verified locally:
- docker compose up brings postgres/auth/minio/smtp to healthy
- bootstrap-local.sh provisions pool + client + bucket + schema
- Cognito signup → confirm → InitiateAuth → backend JWKS verify → users
row auto-created (with deterministic UUID derivation for cognito-local's
non-UUID subs)
- POST /projects, GET /projects, POST /single-documents all return 200
with the expected DB rows and MinIO object
Operator notes captured in README.md: required AWS resources (Cognito
pool, RDS, S3, SES, Bedrock model access, ECS task role permissions),
ghcr.io → ECR re-tag flow, Bedrock model-ID verification step before
first deploy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| ||||
e7593aa7 | Fix frontend lint errors surfaced by new CI | Alex Maingot | 2026-05-14 | ↗ GitHub |
commit bodyThe Re-platform commit introduced .github/workflows/ci.yml which runs `npm run lint` for the first time on this codebase. That surfaced 38 pre-existing errors in code inherited from upstream willchen96/mike, which never ran ESLint in CI. Breakdown of fixes: - 16 react-hooks/set-state-in-effect (new in eslint-plugin-react-hooks 7 / Next 16): converted to the React "adjusting state during render" pattern, useSyncExternalStore for localStorage-backed state, or deferred initial measurements via requestAnimationFrame/setTimeout. - 2 react-hooks/refs in ChatView: dropped a no-op .current entry from a dep array that was already covered by an eslint-disable comment. - 1 react-hooks/immutability in DocView: hoisted scrollToHighlightOnPage above its first useCallback caller. - 1 react-hooks/static-components in WFColumnViewModal: switched the dynamic icon to React.createElement so we don't bind a component to a PascalCase local during render. - 11 @typescript-eslint/no-explicit-any: removed redundant casts (MikeMessage already typed files/error/workflow), typed the caret-from-point document shape, used unknown + narrowing in catch. - 5 react/no-unescaped-entities: escaped apostrophes/quotes in JSX text. - 2 @typescript-eslint/no-require-imports: ignored src/scripts/** in eslint config - the one file there is a CJS build-time conversion script, not part of the app bundle. next build still succeeds. Zero behavior changes intended - the React Compiler-aware rules were all addressed by restructuring effects into pure-render derivations rather than disabling them. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> | ||||
Capture this PR into my fork
Download a Markdown prompt that tells Claude how to port every
commit in this PR into your working tree. Run it via
claude -p < capture-pull-152.md from
inside the repo you want the changes in.