Skip to content

Commit 4919b0d

Browse files
abhijeetmohananabhijeetmohananvai
authored andcommitted
ci: add security analysis and linting workflow
1 parent 7fa536b commit 4919b0d

1 file changed

Lines changed: 296 additions & 0 deletions

File tree

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
name: Security Analysis & Linting
2+
3+
on:
4+
push:
5+
branches: [master, main]
6+
pull_request:
7+
branches: [master, main]
8+
schedule:
9+
# Run weekly on Sundays at midnight
10+
- cron: '0 0 * * 0'
11+
12+
jobs:
13+
lint:
14+
name: Lint & Format Check
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: '3.11'
24+
25+
- name: Install dependencies
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install ruff mypy
29+
- name: Run Ruff linter
30+
run: ruff check src/ --output-format=github
31+
32+
- name: Run Ruff formatter check
33+
run: ruff format src/ --check
34+
35+
- name: Run mypy type checking
36+
run: mypy src/ --ignore-missing-imports --no-error-summary || true
37+
38+
sast:
39+
name: Python SAST (Bandit)
40+
runs-on: ubuntu-latest
41+
steps:
42+
- name: Checkout code
43+
uses: actions/checkout@v4
44+
45+
- name: Set up Python
46+
uses: actions/setup-python@v5
47+
with:
48+
python-version: '3.11'
49+
50+
- name: Install Bandit
51+
run: pip install bandit[toml]
52+
53+
- name: Run Bandit SAST scan
54+
run: |
55+
bandit -r src/ -f json -o bandit-report.json || true
56+
bandit -r src/ -f txt -o bandit-report.txt || true
57+
bandit -r src/ --severity-level medium --confidence-level medium
58+
- name: Upload Bandit report
59+
uses: actions/upload-artifact@v4
60+
if: always()
61+
with:
62+
name: bandit-sast-report
63+
path: |
64+
bandit-report.json
65+
bandit-report.txt
66+
semgrep:
67+
name: Semgrep SAST
68+
runs-on: ubuntu-latest
69+
container:
70+
image: semgrep/semgrep
71+
steps:
72+
- name: Checkout code
73+
uses: actions/checkout@v4
74+
75+
- name: Run Semgrep
76+
run: semgrep scan --config auto --config p/python --config p/security-audit --json -o semgrep-report.json src/ || true
77+
78+
- name: Run Semgrep (text output)
79+
run: semgrep scan --config auto --config p/python --config p/security-audit src/
80+
81+
- name: Upload Semgrep report
82+
uses: actions/upload-artifact@v4
83+
if: always()
84+
with:
85+
name: semgrep-sast-report
86+
path: semgrep-report.json
87+
88+
sonarqube:
89+
name: SonarQube Local Analysis
90+
runs-on: ubuntu-latest
91+
steps:
92+
- name: Checkout code
93+
uses: actions/checkout@v4
94+
with:
95+
fetch-depth: 0
96+
97+
- name: Set up Python
98+
uses: actions/setup-python@v5
99+
with:
100+
python-version: '3.11'
101+
102+
- name: Install dependencies
103+
run: |
104+
python -m pip install --upgrade pip
105+
pip install pytest pytest-cov
106+
pip install -e .
107+
- name: Run tests with coverage
108+
run: |
109+
pytest --cov=src/growmcp --cov-report=xml:coverage.xml || true
110+
continue-on-error: true
111+
112+
- name: Install SonarScanner
113+
run: |
114+
wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip
115+
unzip sonar-scanner-cli-5.0.1.3006-linux.zip
116+
echo "$PWD/sonar-scanner-5.0.1.3006-linux/bin" >> $GITHUB_PATH
117+
- name: Run SonarScanner (Local Analysis)
118+
run: |
119+
sonar-scanner \
120+
-Dsonar.projectKey=growmcp \
121+
-Dsonar.projectName="Groww MCP Server" \
122+
-Dsonar.sources=src/growmcp \
123+
-Dsonar.python.version=3.11 \
124+
-Dsonar.python.coverage.reportPaths=coverage.xml \
125+
-Dsonar.exclusions="**/__pycache__/**,**/*.pyc,**/.venv/**" \
126+
-Dsonar.qualitygate.wait=false \
127+
-Dsonar.scanner.dumpToFile=sonar-report.properties \
128+
|| true
129+
- name: Upload SonarScanner report
130+
uses: actions/upload-artifact@v4
131+
if: always()
132+
with:
133+
name: sonar-local-report
134+
path: |
135+
sonar-report.properties
136+
.scannerwork/
137+
dependency-check:
138+
name: Dependency Security Check
139+
runs-on: ubuntu-latest
140+
steps:
141+
- name: Checkout code
142+
uses: actions/checkout@v4
143+
144+
- name: Set up Python
145+
uses: actions/setup-python@v5
146+
with:
147+
python-version: '3.11'
148+
149+
- name: Install pip-audit
150+
run: pip install pip-audit
151+
152+
- name: Install project dependencies
153+
run: pip install -e .
154+
155+
- name: Run pip-audit
156+
run: pip-audit --desc --format json --output pip-audit-report.json || true
157+
158+
- name: Run pip-audit (text output)
159+
run: pip-audit --desc
160+
161+
- name: Upload pip-audit report
162+
uses: actions/upload-artifact@v4
163+
if: always()
164+
with:
165+
name: dependency-audit-report
166+
path: pip-audit-report.json
167+
168+
secrets-scan:
169+
name: Secret Detection
170+
runs-on: ubuntu-latest
171+
steps:
172+
- name: Checkout code
173+
uses: actions/checkout@v4
174+
with:
175+
fetch-depth: 0
176+
177+
- name: Install Gitleaks
178+
run: |
179+
wget https://github.com/gitleaks/gitleaks/releases/download/v8.18.4/gitleaks_8.18.4_linux_x64.tar.gz
180+
tar -xzf gitleaks_8.18.4_linux_x64.tar.gz
181+
chmod +x gitleaks
182+
- name: Run Gitleaks
183+
run: ./gitleaks detect --source . --report-format json --report-path gitleaks-report.json -v || true
184+
185+
- name: Upload Gitleaks report
186+
uses: actions/upload-artifact@v4
187+
if: always()
188+
with:
189+
name: gitleaks-secrets-report
190+
path: gitleaks-report.json
191+
192+
docker-lint:
193+
name: Dockerfile Lint (Hadolint)
194+
runs-on: ubuntu-latest
195+
steps:
196+
- name: Checkout code
197+
uses: actions/checkout@v4
198+
199+
- name: Run Hadolint
200+
uses: hadolint/hadolint-action@v3.1.0
201+
with:
202+
dockerfile: Dockerfile
203+
format: json
204+
output-file: hadolint-report.json
205+
failure-threshold: warning
206+
continue-on-error: true
207+
208+
- name: Run Hadolint (text output)
209+
run: docker run --rm -i hadolint/hadolint < Dockerfile || true
210+
211+
- name: Upload Hadolint report
212+
uses: actions/upload-artifact@v4
213+
if: always()
214+
with:
215+
name: hadolint-report
216+
path: hadolint-report.json
217+
218+
docker-security:
219+
name: Docker Image Security (Trivy)
220+
runs-on: ubuntu-latest
221+
steps:
222+
- name: Checkout code
223+
uses: actions/checkout@v4
224+
225+
- name: Set up Docker Buildx
226+
uses: docker/setup-buildx-action@v3
227+
228+
- name: Build Docker image
229+
run: docker build -t growmcp:scan .
230+
continue-on-error: true
231+
232+
- name: Run Trivy vulnerability scanner
233+
uses: aquasecurity/trivy-action@master
234+
with:
235+
image-ref: 'growmcp:scan'
236+
format: 'json'
237+
output: 'trivy-image-report.json'
238+
severity: 'CRITICAL,HIGH,MEDIUM'
239+
vuln-type: 'os,library'
240+
continue-on-error: true
241+
242+
- name: Run Trivy (table output)
243+
uses: aquasecurity/trivy-action@master
244+
with:
245+
image-ref: 'growmcp:scan'
246+
format: 'table'
247+
severity: 'CRITICAL,HIGH,MEDIUM'
248+
continue-on-error: true
249+
250+
- name: Upload Trivy report
251+
uses: actions/upload-artifact@v4
252+
if: always()
253+
with:
254+
name: trivy-image-report
255+
path: trivy-image-report.json
256+
257+
docker-filesystem-scan:
258+
name: Docker Filesystem Scan (Trivy)
259+
runs-on: ubuntu-latest
260+
steps:
261+
- name: Checkout code
262+
uses: actions/checkout@v4
263+
264+
- name: Run Trivy filesystem scan
265+
uses: aquasecurity/trivy-action@master
266+
with:
267+
scan-type: 'fs'
268+
scan-ref: '.'
269+
format: 'json'
270+
output: 'trivy-fs-report.json'
271+
severity: 'CRITICAL,HIGH,MEDIUM'
272+
continue-on-error: true
273+
274+
- name: Run Trivy filesystem (table output)
275+
uses: aquasecurity/trivy-action@master
276+
with:
277+
scan-type: 'fs'
278+
scan-ref: '.'
279+
format: 'table'
280+
severity: 'CRITICAL,HIGH,MEDIUM'
281+
282+
- name: Scan Dockerfile for misconfigurations
283+
uses: aquasecurity/trivy-action@master
284+
with:
285+
scan-type: 'config'
286+
scan-ref: '.'
287+
format: 'table'
288+
severity: 'CRITICAL,HIGH,MEDIUM'
289+
continue-on-error: true
290+
291+
- name: Upload Trivy filesystem report
292+
uses: actions/upload-artifact@v4
293+
if: always()
294+
with:
295+
name: trivy-filesystem-report
296+
path: trivy-fs-report.json

0 commit comments

Comments
 (0)