Skip to content

Commit 9561c30

Browse files
authored
feat: switch coverage badge from gist/PAT to GitHub Pages (#8)
## Summary Replace the PAT-dependent gist approach with GitHub Pages deployment. The coverage badge is now built into the reusable workflow — every downstream repo that calls `python-qa.yml` gets automatic badge publishing using only `GITHUB_TOKEN`. ## What changed - **`python-qa.yml`**: Added `coverage-badge` job that extracts coverage, generates shields.io JSON, and deploys to gh-pages via `peaceiris/actions-gh-pages` - **`template-ci.yml`**: Same pattern for this repo's own CI, replacing the schneegans/gist approach - **`README.md`**: Badge URL now points to `nwarila.github.io/python-template/coverage.json` - **`reference/repo-ci.yml`**: Updated permissions to `contents: write`, added badge setup instructions - **Cleanup**: Deleted gist, removed `COVERAGE_GIST_ID` variable ## Before vs after | | Before (gist) | After (gh-pages) | |---|---|---| | PAT required? | Yes (classic PAT, gist scope) | No | | 3rd-party account? | No | No | | Built into reusable workflow? | No | Yes | | Downstream setup | Create PAT, add secret, add workflow steps | Enable Pages, add badge URL | ## Test plan - [x] gh-pages branch created and initialized - [x] GitHub Pages enabled on repo - [x] Badge URL resolves with placeholder data - [x] Gist and COVERAGE_GIST_ID cleaned up
1 parent f4cde48 commit 9561c30

4 files changed

Lines changed: 71 additions & 20 deletions

File tree

.github/workflows/python-qa.yml

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ on:
2121
default: true
2222

2323
permissions:
24-
contents: read
24+
contents: write
2525

2626
jobs:
2727
lint:
@@ -125,6 +125,23 @@ jobs:
125125
run: echo "${{ github.workspace }}\.venv\Scripts" | Out-File -FilePath $env:GITHUB_PATH -Append
126126
- name: Run tests
127127
run: python .github/scripts/check_tests.py
128+
- name: Generate coverage badge data
129+
if: matrix.os == 'ubuntu-latest' && matrix.python == inputs.python-min
130+
shell: bash
131+
run: |
132+
COV=$(python -m coverage report --format=total 2>/dev/null || echo "0")
133+
if [ "$COV" -ge 90 ] 2>/dev/null; then COLOR="brightgreen"
134+
elif [ "$COV" -ge 70 ] 2>/dev/null; then COLOR="yellow"
135+
else COLOR="red"; fi
136+
mkdir -p badge
137+
echo "{\"schemaVersion\":1,\"label\":\"coverage\",\"message\":\"${COV}%\",\"color\":\"${COLOR}\"}" > badge/coverage.json
138+
- name: Upload coverage badge data
139+
if: matrix.os == 'ubuntu-latest' && matrix.python == inputs.python-min
140+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
141+
with:
142+
name: coverage-badge
143+
path: badge/coverage.json
144+
retention-days: 1
128145

129146
security:
130147
runs-on: ubuntu-latest
@@ -184,6 +201,22 @@ jobs:
184201
- name: Run package check
185202
run: python .github/scripts/check_package.py
186203

204+
coverage-badge:
205+
if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
206+
needs: [tests]
207+
runs-on: ubuntu-latest
208+
steps:
209+
- name: Download coverage badge data
210+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
211+
with:
212+
name: coverage-badge
213+
- name: Deploy badge to GitHub Pages
214+
uses: peaceiris/actions-gh-pages@47f197a2200bb9de68ba5f48fad1c088eb1c4a32 # v4.0.0
215+
with:
216+
github_token: ${{ secrets.GITHUB_TOKEN }}
217+
publish_dir: .
218+
keep_files: true
219+
187220
ci-passed:
188221
if: always()
189222
needs: [lint, types, tests, security, spelling, package]

.github/workflows/template-ci.yml

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
branches: [main]
88

99
permissions:
10-
contents: read
10+
contents: write
1111

1212
concurrency:
1313
group: ${{ github.workflow }}-${{ github.ref }}
@@ -57,25 +57,23 @@ jobs:
5757
python-version: "3.11"
5858
- name: Run tests
5959
run: python .github/scripts/check_tests.py
60-
- name: Extract coverage percentage
60+
- name: Generate coverage badge data
6161
if: matrix.os == 'ubuntu-latest'
62-
id: coverage
62+
shell: bash
6363
run: |
64-
COVERAGE=$(python -m coverage report --format=total 2>/dev/null || echo "0")
65-
echo "pct=$COVERAGE" >> "$GITHUB_OUTPUT"
66-
- name: Upload coverage badge
67-
if: matrix.os == 'ubuntu-latest' && github.ref == 'refs/heads/main' && github.event_name == 'push'
68-
continue-on-error: true
69-
uses: schneegans/dynamic-badges-action@e9a478b16159b4d31420099ba146cdc50f134483 # v1.7.0
64+
COV=$(python -m coverage report --format=total 2>/dev/null || echo "0")
65+
if [ "$COV" -ge 90 ] 2>/dev/null; then COLOR="brightgreen"
66+
elif [ "$COV" -ge 70 ] 2>/dev/null; then COLOR="yellow"
67+
else COLOR="red"; fi
68+
mkdir -p badge
69+
echo "{\"schemaVersion\":1,\"label\":\"coverage\",\"message\":\"${COV}%\",\"color\":\"${COLOR}\"}" > badge/coverage.json
70+
- name: Upload coverage badge data
71+
if: matrix.os == 'ubuntu-latest'
72+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
7073
with:
71-
auth: ${{ secrets.GIST_SECRET }}
72-
gistID: ${{ vars.COVERAGE_GIST_ID }}
73-
filename: coverage.json
74-
label: coverage
75-
message: ${{ steps.coverage.outputs.pct }}%
76-
valColorRange: ${{ steps.coverage.outputs.pct }}
77-
minColorRange: 50
78-
maxColorRange: 100
74+
name: coverage-badge
75+
path: badge/coverage.json
76+
retention-days: 1
7977

8078
security:
8179
runs-on: ubuntu-latest
@@ -132,6 +130,22 @@ jobs:
132130
with:
133131
globs: "**/*.md"
134132

133+
coverage-badge:
134+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
135+
needs: [tests]
136+
runs-on: ubuntu-latest
137+
steps:
138+
- name: Download coverage badge data
139+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
140+
with:
141+
name: coverage-badge
142+
- name: Deploy badge to GitHub Pages
143+
uses: peaceiris/actions-gh-pages@47f197a2200bb9de68ba5f48fad1c088eb1c4a32 # v4.0.0
144+
with:
145+
github_token: ${{ secrets.GITHUB_TOKEN }}
146+
publish_dir: .
147+
keep_files: true
148+
135149
ci-passed:
136150
if: always()
137151
needs: [dependency-review, lint, types, tests, security, spelling, package, shellcheck, actionlint, markdownlint]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# python-template
22

33
[![CI](https://github.com/nwarila/python-template/actions/workflows/template-ci.yml/badge.svg)](https://github.com/nwarila/python-template/actions/workflows/template-ci.yml)
4-
[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/NWarila/47ca9a1b16c3730c21cb89449ecb8d6c/raw/coverage.json)](https://github.com/nwarila/python-template/actions/workflows/template-ci.yml)
4+
[![Coverage](https://img.shields.io/endpoint?url=https://nwarila.github.io/python-template/coverage.json)](https://github.com/nwarila/python-template/actions/workflows/template-ci.yml)
55
[![Python](https://img.shields.io/badge/python-%E2%89%A53.11-3776ab?logo=python&logoColor=white)](https://www.python.org)
66
[![Platform](https://img.shields.io/badge/platform-linux%20%7C%20macos%20%7C%20windows-lightgrey)](https://github.com/nwarila/python-template)
77
[![License](https://img.shields.io/github/license/nwarila/python-template)](LICENSE)

reference/repo-ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
# Also add a template-sync.yml workflow that calls self-update.yml via uses:
44
# to receive automatic script and config updates via pull request.
55
# See README.md "Template Sync" for the snippet.
6+
#
7+
# Coverage badge: enable GitHub Pages (Settings > Pages > Source: gh-pages)
8+
# and add to README:
9+
# ![Coverage](https://img.shields.io/endpoint?url=https://<owner>.github.io/<repo>/coverage.json)
610
name: CI
711

812
on:
@@ -12,7 +16,7 @@ on:
1216
branches: [main]
1317

1418
permissions:
15-
contents: read
19+
contents: write
1620

1721
concurrency:
1822
group: ${{ github.workflow }}-${{ github.ref }}

0 commit comments

Comments
 (0)