diff --git a/.github/workflows/e2e-app-store.yml b/.github/workflows/e2e-app-store.yml index fcbca9f2e2..a76c212803 100644 --- a/.github/workflows/e2e-app-store.yml +++ b/.github/workflows/e2e-app-store.yml @@ -1,4 +1,4 @@ -name: E2E App-Store Apps Tests +name: E2E App Store Tests on: workflow_call: env: diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 80bcd2997b..157c560eb2 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,4 +1,4 @@ -name: E2E tests +name: E2E on: workflow_call: env: @@ -41,7 +41,7 @@ env: jobs: e2e: timeout-minutes: 20 - name: E2E tests (${{ matrix.shard }}/${{ strategy.job-total }}) + name: E2E (${{ matrix.shard }}/${{ strategy.job-total }}) runs-on: buildjet-4vcpu-ubuntu-2204 services: postgres: diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000000..720926c948 --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,89 @@ +name: Integration +on: + workflow_call: +env: + NODE_OPTIONS: --max-old-space-size=4096 + ALLOWED_HOSTNAMES: ${{ vars.CI_ALLOWED_HOSTNAMES }} + CALENDSO_ENCRYPTION_KEY: ${{ secrets.CI_CALENDSO_ENCRYPTION_KEY }} + DAILY_API_KEY: ${{ secrets.CI_DAILY_API_KEY }} + DATABASE_URL: ${{ secrets.CI_DATABASE_URL }} + DATABASE_DIRECT_URL: ${{ secrets.CI_DATABASE_URL }} + DEPLOYSENTINEL_API_KEY: ${{ secrets.DEPLOYSENTINEL_API_KEY }} + E2E_TEST_APPLE_CALENDAR_EMAIL: ${{ secrets.E2E_TEST_APPLE_CALENDAR_EMAIL }} + E2E_TEST_APPLE_CALENDAR_PASSWORD: ${{ secrets.E2E_TEST_APPLE_CALENDAR_PASSWORD }} + E2E_TEST_MAILHOG_ENABLED: ${{ vars.E2E_TEST_MAILHOG_ENABLED }} + GOOGLE_API_CREDENTIALS: ${{ secrets.CI_GOOGLE_API_CREDENTIALS }} + EMAIL_SERVER_HOST: ${{ secrets.CI_EMAIL_SERVER_HOST }} + EMAIL_SERVER_PORT: ${{ secrets.CI_EMAIL_SERVER_PORT }} + EMAIL_SERVER_USER: ${{ secrets.CI_EMAIL_SERVER_USER }} + EMAIL_SERVER_PASSWORD: ${{ secrets.CI_EMAIL_SERVER_PASSWORD}} + GOOGLE_LOGIN_ENABLED: ${{ vars.CI_GOOGLE_LOGIN_ENABLED }} + NEXTAUTH_SECRET: ${{ secrets.CI_NEXTAUTH_SECRET }} + NEXTAUTH_URL: ${{ secrets.CI_NEXTAUTH_URL }} + NEXT_PUBLIC_API_V2_URL: ${{ secrets.CI_NEXT_PUBLIC_API_V2_URL }} + NEXT_PUBLIC_API_V2_ROOT_URL: ${{ secrets.CI_NEXT_PUBLIC_API_V2_ROOT_URL }} + NEXT_PUBLIC_IS_E2E: ${{ vars.CI_NEXT_PUBLIC_IS_E2E }} + NEXT_PUBLIC_ORG_SELF_SERVE_ENABLED: ${{ vars.CI_NEXT_PUBLIC_ORG_SELF_SERVE_ENABLED }} + NEXT_PUBLIC_STRIPE_PUBLIC_KEY: ${{ secrets.CI_NEXT_PUBLIC_STRIPE_PUBLIC_KEY }} + NEXT_PUBLIC_WEBAPP_URL: ${{ vars.CI_NEXT_PUBLIC_WEBAPP_URL }} + NEXT_PUBLIC_WEBSITE_URL: ${{ vars.CI_NEXT_PUBLIC_WEBSITE_URL }} + PAYMENT_FEE_FIXED: ${{ vars.CI_PAYMENT_FEE_FIXED }} + PAYMENT_FEE_PERCENTAGE: ${{ vars.CI_PAYMENT_FEE_PERCENTAGE }} + SAML_ADMINS: ${{ secrets.CI_SAML_ADMINS }} + SAML_DATABASE_URL: ${{ secrets.CI_SAML_DATABASE_URL }} + STRIPE_PRIVATE_KEY: ${{ secrets.CI_STRIPE_PRIVATE_KEY }} + STRIPE_CLIENT_ID: ${{ secrets.CI_STRIPE_CLIENT_ID }} + STRIPE_WEBHOOK_SECRET: ${{ secrets.CI_STRIPE_WEBHOOK_SECRET }} + SENDGRID_API_KEY: ${{ secrets.CI_SENDGRID_API_KEY }} + SENDGRID_EMAIL: ${{ secrets.CI_SENDGRID_EMAIL }} + TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TEAM: ${{ secrets.TURBO_TEAM }} +jobs: + integration: + timeout-minutes: 20 + name: Integration + runs-on: buildjet-8vcpu-ubuntu-2204 + services: + postgres: + image: postgres:13 + credentials: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: calendso + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + mailhog: + image: mailhog/mailhog:v1.0.1 + credentials: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + ports: + - 8025:8025 + - 1025:1025 + strategy: + fail-fast: false + steps: + - uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - uses: actions/checkout@v3 + - uses: ./.github/actions/dangerous-git-checkout + - uses: ./.github/actions/yarn-install + - uses: ./.github/actions/cache-db + - name: Run Tests + run: yarn test -- --integrationTestsOnly + - name: Upload Test Results + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: test-results + path: test-results diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index f75e9baa61..4812249579 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -35,8 +35,8 @@ jobs: uses: ./.github/workflows/check-types.yml secrets: inherit - test: - name: Unit tests + unit-test: + name: Tests needs: [changes] if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/unit-tests.yml @@ -70,29 +70,36 @@ jobs: uses: ./.github/workflows/production-build-without-database.yml secrets: inherit + integration-test: + name: Tests + needs: [changes, lint, build, build-api-v1, build-api-v2] + if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }} + uses: ./.github/workflows/integration-tests.yml + secrets: inherit + e2e: - name: E2E tests + name: Tests needs: [changes, lint, build, build-api-v1, build-api-v2] if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e.yml secrets: inherit e2e-app-store: - name: E2E App Store tests + name: Tests needs: [changes, lint, build, build-api-v1, build-api-v2] if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-app-store.yml secrets: inherit e2e-embed: - name: E2E embeds tests + name: Tests needs: [changes, lint, build, build-api-v1, build-api-v2] if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-embed.yml secrets: inherit e2e-embed-react: - name: E2E React embeds tests + name: Tests needs: [changes, lint, build, build-api-v1, build-api-v2] if: ${{ needs.changes.outputs.has-files-requiring-all-checks == 'true' }} uses: ./.github/workflows/e2e-embed-react.yml @@ -106,7 +113,7 @@ jobs: secrets: inherit required: - needs: [changes, lint, type-check, test, build, build-api-v1, build-api-v2, e2e, e2e-embed, e2e-embed-react, e2e-app-store] + needs: [changes, lint, type-check, unit-test, integration-test, build, build-api-v1, build-api-v2, e2e, e2e-embed, e2e-embed-react, e2e-app-store] if: always() runs-on: buildjet-2vcpu-ubuntu-2204 steps: diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 488b55f69d..d4abd9433c 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -1,4 +1,4 @@ -name: Unit tests +name: Unit on: workflow_call: workflow_run: @@ -6,6 +6,7 @@ on: types: [completed] jobs: test: + name: Unit timeout-minutes: 20 runs-on: buildjet-2vcpu-ubuntu-2204 steps: diff --git a/vitest.config.ts b/vitest.config.ts index 2171c07a90..1cd76c3983 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ coverage: { provider: "v8", }, + passWithNoTests: true, testTimeout: 500000, }, }); diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 5a49eac472..1ca9f44dd5 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -2,6 +2,7 @@ import { defineWorkspace } from "vitest/config"; const packagedEmbedTestsOnly = process.argv.includes("--packaged-embed-tests-only"); const timeZoneDependentTestsOnly = process.argv.includes("--timeZoneDependentTestsOnly"); +const integrationTestsOnly = process.argv.includes("--integrationTestsOnly"); // eslint-disable-next-line turbo/no-undeclared-env-vars const envTZ = process.env.TZ; if (timeZoneDependentTestsOnly && !envTZ) { @@ -18,6 +19,22 @@ const workspaces = packagedEmbedTestsOnly }, }, ] + : integrationTestsOnly + ? [ + { + test: { + name: `IntegrationTests`, + include: ["packages/**/*.integration-test.ts", "apps/**/*.integration-test.ts"], + exclude: ["**/node_modules/**/*", "packages/embeds/**/*"], + setupFiles: ["setupVitest.ts"], + }, + resolve: { + alias: { + "~": new URL("./apps/api/v1", import.meta.url).pathname, + }, + }, + }, + ] : // It doesn't seem to be possible to fake timezone per test, so we rerun the entire suite with different TZ. See https://github.com/vitest-dev/vitest/issues/1575#issuecomment-1439286286 timeZoneDependentTestsOnly ? [