ci: Bump actions/upload-artifact from 4 to 5 #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD Pipeline | |
| on: | |
| push: | |
| branches: [ main, develop, feature/* ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| release: | |
| types: [ created ] | |
| env: | |
| NODE_VERSION: '20' | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # Job 1: Lint and Type Check | |
| lint: | |
| name: Lint & Type Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run TypeScript compiler | |
| run: npm run build | |
| continue-on-error: true | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v5 | |
| with: | |
| name: build-output | |
| path: dist/ | |
| retention-days: 7 | |
| # Job 2: Frontend Unit Tests | |
| test-frontend: | |
| name: Frontend Unit Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run frontend tests | |
| run: npm test | |
| continue-on-error: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v5 | |
| if: always() | |
| with: | |
| name: frontend-test-results | |
| path: junit.xml | |
| retention-days: 30 | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v5 | |
| if: always() | |
| with: | |
| name: frontend-coverage-report | |
| path: coverage/ | |
| retention-days: 30 | |
| # Job 3: Backend Unit Tests | |
| test-backend: | |
| name: Backend Unit Tests | |
| runs-on: ubuntu-latest | |
| services: | |
| postgres: | |
| image: postgres:15 | |
| env: | |
| POSTGRES_USER: proofbench | |
| POSTGRES_PASSWORD: proofbench | |
| POSTGRES_DB: proofbench_test | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| cache: 'pip' | |
| - name: Install Python dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e ".[dev,backend]" | |
| - name: Run backend tests with pytest | |
| env: | |
| DATABASE_URL: "postgresql://proofbench:proofbench@localhost:5432/proofbench_test" | |
| working-directory: ./backend | |
| run: | | |
| pytest tests/ \ | |
| --cov=app \ | |
| --cov-report=html \ | |
| --cov-report=term \ | |
| --cov-report=xml \ | |
| --junit-xml=pytest-results.xml \ | |
| --cov-fail-under=85 \ | |
| -v | |
| - name: Upload backend test results | |
| uses: actions/upload-artifact@v5 | |
| if: always() | |
| with: | |
| name: backend-test-results | |
| path: backend/pytest-results.xml | |
| retention-days: 30 | |
| - name: Upload backend coverage report | |
| uses: actions/upload-artifact@v5 | |
| if: always() | |
| with: | |
| name: backend-coverage-report | |
| path: backend/htmlcov/ | |
| retention-days: 30 | |
| - name: Check coverage threshold | |
| working-directory: ./backend | |
| run: | | |
| COVERAGE=$(python -c "import xml.etree.ElementTree as ET; tree = ET.parse('coverage.xml'); root = tree.getroot(); print(round(float(root.attrib['line-rate']) * 100, 2))") | |
| echo "Current coverage: $COVERAGE%" | |
| if (( $(echo "$COVERAGE < 85" | bc -l) )); then | |
| echo "ERROR: Coverage $COVERAGE% is below minimum threshold of 85%" | |
| exit 1 | |
| fi | |
| echo "SUCCESS: Coverage meets minimum threshold" | |
| - name: Upload coverage to Codecov (optional) | |
| uses: codecov/codecov-action@v3 | |
| if: always() | |
| with: | |
| files: ./backend/coverage.xml | |
| flags: backend | |
| name: backend-coverage | |
| fail_ci_if_error: false | |
| # Job 4: Build Docker Image | |
| build-docker: | |
| name: Build Docker Image | |
| runs-on: ubuntu-latest | |
| needs: [lint, test-frontend, test-backend] | |
| if: github.event_name == 'push' || github.event_name == 'release' | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GitHub Container Registry | |
| 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=sha,prefix={{branch}}- | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Job 5: Build Storybook | |
| storybook: | |
| name: Build Storybook | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Build Storybook | |
| run: npm run build-storybook | |
| continue-on-error: true | |
| - name: Deploy to GitHub Pages | |
| uses: peaceiris/actions-gh-pages@v3 | |
| if: success() | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./storybook-static | |
| destination_dir: storybook | |
| # Job 6: Security Scan | |
| security: | |
| name: Security Scan | |
| permissions: | |
| contents: read | |
| security-events: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Run npm audit | |
| run: npm audit --audit-level=moderate | |
| continue-on-error: true | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() | |
| with: | |
| sarif_file: 'trivy-results.sarif' |