name: CI on: push: branches: [main] pull_request: branches: [main] permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} jobs: typecheck: name: Typecheck runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm build - run: pnpm typecheck - run: pnpm run --filter emdash-demo --filter @emdash-cms/demo-cloudflare typecheck - run: pnpm typecheck:templates - run: node scripts/typecheck-public-source.mjs lint: name: Lint runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm build - run: pnpm lint version-check: name: Version Check runs-on: ubuntu-latest timeout-minutes: 5 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 - run: node .github/scripts/check-no-major.mjs changeset-validate: name: Changeset Validation runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: # changeset status --since diffs against origin/main; needs full history. fetch-depth: 0 persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - name: Validate changesets run: | shopt -s extglob if compgen -G ".changeset/!(README).md" > /dev/null; then pnpm changeset status --since=origin/main else echo "No changesets present; skipping validation." fi test: name: Tests runs-on: ubuntu-latest timeout-minutes: 15 services: postgres: image: postgres:17 env: POSTGRES_PASSWORD: test POSTGRES_DB: emdash_test ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile # Build emdash + its deps AND the plugin-cli + registry packages. # They aren't deps of `emdash`, so the `emdash...` filter would # leave them unbuilt and their tests would fail to resolve workspace # links to dist/. - run: pnpm run --filter emdash... --filter "@emdash-cms/plugin-cli" --filter "@emdash-cms/registry-*" --filter "@emdash-cms/plugin-types" build - run: pnpm test:unit env: EMDASH_TEST_PG: postgres://postgres:test@localhost:5432/emdash_test # Render tests use the Astro Vite plugin (vitest.repro.config.ts); # they can't run under the plain-node config in test:unit. - run: pnpm --filter emdash exec vitest run --config vitest.repro.config.ts test-smoke: name: Smoke Tests runs-on: ubuntu-latest timeout-minutes: 30 services: postgres: image: postgres:17 env: POSTGRES_PASSWORD: test POSTGRES_DB: emdash_smoke ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm build - run: pnpm --filter emdash exec vitest run --config vitest.smoke.config.ts env: DATABASE_URL: postgres://postgres:test@localhost:5432/emdash_smoke test-integration: name: Integration Tests runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm build - run: pnpm --filter emdash exec vitest run --config vitest.integration.config.ts test-browser: name: Browser Tests runs-on: ubuntu-latest timeout-minutes: 15 steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm run --filter @emdash-cms/admin... build - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 id: playwright-cache with: path: ~/.cache/ms-playwright key: playwright-${{ hashFiles('pnpm-lock.yaml') }} - run: pnpm exec playwright install --with-deps chromium if: steps.playwright-cache.outputs.cache-hit != 'true' - run: pnpm run --filter @emdash-cms/admin test test-e2e-rollup: name: E2E Tests if: always() needs: [test-e2e] runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: Check E2E shard results run: | if [ "${{ needs.test-e2e.result }}" != "success" ]; then echo "E2E tests failed or were cancelled" exit 1 fi test-e2e: name: E2E tests (${{ matrix.shardIndex }}/${{ matrix.shardTotal }}) runs-on: ubuntu-latest timeout-minutes: 20 strategy: fail-fast: false matrix: shardIndex: [1, 2, 3, 4, 5, 6, 7, 8] shardTotal: [8] steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm run --filter emdash... build - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 id: playwright-cache with: path: ~/.cache/ms-playwright key: playwright-${{ hashFiles('pnpm-lock.yaml') }} - run: pnpm exec playwright install --with-deps chromium if: steps.playwright-cache.outputs.cache-hit != 'true' - run: pnpm exec playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: failure() with: name: playwright-report-${{ matrix.shardIndex }} path: | playwright-report/ test-results/ retention-days: 7 test-e2e-cloudflare: name: E2E Cloudflare (${{ matrix.shardIndex }}/${{ matrix.shardTotal }}) runs-on: ubuntu-latest timeout-minutes: 25 strategy: fail-fast: false matrix: shardIndex: [1, 2, 3, 4, 5, 6, 7, 8] shardTotal: [8] steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm run --filter "emdash-e2e-fixture-cloudflare..." build - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 id: playwright-cache with: path: ~/.cache/ms-playwright key: playwright-${{ hashFiles('pnpm-lock.yaml') }} - run: pnpm exec playwright install --with-deps chromium if: steps.playwright-cache.outputs.cache-hit != 'true' # Runs the full e2e suite against the workerd runtime. Sharded like the Node # lane: per-shard setup (dev-server boot + seed) is ~30s, so wall-clock is # dominated by test execution and shards parallelize it near-linearly. - run: pnpm exec playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} env: EMDASH_E2E_TARGET: cloudflare - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: failure() with: name: playwright-report-cloudflare-${{ matrix.shardIndex }} path: | playwright-report/ test-results/ retention-days: 7