Health check #65
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Persistent scheduled checks that survive across Claude sessions. Mirrors the | |
| # in-session crons (build regression, code-debt audit, community signal) but | |
| # runs in GitHub Actions so it keeps going indefinitely. Outputs a job summary | |
| # that's visible in the Actions tab — no notifications unless something is | |
| # wrong (job fails on regressions). | |
| # | |
| # Cadence is staggered so jobs don't all run at the same minute (avoids the | |
| # universal :00 cron-storm pattern). | |
| name: Health check | |
| on: | |
| schedule: | |
| # Daily build smoke at 07:17 UTC (~08:17 / 09:17 Berlin depending on DST). | |
| - cron: "17 7 * * *" | |
| # Weekly code-debt audit on Mondays at 14:23 UTC. | |
| - cron: "23 14 * * 1" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| issues: read | |
| pull-requests: read | |
| concurrency: | |
| group: health-check | |
| cancel-in-progress: false | |
| jobs: | |
| build-smoke: | |
| # Fires daily AND on Mondays AND on manual dispatch. | |
| name: Daily build smoke | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install Cortex packages | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e packages/cortex-core | |
| pip install -e packages/cortex-cli | |
| - name: Build extreme | |
| id: build | |
| run: | | |
| mkdir -p /tmp/health | |
| cortex build -c examples/extreme.yml -o /tmp/health/ | tee /tmp/build.log | |
| MAIN=$(ls -1 /tmp/health/*.svg 2>/dev/null | wc -l) | |
| VARIANTS=$(ls -1 /tmp/health/variants/*.svg 2>/dev/null | wc -l) | |
| echo "main=$MAIN" >> $GITHUB_OUTPUT | |
| echo "variants=$VARIANTS" >> $GITHUB_OUTPUT | |
| - name: Verify XML well-formedness | |
| run: | | |
| python -c " | |
| import xml.etree.ElementTree as ET, glob | |
| files = glob.glob('/tmp/health/**/*.svg', recursive=True) | |
| failed = [] | |
| for f in files: | |
| try: | |
| ET.parse(f) | |
| except Exception as e: | |
| failed.append((f, str(e))) | |
| if failed: | |
| for f, e in failed: | |
| print(f'BAD: {f}: {e}') | |
| raise SystemExit(1) | |
| print(f'All {len(files)} SVGs parse cleanly') | |
| " | |
| - name: Compare sizes against committed examples/rendered/extreme | |
| run: | | |
| set +e | |
| DELTAS="" | |
| for f in /tmp/health/*.svg /tmp/health/variants/*.svg; do | |
| name=$(basename "$f") | |
| dir=$(dirname "$f" | sed 's|/tmp/health|examples/rendered/extreme|') | |
| committed="$dir/$name" | |
| [ ! -f "$committed" ] && continue | |
| new_size=$(stat -c%s "$f") | |
| old_size=$(stat -c%s "$committed") | |
| if [ "$old_size" -eq 0 ]; then continue; fi | |
| pct=$(awk "BEGIN { printf \"%.0f\", ($new_size - $old_size) * 100 / $old_size }") | |
| if [ "$pct" -gt 20 ] || [ "$pct" -lt -30 ]; then | |
| DELTAS="$DELTAS\n- \`$name\`: ${pct}% (${old_size}B -> ${new_size}B)" | |
| fi | |
| done | |
| { | |
| echo "## Daily build smoke" | |
| echo "" | |
| echo "**Built:** ${{ steps.build.outputs.main }} main + ${{ steps.build.outputs.variants }} variant SVGs" | |
| echo "" | |
| if [ -n "$DELTAS" ]; then | |
| echo "### Size deltas > ±20-30%" | |
| echo -e "$DELTAS" | |
| else | |
| echo "All file sizes within ±20% of committed baseline." | |
| fi | |
| } >> $GITHUB_STEP_SUMMARY | |
| code-debt-audit: | |
| # Only runs on the Monday cron and manual dispatch — daily would be noise. | |
| name: Weekly code-debt audit | |
| if: github.event.schedule == '23 14 * * 1' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install for test enumeration | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e packages/cortex-core | |
| pip install -e packages/cortex-cli | |
| pip install pytest | |
| - name: Audit | |
| run: | | |
| { | |
| echo "## Weekly code-debt audit" | |
| echo "" | |
| echo "### TODO / FIXME markers" | |
| COUNT=$(grep -rn "TODO\|FIXME\|XXX\|HACK" packages/ --include="*.py" 2>/dev/null | wc -l) | |
| echo "**Total: $COUNT**" | |
| if [ "$COUNT" -gt 0 ]; then | |
| echo "" | |
| echo '```' | |
| grep -rn "TODO\|FIXME\|XXX\|HACK" packages/ --include="*.py" 2>/dev/null | head -20 | |
| echo '```' | |
| fi | |
| echo "" | |
| echo "### Skipped tests" | |
| SKIPPED=$(grep -rn "@pytest.mark.skip\|pytest.skip\|skipif" packages/ --include="*.py" 2>/dev/null | wc -l) | |
| echo "**Total: $SKIPPED** $([ $SKIPPED -gt 0 ] && echo '⚠️ hides regressions — investigate')" | |
| echo "" | |
| echo "### Test count" | |
| TESTS=$(python -m pytest packages/ --co -q 2>&1 | grep "tests collected" | head -1) | |
| echo "$TESTS" | |
| echo "" | |
| echo "### Largest builders (>500 lines)" | |
| echo "" | |
| echo '```' | |
| for f in packages/cortex-core/cortex/builders/*.py; do | |
| lines=$(wc -l < "$f") | |
| if [ "$lines" -gt 500 ]; then | |
| echo "$lines $f" | |
| fi | |
| done | sort -rn | head -5 | |
| echo '```' | |
| echo "" | |
| echo "### Total widget builders" | |
| BUILDERS=$(ls packages/cortex-core/cortex/builders/*.py | grep -v __init__ | wc -l) | |
| echo "$BUILDERS builder modules currently shipped" | |
| } >> $GITHUB_STEP_SUMMARY | |
| community-signal: | |
| # Same Monday cadence as debt audit — surfaces external activity. | |
| name: Weekly community signal | |
| if: github.event.schedule == '23 14 * * 1' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Survey issues + PRs | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| { | |
| echo "## Weekly community signal" | |
| echo "" | |
| STARS=$(gh api repos/${{ github.repository }} --jq .stargazers_count) | |
| FORKS=$(gh api repos/${{ github.repository }} --jq .forks_count) | |
| WATCHERS=$(gh api repos/${{ github.repository }} --jq .watchers_count) | |
| echo "**Stars:** $STARS · **Forks:** $FORKS · **Watchers:** $WATCHERS" | |
| echo "" | |
| echo "### Recent open issues (last 10)" | |
| gh issue list --state open --limit 10 --json number,title,createdAt,author \ | |
| --jq '.[] | "- #\(.number) \(.title) — @\(.author.login) (\(.createdAt[:10]))"' \ | |
| || echo "(none)" | |
| echo "" | |
| echo "### Recent PRs from external authors" | |
| OWNER="${{ github.repository_owner }}" | |
| gh pr list --state all --limit 20 --json number,title,author,state,createdAt \ | |
| --jq ".[] | select(.author.login != \"$OWNER\") | \"- #\\(.number) [\\(.state)] \\(.title) — @\\(.author.login)\"" \ | |
| || echo "(none — only first-party PRs)" | |
| } >> $GITHUB_STEP_SUMMARY |