Skip to content

sync-module

sync-module #34

Workflow file for this run

name: Sync module repo ➜ refresh TOC & push to site repo
on:
repository_dispatch:
types: [sync-module]
permissions:
contents: write
jobs:
sync:
runs-on: ubuntu-latest
env:
SITE_REPO: ds-modules/ecc-textbook
GH_PAT: ${{ secrets.ECC_TEXTBOOK_PAT }}
steps:
# -----------------------------------------------------------------------
# 1. Pull THIS repo (so we can commit back into it)
- uses: actions/checkout@v4
with:
fetch-depth: 0
# -----------------------------------------------------------------------
# 2. Remove the old copy of this module & pull fresh
- name: Purge and update module folder
run: |
MODULE="${{ github.event.client_payload.folder_name }}"
rm -rf "$MODULE"
- uses: actions/checkout@v4
with:
repository: ${{ github.event.client_payload.source_repo }}
path: tmp-source
fetch-depth: 0
- name: Copy in new files (skip .git/.github)
run: |
rsync -a --delete --exclude .git --exclude .github tmp-source/ "${{ github.event.client_payload.folder_name }}/"
- name: Remove tmp-source checkout
run: rm -rf tmp-source
# -----------------------------------------------------------------------
# 3. Auto-generate _toc.yml (recursive scan)
- name: Generate _toc.yml (one part per module)
run: |
python - <<'PY'
import pathlib, yaml, re, os
ROOT = pathlib.Path('.') # repo root
modules_dir = ROOT # each top-level folder *is* a module
toc_parts = []
for module_path in sorted(p for p in modules_dir.iterdir() if p.is_dir()):
module_name = module_path.name # e.g. ecc-biology
chapters = []
# Recursively collect every .ipynb under this module (skip checkpoints)
for nb in sorted(module_path.rglob('*.ipynb')):
if 'ipynb_checkpoints' in nb.parts:
continue
rel_to_module = nb.relative_to(module_path).with_suffix('') # drop .ipynb
chapters.append({'file': str(rel_to_module)})
if chapters:
toc_parts.append({
'caption': module_name,
'chapters': chapters
})
toc = {
'format': 'jb-book',
'root' : 'intro', # <— make sure modules/intro.md exists
'parts' : toc_parts
}
with open('_toc.yml', 'w') as f:
yaml.dump(toc, f, sort_keys=False)
PY
# -----------------------------------------------------------------------
# 4. Commit _toc.yml + refreshed module
- name: Commit back to notebooks repo
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if [ -n "$(git status --porcelain)" ]; then
git add .
git commit -m "Auto-sync ${{ github.event.client_payload.folder_name }} + regenerate _toc.yml"
git push
else
echo "Nothing to commit."
fi
# -----------------------------------------------------------------------
# 5. Convert ALL notebooks → MyST Markdown & push to site repo
- name: Install conversion tools
run: pip install jupytext==1.*
- name: Checkout site repo
uses: actions/checkout@v4
with:
repository: ${{ env.SITE_REPO }}
path: site
token: ${{ env.GH_PAT }}
fetch-depth: 0
- name: Convert & copy notebooks (with debug)
run: |
set -euo pipefail
echo "==> Preparing site/modules"
mkdir -p site/modules
declare -a fail_list=()
# Skip ipynb_checkpoints; iterate over every .ipynb file
while IFS= read -r nb; do
md="site/modules/${nb%.ipynb}.md"
mkdir -p "$(dirname "$md")"
echo "Converting $nb → $md"
if ! jupytext "$nb" --to myst -o "$md"; then
echo "::error ::Failed to convert $nb"
fail_list+=("$nb")
fi
done < <(
find . -type d -name 'ipynb_checkpoints' -prune -o \
-type f -name '*.ipynb' -print
)
# Stop the job if anything failed, printing a neat summary
if [ ${#fail_list[@]} -ne 0 ]; then
echo "-----------------------------------------------------------------"
echo "The following notebooks could NOT be converted:"
printf ' - %s\n' "${fail_list[@]}"
echo "-----------------------------------------------------------------"
exit 1
fi
# ---------------------------------------------------------------
# Only reached if every conversion succeeded
echo "Copying book-level files"
cp _toc.yml site/modules/_toc.yml
echo "Copied _toc.ym"
- name: Commit to site repo
run: |
cd site
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if [ -n "$(git status --porcelain)" ]; then
git add .
git commit -m "Sync from notebooks repo $GITHUB_SHA"
git push
else
echo "Site repo already up to date."
fi