name: CI on: push: branches: [ main, develop, "feat/**", "fix/**", "test/**", "docs/**" ] pull_request: branches: [ main ] jobs: # ── Job 1: Lint ──────────────────────────────────────────────── lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip - run: pip install pylint - run: pylint --fail-under=7 $(git ls-files '*.py') || true # Soft fail: warn but don't block on lint score # ── Job 2: Test ──────────────────────────────────────────────── test: name: Test (Python ${{ matrix.python-version }}) runs-on: ubuntu-latest strategy: matrix: python-version: ["3.10", "3.11"] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: pip - name: Install dependencies run: pip install -r requirements.txt pytest pytest-cov - name: Run tests with coverage run: | PYTHONPATH=. python -m pytest tests/ -v \ --cov=codelens_env \ --cov=app \ --cov-report=xml \ --cov-report=term-missing \ --tb=short env: APP_ENV: test TESTING: true - name: Upload coverage report uses: codecov/codecov-action@v4 if: matrix.python-version == '3.11' with: file: ./coverage.xml fail_ci_if_error: false # ── Job 3: Validate environment ──────────────────────────────── validate: name: Validate All Scenarios runs-on: ubuntu-latest needs: test steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip - run: pip install -r requirements.txt - name: Validate all scenarios reachable run: PYTHONPATH=. python scripts/validate.py # ── Job 4: Docker build ──────────────────────────────────────── docker-build: name: Docker Build runs-on: ubuntu-latest needs: test steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - name: Build Docker image uses: docker/build-push-action@v5 with: context: . target: production push: false load: true tags: codelens-env:ci-${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max - name: Test container health run: | docker run -d --name test-container -p 7860:7860 codelens-env:ci-${{ github.sha }} # Poll the /health endpoint with retries for i in {1..15}; do if curl -s -f http://localhost:7860/health > /dev/null; then echo "Health check passed!" docker stop test-container exit 0 fi echo "Waiting for app to start... (retry $i/15)" sleep 2 done echo "Health check FAILED. Showing container logs:" docker logs test-container docker stop test-container exit 1 # ── Job 5: Publish (on main push only) ──────────────────────── publish: name: Publish to GHCR runs-on: ubuntu-latest needs: [test, docker-build] if: github.ref == 'refs/heads/main' && github.event_name == 'push' permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v5 with: context: . target: production push: true tags: | ghcr.io/${{ github.repository }}:latest ghcr.io/${{ github.repository }}:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max