name: Unit tests on: push: branches: - "main" pull_request: branches: - "*" merge_group: concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.merge_group.head_ref || github.ref }} cancel-in-progress: true env: COLUMNS: 150 ZO_RESULT_CACHE_ENABLED: true jobs: check_changes: name: check_changes runs-on: ubuntu-latest permissions: contents: read outputs: has_backend_changes: ${{ steps.check.outputs.has_backend_changes }} has_ui_changes: ${{ steps.check.outputs.has_ui_changes }} steps: - uses: actions/checkout@v5 with: fetch-depth: 0 - id: check run: | CHANGED=$(git diff --name-only origin/${{ github.base_ref || 'main' }} ${{ github.sha }}) if [ -z "$CHANGED" ] || echo "$CHANGED" | grep -qE '^src/|^proto/|^\.cargo/|^Cargo\.(toml|lock)$|^build\.rs$|^rust-toolchain\.toml$'; then echo "has_backend_changes=true" >> $GITHUB_OUTPUT else echo "has_backend_changes=false" >> $GITHUB_OUTPUT fi if [ -z "$CHANGED" ] || echo "$CHANGED" | grep -q '^web/'; then echo "has_ui_changes=true" >> $GITHUB_OUTPUT else echo "has_ui_changes=false" >> $GITHUB_OUTPUT fi backend_unit_tests: needs: [check_changes] if: needs.check_changes.outputs.has_backend_changes == 'true' runs-on: labels: ubicloud-standard-8 permissions: contents: read services: postgres: image: postgres:17.5-alpine3.22 env: POSTGRES_PASSWORD: password POSTGRES_USER: postgres POSTGRES_DB: postgres ports: - 5432:5432 # Health check that verifies postgres is ready to accept connections options: --health-cmd "pg_isready -U postgres" --health-interval 10s --health-timeout 5s --health-retries 10 steps: - name: Clone the current repo uses: actions/checkout@v5 with: fetch-depth: 0 - name: Setup Rust Toolchain uses: dtolnay/rust-toolchain@master with: toolchain: nightly-2025-11-11 targets: x86_64-unknown-linux-gnu - uses: taiki-e/install-action@v2 with: tool: nextest - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true shared-key: unit-tests save-if: ${{ github.ref == 'refs/heads/main' }} - name: Install Protoc run: | bash ./.github/protoc.sh - name: Simulate building frontend code run: mkdir -p web/dist && touch web/dist/index.html - name: Print rustc cfg run: rustc -C target-cpu=native --print cfg - name: Check code formatting run: cargo fmt --all -- --check - name: Run clippy run: cargo --config net.git-fetch-with-cli=true clippy -- -D warnings - name: Wait for PostgreSQL to be ready run: | echo "Waiting for PostgreSQL to be fully ready..." for i in {1..30}; do if PGPASSWORD=password psql -h localhost -U postgres -d postgres -c "SELECT 1" > /dev/null 2>&1; then echo "PostgreSQL is ready!" break fi echo "Waiting for PostgreSQL... attempt $i/30" sleep 2 done - name: Run unit tests run: | # required for all dbs export ZO_INTERNAL_GRPC_TOKEN=fake export ZO_TEXT_DATA_TYPE=text # setup and run with postgres echo "Running with postgres" export ZO_META_STORE=postgres export ZO_META_POSTGRES_DSN=postgres://postgres:password@localhost:5432/postgres ./coverage.sh run-cov # cleanup rm -rf data ./json ./src/infra/data # Run with sqlite echo "Running with sqlite" export ZO_META_STORE=sqlite export ZO_META_POSTGRES_DSN="" ./coverage.sh run-cov # finally check the coverage data ./coverage.sh check ui_unit_tests: needs: [check_changes] if: needs.check_changes.outputs.has_ui_changes == 'true' runs-on: labels: ubicloud-standard-8 permissions: contents: read steps: - name: Clone the current repo uses: actions/checkout@v5 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v5 with: node-version: '22' cache: 'npm' cache-dependency-path: web/package-lock.json - name: Install dependencies working-directory: web run: npm ci - name: Run frontend unit tests with coverage and check thresholds working-directory: web run: ./coverage.sh check unit_tests_summary: runs-on: ubuntu-latest permissions: {} needs: [check_changes, backend_unit_tests, ui_unit_tests] if: always() steps: - name: Check test results run: | if [ "${{ needs.check_changes.result }}" != "success" ]; then echo "check_changes job did not succeed: ${{ needs.check_changes.result }}" exit 1 fi if [ "${{ needs.backend_unit_tests.result }}" == "success" ] || [ "${{ needs.backend_unit_tests.result }}" == "skipped" ]; then echo "Backend tests passed or skipped" else echo "Backend tests failed" exit 1 fi if [ "${{ needs.ui_unit_tests.result }}" == "success" ] || [ "${{ needs.ui_unit_tests.result }}" == "skipped" ]; then echo "UI tests passed or skipped" else echo "UI tests failed" exit 1 fi echo "All tests completed successfully"