Skip to content

Commit 870744b

Browse files
authored
Update ci.yml
1 parent 3dfc3bd commit 870744b

1 file changed

Lines changed: 81 additions & 28 deletions

File tree

.github/workflows/ci.yml

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,93 +13,139 @@ jobs:
1313
PYTHONIOENCODING: "UTF-8"
1414

1515
steps:
16+
# ───────────────────────────────────────────────
17+
# 1. Checkout
18+
# ───────────────────────────────────────────────
1619
- name: 🔄 Check out code
1720
uses: actions/checkout@v4
1821
with:
1922
fetch-depth: 0
2023

21-
- name: 🐍 Set up Python 3.11 with cache
22-
id: setup-python
24+
# ───────────────────────────────────────────────
25+
# 2. Setup Python + cache pip
26+
# ───────────────────────────────────────────────
27+
- name: 🐍 Set up Python 3.11
2328
uses: actions/setup-python@v4
2429
with:
2530
python-version: "3.11"
2631
cache: "pip"
2732

28-
- name: 📦 Install dependencies and tooling
33+
# ───────────────────────────────────────────────
34+
# 3. Install deps & tooling
35+
# ───────────────────────────────────────────────
36+
- name: 📦 Install dependencies & tooling
2937
run: |
3038
echo "::group::Installing dependencies"
3139
python -m pip install --upgrade pip
3240
pip install -r requirements.txt -r requirements-dev.txt
3341
pip install bandit coverage
3442
echo "::endgroup::"
3543
44+
# ───────────────────────────────────────────────
45+
# 4. Run tests & produce coverage reports
46+
# ───────────────────────────────────────────────
3647
- name: 🧪 Run tests and collect coverage
3748
run: |
3849
echo "::group::pytest"
3950
coverage run --source=ChatApp,WebSocketChatApp -m pytest -q
4051
echo "::endgroup::"
52+
# XML report for downstream tools
4153
coverage xml -o coverage.xml
54+
# human-readable text report
4255
coverage report -m > coverage.txt
56+
echo "::group::Coverage report"
57+
cat coverage.txt
58+
echo "::endgroup::"
59+
60+
# ───────────────────────────────────────────────
61+
# 5. Extract coverage percentage
62+
# ───────────────────────────────────────────────
63+
- name: 📤 Extract coverage percent
64+
id: extract_coverage
65+
run: |
66+
# find the TOTAL line, strip '%' and take last column
67+
RATE=$(awk '/^TOTAL/ { gsub("%",""); print $NF }' coverage.txt)
68+
# default to 0.00 if empty
69+
if [ -z "$RATE" ]; then
70+
echo "WARNING: could not parse coverage; defaulting to 0.00"
71+
RATE="0.00"
72+
fi
73+
echo "extracted coverage=$RATE"
74+
echo "coverage=$RATE" >> $GITHUB_OUTPUT
4375
44-
- name: ✅ Enforce minimum test coverage
76+
# ───────────────────────────────────────────────
77+
# 6. Enforce minimum coverage (fail build if below threshold)
78+
# ───────────────────────────────────────────────
79+
- name: ✅ Enforce minimum coverage
4580
run: |
46-
RATE=$(awk '$1 == "TOTAL" {gsub("%",""); print $(NF)}' coverage.txt)
81+
RATE="${{ steps.extract_coverage.outputs.coverage }}"
4782
echo "📊 Total test coverage: $RATE%"
4883
THRESHOLD=70
49-
if [ "$(echo "$RATE < $THRESHOLD" | bc -l)" -eq 1 ]; then
50-
echo "❌ Coverage is below ${THRESHOLD}% failing the build."
84+
if (( $(echo "$RATE < $THRESHOLD" | bc -l) )); then
85+
echo "❌ Coverage $RATE% is below ${THRESHOLD}% failing build."
5186
exit 1
5287
fi
5388
54-
- name: 📤 Extract coverage percent for badge
55-
id: get_coverage
56-
if: github.ref == 'refs/heads/main'
57-
run: |
58-
RATE=$(awk '$1 == "TOTAL" {gsub("%",""); printf "%.2f", $(NF)}' coverage.txt)
59-
echo "coverage=$RATE" >> $GITHUB_OUTPUT
60-
89+
# ───────────────────────────────────────────────
90+
# 7. Prepare badge directory
91+
# ───────────────────────────────────────────────
6192
- name: 🗂 Ensure badge folder exists
6293
if: github.ref == 'refs/heads/main'
6394
run: mkdir -p .github/badges
6495

