name: Update Test Badges on: workflow_dispatch: workflow_run: workflows: ["Build and Push Docker Images"] types: [completed] branches: [main] permissions: contents: write # Prevent parallel badge workflows from racing each other concurrency: group: update-test-badges cancel-in-progress: true jobs: update-badges: name: Update Test Count Badges runs-on: ubuntu-latest # Only run after successful docker builds, not failed ones if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout repository uses: actions/checkout@v6 with: token: ${{ secrets.BADGE_TOKEN || secrets.GITHUB_TOKEN }} - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '22' cache: 'npm' cache-dependency-path: '**/package-lock.json' - name: Install backend dependencies working-directory: backend run: npm ci - name: Install frontend dependencies working-directory: frontend run: npm ci - name: Run backend tests and capture count id: backend-tests working-directory: backend timeout-minutes: 5 env: CI: true run: | OUTPUT=$(npm run test:run 2>&1) || true echo "$OUTPUT" # Strip ANSI escape codes, then extract "Tests X passed" from output CLEAN=$(echo "$OUTPUT" | sed 's/\x1b\[[0-9;]*m//g') PASSED=$(echo "$CLEAN" | grep -oP 'Tests\s+\K\d+(?=\s+passed)' | tail -1) echo "count=$PASSED" >> $GITHUB_OUTPUT - name: Run frontend tests and capture count id: frontend-tests working-directory: frontend timeout-minutes: 5 env: CI: true run: | OUTPUT=$(npm run test:run 2>&1) || true echo "$OUTPUT" # Strip ANSI escape codes, then extract "Tests X passed" from output CLEAN=$(echo "$OUTPUT" | sed 's/\x1b\[[0-9;]*m//g') PASSED=$(echo "$CLEAN" | grep -oP 'Tests\s+\K\d+(?=\s+passed)' | tail -1) echo "count=$PASSED" >> $GITHUB_OUTPUT - name: Update README badges run: | BACKEND_COUNT="${{ steps.backend-tests.outputs.count }}" FRONTEND_COUNT="${{ steps.frontend-tests.outputs.count }}" echo "Backend tests: $BACKEND_COUNT" echo "Frontend tests: $FRONTEND_COUNT" # Only update if we got valid counts if [[ -n "$BACKEND_COUNT" && -n "$FRONTEND_COUNT" ]]; then # URL encode the slash for shields.io BACKEND_BADGE="https://img.shields.io/badge/Backend_Tests-${BACKEND_COUNT}%2F${BACKEND_COUNT}-brightgreen?logo=vitest" FRONTEND_BADGE="https://img.shields.io/badge/Frontend_Tests-${FRONTEND_COUNT}%2F${FRONTEND_COUNT}-brightgreen?logo=vitest" # Update README using sed sed -i "s|https://img.shields.io/badge/Backend_Tests-[^\"]*|$BACKEND_BADGE|g" README.md sed -i "s|https://img.shields.io/badge/Frontend_Tests-[^\"]*|$FRONTEND_BADGE|g" README.md echo "Updated badges in README.md" else echo "Could not extract test counts, skipping update" exit 0 fi - name: Commit and push badge updates run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add README.md if git diff --cached --quiet; then echo "No badge changes to commit" else git commit -m "chore: update test count badges [skip ci]" # Rebase on latest main to avoid push rejection when concurrent # badge workflows or other [skip ci] commits land between checkout and push git pull --rebase origin main git push fi