Add CI/CD workflows, Docker support, and order tools #1
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: Security Analysis & Linting | |
| on: | |
| push: | |
| branches: [master, main] | |
| pull_request: | |
| branches: [master, main] | |
| schedule: | |
| # Run weekly on Sundays at midnight | |
| - cron: '0 0 * * 0' | |
| jobs: | |
| lint: | |
| name: Lint & Format Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install ruff mypy | |
| - name: Run Ruff linter | |
| run: ruff check src/ --output-format=github | |
| - name: Run Ruff formatter check | |
| run: ruff format src/ --check | |
| - name: Run mypy type checking | |
| run: mypy src/ --ignore-missing-imports --no-error-summary || true | |
| sast: | |
| name: Python SAST (Bandit) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Bandit | |
| run: pip install bandit[toml] | |
| - name: Run Bandit SAST scan | |
| run: | | |
| bandit -r src/ -f json -o bandit-report.json || true | |
| bandit -r src/ -f txt -o bandit-report.txt || true | |
| bandit -r src/ --severity-level medium --confidence-level medium | |
| - name: Upload Bandit report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: bandit-sast-report | |
| path: | | |
| bandit-report.json | |
| bandit-report.txt | |
| semgrep: | |
| name: Semgrep SAST | |
| runs-on: ubuntu-latest | |
| container: | |
| image: semgrep/semgrep | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Semgrep | |
| run: semgrep scan --config auto --config p/python --config p/security-audit --json -o semgrep-report.json src/ || true | |
| - name: Run Semgrep (text output) | |
| run: semgrep scan --config auto --config p/python --config p/security-audit src/ | |
| - name: Upload Semgrep report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: semgrep-sast-report | |
| path: semgrep-report.json | |
| sonarqube: | |
| name: SonarQube Local Analysis | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pytest pytest-cov | |
| pip install -e . | |
| - name: Run tests with coverage | |
| run: | | |
| pytest --cov=src/growmcp --cov-report=xml:coverage.xml || true | |
| continue-on-error: true | |
| - name: Install SonarScanner | |
| run: | | |
| wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip | |
| unzip sonar-scanner-cli-5.0.1.3006-linux.zip | |
| echo "$PWD/sonar-scanner-5.0.1.3006-linux/bin" >> $GITHUB_PATH | |
| - name: Run SonarScanner (Local Analysis) | |
| run: | | |
| sonar-scanner \ | |
| -Dsonar.projectKey=growmcp \ | |
| -Dsonar.projectName="Groww MCP Server" \ | |
| -Dsonar.sources=src/growmcp \ | |
| -Dsonar.python.version=3.11 \ | |
| -Dsonar.python.coverage.reportPaths=coverage.xml \ | |
| -Dsonar.exclusions="**/__pycache__/**,**/*.pyc,**/.venv/**" \ | |
| -Dsonar.qualitygate.wait=false \ | |
| -Dsonar.scanner.dumpToFile=sonar-report.properties \ | |
| || true | |
| - name: Upload SonarScanner report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: sonar-local-report | |
| path: | | |
| sonar-report.properties | |
| .scannerwork/ | |
| dependency-check: | |
| name: Dependency Security Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install pip-audit | |
| run: pip install pip-audit | |
| - name: Install project dependencies | |
| run: pip install -e . | |
| - name: Run pip-audit | |
| run: pip-audit --desc --format json --output pip-audit-report.json || true | |
| - name: Run pip-audit (text output) | |
| run: pip-audit --desc | |
| - name: Upload pip-audit report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: dependency-audit-report | |
| path: pip-audit-report.json | |
| secrets-scan: | |
| name: Secret Detection | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Gitleaks | |
| run: | | |
| wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.4/gitleaks_8.18.4_linux_x64.tar.gz | |
| tar -xzf gitleaks_8.18.4_linux_x64.tar.gz | |
| chmod +x gitleaks | |
| - name: Run Gitleaks | |
| run: ./gitleaks detect --source . --report-format json --report-path gitleaks-report.json -v || true | |
| - name: Upload Gitleaks report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: gitleaks-secrets-report | |
| path: gitleaks-report.json | |
| docker-lint: | |
| name: Dockerfile Lint (Hadolint) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Hadolint | |
| uses: hadolint/hadolint-action@v3.1.0 | |
| with: | |
| dockerfile: Dockerfile | |
| format: json | |
| output-file: hadolint-report.json | |
| failure-threshold: warning | |
| continue-on-error: true | |
| - name: Run Hadolint (text output) | |
| run: docker run --rm -i hadolint/hadolint < Dockerfile || true | |
| - name: Upload Hadolint report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: hadolint-report | |
| path: hadolint-report.json | |
| docker-security: | |
| name: Docker Image Security (Trivy) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build Docker image | |
| run: docker build -t growmcp:scan . | |
| continue-on-error: true | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'growmcp:scan' | |
| format: 'json' | |
| output: 'trivy-image-report.json' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| vuln-type: 'os,library' | |
| continue-on-error: true | |
| - name: Run Trivy (table output) | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: 'growmcp:scan' | |
| format: 'table' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| continue-on-error: true | |
| - name: Upload Trivy report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: trivy-image-report | |
| path: trivy-image-report.json | |
| docker-filesystem-scan: | |
| name: Docker Filesystem Scan (Trivy) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy filesystem scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'json' | |
| output: 'trivy-fs-report.json' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| continue-on-error: true | |
| - name: Run Trivy filesystem (table output) | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'table' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| - name: Scan Dockerfile for misconfigurations | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'config' | |
| scan-ref: '.' | |
| format: 'table' | |
| severity: 'CRITICAL,HIGH,MEDIUM' | |
| continue-on-error: true | |
| - name: Upload Trivy filesystem report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: trivy-filesystem-report | |
| path: trivy-fs-report.json |