Merge pull request #428 from wealth4ever123/feat/global-error-handler #233
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 | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main, dev] | |
| schedule: | |
| - cron: '0 0 * * 0' # Weekly scan on Sunday at 00:00 UTC | |
| jobs: | |
| contract: | |
| name: Rust / Soroban contract | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust + wasm32 target | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: wasm32-unknown-unknown | |
| - name: Cache cargo registry | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| contracts/target | |
| key: cargo-${{ hashFiles('contracts/Cargo.lock') }} | |
| - name: Build WASM | |
| working-directory: contracts | |
| run: make build | |
| - name: Run contract tests | |
| working-directory: contracts | |
| run: cargo test | |
| - name: Run contract tests with coverage | |
| working-directory: contracts | |
| run: | | |
| cargo install cargo-tarpaulin | |
| make test-coverage | |
| - name: Upload Contract Coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: contracts/tarpaulin-report.xml | |
| flags: contracts | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Install cargo-audit | |
| run: cargo install cargo-audit | |
| - name: Dependency audit | |
| working-directory: contracts | |
| run: cargo audit | tee audit-report.txt | |
| - name: Upload audit report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: contract-audit-report | |
| path: contracts/audit-report.txt | |
| backend: | |
| name: Node.js backend | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 18 | |
| cache: npm | |
| cache-dependency-path: backend/package-lock.json | |
| - name: Install dependencies | |
| working-directory: backend | |
| run: npm ci | |
| - name: Lint | |
| working-directory: backend | |
| run: npm run lint | |
| - name: Run tests | |
| working-directory: backend | |
| run: npm test | |
| - name: Run tests with coverage | |
| working-directory: backend | |
| run: npm test | |
| - name: Upload Backend Coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: backend/coverage/lcov.info | |
| flags: backend | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Dependency audit | |
| working-directory: backend | |
| run: npm audit --audit-level=high | tee audit-report.txt | |
| - name: Upload audit report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: backend-audit-report | |
| path: backend/audit-report.txt | |
| frontend: | |
| name: Node.js frontend | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 18 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| working-directory: frontend | |
| run: npm ci | |
| - name: Lint | |
| working-directory: frontend | |
| run: npm run lint | |
| - name: Run tests | |
| working-directory: frontend | |
| run: npm test | |
| - name: Run tests with coverage | |
| working-directory: frontend | |
| run: npm run test:coverage | |
| - name: Upload Frontend Coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: frontend/coverage/lcov.info | |
| flags: frontend | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Dependency audit | |
| working-directory: frontend | |
| run: npm audit --audit-level=high | tee audit-report.txt | |
| - name: Upload audit report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: frontend-audit-report | |
| path: frontend/audit-report.txt | |
| python: | |
| name: Python analytics service | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| cache: pip | |
| cache-dependency-path: python-service/requirements.txt | |
| - name: Install dependencies | |
| working-directory: python-service | |
| run: pip install -r requirements.txt | |
| - name: Lint | |
| working-directory: python-service | |
| run: flake8 . | |
| - name: Run tests | |
| working-directory: python-service | |
| run: pytest | |
| - name: Run tests with coverage | |
| working-directory: python-service | |
| run: pytest --cov --cov-report=xml | |
| - name: Upload Python Coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: python-service/coverage.xml | |
| flags: python | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Install pip-audit | |
| run: pip install pip-audit | |
| - name: Dependency audit | |
| working-directory: python-service | |
| run: pip-audit -r requirements.txt | tee audit-report.txt | |
| - name: Upload audit report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: python-audit-report | |
| path: python-service/audit-report.txt | |
| # Gate job: all test jobs must pass before a PR can be merged. | |
| # Configure this job name ("All tests passed") as a required status check | |
| # in Settings → Branches → Branch protection rules for `main`. | |
| all-tests: | |
| name: All tests passed | |
| runs-on: ubuntu-latest | |
| needs: [contract, backend, frontend, python] | |
| if: always() | |
| steps: | |
| - name: Check all test jobs succeeded | |
| run: | | |
| if [[ "${{ needs.contract.result }}" != "success" || \ | |
| "${{ needs.backend.result }}" != "success" || \ | |
| "${{ needs.frontend.result }}" != "success" || \ | |
| "${{ needs.python.result }}" != "success" ]]; then | |
| echo "One or more test jobs failed." | |
| exit 1 | |
| fi | |
| echo "All test jobs passed." | |
| docker: | |
| name: Docker build validation | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build backend image | |
| run: docker build ./backend -t vaccichain-backend:ci | |
| - name: Build frontend image | |
| run: docker build ./frontend -t vaccichain-frontend:ci | |
| - name: Build python-service image | |
| run: docker build ./python-service -t vaccichain-python:ci | |
| container-scan: | |
| name: Container vulnerability scanning | |
| runs-on: ubuntu-latest | |
| needs: docker | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build backend image | |
| run: docker build ./backend -t vaccichain-backend:ci | |
| - name: Build frontend image | |
| run: docker build ./frontend -t vaccichain-frontend:ci | |
| - name: Build python-service image | |
| run: docker build ./python-service -t vaccichain-python:ci | |
| - name: Run Trivy scan on backend | |
| id: scan-backend | |
| uses: aquasecurity/trivy-action@v1 | |
| with: | |
| image-ref: vaccichain-backend:ci | |
| format: sarif | |
| output: backend-trivy.sarif | |
| severity: HIGH,CRITICAL | |
| ignorefile: .trivyignore | |
| exit-code: 1 | |
| continue-on-error: true | |
| - name: Run Trivy scan on frontend | |
| id: scan-frontend | |
| uses: aquasecurity/trivy-action@v1 | |
| with: | |
| image-ref: vaccichain-frontend:ci | |
| format: sarif | |
| output: frontend-trivy.sarif | |
| severity: HIGH,CRITICAL | |
| ignorefile: .trivyignore | |
| exit-code: 1 | |
| continue-on-error: true | |
| - name: Run Trivy scan on python-service | |
| id: scan-python | |
| uses: aquasecurity/trivy-action@v1 | |
| with: | |
| image-ref: vaccichain-python:ci | |
| format: sarif | |
| output: python-trivy.sarif | |
| severity: HIGH,CRITICAL | |
| ignorefile: .trivyignore | |
| exit-code: 1 | |
| continue-on-error: true | |
| - name: Upload Trivy results to GitHub Security | |
| if: always() | |
| uses: github/codeql-action/upload-sarif@v3 | |
| with: | |
| sarif_file: | | |
| backend-trivy.sarif | |
| frontend-trivy.sarif | |
| python-trivy.sarif | |
| - name: Upload scan artifacts | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: trivy-scan-results | |
| path: | | |
| backend-trivy.sarif | |
| frontend-trivy.sarif | |
| python-trivy.sarif | |
| retention-days: 30 | |
| - name: Fail on HIGH/CRITICAL vulnerabilities | |
| if: always() | |
| run: | | |
| if [[ "${{ steps.scan-backend.outcome }}" == "failure" || "${{ steps.scan-frontend.outcome }}" == "failure" || "${{ steps.scan-python.outcome }}" == "failure" ]]; then | |
| echo "One or more container images contain HIGH or CRITICAL vulnerabilities." | |
| exit 1 | |
| fi | |
| container-scan-scheduled: | |
| name: Weekly container vulnerability scan | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'schedule' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build backend image | |
| run: docker build ./backend -t vaccichain-backend:prod | |
| - name: Build frontend image | |
| run: docker build ./frontend -t vaccichain-frontend:prod | |
| - name: Build python-service image | |
| run: docker build ./python-service -t vaccichain-python:prod | |
| - name: Run Trivy scan on backend | |
| id: scan-scheduled-backend | |
| uses: aquasecurity/trivy-action@v1 | |
| with: | |
| image-ref: vaccichain-backend:prod | |
| format: table | |
| output: backend-scan.txt | |
| ignorefile: .trivyignore | |
| severity: HIGH,CRITICAL | |
| exit-code: 1 | |
| continue-on-error: true | |
| - name: Run Trivy scan on frontend | |
| id: scan-scheduled-frontend | |
| uses: aquasecurity/trivy-action@v1 | |
| with: | |
| image-ref: vaccichain-frontend:prod | |
| format: table | |
| output: frontend-scan.txt | |
| ignorefile: .trivyignore | |
| severity: HIGH,CRITICAL | |
| exit-code: 1 | |
| continue-on-error: true | |
| - name: Run Trivy scan on python-service | |
| id: scan-scheduled-python | |
| uses: aquasecurity/trivy-action@v1 | |
| with: | |
| image-ref: vaccichain-python:prod | |
| format: table | |
| output: python-scan.txt | |
| ignorefile: .trivyignore | |
| severity: HIGH,CRITICAL | |
| exit-code: 1 | |
| continue-on-error: true | |
| - name: Upload scan results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: weekly-trivy-scans | |
| path: | | |
| backend-scan.txt | |
| frontend-scan.txt | |
| python-scan.txt | |
| retention-days: 90 | |
| - name: Fail on HIGH/CRITICAL vulnerabilities | |
| if: always() | |
| run: | | |
| if [[ "${{ steps.scan-scheduled-backend.outcome }}" == "failure" || "${{ steps.scan-scheduled-frontend.outcome }}" == "failure" || "${{ steps.scan-scheduled-python.outcome }}" == "failure" ]]; then | |
| echo "One or more scheduled container images contain HIGH or CRITICAL vulnerabilities." | |
| exit 1 | |
| fi |