From eba1d0aff5efc603137c42b51182acbf085a3b12 Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Fri, 9 Jan 2026 19:26:40 +0000 Subject: [PATCH 01/10] feat: implement git checkout caching to speed up CI workflows - Create cache-checkout action to save/restore git working directory - Update prepare job in pr.yml to cache checkout after dangerous-git-checkout - Update all downstream workflows to restore from cache instead of checkout - Pass commit-sha to all workflow calls for cache key consistency This reduces the number of full git checkouts from 20+ per workflow run to just 1, significantly improving CI performance especially for large repos. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/cache-checkout/action.yml | 36 ++++++++++++++ .github/workflows/api-v1-production-build.yml | 12 ++++- .github/workflows/api-v2-production-build.yml | 12 ++++- .github/workflows/api-v2-unit-tests.yml | 12 ++++- .github/workflows/atoms-production-build.yml | 12 ++++- .../check-api-v2-breaking-changes.yml | 12 ++++- .github/workflows/check-types.yml | 12 ++++- .github/workflows/companion-build.yml | 12 ++++- .github/workflows/docs-build.yml | 12 ++++- .github/workflows/e2e-api-v2.yml | 12 ++++- .github/workflows/e2e-app-store.yml | 12 ++++- .github/workflows/e2e-embed-react.yml | 12 ++++- .github/workflows/e2e-embed.yml | 12 ++++- .github/workflows/e2e.yml | 12 ++++- .github/workflows/integration-tests.yml | 12 ++++- .github/workflows/lint.yml | 12 ++++- .github/workflows/pr.yml | 48 +++++++++++++++++-- .../production-build-without-database.yml | 12 ++++- .github/workflows/setup-db.yml | 11 ++++- .github/workflows/unit-tests.yml | 12 ++++- 20 files changed, 277 insertions(+), 22 deletions(-) create mode 100644 .github/actions/cache-checkout/action.yml diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml new file mode 100644 index 00000000000000..09109e1c5ca614 --- /dev/null +++ b/.github/actions/cache-checkout/action.yml @@ -0,0 +1,36 @@ +name: Cache Git Checkout +description: "Save or restore git checkout from cache to speed up CI workflows" +inputs: + mode: + description: "Mode of operation: 'save' to cache the checkout, 'restore' to restore from cache" + required: true + commit-sha: + description: "The commit SHA to use as cache key" + required: true + +runs: + using: "composite" + steps: + - name: Restore git checkout from cache + if: ${{ inputs.mode == 'restore' }} + uses: actions/cache/restore@v4 + id: cache-restore + with: + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true + + - name: Save git checkout to cache + if: ${{ inputs.mode == 'save' }} + uses: actions/cache/save@v4 + with: + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} diff --git a/.github/workflows/api-v1-production-build.yml b/.github/workflows/api-v1-production-build.yml index 26d08fa9e8073d..3a8414c090d345 100644 --- a/.github/workflows/api-v1-production-build.yml +++ b/.github/workflows/api-v1-production-build.yml @@ -2,6 +2,11 @@ name: Production Builds on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: contents: read @@ -65,7 +70,12 @@ jobs: - 5432:5432 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - name: Cache API v1 production build diff --git a/.github/workflows/api-v2-production-build.yml b/.github/workflows/api-v2-production-build.yml index 177199661f6c32..1c4ce2e3dd7735 100644 --- a/.github/workflows/api-v2-production-build.yml +++ b/.github/workflows/api-v2-production-build.yml @@ -2,6 +2,11 @@ name: Production Build on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string env: DATABASE_URL: ${{ secrets.CI_DATABASE_URL }} @@ -35,7 +40,12 @@ jobs: - 5432:5432 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - name: Generate Prisma schemas working-directory: apps/api/v2 diff --git a/.github/workflows/api-v2-unit-tests.yml b/.github/workflows/api-v2-unit-tests.yml index 5c6fd7b69c4e5b..d98599a1a92e98 100644 --- a/.github/workflows/api-v2-unit-tests.yml +++ b/.github/workflows/api-v2-unit-tests.yml @@ -1,6 +1,11 @@ name: API v2 Unit on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string env: LINGO_DOT_DEV_API_KEY: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }} permissions: @@ -12,7 +17,12 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - run: yarn prisma generate - name: Run API v2 unit tests diff --git a/.github/workflows/atoms-production-build.yml b/.github/workflows/atoms-production-build.yml index b8fc029accedc3..7e30bc5ab97b8c 100644 --- a/.github/workflows/atoms-production-build.yml +++ b/.github/workflows/atoms-production-build.yml @@ -2,6 +2,11 @@ name: Atoms production Build on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string jobs: build: @@ -12,7 +17,12 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - name: Cache atoms production build uses: actions/cache@v4 diff --git a/.github/workflows/check-api-v2-breaking-changes.yml b/.github/workflows/check-api-v2-breaking-changes.yml index b41d3b719b7bff..39ceecac10c5a9 100644 --- a/.github/workflows/check-api-v2-breaking-changes.yml +++ b/.github/workflows/check-api-v2-breaking-changes.yml @@ -2,6 +2,11 @@ name: Check API v2 breaking changes on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: contents: read @@ -34,7 +39,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - name: Generate Swagger diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index f640b75d9633c2..5f6db588cf5ed6 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -1,6 +1,11 @@ name: Check types on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string env: NODE_OPTIONS: --max-old-space-size=4096 TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} @@ -12,7 +17,12 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - name: Show info run: node -e "console.log(require('v8').getHeapStatistics())" diff --git a/.github/workflows/companion-build.yml b/.github/workflows/companion-build.yml index 12985b43eb228a..1866ad692b71a6 100644 --- a/.github/workflows/companion-build.yml +++ b/.github/workflows/companion-build.yml @@ -2,6 +2,11 @@ name: Companion Builds on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: contents: read @@ -17,7 +22,12 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - name: Setup Bun uses: oven-sh/setup-bun@v1 diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index ccf44ed8a6ac46..45e8d6131bd07c 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -3,6 +3,11 @@ name: Build on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string jobs: build: @@ -12,7 +17,12 @@ jobs: runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - name: Cache Docs build uses: actions/cache@v4 id: cache-docs-build diff --git a/.github/workflows/e2e-api-v2.yml b/.github/workflows/e2e-api-v2.yml index 267c6baf958f49..d3cff8a9d27c41 100644 --- a/.github/workflows/e2e-api-v2.yml +++ b/.github/workflows/e2e-api-v2.yml @@ -1,6 +1,11 @@ name: Check breaking changes and run E2E on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string env: ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }} API_KEY_PREFIX: ${{ secrets.CI_API_KEY_PREFIX }} @@ -74,7 +79,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - name: Build platform packages with Turbo diff --git a/.github/workflows/e2e-app-store.yml b/.github/workflows/e2e-app-store.yml index e3e1774c805d28..055c7645fcfecb 100644 --- a/.github/workflows/e2e-app-store.yml +++ b/.github/workflows/e2e-app-store.yml @@ -1,6 +1,11 @@ name: E2E App Store Tests on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: actions: write contents: read @@ -81,7 +86,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e-embed-react.yml b/.github/workflows/e2e-embed-react.yml index a58cac84840255..b9f52b366104eb 100644 --- a/.github/workflows/e2e-embed-react.yml +++ b/.github/workflows/e2e-embed-react.yml @@ -1,6 +1,11 @@ name: E2E Embed React tests and booking flow (for non-embed as well) on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: actions: write contents: read @@ -73,7 +78,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e-embed.yml b/.github/workflows/e2e-embed.yml index c3b9b5e3c642ea..6312e5615831de 100644 --- a/.github/workflows/e2e-embed.yml +++ b/.github/workflows/e2e-embed.yml @@ -1,6 +1,11 @@ name: E2E Embed Core tests and booking flow (for non-embed as well) on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: actions: write contents: read @@ -81,7 +86,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 54a20cb066ce53..f3c27b573434d7 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,6 +1,11 @@ name: E2E on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: actions: write contents: read @@ -82,7 +87,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 83605ea5ccba94..bf6aaf5b3d7821 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -1,6 +1,11 @@ name: Integration on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: contents: read env: @@ -79,7 +84,12 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - run: yarn prisma generate - uses: ./.github/actions/cache-db diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 76dd0d24a400f7..db870e9230888f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,11 @@ name: Lint on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: actions: write contents: read @@ -10,7 +15,12 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - name: Run Lint run: yarn lint diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 3a05287fdfb06b..8d872b5ae7e640 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -175,6 +175,15 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/dangerous-git-checkout + - name: Get Latest Commit SHA + id: get_sha + run: | + echo "commit-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + - name: Cache git checkout + uses: ./.github/actions/cache-checkout + with: + mode: save + commit-sha: ${{ steps.get_sha.outputs.commit-sha }} - name: Generate DB cache key id: cache-db-key uses: ./.github/actions/cache-db-key @@ -212,10 +221,6 @@ jobs: - "packages/trpc/**" - "packages/prisma/schema.prisma" - "docs/api-reference/v2/**" - - name: Get Latest Commit SHA - id: get_sha - run: | - echo "commit-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Check if PR exists with ready-for-e2e label for this SHA id: check-if-pr-has-label uses: actions/github-script@v7 @@ -290,6 +295,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/check-types.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit lint: @@ -297,6 +304,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/lint.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit unit-test: @@ -304,6 +313,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/unit-tests.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit api-v2-unit-test: @@ -311,6 +322,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/api-v2-unit-tests.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit setup-db: @@ -320,6 +333,7 @@ jobs: uses: ./.github/workflows/setup-db.yml with: DB_CACHE_HIT: ${{ needs.prepare.outputs.db-cache-hit }} + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-api-v1: @@ -327,6 +341,8 @@ jobs: needs: [prepare, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/api-v1-production-build.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-api-v2: @@ -334,6 +350,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/api-v2-production-build.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-atoms: @@ -341,6 +359,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/atoms-production-build.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-docs: @@ -348,6 +368,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/docs-build.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-companion: @@ -355,6 +377,8 @@ jobs: needs: [prepare] if: needs.prepare.outputs.has_companion == 'true' uses: ./.github/workflows/companion-build.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build: @@ -362,6 +386,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/production-build-without-database.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit integration-test: @@ -369,6 +395,8 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/integration-tests.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e: @@ -376,6 +404,8 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit check-api-v2-breaking-changes: @@ -383,6 +413,8 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-api-v2-changes == 'true' }} uses: ./.github/workflows/check-api-v2-breaking-changes.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-api-v2: @@ -390,6 +422,8 @@ jobs: needs: [prepare, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-api-v2.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-app-store: @@ -397,6 +431,8 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-app-store.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-embed: @@ -404,6 +440,8 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-embed.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-embed-react: @@ -411,6 +449,8 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-embed-react.yml + with: + commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit analyze: diff --git a/.github/workflows/production-build-without-database.yml b/.github/workflows/production-build-without-database.yml index 78920c5fb671f2..628384a9fce4b3 100644 --- a/.github/workflows/production-build-without-database.yml +++ b/.github/workflows/production-build-without-database.yml @@ -1,6 +1,11 @@ name: Production Builds on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: contents: read @@ -43,7 +48,12 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - run: yarn prisma generate - name: Generate cache key diff --git a/.github/workflows/setup-db.yml b/.github/workflows/setup-db.yml index f0634a0c68502e..eec03575469f26 100644 --- a/.github/workflows/setup-db.yml +++ b/.github/workflows/setup-db.yml @@ -8,6 +8,10 @@ on: type: string default: "false" description: "Whether the DB cache was hit (skip yarn-install and cache-db if true)" + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string permissions: contents: read @@ -47,7 +51,12 @@ jobs: - 5432:5432 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install if: inputs.DB_CACHE_HIT != 'true' - run: yarn prisma generate diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index a922ec9698aaad..56ccf5b9a2397a 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,6 +1,11 @@ name: Unit on: workflow_call: + inputs: + commit-sha: + description: "Commit SHA for cache key" + required: true + type: string env: LINGO_DOT_DEV_API_KEY: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }} permissions: @@ -12,7 +17,12 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - uses: actions/checkout@v4 - - uses: ./.github/actions/dangerous-git-checkout + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore + commit-sha: ${{ inputs.commit-sha }} - uses: ./.github/actions/yarn-install - run: yarn prisma generate - run: yarn test -- --no-isolate From 7ab859bb534dea77cb1491cec9d5986ff0fa1656 Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Fri, 9 Jan 2026 19:33:06 +0000 Subject: [PATCH 02/10] refactor: use actions/cache/restore directly instead of custom action Remove sparse-checkout and use actions/cache/restore@v4 directly in all downstream workflows. This eliminates the need for any git fetch operation before restoring from cache, making the optimization more effective. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/api-v1-production-build.yml | 15 +++++++++------ .github/workflows/api-v2-production-build.yml | 15 +++++++++------ .github/workflows/api-v2-unit-tests.yml | 15 +++++++++------ .github/workflows/atoms-production-build.yml | 15 +++++++++------ .../workflows/check-api-v2-breaking-changes.yml | 15 +++++++++------ .github/workflows/check-types.yml | 15 +++++++++------ .github/workflows/companion-build.yml | 15 +++++++++------ .github/workflows/docs-build.yml | 15 +++++++++------ .github/workflows/e2e-api-v2.yml | 15 +++++++++------ .github/workflows/e2e-app-store.yml | 15 +++++++++------ .github/workflows/e2e-embed-react.yml | 15 +++++++++------ .github/workflows/e2e-embed.yml | 15 +++++++++------ .github/workflows/e2e.yml | 15 +++++++++------ .github/workflows/integration-tests.yml | 15 +++++++++------ .github/workflows/lint.yml | 15 +++++++++------ .../production-build-without-database.yml | 15 +++++++++------ .github/workflows/setup-db.yml | 15 +++++++++------ .github/workflows/unit-tests.yml | 15 +++++++++------ 18 files changed, 162 insertions(+), 108 deletions(-) diff --git a/.github/workflows/api-v1-production-build.yml b/.github/workflows/api-v1-production-build.yml index 3a8414c090d345..d8ca35eed7f7a1 100644 --- a/.github/workflows/api-v1-production-build.yml +++ b/.github/workflows/api-v1-production-build.yml @@ -69,13 +69,16 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - name: Cache API v1 production build diff --git a/.github/workflows/api-v2-production-build.yml b/.github/workflows/api-v2-production-build.yml index 1c4ce2e3dd7735..a3d27cf0568057 100644 --- a/.github/workflows/api-v2-production-build.yml +++ b/.github/workflows/api-v2-production-build.yml @@ -39,13 +39,16 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - name: Generate Prisma schemas working-directory: apps/api/v2 diff --git a/.github/workflows/api-v2-unit-tests.yml b/.github/workflows/api-v2-unit-tests.yml index d98599a1a92e98..08b26b1977ab6b 100644 --- a/.github/workflows/api-v2-unit-tests.yml +++ b/.github/workflows/api-v2-unit-tests.yml @@ -16,13 +16,16 @@ jobs: timeout-minutes: 20 runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - run: yarn prisma generate - name: Run API v2 unit tests diff --git a/.github/workflows/atoms-production-build.yml b/.github/workflows/atoms-production-build.yml index 7e30bc5ab97b8c..b3c107543e1726 100644 --- a/.github/workflows/atoms-production-build.yml +++ b/.github/workflows/atoms-production-build.yml @@ -16,13 +16,16 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - name: Cache atoms production build uses: actions/cache@v4 diff --git a/.github/workflows/check-api-v2-breaking-changes.yml b/.github/workflows/check-api-v2-breaking-changes.yml index 39ceecac10c5a9..728a9cb3e13240 100644 --- a/.github/workflows/check-api-v2-breaking-changes.yml +++ b/.github/workflows/check-api-v2-breaking-changes.yml @@ -38,13 +38,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - name: Generate Swagger diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index 5f6db588cf5ed6..3f87ae2b055bcb 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -16,13 +16,16 @@ jobs: check-types: runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - name: Show info run: node -e "console.log(require('v8').getHeapStatistics())" diff --git a/.github/workflows/companion-build.yml b/.github/workflows/companion-build.yml index 1866ad692b71a6..91409ac616a0f2 100644 --- a/.github/workflows/companion-build.yml +++ b/.github/workflows/companion-build.yml @@ -21,13 +21,16 @@ jobs: timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - name: Setup Bun uses: oven-sh/setup-bun@v1 diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 45e8d6131bd07c..104689b0212b59 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -16,13 +16,16 @@ jobs: contents: read runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - name: Cache Docs build uses: actions/cache@v4 id: cache-docs-build diff --git a/.github/workflows/e2e-api-v2.yml b/.github/workflows/e2e-api-v2.yml index d3cff8a9d27c41..fb8d2271bdd198 100644 --- a/.github/workflows/e2e-api-v2.yml +++ b/.github/workflows/e2e-api-v2.yml @@ -78,13 +78,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - name: Build platform packages with Turbo diff --git a/.github/workflows/e2e-app-store.yml b/.github/workflows/e2e-app-store.yml index 055c7645fcfecb..c2e9ad98273cf4 100644 --- a/.github/workflows/e2e-app-store.yml +++ b/.github/workflows/e2e-app-store.yml @@ -85,13 +85,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e-embed-react.yml b/.github/workflows/e2e-embed-react.yml index b9f52b366104eb..931cd77a661e26 100644 --- a/.github/workflows/e2e-embed-react.yml +++ b/.github/workflows/e2e-embed-react.yml @@ -77,13 +77,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e-embed.yml b/.github/workflows/e2e-embed.yml index 6312e5615831de..4cae09dafcf115 100644 --- a/.github/workflows/e2e-embed.yml +++ b/.github/workflows/e2e-embed.yml @@ -85,13 +85,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f3c27b573434d7..0586fa25956e4e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -86,13 +86,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index bf6aaf5b3d7821..5731ac264fd966 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -83,13 +83,16 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - run: yarn prisma generate - uses: ./.github/actions/cache-db diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index db870e9230888f..a3ee9357bb2a5b 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,13 +14,16 @@ jobs: runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - name: Run Lint run: yarn lint diff --git a/.github/workflows/production-build-without-database.yml b/.github/workflows/production-build-without-database.yml index 628384a9fce4b3..c65591c27c9268 100644 --- a/.github/workflows/production-build-without-database.yml +++ b/.github/workflows/production-build-without-database.yml @@ -47,13 +47,16 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - run: yarn prisma generate - name: Generate cache key diff --git a/.github/workflows/setup-db.yml b/.github/workflows/setup-db.yml index eec03575469f26..27ec749b11b726 100644 --- a/.github/workflows/setup-db.yml +++ b/.github/workflows/setup-db.yml @@ -50,13 +50,16 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install if: inputs.DB_CACHE_HIT != 'true' - run: yarn prisma generate diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 56ccf5b9a2397a..54abe4dfacc7b8 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,13 +16,16 @@ jobs: timeout-minutes: 20 runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - - uses: actions/checkout@v4 + - name: Restore git checkout from cache + uses: actions/cache/restore@v4 with: - sparse-checkout: .github - - uses: ./.github/actions/cache-checkout - with: - mode: restore - commit-sha: ${{ inputs.commit-sha }} + path: | + . + !.git + !node_modules + !**/node_modules + key: git-checkout-${{ inputs.commit-sha }} + fail-on-cache-miss: true - uses: ./.github/actions/yarn-install - run: yarn prisma generate - run: yarn test -- --no-isolate From 12e49c1f9d1855edc9c15b84e9cb949167a5c653 Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Fri, 9 Jan 2026 19:42:04 +0000 Subject: [PATCH 03/10] refactor: use github.event.pull_request.head.sha for cache key - Remove commit-sha input from all downstream workflows - Update cache-checkout action to use github.event.pull_request.head.sha directly - Remove commit-sha output from prepare job - Remove commit-sha from all workflow calls in pr.yml - Keep sparse-checkout of .github to access the cache-checkout action This eliminates the need to pass commit-sha around while still using a reusable action for the cache restore logic. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/cache-checkout/action.yml | 7 +--- .github/workflows/api-v1-production-build.yml | 19 +++------ .github/workflows/api-v2-production-build.yml | 19 +++------ .github/workflows/api-v2-unit-tests.yml | 19 +++------ .github/workflows/atoms-production-build.yml | 19 +++------ .../check-api-v2-breaking-changes.yml | 19 +++------ .github/workflows/check-types.yml | 19 +++------ .github/workflows/companion-build.yml | 19 +++------ .github/workflows/docs-build.yml | 19 +++------ .github/workflows/e2e-api-v2.yml | 19 +++------ .github/workflows/e2e-app-store.yml | 19 +++------ .github/workflows/e2e-embed-react.yml | 19 +++------ .github/workflows/e2e-embed.yml | 19 +++------ .github/workflows/e2e.yml | 19 +++------ .github/workflows/integration-tests.yml | 19 +++------ .github/workflows/lint.yml | 19 +++------ .github/workflows/pr.yml | 41 ------------------- .../production-build-without-database.yml | 19 +++------ .github/workflows/setup-db.yml | 18 +++----- .github/workflows/unit-tests.yml | 19 +++------ 20 files changed, 92 insertions(+), 297 deletions(-) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index 09109e1c5ca614..7ebcb2892386de 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -4,9 +4,6 @@ inputs: mode: description: "Mode of operation: 'save' to cache the checkout, 'restore' to restore from cache" required: true - commit-sha: - description: "The commit SHA to use as cache key" - required: true runs: using: "composite" @@ -21,7 +18,7 @@ runs: !.git !node_modules !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} + key: git-checkout-${{ github.event.pull_request.head.sha }} fail-on-cache-miss: true - name: Save git checkout to cache @@ -33,4 +30,4 @@ runs: !.git !node_modules !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} + key: git-checkout-${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/api-v1-production-build.yml b/.github/workflows/api-v1-production-build.yml index d8ca35eed7f7a1..380340d37d13b2 100644 --- a/.github/workflows/api-v1-production-build.yml +++ b/.github/workflows/api-v1-production-build.yml @@ -2,11 +2,6 @@ name: Production Builds on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: contents: read @@ -69,16 +64,12 @@ jobs: ports: - 5432:5432 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - name: Cache API v1 production build diff --git a/.github/workflows/api-v2-production-build.yml b/.github/workflows/api-v2-production-build.yml index a3d27cf0568057..2d2e9cb47216c0 100644 --- a/.github/workflows/api-v2-production-build.yml +++ b/.github/workflows/api-v2-production-build.yml @@ -2,11 +2,6 @@ name: Production Build on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string env: DATABASE_URL: ${{ secrets.CI_DATABASE_URL }} @@ -39,16 +34,12 @@ jobs: ports: - 5432:5432 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - name: Generate Prisma schemas working-directory: apps/api/v2 diff --git a/.github/workflows/api-v2-unit-tests.yml b/.github/workflows/api-v2-unit-tests.yml index 08b26b1977ab6b..bc33f8b4a853a1 100644 --- a/.github/workflows/api-v2-unit-tests.yml +++ b/.github/workflows/api-v2-unit-tests.yml @@ -1,11 +1,6 @@ name: API v2 Unit on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string env: LINGO_DOT_DEV_API_KEY: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }} permissions: @@ -16,16 +11,12 @@ jobs: timeout-minutes: 20 runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - run: yarn prisma generate - name: Run API v2 unit tests diff --git a/.github/workflows/atoms-production-build.yml b/.github/workflows/atoms-production-build.yml index b3c107543e1726..ef6f9a4210536f 100644 --- a/.github/workflows/atoms-production-build.yml +++ b/.github/workflows/atoms-production-build.yml @@ -2,11 +2,6 @@ name: Atoms production Build on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string jobs: build: @@ -16,16 +11,12 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 30 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - name: Cache atoms production build uses: actions/cache@v4 diff --git a/.github/workflows/check-api-v2-breaking-changes.yml b/.github/workflows/check-api-v2-breaking-changes.yml index 728a9cb3e13240..270f0bd08ccf8f 100644 --- a/.github/workflows/check-api-v2-breaking-changes.yml +++ b/.github/workflows/check-api-v2-breaking-changes.yml @@ -2,11 +2,6 @@ name: Check API v2 breaking changes on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: contents: read @@ -38,16 +33,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - name: Generate Swagger diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index 3f87ae2b055bcb..bd2da476723597 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -1,11 +1,6 @@ name: Check types on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string env: NODE_OPTIONS: --max-old-space-size=4096 TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} @@ -16,16 +11,12 @@ jobs: check-types: runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - name: Show info run: node -e "console.log(require('v8').getHeapStatistics())" diff --git a/.github/workflows/companion-build.yml b/.github/workflows/companion-build.yml index 91409ac616a0f2..58cd1be35d987e 100644 --- a/.github/workflows/companion-build.yml +++ b/.github/workflows/companion-build.yml @@ -2,11 +2,6 @@ name: Companion Builds on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: contents: read @@ -21,16 +16,12 @@ jobs: timeout-minutes: 30 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - name: Setup Bun uses: oven-sh/setup-bun@v1 diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 104689b0212b59..6e869ff753b8c1 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -3,11 +3,6 @@ name: Build on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string jobs: build: @@ -16,16 +11,12 @@ jobs: contents: read runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - name: Cache Docs build uses: actions/cache@v4 id: cache-docs-build diff --git a/.github/workflows/e2e-api-v2.yml b/.github/workflows/e2e-api-v2.yml index fb8d2271bdd198..9656c4b4737143 100644 --- a/.github/workflows/e2e-api-v2.yml +++ b/.github/workflows/e2e-api-v2.yml @@ -1,11 +1,6 @@ name: Check breaking changes and run E2E on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string env: ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }} API_KEY_PREFIX: ${{ secrets.CI_API_KEY_PREFIX }} @@ -78,16 +73,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - name: Build platform packages with Turbo diff --git a/.github/workflows/e2e-app-store.yml b/.github/workflows/e2e-app-store.yml index c2e9ad98273cf4..d7bede4762d0d2 100644 --- a/.github/workflows/e2e-app-store.yml +++ b/.github/workflows/e2e-app-store.yml @@ -1,11 +1,6 @@ name: E2E App Store Tests on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: actions: write contents: read @@ -85,16 +80,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e-embed-react.yml b/.github/workflows/e2e-embed-react.yml index 931cd77a661e26..5ece5472a754b9 100644 --- a/.github/workflows/e2e-embed-react.yml +++ b/.github/workflows/e2e-embed-react.yml @@ -1,11 +1,6 @@ name: E2E Embed React tests and booking flow (for non-embed as well) on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: actions: write contents: read @@ -77,16 +72,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e-embed.yml b/.github/workflows/e2e-embed.yml index 4cae09dafcf115..eec3307fc36c15 100644 --- a/.github/workflows/e2e-embed.yml +++ b/.github/workflows/e2e-embed.yml @@ -1,11 +1,6 @@ name: E2E Embed Core tests and booking flow (for non-embed as well) on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: actions: write contents: read @@ -85,16 +80,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 0586fa25956e4e..8495fef8231d73 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,11 +1,6 @@ name: E2E on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: actions: write contents: read @@ -86,16 +81,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - uses: ./.github/actions/yarn-playwright-install - run: yarn prisma generate diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 5731ac264fd966..1ea84258531392 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -1,11 +1,6 @@ name: Integration on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: contents: read env: @@ -83,16 +78,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - run: yarn prisma generate - uses: ./.github/actions/cache-db diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a3ee9357bb2a5b..a141c1579f2815 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,11 +1,6 @@ name: Lint on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: actions: write contents: read @@ -14,16 +9,12 @@ jobs: runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - name: Run Lint run: yarn lint diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 8d872b5ae7e640..d63fcd71e20122 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -169,21 +169,15 @@ jobs: has-files-requiring-all-checks: ${{ steps.filter.outputs.has-files-requiring-all-checks }} has_companion: ${{ steps.filter.outputs.has_companion }} has-api-v2-changes: ${{ steps.filter.outputs.has-api-v2-changes }} - commit-sha: ${{ steps.get_sha.outputs.commit-sha }} run-e2e: ${{ steps.check-if-pr-has-label.outputs.run-e2e == 'true' }} db-cache-hit: ${{ steps.cache-db-check.outputs.cache-hit }} steps: - uses: actions/checkout@v4 - uses: ./.github/actions/dangerous-git-checkout - - name: Get Latest Commit SHA - id: get_sha - run: | - echo "commit-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Cache git checkout uses: ./.github/actions/cache-checkout with: mode: save - commit-sha: ${{ steps.get_sha.outputs.commit-sha }} - name: Generate DB cache key id: cache-db-key uses: ./.github/actions/cache-db-key @@ -295,8 +289,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/check-types.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit lint: @@ -304,8 +296,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/lint.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit unit-test: @@ -313,8 +303,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/unit-tests.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit api-v2-unit-test: @@ -322,8 +310,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/api-v2-unit-tests.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit setup-db: @@ -333,7 +319,6 @@ jobs: uses: ./.github/workflows/setup-db.yml with: DB_CACHE_HIT: ${{ needs.prepare.outputs.db-cache-hit }} - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-api-v1: @@ -341,8 +326,6 @@ jobs: needs: [prepare, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/api-v1-production-build.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-api-v2: @@ -350,8 +333,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/api-v2-production-build.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-atoms: @@ -359,8 +340,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/atoms-production-build.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-docs: @@ -368,8 +347,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/docs-build.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build-companion: @@ -377,8 +354,6 @@ jobs: needs: [prepare] if: needs.prepare.outputs.has_companion == 'true' uses: ./.github/workflows/companion-build.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit build: @@ -386,8 +361,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/production-build-without-database.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit integration-test: @@ -395,8 +368,6 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/integration-tests.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e: @@ -404,8 +375,6 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit check-api-v2-breaking-changes: @@ -413,8 +382,6 @@ jobs: needs: [prepare] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-api-v2-changes == 'true' }} uses: ./.github/workflows/check-api-v2-breaking-changes.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-api-v2: @@ -422,8 +389,6 @@ jobs: needs: [prepare, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-api-v2.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-app-store: @@ -431,8 +396,6 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-app-store.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-embed: @@ -440,8 +403,6 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-embed.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit e2e-embed-react: @@ -449,8 +410,6 @@ jobs: needs: [prepare, build, setup-db] if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-embed-react.yml - with: - commit-sha: ${{ needs.prepare.outputs.commit-sha }} secrets: inherit analyze: diff --git a/.github/workflows/production-build-without-database.yml b/.github/workflows/production-build-without-database.yml index c65591c27c9268..512efe6ac710be 100644 --- a/.github/workflows/production-build-without-database.yml +++ b/.github/workflows/production-build-without-database.yml @@ -1,11 +1,6 @@ name: Production Builds on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: contents: read @@ -47,16 +42,12 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 30 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - run: yarn prisma generate - name: Generate cache key diff --git a/.github/workflows/setup-db.yml b/.github/workflows/setup-db.yml index 27ec749b11b726..66e4ea042fd484 100644 --- a/.github/workflows/setup-db.yml +++ b/.github/workflows/setup-db.yml @@ -8,10 +8,6 @@ on: type: string default: "false" description: "Whether the DB cache was hit (skip yarn-install and cache-db if true)" - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string permissions: contents: read @@ -50,16 +46,12 @@ jobs: ports: - 5432:5432 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 + with: + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + mode: restore - uses: ./.github/actions/yarn-install if: inputs.DB_CACHE_HIT != 'true' - run: yarn prisma generate diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 54abe4dfacc7b8..532ddb77a81ba9 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,11 +1,6 @@ name: Unit on: workflow_call: - inputs: - commit-sha: - description: "Commit SHA for cache key" - required: true - type: string env: LINGO_DOT_DEV_API_KEY: ${{ secrets.CI_LINGO_DOT_DEV_API_KEY }} permissions: @@ -16,16 +11,12 @@ jobs: timeout-minutes: 20 runs-on: blacksmith-4vcpu-ubuntu-2404 steps: - - name: Restore git checkout from cache - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: | - . - !.git - !node_modules - !**/node_modules - key: git-checkout-${{ inputs.commit-sha }} - fail-on-cache-miss: true + sparse-checkout: .github + - uses: ./.github/actions/cache-checkout + with: + mode: restore - uses: ./.github/actions/yarn-install - run: yarn prisma generate - run: yarn test -- --no-isolate From 0e85c4170433fc44d3f9e8fdcf9a2296295386be Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Sat, 10 Jan 2026 02:45:54 +0000 Subject: [PATCH 04/10] fix: update cache key to include branch name and add cache cleanup Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/cache-checkout/action.yml | 4 ++-- .github/workflows/delete-blacksmith-cache.yml | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index 7ebcb2892386de..8547261356b7af 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -18,7 +18,7 @@ runs: !.git !node_modules !**/node_modules - key: git-checkout-${{ github.event.pull_request.head.sha }} + key: git-checkout-${{ github.event.pull_request.head.ref }}-${{ github.event.pull_request.head.sha }} fail-on-cache-miss: true - name: Save git checkout to cache @@ -30,4 +30,4 @@ runs: !.git !node_modules !**/node_modules - key: git-checkout-${{ github.event.pull_request.head.sha }} + key: git-checkout-${{ github.event.pull_request.head.ref }}-${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/delete-blacksmith-cache.yml b/.github/workflows/delete-blacksmith-cache.yml index 26addc991fecc6..2ee4bf8985012c 100644 --- a/.github/workflows/delete-blacksmith-cache.yml +++ b/.github/workflows/delete-blacksmith-cache.yml @@ -31,3 +31,13 @@ jobs: with: key: ${{ env.CACHE_NAME }}-${{ github.event.pull_request.head.ref }} prefix: "true" + + delete-git-checkout-cache-on-pr-close: + if: github.event_name == 'pull_request' && github.event.action == 'closed' + runs-on: blacksmith-2vcpu-ubuntu-2404 + steps: + - name: Delete git-checkout cache + uses: useblacksmith/cache-delete@v1 + with: + key: git-checkout-${{ github.event.pull_request.head.ref }} + prefix: "true" From 17d00c204607e98c241401d03584423acd04f632 Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Sat, 10 Jan 2026 02:52:38 +0000 Subject: [PATCH 05/10] fix: use github.head_ref and github.sha for cache key Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/cache-checkout/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index 8547261356b7af..d2a8e66864e89a 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -18,7 +18,7 @@ runs: !.git !node_modules !**/node_modules - key: git-checkout-${{ github.event.pull_request.head.ref }}-${{ github.event.pull_request.head.sha }} + key: git-checkout-${{ github.head_ref || github.ref_name }}-${{ github.sha }} fail-on-cache-miss: true - name: Save git checkout to cache @@ -30,4 +30,4 @@ runs: !.git !node_modules !**/node_modules - key: git-checkout-${{ github.event.pull_request.head.ref }}-${{ github.event.pull_request.head.sha }} + key: git-checkout-${{ github.head_ref || github.ref_name }}-${{ github.sha }} From 92d32cf694b7f6eb43e3cd74fcdd7aa943a73222 Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Sat, 10 Jan 2026 02:58:13 +0000 Subject: [PATCH 06/10] fix: add prefix delete before saving cache to clear previous caches Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/cache-checkout/action.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index d2a8e66864e89a..fba94c7f99895b 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -21,6 +21,13 @@ runs: key: git-checkout-${{ github.head_ref || github.ref_name }}-${{ github.sha }} fail-on-cache-miss: true + - name: Delete previous git-checkout caches for this branch + if: ${{ inputs.mode == 'save' }} + uses: useblacksmith/cache-delete@v1 + with: + key: git-checkout-${{ github.head_ref || github.ref_name }} + prefix: "true" + - name: Save git checkout to cache if: ${{ inputs.mode == 'save' }} uses: actions/cache/save@v4 From 7aeafa4ef01e84b8160a8f5f558d421957fa44ef Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Sat, 10 Jan 2026 03:07:26 +0000 Subject: [PATCH 07/10] perf: add sparse-checkout to exclude example-apps and mp4 files Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/actions/dangerous-git-checkout/action.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/dangerous-git-checkout/action.yml b/.github/actions/dangerous-git-checkout/action.yml index c2dccc4e290e27..6a3dd50f87d5cc 100644 --- a/.github/actions/dangerous-git-checkout/action.yml +++ b/.github/actions/dangerous-git-checkout/action.yml @@ -8,3 +8,8 @@ runs: with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 2 + sparse-checkout-cone-mode: false + sparse-checkout: | + /* + !/example-apps/ + !**/*.mp4 From 32d6f3ef575c9f5e61fce80078e829331444edb9 Mon Sep 17 00:00:00 2001 From: "keith@cal.com" Date: Sat, 10 Jan 2026 03:13:40 +0000 Subject: [PATCH 08/10] fix: restore get_sha step and commit-sha output that was accidentally removed Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .github/workflows/pr.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index d63fcd71e20122..b99abd9df869b7 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -169,6 +169,7 @@ jobs: has-files-requiring-all-checks: ${{ steps.filter.outputs.has-files-requiring-all-checks }} has_companion: ${{ steps.filter.outputs.has_companion }} has-api-v2-changes: ${{ steps.filter.outputs.has-api-v2-changes }} + commit-sha: ${{ steps.get_sha.outputs.commit-sha }} run-e2e: ${{ steps.check-if-pr-has-label.outputs.run-e2e == 'true' }} db-cache-hit: ${{ steps.cache-db-check.outputs.cache-hit }} steps: @@ -215,6 +216,10 @@ jobs: - "packages/trpc/**" - "packages/prisma/schema.prisma" - "docs/api-reference/v2/**" + - name: Get Latest Commit SHA + id: get_sha + run: | + echo "commit-sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Check if PR exists with ready-for-e2e label for this SHA id: check-if-pr-has-label uses: actions/github-script@v7 From cdcf664320e15f6464675f9219aa9a35ee5bafd2 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 10 Jan 2026 09:03:56 +0000 Subject: [PATCH 09/10] fix: add trailing dash to cache key prefix to prevent accidental deletion of other branches' caches The prefix-based cache deletion was using 'git-checkout-{branch}' which would accidentally match and delete caches for branches with similar prefixes. For example, branch 'feature' would delete caches for 'feature-2', 'feature-new', etc. Adding a trailing '-' ensures exact branch matching: - 'git-checkout-feature-' matches 'git-checkout-feature-abc123' (intended) - 'git-checkout-feature-' does NOT match 'git-checkout-feature-2-def456' (correct) Fixes both the cache-checkout action and the PR close cleanup workflow. Co-Authored-By: unknown <> --- .github/actions/cache-checkout/action.yml | 2 +- .github/workflows/delete-blacksmith-cache.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index fba94c7f99895b..514d8e4c007cee 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -25,7 +25,7 @@ runs: if: ${{ inputs.mode == 'save' }} uses: useblacksmith/cache-delete@v1 with: - key: git-checkout-${{ github.head_ref || github.ref_name }} + key: git-checkout-${{ github.head_ref || github.ref_name }}- prefix: "true" - name: Save git checkout to cache diff --git a/.github/workflows/delete-blacksmith-cache.yml b/.github/workflows/delete-blacksmith-cache.yml index 2ee4bf8985012c..5a84df5f482dcc 100644 --- a/.github/workflows/delete-blacksmith-cache.yml +++ b/.github/workflows/delete-blacksmith-cache.yml @@ -39,5 +39,5 @@ jobs: - name: Delete git-checkout cache uses: useblacksmith/cache-delete@v1 with: - key: git-checkout-${{ github.event.pull_request.head.ref }} + key: git-checkout-${{ github.event.pull_request.head.ref }}- prefix: "true" From 83cc88921fa81b09b0e4f13c4c0b341970f32fc1 Mon Sep 17 00:00:00 2001 From: ofir-frd Date: Tue, 20 Jan 2026 20:02:26 +0200 Subject: [PATCH 10/10] Apply changes for benchmark PR --- .github/workflows/api-v2-unit-tests.yml | 2 +- AGENTS.md | 318 ++++++++---------------- 2 files changed, 101 insertions(+), 219 deletions(-) diff --git a/.github/workflows/api-v2-unit-tests.yml b/.github/workflows/api-v2-unit-tests.yml index bc33f8b4a853a1..822ff051054a88 100644 --- a/.github/workflows/api-v2-unit-tests.yml +++ b/.github/workflows/api-v2-unit-tests.yml @@ -23,4 +23,4 @@ jobs: working-directory: apps/api/v2 run: | export NODE_OPTIONS="--max_old_space_size=8192" - yarn workspace @calcom/platform-libraries build && yarn test + TZ=America/New_York yarn workspace @calcom/platform-libraries build && yarn test diff --git a/AGENTS.md b/AGENTS.md index a7dbde3ac4611c..879c978338fdb5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,221 +1,103 @@ -# Cal.com Development Guide for AI Agents +# Compliance Rules -You are a senior Cal.com engineer working in a Yarn/Turbo monorepo. You prioritize type safety, security, and small, reviewable diffs. +This file contains the compliance and code quality rules for this repository. -## Do +## 1. Repository and Service Classes Must Follow Naming Conventions -- Use `select` instead of `include` in Prisma queries for performance and security -- Use `import type { X }` for TypeScript type imports -- Use early returns to reduce nesting: `if (!booking) return null;` -- Use `ErrorWithCode` for errors in non-tRPC files (services, repositories, utilities); use `TRPCError` only in tRPC routers -- Use conventional commits: `feat:`, `fix:`, `refactor:` -- Create PRs in draft mode by default -- Run `yarn type-check:ci --force` before concluding CI failures are unrelated to your changes -- Import directly from source files, not barrel files (e.g., `@calcom/ui/components/button` not `@calcom/ui`) -- Add translations to `apps/web/public/static/locales/en/common.json` for all UI strings -- Use `date-fns` or native `Date` instead of Day.js when timezone awareness isn't needed -- Put permission checks in `page.tsx`, never in `layout.tsx` -- Use `ast-grep` for searching if available; otherwise use `rg` (ripgrep), then fall back to `grep` -- Use Biome for formatting and linting - - -## Don't - -- Never use `as any` - use proper type-safe solutions instead -- Never expose `credential.key` field in API responses or queries -- Never commit secrets or API keys -- Never modify `*.generated.ts` files directly - they're created by app-store-cli -- Never put business logic in repositories - that belongs in Services -- Never use barrel imports from index.ts files -- Never skip running type checks before pushing -- Never create large PRs (>500 lines or >10 files) - split them instead - -## Commands - -### File-scoped (preferred for speed) - -```bash -# Type check - always run on changed files -yarn type-check:ci --force - -# Lint and format single file -yarn biome check --write path/to/file.tsx - -# Unit test specific file -yarn vitest run path/to/file.test.ts - -# Unit test specific file + specific test -yarn vitest run path/to/file.test.ts --testNamePattern="specific test name" - -# Integration test specific file -yarn test path/to/file.integration-test.ts -- --integrationTestsOnly - -# Integration test specific file + specific test -yarn test path/to/file.integration-test.ts --testNamePattern="specific test name" -- --integrationTestsOnly - -# E2E test specific file -PLAYWRIGHT_HEADLESS=1 yarn e2e path/to/file.e2e.ts - -# E2E test specific file + specific test -PLAYWRIGHT_HEADLESS=1 yarn e2e path/to/file.e2e.ts --grep "specific test name" -``` - -### Project-wide (use sparingly) - -```bash -# Development -yarn dev # Start dev server -yarn dx # Dev with database setup - -# Build & check -yarn build # Build all packages -yarn biome check --write . # Lint and format all -yarn type-check # Type check all - -# Tests (use TZ=UTC for consistency) -TZ=UTC yarn test # All unit tests -yarn e2e # All E2E tests - -# Database -yarn prisma generate # Regenerate types after schema changes -yarn workspace @calcom/prisma db-migrate # Run migrations -``` - -### Biome focused workflow -+ -```bash -yarn biome check --write . -yarn type-check:ci --force -``` - - -## Boundaries - -### Always do -- Run type check on changed files before committing -- Run relevant tests before pushing -- Use `select` in Prisma queries -- Follow conventional commits for PR titles -- Run Biome before pushing - -### Ask first -- Adding new dependencies -- Schema changes to `packages/prisma/schema.prisma` -- Changes affecting multiple packages -- Deleting files -- Running full build or E2E suites - -### Never do -- Commit secrets, API keys, or `.env` files -- Expose `credential.key` in any query -- Use `as any` type casting -- Force push or rebase shared branches -- Modify generated files directly - -## Project Structure - -``` -apps/web/ # Main Next.js application -packages/prisma/ # Database schema (schema.prisma) and migrations -packages/trpc/ # tRPC API layer (routers in server/routers/) -packages/ui/ # Shared UI components -packages/features/ # Feature-specific code -packages/app-store/ # Third-party integrations -packages/lib/ # Shared utilities -``` - -### Key files -- Routes: `apps/web/app/` (App Router) -- Database schema: `packages/prisma/schema.prisma` -- tRPC routers: `packages/trpc/server/routers/` -- Translations: `apps/web/public/static/locales/en/common.json` -- Workflow constants: `packages/features/ee/workflows/lib/constants.ts` - -## Tech Stack - -- **Framework**: Next.js 13+ (App Router in some areas) -- **Language**: TypeScript (strict) -- **Database**: PostgreSQL with Prisma ORM -- **API**: tRPC for type-safe APIs -- **Auth**: NextAuth.js -- **Styling**: Tailwind CSS -- **Testing**: Vitest (unit), Playwright (E2E) -- **i18n**: next-i18next - -## Code Examples - -### Good error handling - -```typescript -// Good - Descriptive error with context -throw new Error(`Unable to create booking: User ${userId} has no available time slots for ${date}`); - -// Bad - Generic error -throw new Error("Booking failed"); -``` - -For which error class to use (`ErrorWithCode` vs `TRPCError`) and concrete examples, see [Error Types in knowledge-base.md](agents/knowledge-base.md#error-types). - -### Good Prisma query - -```typescript -// Good - Use select for performance and security -const booking = await prisma.booking.findFirst({ - select: { - id: true, - title: true, - user: { - select: { - id: true, - name: true, - email: true, - } - } - } -}); - -// Bad - Include fetches all fields including sensitive ones -const booking = await prisma.booking.findFirst({ - include: { user: true } -}); -``` - -### Good imports - -```typescript -// Good - Type imports and direct paths -import type { User } from "@prisma/client"; -import { Button } from "@calcom/ui/components/button"; - -// Bad - Regular import for types, barrel imports -import { User } from "@prisma/client"; -import { Button } from "@calcom/ui"; -``` - -## PR Checklist - -- [ ] Title follows conventional commits: `feat(scope): description` -- [ ] Type check passes: `yarn type-check:ci --force` -- [ ] Lint passes: `yarn lint:fix` -- [ ] Relevant tests pass -- [ ] Diff is small and focused (<500 lines, <10 files) -- [ ] No secrets or API keys committed -- [ ] UI strings added to translation files -- [ ] Created as draft PR - -## When Stuck - -- Ask a clarifying question before making large speculative changes -- Propose a short plan for complex tasks -- Open a draft PR with notes if unsure about approach -- Fix type errors before test failures - they're often the root cause -- Run `yarn prisma generate` if you see missing enum/type errors - -## Extended Documentation - -For detailed information, see the `agents/` directory: - -- **[agents/README.md](agents/README.md)** - Architecture overview and patterns -- **[agents/commands.md](agents/commands.md)** - Complete command reference -- **[agents/knowledge-base.md](agents/knowledge-base.md)** - Domain knowledge and best practices -- **[agents/coding-standards.md](agents/coding-standards.md)** - Coding standards with examples +**Objective:** Ensure consistency and discoverability by requiring repository classes to use 'PrismaRepository' pattern and service classes to use 'Service' pattern, with filenames matching class names exactly in PascalCase + +**Success Criteria:** Repository files are named 'PrismaRepository.ts' with matching exported class names (e.g., PrismaAppRepository), and service files are named 'Service.ts' with matching class names (e.g., MembershipService) + +**Failure Criteria:** Repository or service files use generic names like 'app.ts', use dot-suffixes like '.service.ts' or '.repository.ts', or have filename/class name mismatches + +--- + +## 2. Prevent Circular Dependencies Between Core Packages + +**Objective:** Maintain clear architectural boundaries and prevent circular dependencies by enforcing import restrictions between core packages (lib, app-store, features, trpc) + +**Success Criteria:** The lib package does not import from app-store, features, or trpc; app-store does not import from features or trpc; features does not import from trpc; and trpc does not import from apps/web + +**Failure Criteria:** Code contains imports that violate the dependency hierarchy, such as lib importing from features, app-store importing from trpc, or any other restricted cross-package imports + +--- + +## 3. Use Biome for Code Formatting with Standardized Configuration + +**Objective:** Ensure consistent code formatting across the entire codebase by using Biome with specific formatting rules for line width, indentation, quotes, and semicolons + +**Success Criteria:** All TypeScript/JavaScript files use 110 character line width, 2-space indentation, LF line endings, double quotes for JSX, always include semicolons, use ES5 trailing commas, and always use arrow function parentheses + +**Failure Criteria:** Code files deviate from the standard formatting rules, such as using single quotes in JSX, omitting semicolons, using different indentation widths, or exceeding line width limits + +--- + +## 4. Default Exports Allowed Only in Next.js Page and Layout Files + +**Objective:** Enforce named exports throughout the codebase for better refactoring and tree-shaking, while allowing default exports only where Next.js requires them (page.tsx and layout.tsx files) + +**Success Criteria:** Files use named exports (export const, export function, export class) except for files matching patterns 'apps/web/app/**/page.tsx', 'apps/web/app/**/layout.tsx', and 'apps/web/app/pages/**/*.tsx' which may use default exports + +**Failure Criteria:** Non-page/layout files use default exports, or page/layout files fail to export the required default component + +--- + +## 5. Schema and Handler Files Must Be Separated with Type-Safe Patterns + +**Objective:** Maintain separation of concerns and type safety by requiring schema definitions in separate '.schema.ts' files with both Zod schema and TypeScript type exports, while handlers in '.handler.ts' files use these typed schemas + +**Success Criteria:** Schema files export both a TypeScript type (TInputSchema) and a corresponding Zod schema (ZInputSchema: z.ZodTypeInputSchema>), and handler files import and use these typed schemas for validation + +**Failure Criteria:** Schema and handler logic are mixed in the same file, schema files lack either TypeScript types or Zod schemas, or handler files perform validation without using the defined schemas + +--- + +## 6. Lint Staged Files Before Commit with Error-on-Warnings Enforcement + +**Objective:** Ensure code quality by running Biome linting on staged files before commits and treating warnings as errors unless explicitly skipped via SKIP_WARNINGS environment variable + +**Success Criteria:** Pre-commit hook runs 'biome lint --error-on-warnings' on staged TypeScript/JavaScript files, 'biome format' on JSON files, and 'prisma format' on schema.prisma, and all checks pass before commit is allowed + +**Failure Criteria:** Commits are made with linting warnings or formatting issues, staged files are not checked before commit, or the pre-commit hook is bypassed without proper justification + +--- + +## 7. Environment Variables Must Not Be Accessed Directly in Non-Configuration Code + +**Objective:** Prevent runtime errors and improve testability by avoiding direct process.env access in business logic and instead using centralized configuration modules or environment-specific checks + +**Success Criteria:** Direct process.env access is limited to configuration files, environment detection utilities (isENVProd, isENVDev), and build-time configuration, while business logic receives environment values through dependency injection or configuration objects + +**Failure Criteria:** Business logic, handlers, or service classes directly access process.env properties instead of using configuration abstractions or injected values + +--- + +## 8. All Tests Must Use Vitest Framework and UTC Timezone + +**Objective:** Ensure consistent test execution and prevent timezone-related bugs by standardizing on Vitest as the test framework and enforcing UTC timezone for all test runs + +**Success Criteria:** Test files use Vitest syntax (vi.mock, vi.fn, describe, it, expect), test commands set TZ=UTC environment variable, and tests do not depend on local timezone settings + +**Failure Criteria:** Tests use Jest-specific APIs, test commands omit TZ=UTC setting, or tests fail when run in different timezones + +--- + +## 9. React Components Must Use react-hook-form with Zod Schema Validation + +**Objective:** Ensure consistent form handling and validation by requiring React Hook Form with Zod resolver for all form components, providing type-safe validation and error handling + +**Success Criteria:** Form components use useForm hook with zodResolver, define Zod schemas for form validation, use Controller or register for form fields, and properly handle validation errors with error messages + +**Failure Criteria:** Form components implement custom validation logic without react-hook-form, lack Zod schema validation, or fail to properly display validation errors to users + +--- + +## 10. Custom Error Classes Must Use Hierarchical Structure with Typed Codes + +**Objective:** Enable robust error handling and debugging by requiring custom error classes that extend base Error classes with typed error codes, HTTP status codes, and structured error information + +**Success Criteria:** Error classes extend from base error types (HttpError, CalendarAppError, ErrorWithCode), include typed error codes for categorization, provide statusCode for HTTP errors, and include relevant context (URL, method, cause) + +**Failure Criteria:** Code throws generic Error objects, lacks error categorization, omits HTTP status codes for API errors, or fails to include sufficient debugging context + +---