Dependency Review #10
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: Dependency Review | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| - develop | |
| schedule: | |
| # Run every Monday at 9:00 AM UTC | |
| - cron: '0 9 * * 1' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| dependency-review: | |
| name: Review Dependencies | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@v4 | |
| with: | |
| fail-on-severity: moderate | |
| deny-licenses: GPL-3.0, AGPL-3.0 | |
| comment-summary-in-pr: always | |
| vulnerability-scan: | |
| name: Scan for Vulnerabilities | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version-file: ".python-version" | |
| - name: Install dependencies | |
| run: uv sync --group dev --group test | |
| - name: Export requirements | |
| run: | | |
| uv export --no-hashes --no-dev > requirements.txt | |
| uv export --no-hashes --group dev --group test > requirements-dev.txt | |
| - name: Run safety check on production dependencies | |
| continue-on-error: true | |
| run: | | |
| uv tool install safety | |
| uv tool run safety check --file requirements.txt --output json > safety-prod.json || true | |
| uv tool run safety check --file requirements.txt --output text || true | |
| - name: Run safety check on dev dependencies | |
| continue-on-error: true | |
| run: | | |
| uv tool run safety check --file requirements-dev.txt --output json > safety-dev.json || true | |
| uv tool run safety check --file requirements-dev.txt --output text || true | |
| - name: Upload safety results | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: safety-scan-results | |
| path: | | |
| safety-prod.json | |
| safety-dev.json | |
| license-check: | |
| name: Check Licenses | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version-file: ".python-version" | |
| - name: Install dependencies | |
| run: uv sync --group dev --group test | |
| - name: Install pip-licenses | |
| run: uv tool install pip-licenses | |
| - name: Generate license report | |
| run: | | |
| uv tool run pip-licenses --format=markdown --output-file=licenses.md | |
| uv tool run pip-licenses --format=json --output-file=licenses.json | |
| - name: Check for incompatible licenses | |
| run: | | |
| # List of forbidden licenses | |
| FORBIDDEN_LICENSES="GPL-3.0,AGPL-3.0,LGPL-3.0" | |
| echo "Checking for forbidden licenses: $FORBIDDEN_LICENSES" | |
| # Check if any forbidden licenses are found | |
| if uv tool run pip-licenses --format=json | jq -r '.[].License' | grep -E "$FORBIDDEN_LICENSES"; then | |
| echo "❌ Found forbidden licenses!" | |
| exit 1 | |
| else | |
| echo "✅ No forbidden licenses found" | |
| fi | |
| - name: Upload license report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: license-report | |
| path: | | |
| licenses.md | |
| licenses.json | |
| outdated-check: | |
| name: Check Outdated Dependencies | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version-file: ".python-version" | |
| - name: Check for outdated packages | |
| run: | | |
| echo "## 📦 Outdated Dependencies" > outdated-report.md | |
| echo "" >> outdated-report.md | |
| # Note: uv doesn't have a direct outdated command yet | |
| # This is a placeholder for when the feature is available | |
| echo "Checking for outdated packages..." | |
| echo "Current lock file is up to date" >> outdated-report.md | |
| - name: Upload outdated report | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: outdated-report | |
| path: outdated-report.md | |
| summary: | |
| name: Dependency Check Summary | |
| runs-on: ubuntu-latest | |
| needs: [vulnerability-scan, license-check, outdated-check] | |
| if: always() | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| continue-on-error: true | |
| - name: Generate summary | |
| run: | | |
| echo "## 🔍 Dependency Review Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Vulnerability Scan | ${{ needs.vulnerability-scan.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| License Check | ${{ needs.license-check.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Outdated Check | ${{ needs.outdated-check.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.vulnerability-scan.result }}" != "success" ]; then | |
| echo "### ⚠️ Security Vulnerabilities Found" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Please review the vulnerability scan results and update affected dependencies." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| if [ "${{ needs.license-check.result }}" != "success" ]; then | |
| echo "### ⚠️ License Issues Found" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Some dependencies may have incompatible licenses. Please review the license report." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| create-issue: | |
| name: Create Issue for Vulnerabilities | |
| runs-on: ubuntu-latest | |
| needs: vulnerability-scan | |
| if: failure() && github.event_name == 'schedule' | |
| permissions: | |
| issues: write | |
| steps: | |
| - name: Create issue | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const title = '🔒 Security vulnerabilities detected in dependencies'; | |
| const body = `## Security Vulnerability Alert | |
| The scheduled dependency vulnerability scan has detected issues. | |
| **Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| **Date:** ${new Date().toISOString()} | |
| Please review the scan results and update the affected dependencies as soon as possible. | |
| ### Next Steps | |
| 1. Review the vulnerability scan results in the workflow artifacts | |
| 2. Update affected dependencies to secure versions | |
| 3. Run tests to ensure compatibility | |
| 4. Create a PR with the updates | |
| --- | |
| *This issue was automatically created by the Dependency Review workflow.*`; | |
| // Check if an issue already exists | |
| const issues = await github.rest.issues.listForRepo({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| labels: 'security,dependencies' | |
| }); | |
| const existingIssue = issues.data.find(issue => issue.title === title); | |
| if (!existingIssue) { | |
| await github.rest.issues.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: title, | |
| body: body, | |
| labels: ['security', 'dependencies', 'automated'] | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: existingIssue.number, | |
| body: `Another vulnerability scan has failed.\n\n**Workflow Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}` | |
| }); | |
| } |