diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml new file mode 100644 index 000000000..a1fdac0db --- /dev/null +++ b/.github/workflows/typecheck.yml @@ -0,0 +1,55 @@ +name: Typecheck + +# Runs `yarn typecheck` from the repository root, which invokes +# `tsc --noEmit` in every TypeScript workspace. Complements the existing +# Lint and Test workflows (which do not run tsc) and catches type errors in +# seconds instead of waiting for the slow Docker-image build in pr-gate.yml. +# +# The web workspace is excluded here because `tsc --noEmit` in `packages/web` +# depends on `.next/types/**/*.ts` (declared in its tsconfig.json `include`) +# being generated by `next build`. Web is already type-checked transitively +# via the Docker build in pr-gate.yml. See issue #1437. + +on: + pull_request: + branches: ["main"] + + +jobs: + typecheck: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: "true" + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.x' + cache: 'yarn' + cache-dependency-path: '**/yarn.lock' + + - name: Install + run: yarn install --frozen-lockfile + + # Build the type-source-of-truth workspaces first (schemas, db, shared, + # query-language) so their generated .d.ts files are fresh. Without + # this step, downstream workspaces see stale types and `tsc --noEmit` + # surfaces drift as errors. + - name: Build dependencies + run: yarn build:deps + + # The db workspace's generated Prisma client must exist before its + # typecheck runs. Without this step, db's typecheck reports errors + # because the source-of-truth schema is newer than the generated client. + - name: Generate Prisma client + run: yarn workspace @sourcebot/db prisma:generate + + # Excludes @sourcebot/web (see comment above). Runs tsc --noEmit in + # each remaining workspace in topological order. + - name: Typecheck + run: yarn workspaces foreach --all --topological --exclude @sourcebot/web run typecheck diff --git a/package.json b/package.json index ed846875f..b5d7fa757 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "build": "cross-env SKIP_ENV_VALIDATION=1 yarn workspaces foreach --all --topological run build", "test": "yarn workspaces foreach --all --topological run test", "lint": "yarn workspaces foreach --all --topological run lint", + "typecheck": "yarn workspaces foreach --all --topological run typecheck", "dev": "concurrently --kill-others --names \"zoekt,worker,web,schemas\" 'yarn dev:zoekt' 'yarn dev:backend' 'yarn dev:web' 'yarn watch:schemas'", "with-env": "cross-env PATH=\"$PWD/bin:$PATH\" dotenv -e .env.development -c --", "dev:zoekt": "yarn with-env zoekt-webserver -index .sourcebot/index -rpc", diff --git a/packages/backend/package.json b/packages/backend/package.json index 7345ec2a2..b8739faba 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -8,6 +8,7 @@ "dev:watch": "tsc-watch --preserveWatchOutput --onSuccess \"yarn dev\"", "dev": "node ./dist/index.js", "build": "tsc", + "typecheck": "tsc --noEmit", "test": "cross-env SKIP_ENV_VALIDATION=1 vitest --config ./vitest.config.ts" }, "devDependencies": { diff --git a/packages/db/package.json b/packages/db/package.json index db623c5a2..ff728d659 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -5,6 +5,7 @@ "private": true, "scripts": { "build": "yarn prisma:generate && tsc", + "typecheck": "tsc --noEmit", "postinstall": "yarn build", "prisma:generate": "prisma generate", "prisma:generate:watch": "prisma generate --watch", diff --git a/packages/schemas/package.json b/packages/schemas/package.json index 3719a6da5..79dcae370 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "build": "yarn generate && tsc", + "typecheck": "tsc --noEmit", "generate": "tsx tools/generate.ts", "watch": "nodemon --watch ../../schemas -e json -x 'yarn build'", "postinstall": "yarn build" diff --git a/packages/shared/package.json b/packages/shared/package.json index 2a16111ff..7c4b4019e 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -5,6 +5,7 @@ "private": true, "scripts": { "build": "tsc", + "typecheck": "tsc --noEmit", "build:watch": "tsc-watch --preserveWatchOutput", "postinstall": "yarn build", "test": "vitest --config ./vitest.config.ts", diff --git a/packages/web/package.json b/packages/web/package.json index 0f06c0d58..01bc5bd2c 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -7,6 +7,7 @@ "build": "cross-env SKIP_ENV_VALIDATION=1 next build", "start": "next start", "lint": "cross-env SKIP_ENV_VALIDATION=1 eslint .", + "typecheck": "tsc --noEmit", "test": "cross-env SKIP_ENV_VALIDATION=1 vitest", "openapi:generate": "tsx tools/generateOpenApi.ts", "generate:protos": "proto-loader-gen-types --includeComments --longs=Number --enums=String --defaults --oneofs --grpcLib=@grpc/grpc-js --keepCase --includeDirs=../../vendor/zoekt/grpc/protos --outDir=src/proto zoekt/webserver/v1/webserver.proto zoekt/webserver/v1/query.proto",