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:
- Catalog Generation – The workflow executes
python3 scripts/build_catalog.pyto scan thephases/directory and produce an updatedcatalog.jsonwith current totals. - Count Synchronization – The command
python3 scripts/check_readme_counts.py --fixreads the catalog and rewrites any divergent numbers inREADME.mdusing regex patterns that match badge URLs, alt-text, and prose snippets. - Conditional Committing – The workflow checks if
README.mdwas modified. If unchanged, the job exits silently. If changed, it stages the file, commits with the messagechore(readme): sync counts, and pushes to themainbranch. - 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-syncjob in.github/workflows/curriculum.ymltriggers exclusively on pushes tomain, including merge events. scripts/build_catalog.pygenerates authoritative metrics by scanning thephases/directory structure and writing tocatalog.json.scripts/check_readme_counts.py --fixuses regex pattern matching to update hard-coded statistics inREADME.mdwithout manual intervention.- Automated commits use the prefix
chore(readme): sync countsand 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →