Navigation
Getting StartedUpdated July 3, 2026

Submodule Management & Automation

how-togit-submodulesautomationgithub-actionsmonorepotroubleshootingworkflow

Submodule management and automation

This page covers the CI/automation side of submodule management: the GitHub Actions workflows, the .megadoc/ fallback scripts, and how to recover when the automation fails. For the local developer workflow (clone, init, update, worktree interaction), see Submodules guide.


Quick navigation


Overview

MEGADOC aggregates ~74 git submodules into a single MkDocs site via the mkdocs-monorepo-plugin. Two GitHub Actions workflows keep this safe at scale:

Workflow filePurpose
.github/workflows/submodule-adder.ymlReads submodules_source.txt, opens a PR that adds any missing submodules.
.github/workflows/validate-submodules.ymlRuns .megadoc/scripts/validate-submodules.py and apply-fallbacks.py; auto-files issues against non-compliant repos.

Workflows and triggers

  • submodule-adder.yml is manual only (on: workflow_dispatch:). Run it from the GitHub UI: Actions → Load Submodules → Run workflow. It reads submodules_source.txt, diffs against .gitmodules, and runs git submodule add for each new entry.
  • validate-submodules.yml triggers on workflow_dispatch and on push to main when any of .gitmodules, .megadoc/scripts/apply-fallbacks.py, .megadoc/scripts/validate-submodules.py, .megadoc/README.md, or .megadoc/templates/issue-template.md change. There is no PR trigger and no scheduled cron. It enforces the required mkdocs.yml + docs/ + docs/index.md structure on every submodule and creates issues in upstream repos missing the structure.

Step-by-step: onboarding a new submodule

  1. Create a feature branch / worktree from main.

  2. Append the repo slug to submodules_source.txt — one <org>/<repo> per line, no scheme, no path, no branch. Example:

    optum-tech-compute/ohemr-ansible-role-example
    
  3. Commit using a conventional-commits message:

    git add submodules_source.txt
    git commit -m "chore(submodules): add ohemr-ansible-role-example"
    git push -u origin <branch>
    
  4. Open a PR with the submodules_source.txt change, then trigger the workflow manually from Actions → Load Submodules → Run workflow. The job will run git submodule add for each new entry and push the commit back onto the PR branch.

  5. After the next push to main (or a manual workflow_dispatch), validate-submodules.yml runs against the new submodule. If it lacks the required structure, an issue is auto-filed in the upstream repo and the .megadoc/ fallback layer keeps the build green.

  6. Review the rendered docs locally:

    git submodule update --init --recursive
    mkdocs build --strict
    mkdocs serve
    
  7. Merge the PR once mkdocs build --strict and the docs-quality-check.yml checks are green.


The .megadoc/ fallback system

When a submodule has not yet adopted the required documentation structure, the fallback layer keeps the MEGADOC build green and the issue tracked.

PathRole
.megadoc/scripts/validate-submodules.pyScans submodules/, writes a JSON report of missing files, and (on CI) opens GitHub issues.
.megadoc/scripts/apply-fallbacks.pyReads the report, writes minimal mkdocs.yml / docs/index.md shims under .megadoc/fallbacks/.
.megadoc/fallbacks/<submodule>/Generated, build-time-only stand-ins; the nav: includes resolve to these when the real ones are absent.

Run the pair locally before pushing a submodule bump:

python3 .megadoc/scripts/validate-submodules.py --output megadoc-validation.json
python3 .megadoc/scripts/apply-fallbacks.py --report megadoc-validation.json
mkdocs build --strict

The --output / --report flags match the contract used by .github/workflows/validate-submodules.yml in CI.


Best practices

  • Default branch tracking is implicit; if you need a non-default branch, edit .gitmodules after the adder workflow runs and commit the change.
  • Open one submodule per PR; mass-adding them makes review and bisect painful.
  • The adder workflow constructs HTTPS clone URLs; do not paste SSH URLs or full URLs into submodules_source.txt — only <org>/<repo> slugs.
  • Use conventional-commits scope submodules (e.g. chore(submodules): bump ohemr-ansible-role-odb) so semantic-release and the org ruleset accept the message.
  • Re-run validate-submodules.py after every bump; submodules drift.

Troubleshooting

SymptomLikely causeFix
submodule-adder.yml PR is emptyEntry already present in .gitmodulesInspect .gitmodules; remove the duplicate from submodules_source.txt.
mkdocs build fails with "could not include submodules/<x>/mkdocs.yml"Submodule not initializedgit submodule update --init --recursive
validate-submodules.yml opens an issue in your repoSubmodule is missing docs/, mkdocs.yml, or docs/index.mdLand the missing files in the upstream repo, or rely on .megadoc/fallbacks/ until you can.
Submodule appears empty in a worktree.git/modules/ not yet populated for that worktreeRun git submodule update --init --recursive inside the worktree root.
submodule-adder.yml cannot pushBranch protection / org ruleset blocks workflow commitsHave a maintainer rerun under a token with the appropriate ruleset bypass; do not disable the rule.

Resources and next steps

  • Submodules guide — local developer workflow (clone, init, update, worktrees).
  • Contributing overview — see the "Working with Submodules" section.
  • .megadoc/scripts/validate-submodules.py and .megadoc/scripts/apply-fallbacks.py — the canonical implementation of the fallback layer.
  • .github/workflows/submodule-adder.yml and .github/workflows/validate-submodules.yml — the CI side of this workflow.