How README Counts Are Auto-Synced by CI on Merge in AI Engineering Curriculum

When a commit lands on the main branch, the readme-counts-sync CI job automatically regenerates the curriculum catalog and rewrites any mismatched statistics in README.md before committing the fixes back to the repository.

The rohitg00/ai-engineering-from-scratch repository maintains dynamic statistics—such as lesson counts, phase totals, and artifact numbers—directly in its README.md. To ensure these hard-coded values remain accurate as the curriculum evolves, the project employs a continuous integration pipeline that automatically synchronizes README counts on every merge to main.

The Auto-Sync Pipeline Architecture

The synchronization process relies on three coordinated components: a catalog generator, a README validator, and a GitHub Actions workflow.

Source of Truth Generation

The scripts/build_catalog.py utility serves as the authority for curriculum metrics. It traverses the phases/ directory structure, enumerating every lesson, code file, and output artifact. The script outputs a catalog.json file containing a totals block with fields like lessons, phases, skills, prompts, and artifacts.

README Validation and Patching

The scripts/check_readme_counts.py script performs the actual synchronization. When invoked with the --fix flag, it reads both catalog.json and README.md, then applies targeted regular-expression replacements to align the documented counts with the generated totals.

The core logic resides in the apply_fixes function:


# scripts/check_readme_counts.py

def apply_fixes(readme_text: str, totals: dict[str, int]) -> str:
    for pattern in PATTERNS:
        expected = totals[pattern.field]

        def replace(match: re.Match[str], expected: int = expected) -> str:
            whole = match.group(0)
            old = match.group(1)
            start = match.start(1) - match.start()
            return whole[:start] + str(expected) + whole[start + len(old):]

        readme_text = pattern.regex.sub(replace, readme_text)
    return readme_text

Automated Commit Workflow

The .github/workflows/curriculum.yml file defines the readme-counts-sync job, which executes only on push events to main. The job requires contents: write permissions to push automated commits.


# .github/workflows/curriculum.yml

- name: readme-counts-sync
  runs-on: ubuntu-latest
  permissions:
    contents: write
  if: github.event_name == 'push'
  steps:
    - uses: actions/checkout@v4
      with:
        ref: ${{ github.ref }}
        token: ${{ secrets.GITHUB_TOKEN }}
    - uses: actions/setup-python@v5
      with:
        python-version: "3.12"
    - name: build ephemeral catalog
      run: python3 scripts/build_catalog.py
    - name: sync README counts
      run: python3 scripts/check_readme_counts.py --fix
    - name: commit + push if README changed
      env:
        BOT_COMMIT_PREFIX: "chore(readme): sync counts"
      run: |
        if git diff --quiet README.md; then exit 0; fi
        git config user.name "github-actions[bot]"
        git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
        git add README.md
        git commit -m "$BOT_COMMIT_PREFIX"
        git push origin HEAD:${{ github.ref#refs/heads/ }}

Step-by-Step Execution Flow

When a pull request merges into main, the following sequence ensures the README stays current:

  1. Catalog Generation – The workflow executes python3 scripts/build_catalog.py to scan the phases/ directory and produce an updated catalog.json with current totals.
  2. Count Synchronization – The command python3 scripts/check_readme_counts.py --fix reads the catalog and rewrites any divergent numbers in README.md using regex patterns that match badge URLs, alt-text, and prose snippets.
  3. Conditional Committing – The workflow checks if README.md was modified. If unchanged, the job exits silently. If changed, it stages the file, commits with the message chore(readme): sync counts, and pushes to the main branch.
  4. Self-Healing Verification – Subsequent pushes find the README already synchronized, resulting in no-op runs that conserve CI resources.

Preventing Drift in Pull Requests

To provide early feedback, the repository includes a separate readme-counts-drift job that runs on pull request branches. This job executes the check without the --fix flag, warning authors that the main branch will automatically correct any discrepancies post-merge. This dual-job approach allows developers to preview changes while guaranteeing the source of truth remains accurate.

Summary

  • The readme-counts-sync job in .github/workflows/curriculum.yml triggers exclusively on pushes to main, including merge events.
  • scripts/build_catalog.py generates authoritative metrics by scanning the phases/ directory structure and writing to catalog.json.
  • scripts/check_readme_counts.py --fix uses regex pattern matching to update hard-coded statistics in README.md without manual intervention.
  • Automated commits use the prefix chore(readme): sync counts and only occur when the README actually changes, creating a self-healing documentation system.

Frequently Asked Questions

What triggers the README count synchronization?

The synchronization triggers on any push event to the main branch, which includes merged pull requests. The job is explicitly gated by the condition if: github.event_name == 'push' in the workflow configuration.

How does the script know which numbers to update in the README?

The check_readme_counts.py script uses a predefined set of regular-expression patterns that target specific fields—such as badge URLs, alt-text attributes, and inline prose—associated with lesson, phase, and artifact counts. Each pattern maps to a field in the totals block of catalog.json.

Can I run the count synchronization locally before pushing?

Yes. Execute python3 scripts/build_catalog.py followed by python3 scripts/check_readme_counts.py --fix from the repository root. This regenerates catalog.json and updates README.md in-place, allowing you to verify the exact changes that CI would apply.

What happens if the README is already correct?

If git diff --quiet README.md detects no changes after running the sync scripts, the workflow exits immediately without creating a commit. This idempotent behavior ensures the git history remains clean and free from unnecessary automated commits.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →