Some checks failed
Security & Dependency Updates / Dependency Security Scan (push) Successful in 29s
Security & Dependency Updates / Docker Security Scan (push) Failing after 53s
Security & Dependency Updates / License Compliance (push) Successful in 13s
Security & Dependency Updates / Check for Dependency Updates (push) Successful in 19s
Security & Dependency Updates / Code Quality Metrics (push) Successful in 11s
Security & Dependency Updates / Security Summary (push) Successful in 7s
Features: - Real-time water level monitoring for Ping River Basin (16 stations) - Coverage from Chiang Dao to Nakhon Sawan in Northern Thailand - FastAPI web interface with interactive dashboard and station management - Multi-database support (SQLite, MySQL, PostgreSQL, InfluxDB, VictoriaMetrics) - Comprehensive monitoring with health checks and metrics collection - Docker deployment with Grafana integration - Production-ready architecture with enterprise-grade observability CI/CD & Automation: - Complete Gitea Actions workflows for CI/CD, security, and releases - Multi-Python version testing (3.9-3.12) - Multi-architecture Docker builds (amd64, arm64) - Daily security scanning and dependency monitoring - Automated documentation generation - Performance testing and validation Production Ready: - Type safety with Pydantic models and comprehensive type hints - Data validation layer with range checking and error handling - Rate limiting and request tracking for API protection - Enhanced logging with rotation, colors, and performance metrics - Station management API for dynamic CRUD operations - Comprehensive documentation and deployment guides Technical Stack: - Python 3.9+ with FastAPI and Pydantic - Multi-database architecture with adapter pattern - Docker containerization with multi-stage builds - Grafana dashboards for visualization - Gitea Actions for CI/CD automation - Enterprise monitoring and alerting Ready for deployment to B4L infrastructure!
386 lines
12 KiB
YAML
386 lines
12 KiB
YAML
name: Security & Dependency Updates
|
|
|
|
on:
|
|
schedule:
|
|
# Run security scans daily at 3 AM UTC
|
|
- cron: '0 3 * * *'
|
|
workflow_dispatch:
|
|
push:
|
|
paths:
|
|
- 'requirements*.txt'
|
|
- 'Dockerfile'
|
|
- '.gitea/workflows/security.yml'
|
|
|
|
env:
|
|
PYTHON_VERSION: '3.11'
|
|
|
|
jobs:
|
|
# Dependency vulnerability scan
|
|
dependency-scan:
|
|
name: Dependency Security Scan
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install safety bandit semgrep
|
|
|
|
- name: Run Safety check
|
|
run: |
|
|
safety check -r requirements.txt --json --output safety-report.json || true
|
|
safety check -r requirements-dev.txt --json --output safety-dev-report.json || true
|
|
|
|
- name: Run Bandit security scan
|
|
run: |
|
|
bandit -r src/ -f json -o bandit-report.json || true
|
|
|
|
- name: Run Semgrep security scan
|
|
run: |
|
|
semgrep --config=auto src/ --json --output=semgrep-report.json || true
|
|
|
|
- name: Upload security reports
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: security-reports-${{ github.run_number }}
|
|
path: |
|
|
safety-report.json
|
|
safety-dev-report.json
|
|
bandit-report.json
|
|
semgrep-report.json
|
|
|
|
- name: Check for critical vulnerabilities
|
|
run: |
|
|
echo "🔍 Checking for critical vulnerabilities..."
|
|
|
|
# Check Safety results
|
|
if [ -f safety-report.json ]; then
|
|
critical_count=$(jq '.vulnerabilities | length' safety-report.json 2>/dev/null || echo "0")
|
|
if [ "$critical_count" -gt 0 ]; then
|
|
echo "⚠️ Found $critical_count dependency vulnerabilities"
|
|
jq '.vulnerabilities[] | "- \(.package_name) \(.installed_version): \(.vulnerability_id)"' safety-report.json
|
|
else
|
|
echo "✅ No dependency vulnerabilities found"
|
|
fi
|
|
fi
|
|
|
|
# Check Bandit results
|
|
if [ -f bandit-report.json ]; then
|
|
high_severity=$(jq '.results[] | select(.issue_severity == "HIGH") | length' bandit-report.json 2>/dev/null | wc -l)
|
|
if [ "$high_severity" -gt 0 ]; then
|
|
echo "⚠️ Found $high_severity high-severity security issues"
|
|
else
|
|
echo "✅ No high-severity security issues found"
|
|
fi
|
|
fi
|
|
|
|
# Docker image security scan
|
|
docker-security-scan:
|
|
name: Docker Security Scan
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Build Docker image for scanning
|
|
run: |
|
|
docker build -t ping-river-monitor:scan .
|
|
|
|
- name: Run Trivy vulnerability scanner
|
|
uses: aquasecurity/trivy-action@master
|
|
with:
|
|
image-ref: 'ping-river-monitor:scan'
|
|
format: 'json'
|
|
output: 'trivy-report.json'
|
|
|
|
- name: Run Trivy filesystem scan
|
|
uses: aquasecurity/trivy-action@master
|
|
with:
|
|
scan-type: 'fs'
|
|
scan-ref: '.'
|
|
format: 'json'
|
|
output: 'trivy-fs-report.json'
|
|
|
|
- name: Upload Trivy reports
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: trivy-reports-${{ github.run_number }}
|
|
path: |
|
|
trivy-report.json
|
|
trivy-fs-report.json
|
|
|
|
- name: Check Trivy results
|
|
run: |
|
|
echo "🔍 Analyzing Docker security scan results..."
|
|
|
|
if [ -f trivy-report.json ]; then
|
|
critical_vulns=$(jq '.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL") | length' trivy-report.json 2>/dev/null | wc -l)
|
|
high_vulns=$(jq '.Results[]?.Vulnerabilities[]? | select(.Severity == "HIGH") | length' trivy-report.json 2>/dev/null | wc -l)
|
|
|
|
echo "Critical vulnerabilities: $critical_vulns"
|
|
echo "High vulnerabilities: $high_vulns"
|
|
|
|
if [ "$critical_vulns" -gt 0 ]; then
|
|
echo "❌ Critical vulnerabilities found in Docker image!"
|
|
exit 1
|
|
elif [ "$high_vulns" -gt 5 ]; then
|
|
echo "⚠️ Many high-severity vulnerabilities found"
|
|
else
|
|
echo "✅ Docker image security scan passed"
|
|
fi
|
|
fi
|
|
|
|
# License compliance check
|
|
license-check:
|
|
name: License Compliance
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install pip-licenses
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install pip-licenses
|
|
pip install -r requirements.txt
|
|
|
|
- name: Check licenses
|
|
run: |
|
|
echo "📄 Checking dependency licenses..."
|
|
pip-licenses --format=json --output-file=licenses.json
|
|
pip-licenses --format=markdown --output-file=licenses.md
|
|
|
|
# Check for problematic licenses
|
|
problematic_licenses=("GPL" "AGPL" "LGPL")
|
|
|
|
for license in "${problematic_licenses[@]}"; do
|
|
if grep -i "$license" licenses.json; then
|
|
echo "⚠️ Found potentially problematic license: $license"
|
|
fi
|
|
done
|
|
|
|
echo "✅ License check completed"
|
|
|
|
- name: Upload license report
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: license-report-${{ github.run_number }}
|
|
path: |
|
|
licenses.json
|
|
licenses.md
|
|
|
|
# Dependency update check
|
|
dependency-update:
|
|
name: Check for Dependency Updates
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install pip-check-updates equivalent
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install pip-review
|
|
|
|
- name: Check for outdated packages
|
|
run: |
|
|
echo "📦 Checking for outdated packages..."
|
|
pip install -r requirements.txt
|
|
pip list --outdated --format=json > outdated-packages.json || true
|
|
|
|
if [ -s outdated-packages.json ]; then
|
|
echo "📋 Outdated packages found:"
|
|
cat outdated-packages.json | jq -r '.[] | "- \(.name): \(.version) -> \(.latest_version)"'
|
|
else
|
|
echo "✅ All packages are up to date"
|
|
fi
|
|
|
|
- name: Create dependency update issue
|
|
if: github.event_name == 'schedule'
|
|
run: |
|
|
if [ -s outdated-packages.json ] && [ "$(cat outdated-packages.json)" != "[]" ]; then
|
|
echo "📝 Creating dependency update issue..."
|
|
|
|
# Create issue body
|
|
cat > issue-body.md << 'EOF'
|
|
## 📦 Dependency Updates Available
|
|
|
|
The following packages have updates available:
|
|
|
|
EOF
|
|
|
|
cat outdated-packages.json | jq -r '.[] | "- **\(.name)**: \(.version) → \(.latest_version)"' >> issue-body.md
|
|
|
|
cat >> issue-body.md << 'EOF'
|
|
|
|
## 🔍 Security Impact
|
|
|
|
Please review each update for:
|
|
- Security fixes
|
|
- Breaking changes
|
|
- Compatibility issues
|
|
|
|
## ✅ Action Items
|
|
|
|
- [ ] Review changelog for each package
|
|
- [ ] Test updates in development environment
|
|
- [ ] Update requirements.txt
|
|
- [ ] Run full test suite
|
|
- [ ] Deploy to staging for validation
|
|
|
|
---
|
|
*This issue was automatically created by the security workflow.*
|
|
EOF
|
|
|
|
echo "Issue body created. In a real implementation, you would create a Gitea issue here."
|
|
cat issue-body.md
|
|
fi
|
|
|
|
- name: Upload dependency reports
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: dependency-reports-${{ github.run_number }}
|
|
path: |
|
|
outdated-packages.json
|
|
issue-body.md
|
|
|
|
# Code quality metrics
|
|
code-quality:
|
|
name: Code Quality Metrics
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v4
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install quality tools
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install radon xenon vulture
|
|
pip install -r requirements.txt
|
|
|
|
- name: Calculate code complexity
|
|
run: |
|
|
echo "📊 Calculating code complexity..."
|
|
radon cc src/ --json > complexity-report.json
|
|
radon mi src/ --json > maintainability-report.json
|
|
|
|
echo "🔍 Complexity Summary:"
|
|
radon cc src/ --average
|
|
|
|
echo "🔧 Maintainability Summary:"
|
|
radon mi src/
|
|
|
|
- name: Find dead code
|
|
run: |
|
|
echo "🧹 Checking for dead code..."
|
|
vulture src/ --json > dead-code-report.json || true
|
|
|
|
- name: Check for code smells
|
|
run: |
|
|
echo "👃 Checking for code smells..."
|
|
xenon --max-absolute B --max-modules A --max-average A src/ || true
|
|
|
|
- name: Upload quality reports
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: code-quality-reports-${{ github.run_number }}
|
|
path: |
|
|
complexity-report.json
|
|
maintainability-report.json
|
|
dead-code-report.json
|
|
|
|
# Security summary
|
|
security-summary:
|
|
name: Security Summary
|
|
runs-on: ubuntu-latest
|
|
needs: [dependency-scan, docker-security-scan, license-check, code-quality]
|
|
if: always()
|
|
|
|
steps:
|
|
- name: Download all artifacts
|
|
uses: actions/download-artifact@v3
|
|
|
|
- name: Generate security summary
|
|
run: |
|
|
echo "# 🔒 Security Scan Summary" > security-summary.md
|
|
echo "" >> security-summary.md
|
|
echo "**Scan Date:** $(date -u)" >> security-summary.md
|
|
echo "**Repository:** ${{ github.repository }}" >> security-summary.md
|
|
echo "**Commit:** ${{ github.sha }}" >> security-summary.md
|
|
echo "" >> security-summary.md
|
|
|
|
echo "## 📊 Results" >> security-summary.md
|
|
echo "" >> security-summary.md
|
|
|
|
# Dependency scan results
|
|
if [ -f security-reports-*/safety-report.json ]; then
|
|
vuln_count=$(jq '.vulnerabilities | length' security-reports-*/safety-report.json 2>/dev/null || echo "0")
|
|
if [ "$vuln_count" -eq 0 ]; then
|
|
echo "- ✅ **Dependency Scan**: No vulnerabilities found" >> security-summary.md
|
|
else
|
|
echo "- ⚠️ **Dependency Scan**: $vuln_count vulnerabilities found" >> security-summary.md
|
|
fi
|
|
else
|
|
echo "- ❓ **Dependency Scan**: Results not available" >> security-summary.md
|
|
fi
|
|
|
|
# Docker scan results
|
|
if [ -f trivy-reports-*/trivy-report.json ]; then
|
|
echo "- ✅ **Docker Scan**: Completed" >> security-summary.md
|
|
else
|
|
echo "- ❓ **Docker Scan**: Results not available" >> security-summary.md
|
|
fi
|
|
|
|
# License check results
|
|
if [ -f license-report-*/licenses.json ]; then
|
|
echo "- ✅ **License Check**: Completed" >> security-summary.md
|
|
else
|
|
echo "- ❓ **License Check**: Results not available" >> security-summary.md
|
|
fi
|
|
|
|
# Code quality results
|
|
if [ -f code-quality-reports-*/complexity-report.json ]; then
|
|
echo "- ✅ **Code Quality**: Analyzed" >> security-summary.md
|
|
else
|
|
echo "- ❓ **Code Quality**: Results not available" >> security-summary.md
|
|
fi
|
|
|
|
echo "" >> security-summary.md
|
|
echo "## 🔗 Detailed Reports" >> security-summary.md
|
|
echo "" >> security-summary.md
|
|
echo "Detailed reports are available in the workflow artifacts." >> security-summary.md
|
|
|
|
cat security-summary.md
|
|
|
|
- name: Upload security summary
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: security-summary-${{ github.run_number }}
|
|
path: security-summary.md |