From 767b2d6429189006c2c823e50d71d4657011ac3c Mon Sep 17 00:00:00 2001 From: perf3ct Date: Tue, 17 Jun 2025 19:14:27 +0000 Subject: [PATCH] feat(ci): add github actions --- .github/workflows/docker-build.yml | 63 +++++++++++++ .github/workflows/test-e2e.yml | 124 +++++++++++++++++++++++++ .github/workflows/test-integration.yml | 76 +++++++++++++++ .github/workflows/test-unit.yml | 82 ++++++++++++++++ 4 files changed, 345 insertions(+) create mode 100644 .github/workflows/docker-build.yml create mode 100644 .github/workflows/test-e2e.yml create mode 100644 .github/workflows/test-integration.yml create mode 100644 .github/workflows/test-unit.yml diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..dd92c08 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,63 @@ +name: Docker Build + +on: + push: + branches: + - master + - main + tags: + - 'v*' + pull_request: + branches: + - master + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the Container registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max \ No newline at end of file diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml new file mode 100644 index 0000000..6324497 --- /dev/null +++ b/.github/workflows/test-e2e.yml @@ -0,0 +1,124 @@ +name: E2E Tests + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + +env: + CARGO_TERM_COLOR: always + +jobs: + e2e-tests: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: readur_test + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + tesseract-ocr \ + tesseract-ocr-eng \ + libtesseract-dev \ + libleptonica-dev \ + pkg-config \ + libclang-dev \ + clang + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Install sqlx-cli + run: cargo install sqlx-cli --no-default-features --features postgres + + - name: Run database migrations + run: sqlx migrate run + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/readur_test + + - name: Build backend + run: cargo build --release + + - name: Build frontend + working-directory: ./frontend + run: | + npm ci + npm run build + + - name: Start backend server + run: | + ./target/release/readur & + echo $! > backend.pid + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/readur_test + JWT_SECRET: test-secret-key + PORT: 8000 + FRONTEND_PATH: ./frontend/dist + UPLOAD_PATH: ./uploads + WATCH_PATH: ./watch + + - name: Wait for backend to be ready + run: | + for i in {1..30}; do + if curl -f http://localhost:8000/api/health > /dev/null 2>&1; then + echo "Backend is ready" + break + fi + echo "Waiting for backend... ($i/30)" + sleep 2 + done + + - name: Run frontend E2E tests + working-directory: ./frontend + run: npm test -- SearchPage.integration.test + env: + VITE_API_URL: http://localhost:8000 + + - name: Stop backend server + if: always() + run: | + if [ -f backend.pid ]; then + kill $(cat backend.pid) || true + rm backend.pid + fi \ No newline at end of file diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml new file mode 100644 index 0000000..8e5f67e --- /dev/null +++ b/.github/workflows/test-integration.yml @@ -0,0 +1,76 @@ +name: Integration Tests + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + +env: + CARGO_TERM_COLOR: always + DATABASE_URL: postgres://postgres:postgres@localhost:5432/readur_test + +jobs: + integration-tests: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: readur_test + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + tesseract-ocr \ + tesseract-ocr-eng \ + libtesseract-dev \ + libleptonica-dev \ + pkg-config \ + libclang-dev \ + clang + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Run database migrations + run: | + cargo install sqlx-cli --no-default-features --features postgres + sqlx migrate run + + - name: Run integration tests + run: | + cargo test --test '*' -- --test-threads=1 + env: + TEST_DATABASE_URL: ${{ env.DATABASE_URL }} + RUST_LOG: debug \ No newline at end of file diff --git a/.github/workflows/test-unit.yml b/.github/workflows/test-unit.yml new file mode 100644 index 0000000..f9aaf1a --- /dev/null +++ b/.github/workflows/test-unit.yml @@ -0,0 +1,82 @@ +name: Unit Tests + +on: + push: + branches: + - master + - main + pull_request: + branches: + - master + - main + +env: + CARGO_TERM_COLOR: always + +jobs: + rust-unit-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + tesseract-ocr \ + tesseract-ocr-eng \ + libtesseract-dev \ + libleptonica-dev \ + pkg-config \ + libclang-dev \ + clang + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Run Rust unit tests + run: | + cargo test --lib + cargo test --tests unit_tests + + frontend-unit-tests: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./frontend + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: frontend/package-lock.json + + - name: Install dependencies + run: npm ci + + - name: Run type checking + run: npm run type-check + + - name: Run unit tests + run: npm test -- --run \ No newline at end of file