diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 1a76f33..63a2f0b 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -11,113 +11,74 @@ env: IMAGE_NAME: ${{ secrets.APP_NAME || 'sharenet' }} jobs: - # Job 1: Testing - All containers run inside DinD for complete isolation + # Job 1: Testing - Uses DinD with multiple containers for comprehensive testing test: - name: Test Backend and Frontend (Fully Isolated DinD) + name: Run Tests (DinD) runs-on: [self-hosted, dind] - + if: github.ref == 'refs/heads/main' + steps: - name: Checkout code uses: actions/checkout@v4 - - name: Setup Containerized CI/CD Environment + - name: Setup Containerized Testing Environment run: | - # Start DinD container - cd /opt/${{ secrets.APP_NAME || 'sharenet' }} - docker compose -f ci-cd-compose.yml up -d + # Start testing environment using dedicated compose file + docker compose -f docker-compose.test.yml up -d - # Wait for DinD to be ready - echo "Waiting for DinD container to be ready..." - timeout 60 bash -c 'until docker compose -f ci-cd-compose.yml ps | grep -q "healthy"; do sleep 2; done' + # Wait for all services to be ready + echo "Waiting for testing environment to be ready..." + timeout 120 bash -c 'until docker compose -f docker-compose.test.yml ps | grep -q "healthy" && docker compose -f docker-compose.test.yml ps | grep -q "Up"; do sleep 2; done' - # Verify DinD is working - docker exec ci-cd-dind docker version - - # Create testing containers inside DinD for complete isolation - echo "Creating testing containers inside DinD..." - - # Start PostgreSQL container inside DinD - docker exec ci-cd-dind docker run -d \ - --name ci-cd-postgres \ - --restart unless-stopped \ - -e POSTGRES_DB=${{ secrets.APP_NAME || 'sharenet' }}_test \ - -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=postgres \ - -p 5432:5432 \ - postgres:15-alpine - - # Wait for PostgreSQL to be ready - echo "Waiting for PostgreSQL to be ready..." - timeout 60 bash -c 'until docker exec ci-cd-dind docker exec ci-cd-postgres pg_isready -U postgres; do sleep 1; done' - - # Start Rust toolchain container inside DinD - docker exec ci-cd-dind docker run -d \ - --name ci-cd-rust \ - --restart unless-stopped \ - -v /workspace/backend:/workspace/backend \ - --network host \ - rust:1.75-slim \ - sleep infinity - - # Start Node.js toolchain container inside DinD - docker exec ci-cd-dind docker run -d \ - --name ci-cd-node \ - --restart unless-stopped \ - -v /workspace/frontend:/workspace/frontend \ - node:20-slim \ - sleep infinity + # Verify all containers are running + docker compose -f docker-compose.test.yml ps - name: Install SQLx CLI in Rust container run: | - docker exec ci-cd-rust cargo install sqlx-cli --no-default-features --features postgres + docker exec ci-cd-test-rust cargo install sqlx-cli --no-default-features --features postgres - name: Validate migration files env: - DATABASE_URL: postgres://postgres:postgres@localhost:5432/${{ secrets.APP_NAME || 'sharenet' }}_test + DATABASE_URL: postgres://postgres:postgres@localhost:5432/sharenet_test run: | # Wait for PostgreSQL to be ready echo "Waiting for PostgreSQL to be ready..." timeout 60 bash -c 'until pg_isready -h localhost -p 5432 -U postgres; do sleep 1; done' # Create test database if it doesn't exist - docker exec ci-cd-rust sqlx database create --database-url "$DATABASE_URL" || true + docker exec ci-cd-test-rust sqlx database create --database-url "$DATABASE_URL" || true # Run initial migrations to set up the database - docker exec ci-cd-rust sqlx migrate run --database-url "$DATABASE_URL" || true + docker exec ci-cd-test-rust sqlx migrate run --database-url "$DATABASE_URL" || true # Validate migration files - docker exec ci-cd-rust ./scripts/validate_migrations.sh --verbose + docker exec ci-cd-test-rust ./scripts/validate_migrations.sh --verbose - name: Run backend tests working-directory: ./backend env: - DATABASE_URL: postgres://postgres:postgres@localhost:5432/${{ secrets.APP_NAME || 'sharenet' }}_test + DATABASE_URL: postgres://postgres:postgres@localhost:5432/sharenet_test run: | # Run tests with increased parallelism for Rust - docker exec ci-cd-rust cargo test --all --jobs 4 - docker exec ci-cd-rust cargo clippy --all -- -D warnings - docker exec ci-cd-rust cargo fmt --all -- --check + docker exec ci-cd-test-rust cargo test --all --jobs 4 + docker exec ci-cd-test-rust cargo clippy --all -- -D warnings + docker exec ci-cd-test-rust cargo fmt --all -- --check - name: Install frontend dependencies run: | - docker exec ci-cd-node npm ci + docker exec ci-cd-test-node npm ci - name: Run frontend tests run: | - docker exec ci-cd-node npm run lint - docker exec ci-cd-node npm run type-check - docker exec ci-cd-node npm run build + docker exec ci-cd-test-node npm run lint + docker exec ci-cd-test-node npm run type-check + docker exec ci-cd-test-node npm run build - name: Cleanup Containerized Environment if: always() run: | - # Clean up all containers inside DinD - docker exec ci-cd-dind docker stop ci-cd-postgres ci-cd-rust ci-cd-node || true - docker exec ci-cd-dind docker rm ci-cd-postgres ci-cd-rust ci-cd-node || true - - # Stop DinD container - cd /opt/${{ secrets.APP_NAME || 'sharenet' }} - docker compose -f ci-cd-compose.yml down + # Stop and remove all testing containers + docker compose -f docker-compose.test.yml down # Job 2: Building - Uses DinD for isolated image building and pushing build-and-push: diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..7ea569b --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,79 @@ +version: '3.8' + +services: + # DinD container for isolated Docker operations + dind: + image: docker:dind + container_name: ci-cd-test-dind + privileged: true + restart: unless-stopped + environment: + DOCKER_TLS_CERTDIR: "" + ports: + - "2375:2375" + volumes: + - /var/lib/docker + healthcheck: + test: ["CMD", "docker", "version"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - ci-cd-test-network + + # PostgreSQL for testing + postgres: + image: postgres:15-alpine + container_name: ci-cd-test-postgres + restart: unless-stopped + environment: + POSTGRES_DB: sharenet_test + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - ci-cd-test-network + + # Rust toolchain container for backend testing + rust-toolchain: + image: rust:1.75-slim + container_name: ci-cd-test-rust + restart: unless-stopped + volumes: + - ./backend:/workspace/backend + - /var/run/docker.sock:/var/run/docker.sock + working_dir: /workspace/backend + depends_on: + dind: + condition: service_healthy + postgres: + condition: service_healthy + networks: + - ci-cd-test-network + command: sleep infinity + + # Node.js toolchain container for frontend testing + node-toolchain: + image: node:20-slim + container_name: ci-cd-test-node + restart: unless-stopped + volumes: + - ./frontend:/workspace/frontend + - /var/run/docker.sock:/var/run/docker.sock + working_dir: /workspace/frontend + depends_on: + dind: + condition: service_healthy + networks: + - ci-cd-test-network + command: sleep infinity + +networks: + ci-cd-test-network: + driver: bridge \ No newline at end of file