name: Dependency Vulnerability Checker

on:
  push:
    branches: [main, develop]
    paths:
      - '**/package.json'
      - '**/package-lock.json'
      - '**/yarn.lock'
      - '**/pnpm-lock.yaml'
      - '**/requirements.txt'
      - '**/requirements*.txt'
      - '**/Pipfile.lock'
      - '**/pyproject.toml'
      - '**/go.sum'
      - '**/Cargo.lock'
  pull_request:
    branches: [main, develop]
  schedule:
    - cron: '0 8 * * 1'   # every Monday at 08:00 UTC
  workflow_dispatch:

permissions:
  contents: read
  security-events: write   # upload SARIF to GitHub Security tab
  pull-requests: write

jobs:
  npm-audit:
    name: Node.js — npm audit
    runs-on: ubuntu-latest
    if: hashFiles('**/package-lock.json') != ''
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        run: npm ci

      - name: Run npm audit
        run: npm audit --audit-level=high --json > npm-audit.json || true

      - name: Upload npm audit report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: npm-audit-report
          path: npm-audit.json

  python-safety:
    name: Python — pip-audit
    runs-on: ubuntu-latest
    if: hashFiles('**/requirements*.txt') != ''
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: pip

      - name: Install pip-audit
        run: pip install pip-audit

      - name: Run pip-audit
        run: |
          pip-audit -r requirements.txt \
            --format json \
            --output pip-audit.json || true

      - name: Upload pip-audit report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: pip-audit-report
          path: pip-audit.json

  trivy:
    name: Trivy — filesystem scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: fs
          scan-ref: .
          severity: HIGH,CRITICAL
          format: sarif
          output: trivy-results.sarif
          exit-code: '0'   # set to '1' to fail on findings

      - name: Upload Trivy results to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: trivy-results.sarif

  snyk:
    name: Snyk — dependency scan
    runs-on: ubuntu-latest
    if: vars.ENABLE_SNYK == 'true'
    steps:
      - uses: actions/checkout@v4

      - name: Run Snyk to check for vulnerabilities
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high --json-file-output=snyk-results.json
        continue-on-error: true

      - name: Upload Snyk results
        uses: actions/upload-artifact@v4
        with:
          name: snyk-report
          path: snyk-results.json

  summary:
    name: Vulnerability Summary
    runs-on: ubuntu-latest
    needs: [npm-audit, python-safety, trivy]
    if: always()
    steps:
      - name: Download all reports
        uses: actions/download-artifact@v4

      - name: Write job summary
        run: |
          echo "## Dependency Vulnerability Scan Results" >> $GITHUB_STEP_SUMMARY
          echo "| Scanner | Status |" >> $GITHUB_STEP_SUMMARY
          echo "|---------|--------|" >> $GITHUB_STEP_SUMMARY
          echo "| npm audit | ${{ needs.npm-audit.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| pip-audit | ${{ needs.python-safety.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Trivy     | ${{ needs.trivy.result }} |" >> $GITHUB_STEP_SUMMARY
