This document describes how to set up automatic submodule updates so that when someone pushes to the submodule repository, the parent repository automatically pulls the latest submodule reference and pushes it.
Push to submodule repo (main branch)
|
v
GitHub Action in submodule repo (notify-parent.yml)
→ sends repository_dispatch event to parent repo
|
v
GitHub Action in parent repo (update-submodule.yml)
→ checks out the target branch (e.g., Staaging)
→ pulls latest submodule ref
→ commits the updated pointer
→ pushes to that branch
|
v
Odoo.sh picks up the new commit automatically
| Role | Repository | SSH URL |
|---|---|---|
| Parent | odoo_sh_dunecrest |
git@github.com:MantleInternational/odoo_sh_dunecrest.git |
| Submodule | odoo_sh_dunecrest_crm |
git@github.com:MantleInternational/odoo_sh_dunecrest_crm.git |
- You are an admin of the GitHub organization (
MantleInternational) - Both repositories are set up with the submodule relationship (
.gitmodulesexists in the parent) - You are on the
mainbranch of the parent repo (the workflow file must live on the default branch)
- Go to github.com -> click your profile picture (top-right) -> Settings
- Scroll to Developer settings (bottom of left sidebar)
- Click Personal access tokens -> Fine-grained tokens -> Generate new token
- Configure:
- Token name:
odoo_sh_dunecrest_crm-auto-update - Expiration: 1 year (or your preference)
- Resource owner:
MantleInternational - Repository access: Select "Only select repositories" -> choose both:
MantleInternational/odoo_sh_dunecrestMantleInternational/odoo_sh_dunecrest_crm
- Permissions:
- Contents: Read and Write
- Token name:
- Click Generate token
- Copy the token immediately -- you will not see it again
Fine-grained tokens for organization repos may require org-level approval:
- Go to github.com/organizations/MantleInternational/settings/personal-access-tokens/active
- Find the token
odoo_sh_dunecrest_crm-auto-update - If it shows as pending, click to approve it
Important: Store this token securely. You will paste it into two GitHub repository secrets in the next steps.
The submodule repo needs the token to trigger the parent repo's workflow.
- Go to github.com/MantleInternational/odoo_sh_dunecrest_crm
- Click Settings -> Secrets and variables -> Actions
- Click New repository secret
- Name:
PARENT_REPO_TOKEN - Secret: paste the token from Step 1
- Name:
- Click Add secret
The parent repo needs the token to clone the private submodule and push the updated reference.
- Go to github.com/MantleInternational/odoo_sh_dunecrest
- Click Settings -> Secrets and variables -> Actions
- Click New repository secret
- Name:
PARENT_REPO_TOKEN - Secret: paste the same token from Step 1
- Name:
- Click Add secret
This workflow runs whenever someone pushes to the main branch of the submodule. It sends a repository_dispatch event to the parent repo, which triggers the parent's workflow.
Create the file .github/workflows/notify-parent.yml in the submodule repo (odoo_sh_dunecrest_crm):
name: Notify Parent Repo
on:
push:
branches: [main]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Trigger parent repo update
run: |
curl -X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.PARENT_REPO_TOKEN }}" \
https://api.github.com/repos/MantleInternational/odoo_sh_dunecrest/dispatches \
-d '{"event_type":"submodule-updated"}'What this does:
- Triggers on any push to
mainin the submodule repo - Sends an HTTP POST to the GitHub API, telling the parent repo that the submodule was updated
- Uses the
PARENT_REPO_TOKENsecret to authenticate the API call
Commit and push this file:
cd odoo_sh_dunecrest_crm
git checkout main
git add .github/workflows/notify-parent.yml
git commit -m "ci: notify parent repo on push to main"
git push origin mainThis workflow runs when it receives the repository_dispatch event from the submodule. It pulls the latest submodule reference, commits the change, and pushes.
Create the file .github/workflows/update-submodule.yml in the parent repo (odoo_sh_dunecrest) on the main branch:
name: Update Submodule
on:
repository_dispatch:
types: [submodule-updated]
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.PARENT_REPO_TOKEN }}
ref: Staaging
- name: Update submodule to latest
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git config --global url."https://x-access-token:${{ secrets.PARENT_REPO_TOKEN }}@github.com/".insteadOf "git@github.com:"
git submodule update --init --remote odoo_sh_dunecrest_crm
git add odoo_sh_dunecrest_crm
git diff --cached --quiet || git commit -m "chore: update odoo_sh_dunecrest_crm submodule"
git pushWhat each line does:
| Line | Purpose |
|---|---|
repository_dispatch: types: [submodule-updated] |
Listens for the event sent by the submodule's workflow |
token: ${{ secrets.PARENT_REPO_TOKEN }} |
Checks out the repo with the PAT so git push works (default GITHUB_TOKEN cannot trigger other workflows) |
ref: Staaging |
Checks out the Staaging branch (change this to target a different branch) |
git config --global url...insteadOf |
Rewrites SSH URLs (git@github.com:) to HTTPS with token auth, so the GitHub Actions runner can clone private submodules without SSH keys |
git submodule update --init --remote |
Pulls the latest commit from the submodule's tracked branch (main) |
git diff --cached --quiet || git commit |
Only commits if the submodule pointer actually changed (avoids empty commits) |
git push |
Pushes the updated submodule reference to the parent repo |
Important: This workflow file must exist on the main branch (the default branch). GitHub only processes repository_dispatch events from the default branch. The ref: Staaging parameter controls which branch gets checked out and updated -- it does NOT need to match the branch the workflow file lives on.
Commit and push this file to main:
cd odoo_sh_dunecrest # parent repo root
git checkout main
git add .github/workflows/update-submodule.yml
git commit -m "ci: auto-update submodule on upstream push"
git push origin mainIf you are working on a different branch (e.g.,
Staaging): commit the file there, push, then create a Pull Request from that branch tomainand merge it. The workflow will not activate until it exists onmain.
Push an empty test commit to the submodule:
cd odoo_sh_dunecrest_crm
git commit --allow-empty -m "test: trigger auto-update workflow"
git push origin mainThen verify:
- Go to github.com/MantleInternational/odoo_sh_dunecrest_crm -> Actions tab
- You should see a green "Notify Parent Repo" run
- Go to github.com/MantleInternational/odoo_sh_dunecrest -> Actions tab
- You should see a green "Update Submodule" run
- Check the
Staagingbranch commit history -- there should be a new commit:chore: update odoo_sh_dunecrest_crm submodule
If a colleague doesn't have SSH set up, they can use HTTPS for the submodule only (without breaking Odoo.sh which requires SSH on the parent repo):
git config submodule.odoo_sh_dunecrest_crm.url https://github.com/MantleInternational/odoo_sh_dunecrest_crm.gitThis only affects the submodule URL locally -- the parent repo's SSH remote stays untouched.
By default (without ref), the workflow updates the default branch (main). To target a different branch, add ref: <branch-name> to the checkout step in update-submodule.yml:
- uses: actions/checkout@v4
with:
token: ${{ secrets.PARENT_REPO_TOKEN }}
ref: Staaging # <-- target branchIf you want to update multiple branches (e.g., both main and Staaging), use a matrix strategy:
name: Update Submodule
on:
repository_dispatch:
types: [submodule-updated]
jobs:
update:
runs-on: ubuntu-latest
strategy:
matrix:
branch: [main, Staaging]
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.PARENT_REPO_TOKEN }}
ref: ${{ matrix.branch }}
- name: Update submodule to latest on ${{ matrix.branch }}
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git config --global url."https://x-access-token:${{ secrets.PARENT_REPO_TOKEN }}@github.com/".insteadOf "git@github.com:"
git submodule update --init --remote odoo_sh_dunecrest_crm
git add odoo_sh_dunecrest_crm
git diff --cached --quiet || git commit -m "chore: update odoo_sh_dunecrest_crm submodule"
git pushThis runs the update job once per branch listed in the matrix.branch array. Add or remove branches as needed.
- Ensure the PAT has Contents: Read and Write permission for both repositories
- If using a fine-grained token: ensure both repos are selected under Repository access, and the token is approved at the organization level (org Settings -> Personal access tokens -> approve the token)
- If using a classic token: ensure it has the
reposcope - Ensure the token owner has write access to both repositories
- The
update-submodule.ymlfile must exist on the default branch (main).repository_dispatchevents only trigger workflows on the default branch. - Check that the
event_typematches exactly:submodule-updatedin both files
- The
git config --global url...insteadOfline rewrites SSH URLs to HTTPS. If it's still failing, verify thePARENT_REPO_TOKENsecret has the correct token value in the parent repo.
- The workflow file is not on the
mainbranch yet. Merge it tomainfirst.
- Regenerate the token and update the
PARENT_REPO_TOKENsecret in both repos.
The PAT expires on the date you set during creation. When it expires:
- Go to GitHub -> Settings -> Developer settings -> Personal access tokens -> Fine-grained tokens
- Find
odoo_sh_dunecrest_crm-auto-updateand click Regenerate token - Copy the new token
- Update the
PARENT_REPO_TOKENsecret in both repos:odoo_sh_dunecrest-> Settings -> Secrets and variables -> Actions -> editPARENT_REPO_TOKENodoo_sh_dunecrest_crm-> Settings -> Secrets and variables -> Actions -> editPARENT_REPO_TOKEN
To add auto-update for another submodule (e.g., odoo_sh_dunecrest_accounting):
- Submodule repo: Add a
.github/workflows/notify-parent.ymlfile (same as Step 4, with thePARENT_REPO_TOKENsecret added to the new submodule repo) - Parent repo: Update
update-submodule.ymlto also update the new submodule:Or usegit submodule update --init --remote odoo_sh_dunecrest_crm git submodule update --init --remote odoo_sh_dunecrest_accounting
--remotewithout specifying a name to update all submodules:git submodule update --init --remote - PAT: Update the fine-grained token to include the new submodule repo in its Repository access list