name: CI on: push: branches: [main, master] pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # Everything that does not need a database, once. static: name: types, lint and rules coverage runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm typecheck - run: pnpm lint # RULES.md section 10: the tax logic is the product, so its coverage is a gate. - run: pnpm test:coverage # The same suite against both dialects. SPEC.md section 13: the product claims to run on # SQLite and on Postgres, so both are run rather than one being assumed from the other. test: name: tests (${{ matrix.dialect }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: dialect: [sqlite, postgres] services: postgres: image: postgres:16-alpine env: POSTGRES_USER: impuestos POSTGRES_PASSWORD: impuestos POSTGRES_DB: impuestos ports: ['5432:5432'] options: >- --health-cmd "pg_isready -U impuestos" --health-interval 5s --health-timeout 5s --health-retries 10 # Scaled mode requires S3, so the driver is exercised against a real object store # rather than assumed from the local one. minio: image: bitnami/minio:latest env: MINIO_ROOT_USER: impuestos MINIO_ROOT_PASSWORD: impuestos-secret MINIO_DEFAULT_BUCKETS: comprobantes ports: ['9000:9000'] options: >- --health-cmd "curl -f http://localhost:9000/minio/health/live" --health-interval 5s --health-timeout 5s --health-retries 20 steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile # TEST_DATABASE_URL unset means SQLite in memory, which is what the harness falls # back to. Set, every harness builds itself a database of its own inside this server, # and the two-worker claim test in scale.test.ts stops skipping. - name: Run the suite env: TEST_DATABASE_URL: ${{ matrix.dialect == 'postgres' && 'postgres://impuestos:impuestos@localhost:5432/impuestos' || '' }} TEST_S3_ENDPOINT: http://localhost:9000 TEST_S3_BUCKET: comprobantes TEST_S3_REGION: us-east-1 TEST_S3_ACCESS_KEY_ID: impuestos TEST_S3_SECRET_ACCESS_KEY: impuestos-secret run: pnpm test # The golden paths, against a built stack rather than the dev server. SQLite and local # files: that is the combined mode compose ships, and it is the one the helpers in # e2e/db.ts can read, since they open the database file to check what a flow wrote. e2e: name: playwright runs-on: ubuntu-latest env: DATABASE_URL: sqlite:./apps/api/data/app.db STORAGE_DRIVER: local STORAGE_LOCAL_PATH: ./apps/api/data/files BETTER_AUTH_SECRET: ci-secret-that-is-long-enough-32-chars BETTER_AUTH_URL: http://localhost:3005 APP_PUBLIC_URL: http://localhost:3005 PORT: '4000' API_INTERNAL_URL: http://localhost:4000 E2E_BASE_URL: http://localhost:3005 steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm exec playwright install --with-deps chromium - run: pnpm db:migrate - run: pnpm db:seed - run: pnpm build - name: Start the stack run: | node --import tsx apps/api/src/index.ts & pnpm --filter @impuestos/web start & npx --yes wait-on http://localhost:4000/readyz http://localhost:3005/healthz -t 120000 - run: pnpm test:e2e - uses: actions/upload-artifact@v4 if: failure() with: name: playwright-report path: playwright-report/ retention-days: 7