Skip to content

Dependency Scan

Dependency Scan #6

name: Dependency Scan
on:
schedule:
- cron: '0 0 * * 1' # Run weekly on Monday at midnight UTC
workflow_dispatch:
inputs:
org_name:
description: 'GitHub Organization Name (optional)'
required: false
repo_list:
description: 'Comma-separated list of repositories (optional)'
required: false
log_level:
description: 'Logging level'
required: false
type: choice
options:
- INFO
- DEBUG
- WARNING
- ERROR
default: 'INFO'
vulnerability_threshold:
description: 'Number of vulnerabilities to trigger issue creation'
required: false
type: number
default: 10
permissions:
security-events: read
contents: write # Needed for committing the report
issues: write # Needed for creating issues
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
repository: ${{ github.repository_owner }}/.github # Checkout .github repo
ref: main # Or your default branch
token: ${{ secrets.DEPENDENCY_SCAN_TOKEN }} # Use a PAT or GitHub App token with appropriate permissions!
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Generate timestamp
id: timestamp
run: echo "timestamp=$(date +%Y%m%d_%H%M%S)" >> $GITHUB_OUTPUT
- name: Run dependency scan
id: run-scan
env:
GITHUB_TOKEN: ${{ secrets.DEPENDENCY_SCAN_TOKEN }}
ORG_NAME: ${{ github.event.inputs.org_name || github.repository_owner }}
REPO_LIST: ${{ github.event.inputs.repo_list }}
REPORT_FILE: "vulnerability_report_${{ steps.timestamp.outputs.timestamp }}.csv"
run: |
COMMAND="python scripts/dependency_scanner.py \
--token $GITHUB_TOKEN \
--output $REPORT_FILE \
--log-level ${{ github.event.inputs.log_level || 'INFO' }} \
--max-workers ${{ github.event.inputs.max_workers || 10 }} \
--max-retries 3"
if [[ -n "$ORG_NAME" ]]; then
COMMAND="$COMMAND --org $ORG_NAME"
fi
if [[ -n "$REPO_LIST" ]]; then
COMMAND="$COMMAND --repo-list $REPO_LIST"
fi
$COMMAND
echo "report_path=reports/$REPORT_FILE" >> $GITHUB_OUTPUT
- name: Check for No Repositories
id: check-repos
if: success()
run: |
if grep -q "__NO_REPOS__" ${{ steps.run-scan.outputs.report_path }}/../output.txt; then
echo "No repositories found in the organization. Exiting."
exit 1
fi
- name: Process report statistics (inline)
id: stats
if: success() && steps.check-repos.outcome == 'success'
run: |
STATS=$(grep "__STATS_START__" ${{ steps.run-scan.outputs.report_path }}/../output.txt | sed 's/__STATS_START__//' | sed 's/__STATS_END__//')
echo "total_vulnerabilities=$(echo $STATS | cut -d',' -f1 | cut -d'=' -f2)" >> $GITHUB_OUTPUT
echo "processed_repos=$(echo $STATS | cut -d',' -f2 | cut -d'=' -f2)" >> $GITHUB_OUTPUT
echo "Total vulnerabilities found: $(echo $STATS | cut -d',' -f1 | cut -d'=' -f2)"
echo "Processed repos: $(echo $STATS | cut -d',' -f2 | cut -d'=' -f2)"
- name: Create summary issue (using github-script)
if: success() && steps.check-repos.outcome == 'success' && steps.stats.outputs.total_vulnerabilities > inputs.vulnerability_threshold
uses: actions/github-script@v7
with:
script: |
const stats = {
total: '${{ steps.stats.outputs.total_vulnerabilities }}',
processedRepos: '${{ steps.stats.outputs.processed_repos }}',
};
const now = new Date();
const formattedDate = now.toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
const body = `
# Dependency Vulnerability Report Summary
Report generated on: ${now.toISOString()}
## Statistics
- Total vulnerabilities found: ${stats.total}
- Repositories processed: ${stats.processedRepos}
## Details
- Report artifact: [Download report](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})
- Workflow run: [View details](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})
## Configuration
- Log level: ${{ github.event.inputs.log_level || 'INFO' }}
- Vulnerability threshold: ${{ github.event.inputs.vulnerability_threshold || '10'}}
`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: \`⚠️ Dependency Vulnerability Report - \${formattedDate}\`,
body: body,
labels: ['dependency-vulnerability', 'report']
});
- name: Commit and Push Report
if: success() && steps.check-repos.outcome == 'success'
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "Add dependency vulnerability report: ${{ steps.timestamp.outputs.timestamp }}"
repository: ./ # Commit to the root of the checked-out repo
file_pattern: reports/*.csv
commit_user_name: GitHub Actions
commit_user_email: [email protected]
commit_author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
push_options: '--force'
token: ${{ secrets.DEPENDENCY_SCAN_TOKEN }}
- name: Notify on failure
if: failure()
uses: actions/github-script@v7
with:
script: |
const body = `
# 🚨 Dependency Vulnerability Report Generation Failed
Workflow run failed at ${new Date().toISOString()}
## Details
- Run ID: \`${context.runId}\`
- Trigger: ${context.eventName}
- Actor: @${context.actor}
## Links
- [View run details](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId})
- [View workflow file](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/blob/main/.github/workflows/dependency-scan.yml)
Please check the workflow logs for detailed error information.
`;
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '🚨 Dependency Vulnerability Report Generation Failed',
body: body,
labels: ['dependency-vulnerability', 'failed']
});
- name: Clean up
if: always()
run: |
echo "No clean up required."
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true