diff --git a/.github/workflows/check-api-v2-breaking-changes.yml b/.github/workflows/check-api-v2-breaking-changes.yml new file mode 100644 index 0000000000..982ad80c23 --- /dev/null +++ b/.github/workflows/check-api-v2-breaking-changes.yml @@ -0,0 +1,53 @@ +name: Check API v2 breaking changes + +on: + workflow_call: + +permissions: + contents: read + +env: + API_KEY_PREFIX: ${{ secrets.CI_API_KEY_PREFIX }} + API_PORT: ${{ vars.CI_API_V2_PORT }} + API_URL: "http://localhost" + CALCOM_LICENSE_KEY: ${{ secrets.CI_CALCOM_LICENSE_KEY }} + DATABASE_URL: ${{ secrets.CI_DATABASE_URL }} + DATABASE_READ_URL: ${{ secrets.CI_DATABASE_URL }} + DATABASE_WRITE_URL: ${{ secrets.CI_DATABASE_URL }} + JWT_SECRET: ${{ secrets.CI_JWT_SECRET }} + NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }} + NODE_ENV: ${{ vars.CI_NODE_ENV }} + NODE_OPTIONS: --max-old-space-size=4096 + REDIS_URL: "redis://localhost:6379" + STRIPE_API_KEY: ${{ secrets.CI_STRIPE_PRIVATE_KEY }} + STRIPE_WEBHOOK_SECRET: ${{ secrets.CI_STRIPE_WEBHOOK_SECRET }} + WEB_APP_URL: "https://app.cal.com" + +jobs: + check-api-v2-breaking-changes: + name: Check API v2 breaking changes + timeout-minutes: 10 + runs-on: buildjet-4vcpu-ubuntu-2204 + steps: + - uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - uses: actions/checkout@v4 + - uses: ./.github/actions/dangerous-git-checkout + - uses: ./.github/actions/yarn-install + + - name: Generate Swagger + working-directory: apps/api/v2 + run: yarn generate-swagger + + - name: Check API v2 breaking changes + run: | + docker run --rm \ + -v "$PWD:/work" -w /work \ + tufin/oasdiff:latest \ + breaking \ + https://raw.githubusercontent.com/calcom/cal.com/refs/heads/main/docs/api-reference/v2/openapi.json \ + docs/api-reference/v2/openapi.json \ + --fail-on ERR \ + --err-ignore .github/oasdiff-err-ignore.txt diff --git a/.github/workflows/e2e-api-v2.yml b/.github/workflows/e2e-api-v2.yml index 254d6c9085..93c48ced24 100644 --- a/.github/workflows/e2e-api-v2.yml +++ b/.github/workflows/e2e-api-v2.yml @@ -30,7 +30,7 @@ env: jobs: e2e: timeout-minutes: 20 - name: E2E API v2 + name: E2E API v2 (${{ matrix.shard }}/${{ strategy.job-total }}) runs-on: buildjet-16vcpu-ubuntu-2204 services: postgres: @@ -63,6 +63,8 @@ jobs: --health-retries 5 strategy: fail-fast: false + matrix: + shard: [1, 2, 3, 4] steps: - uses: docker/login-action@v3 with: @@ -73,32 +75,17 @@ jobs: - uses: ./.github/actions/yarn-install - uses: ./.github/actions/cache-db - - name: Generate Swagger - working-directory: apps/api/v2 - run: yarn generate-swagger - - - name: Check breaking changes - run: | - docker run --rm \ - -v "$PWD:/work" -w /work \ - tufin/oasdiff:latest \ - breaking \ - https://raw.githubusercontent.com/calcom/cal.com/refs/heads/main/docs/api-reference/v2/openapi.json \ - docs/api-reference/v2/openapi.json \ - --fail-on ERR \ - --err-ignore .github/oasdiff-err-ignore.txt - - name: Run Tests working-directory: apps/api/v2 run: | - yarn workspace @calcom/platform-libraries build && yarn test:e2e + yarn test:e2e --shard=${{ matrix.shard }}/${{ strategy.job-total }} EXIT_CODE=$? - echo "yarn workspace @calcom/platform-libraries build && yarn test:e2e command exit code: $EXIT_CODE" + echo "yarn test:e2e --shard=${{ matrix.shard }}/${{ strategy.job-total }} command exit code: $EXIT_CODE" exit $EXIT_CODE - name: Upload Test Results if: ${{ always() }} uses: actions/upload-artifact@v4 with: - name: test-results-api-v2 + name: test-results-api-v2-shard-${{ matrix.shard }} path: test-results diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 968070e169..ba46275dfe 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -204,6 +204,13 @@ jobs: uses: ./.github/workflows/e2e.yml secrets: inherit + check-api-v2-breaking-changes: + name: Check API v2 breaking changes + needs: [prepare, deps] + if: ${{ needs.prepare.outputs.run-e2e == 'true' && needs.prepare.outputs.has-files-requiring-all-checks == 'true' }} + uses: ./.github/workflows/check-api-v2-breaking-changes.yml + secrets: inherit + e2e-api-v2: name: Tests needs: [prepare, setup-db] @@ -245,6 +252,7 @@ jobs: lint, type-check, unit-test, + check-api-v2-breaking-changes, integration-test, build, build-api-v1, @@ -271,6 +279,7 @@ jobs: needs.lint.result != 'success' || needs.type-check.result != 'success' || needs.unit-test.result != 'success' || + needs.check-api-v2-breaking-changes.result != 'success' || needs.build.result != 'success' || needs.build-api-v1.result != 'success' || needs.build-api-v2.result != 'success' || diff --git a/apps/api/v2/jest-e2e.ts b/apps/api/v2/jest-e2e.ts index 6f87c2bc68..50bd478280 100644 --- a/apps/api/v2/jest-e2e.ts +++ b/apps/api/v2/jest-e2e.ts @@ -1,5 +1,22 @@ import type { Config } from "jest"; +// Detect if sharding is being used by checking for --shard flag +const isSharding = process.argv.some((arg) => arg.includes("--shard")); + +// For Jest e2e, we reduce parallelism when sharding in CI to improve test isolation +// since tests share database state and can interfere with each other +const getMaxWorkers = () => { + if (process.env.CI && isSharding) { + // In CI with sharding: reduce workers to improve test isolation + // Sharding already provides parallelism across shards (4 parallel jobs) + return 4; + } + // Local development or non-sharded: use more workers (similar to Playwright) + return 8; +}; + +const maxWorkers = getMaxWorkers(); + const config: Config = { preset: "ts-jest", moduleFileExtensions: ["js", "json", "ts"], @@ -17,7 +34,7 @@ const config: Config = { setupFilesAfterEnv: ["/test/jest.setup-e2e.ts"], reporters: ["default", "jest-summarizing-reporter"], workerIdleMemoryLimit: "512MB", - maxWorkers: 8, + maxWorkers, testPathIgnorePatterns: ["/dist/", "/node_modules/"], transformIgnorePatterns: ["/dist/", "/node_modules/"], };