96+
# ───────────────────────────────────────────────
97+
# 8. Generate coverage badge
98+
# ───────────────────────────────────────────────
6599
- name: 🏷️ Generate coverage badge
66100
if: github.ref == 'refs/heads/main'
67101
uses: emibcn/badge-action@v1
68102
with:
69103
label: coverage
70-
status: "${{ steps.get_coverage.outputs.coverage }}%"
104+
status: "${{ steps.extract_coverage.outputs.coverage }}%"
71105
color: green
72106
path: .github/badges/coverage.svg
73107

74-
- name: 📌 Commit coverage badge
108+
# ───────────────────────────────────────────────
109+
# 9. Commit coverage reports & badge
110+
# ───────────────────────────────────────────────
111+
- name: 📌 Commit coverage artefacts
75112
if: github.ref == 'refs/heads/main'
76113
uses: EndBug/add-and-commit@v9
77114
with:
78115
add: |
116+
coverage.xml
117+
coverage.txt
79118
.github/badges/coverage.svg
80-
coverage-summary.json
81-
message: "chore(ci): update coverage badge [skip ci]"
82-
119+
message: chore(ci): update coverage reports & badge [skip ci]
83120

84-
- name: 🛡️ Bandit Static Analysis (SAST)
121+
# ───────────────────────────────────────────────
122+
# 10. Bandit static analysis
123+
# ───────────────────────────────────────────────
124+
- name: 🛡️ Run Bandit
85125
run: |
86126
echo "::group::Bandit scan"
87127
bandit -r websocket_chatapp -lll -f json -o bandit.json
88128
echo "::endgroup::"
89129
130+
# ───────────────────────────────────────────────
131+
# 11. Build Docker image (Buildx + cache)
132+
# ───────────────────────────────────────────────
90133
- name: 🐳 Set up Docker Buildx
91134
uses: docker/setup-buildx-action@v2
92135

93-
- name: 🏗️ Build Docker Image
136+
- name: 🏗️ Build Docker image
94137
uses: docker/build-push-action@v5
95138
with:
96139
context: .
97140
tags: chatapp:test
98141
load: true
99142
cache-from: type=gha
100-
cache-to: type=gha,mode=max
143+
cache-to: type=gha,mode=max
101144

102-
- name: 🔍 Scan Docker Image (Trivy)
145+
# ───────────────────────────────────────────────
146+
# 12. Trivy vulnerability scan
147+
# ───────────────────────────────────────────────
148+
- name: 🔍 Scan image with Trivy
103149
id: trivy
104150
uses: aquasecurity/trivy-action@0.31.0
105151
with:
@@ -109,29 +155,35 @@ jobs:
109155
ignore-unfixed: true
110156
exit-code: 0
111157

112-
- name: 🚨 Fail on High CVSS (Trivy)
158+
- name: 🚨 Fail on high CVSS
113159
run: |
114160
echo "::group::Evaluating Trivy results"
115161
if jq '.Results[].Vulnerabilities[] | select((.CVSS.nvd.V3Score // 0) > 7)' trivy-image.json | grep -q .; then
116-
echo '❌ High/critical CVEs detected – failing build.'
162+
echo "❌ High/critical CVEs (CVSS > 7) — failing build."
117163
exit 1
118164
fi
119165
echo "::endgroup::"
120166
167+
# ───────────────────────────────────────────────
168+
# 13. Secret scanning with Gitleaks
169+
# ───────────────────────────────────────────────
121170
- name: 🔐 Install Gitleaks
122171
run: |
123172
curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.24.3/gitleaks_8.24.3_linux_x64.tar.gz -o gitleaks.tar.gz
124173
tar -xzf gitleaks.tar.gz gitleaks
125174
sudo mv gitleaks /usr/local/bin/
126175
127-
- name: 🔍 Secret scan with Gitleaks
176+
- name: 🔍 Run Gitleaks
128177
run: |
129-
echo "::group::Gitleaks"
178+
echo "::group::Gitleaks scan"
130179
gitleaks detect --source . --no-git -c .gitleaks.toml \
131180
--report-format json --report-path gitleaks.json
132181
echo "::endgroup::"
133182
134-
- name: ☁️ Upload Security Artifacts
183+
# ───────────────────────────────────────────────
184+
# 14. Upload security artefacts
185+
# ───────────────────────────────────────────────
186+
- name: ☁️ Upload security artefacts
135187
if: always()
136188
uses: actions/upload-artifact@v4
137189
with:
@@ -141,3 +193,4 @@ jobs:
141193
trivy-image.json
142194
gitleaks.json
143195
coverage.xml
196+
coverage.txt

0 commit comments

Comments
 (0)