-
Notifications
You must be signed in to change notification settings - Fork 723
feat(ci): add automated badge update workflow (#138) #343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,79 @@ | ||||||||||||||||||||||||
| name: Update Badges | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||
| workflow_run: | ||||||||||||||||||||||||
| workflows: ["Test Suite"] | ||||||||||||||||||||||||
| types: [completed] | ||||||||||||||||||||||||
| branches: [main] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||
| contents: write | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||
| update-badges: | ||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||
| if: github.event.workflow_run.conclusion == 'success' | ||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | ||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||
| token: ${{ secrets.GITHUB_TOKEN }} | ||||||||||||||||||||||||
| fetch-depth: 2 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - name: Check if last commit was a badge update | ||||||||||||||||||||||||
| id: skip-check | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| LAST_MSG=$(git log -1 --pretty=%B) | ||||||||||||||||||||||||
| if echo "$LAST_MSG" | grep -qiE '^(ci|chore)\(.*badge\)|^\[skip badges\]|^chore: update badge'; then | ||||||||||||||||||||||||
| echo "skip=true" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||
| echo "Skipping: last commit was a badge update ($LAST_MSG)" | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "skip=false" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - name: Count tests | ||||||||||||||||||||||||
| id: count | ||||||||||||||||||||||||
| if: steps.skip-check.outputs.skip != 'true' | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| TEST_COUNT=$(grep -rE '^\s*@test\s' tests/unit/ tests/integration/ | wc -l) | ||||||||||||||||||||||||
| TEST_FILES=$(find tests/unit/ tests/integration/ -name "*.bats" | wc -l) | ||||||||||||||||||||||||
| echo "TEST_COUNT=$TEST_COUNT" >> $GITHUB_ENV | ||||||||||||||||||||||||
| echo "TEST_FILES=$TEST_FILES" >> $GITHUB_ENV | ||||||||||||||||||||||||
| echo "test_count=$TEST_COUNT" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||
| echo "test_files=$TEST_FILES" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||
| echo "Tests: $TEST_COUNT across $TEST_FILES files" | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - name: Update README.md test badge | ||||||||||||||||||||||||
| if: steps.skip-check.outputs.skip != 'true' | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| sed -i "s|https://img.shields.io/badge/tests-[0-9]*%20passing|https://img.shields.io/badge/tests-${TEST_COUNT}%20passing|g" README.md | ||||||||||||||||||||||||
| sed -i "s|tests-[0-9]*%20passing|tests-${TEST_COUNT}%20passing|g" README.md | ||||||||||||||||||||||||
| sed -i "s/\*\*Test Coverage\*\*: [0-9]* tests/\*\*Test Coverage\*\*: ${TEST_COUNT} tests/g" README.md | ||||||||||||||||||||||||
| sed -i "s/\*\*[0-9]* tests\*\* across/\*\*${TEST_COUNT} tests\*\* across/g" README.md | ||||||||||||||||||||||||
|
Comment on lines
+48
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [minor] Two README test-count references use patterns that no Failure scenario: README currently shows
Suggested change
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - name: Update CLAUDE.md test references | ||||||||||||||||||||||||
| if: steps.skip-check.outputs.skip != 'true' | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| # Update any test count text in CLAUDE.md (if present) | ||||||||||||||||||||||||
| sed -i "s/\*\*Test Coverage\*\*: [0-9]* tests/\*\*Test Coverage\*\*: ${TEST_COUNT} tests/g" CLAUDE.md || true | ||||||||||||||||||||||||
| sed -i "s/[0-9]* tests, 100% pass rate/${TEST_COUNT} tests, 100% pass rate/g" CLAUDE.md || true | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - name: Check for changes | ||||||||||||||||||||||||
| id: changes | ||||||||||||||||||||||||
| if: steps.skip-check.outputs.skip != 'true' | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| if git diff --quiet; then | ||||||||||||||||||||||||
| echo "changed=false" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||
| echo "No badge changes needed." | ||||||||||||||||||||||||
| else | ||||||||||||||||||||||||
| echo "changed=true" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||
| git diff | ||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - name: Commit and push changes | ||||||||||||||||||||||||
| if: steps.skip-check.outputs.skip != 'true' && steps.changes.outputs.changed == 'true' | ||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||
| git config user.name "github-actions[bot]" | ||||||||||||||||||||||||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||||||||||||||||||||||||
| git add README.md CLAUDE.md | ||||||||||||||||||||||||
| git commit -m "ci(badge): update test count to ${TEST_COUNT} (${TEST_FILES} files)" | ||||||||||||||||||||||||
| git push | ||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [minor] With no Failure scenario: PR A and PR B land on |
||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| # Issue #138: feat: automate version and test count badges via GitHub Actions | ||
|
|
||
| ## Plan | ||
|
|
||
| ## Problem | ||
|
|
||
| Version badges in README.md and CLAUDE.md require manual updates, leading to drift between actual state and documented state. This was caught during PR #137 review where badges showed `v0.10.1` and `310 tests` instead of `v0.11.2` and `440 tests`. | ||
|
|
||
| ## Proposed Solution | ||
|
|
||
| Implement a GitHub Actions workflow that automatically updates badges after: | ||
| 1. Test suite runs (update test count) | ||
| 2. Releases are published (update version) | ||
|
|
||
| ### Implementation Plan | ||
|
|
||
| **Phase 1: Test Count Automation** | ||
|
|
||
| Create `.github/workflows/update-badges.yml`: | ||
|
|
||
| ```yaml | ||
| name: Update Badges | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main] | ||
| workflow_run: | ||
| workflows: ["CI"] | ||
| types: [completed] | ||
| branches: [main] | ||
|
|
||
| jobs: | ||
| update-badges: | ||
| runs-on: ubuntu-latest | ||
| if: github.event.workflow_run.conclusion == 'success' || github.event_name == 'push' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Get test count | ||
| run: | | ||
| TEST_COUNT=$(npm test 2>&1 | grep -c "^ok " || echo "0") | ||
| echo "TEST_COUNT=$TEST_COUNT" >> $GITHUB_ENV | ||
|
|
||
| - name: Update badges if changed | ||
| run: | | ||
| # Update README.md test badge | ||
| sed -i "s/tests-[0-9]*%20passing/tests-${TEST_COUNT}%20passing/" README.md | ||
|
|
||
| # Update CLAUDE.md test count | ||
| sed -i "s/Tests\*\*: [0-9]* passing/Tests**: ${TEST_COUNT} passing/" CLAUDE.md | ||
|
|
||
| - name: Check for changes | ||
| id: changes | ||
| run: | | ||
| if git diff --quiet; then | ||
| echo "changed=false" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "changed=true" >> $GITHUB_OUTPUT | ||
| fi | ||
|
|
||
| - name: Commit changes | ||
| if: steps.changes.outputs.changed == 'true' | ||
| run: | | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add README.md CLAUDE.md | ||
| git commit -m "chore: update test count badge to ${TEST_COUNT}" | ||
| git push | ||
| ``` | ||
|
|
||
| **Phase 2: Version Automation (Future)** | ||
|
|
||
| When GitHub Releases are adopted: | ||
| - Trigger on `release: [published]` | ||
| - Extract version from release tag | ||
| - Update version badges in README.md, CLAUDE.md | ||
| - Consider using shields.io dynamic badges: `` | ||
|
|
||
| ### Files to Update | ||
|
|
||
| | File | Badge Type | Current Format | | ||
| |------|-----------|----------------| | ||
| | README.md | Version | `` | | ||
| | README.md | Tests | `` | | ||
| | CLAUDE.md | Both | `**Version**: vX.X.X \| **Tests**: XXX passing` | | ||
|
|
||
| ### Acceptance Criteria | ||
|
|
||
| - [ ] Workflow runs after successful CI on main branch | ||
| - [ ] Test count badge updates automatically | ||
| - [ ] No workflow runs on badge-only commits (prevent infinite loop) | ||
| - [ ] Commit messages follow conventional commit format | ||
|
|
||
| ### Future Enhancements | ||
|
|
||
| - [ ] Integrate with GitHub Releases for version automation | ||
| - [ ] Consider switching to dynamic shields.io badges | ||
| - [ ] Add badge for code coverage percentage | ||
|
|
||
| ## Related | ||
|
|
||
| - PR #137 - Manual badge update that prompted this issue | ||
|
|
||
| ## Acceptance Criteria | ||
|
|
||
| - [ ] Workflow runs after successful CI on main branch | ||
| - [ ] Test count badge updates automatically | ||
| - [ ] No workflow runs on badge-only commits (prevent infinite loop) | ||
| - [ ] Commit messages follow conventional commit format |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[minor] The count excludes
tests/e2e/, so the badge advertises fewer tests than the suite actually runs and than the README's own prose claims.Failure scenario:
grepovertests/unit/ tests/integration/yields 1279, but the real total includingtests/e2e/is 1297 (the@testregex itself is fine — the only lines it "misses" are email addresses likee2e@test.local). README line 1201, which this workflow is meant to keep accurate, explicitly states the count covers "unit, integration, and end-to-end," so writing 1279 onto it makes that sentence false. Either includetests/e2e/or drop "end-to-end" from the README wording.