'Using GitHub Actions to automatically update the repo's submodules

Title says it all. I tried using a bunch of different git commands like git submodule update --remote --merge and git submodule foreach git pull origin master which work fine on my computer, but not when it's run on GitHub actions. I tried adding git status to the workflow and the status just shows "Up to date with origin/master, nothing to commit" or something like that.



Solution 1:[1]

If you need to auto update references to your submodules via GitHub actions:

Create a new workflow in your parent repository that will synchronize references:

name: 'Submodules Sync'

on:
  # Allows you to run this workflow manually from the Actions tab or through HTTP API
  workflow_dispatch:

jobs:
  sync:
    name: 'Submodules Sync'
    runs-on: ubuntu-latest

    # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
    defaults:
      run:
        shell: bash

    steps:
    # Checkout the repository to the GitHub Actions runner
    - name: Checkout
      uses: actions/checkout@v2
      with:
        token: ${{ secrets.CI_TOKEN }}
        submodules: true

    # Update references
    - name: Git Sumbodule Update
      run: |
        git pull --recurse-submodules
        git submodule update --remote --recursive

    - name: Commit update
      run: |
        git config --global user.name 'Git bot'
        git config --global user.email '[email protected]'
        git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
        git commit -am "Auto updated submodule references" && git push || echo "No changes to commit"

where

  • CI_TOKEN is a security token variable in GitHub that have 'Read-Write' access to the parent repository, and 'Read' access to submodule repositories.

In the child (submodule) GitHub action notify the parent about changes.

name: 'Submodule Notify Parent'

on:
  push:
    branches:
      - main    

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  notify:
    name: 'Submodule Notify Parent'
    runs-on: ubuntu-latest

    # Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
    defaults:
      run:
        shell: bash

    steps:
    - name: Github REST API Call
      env:
        CI_TOKEN: ${{ secrets.CI_TOKEN }}
        PARENT_REPO: <my_organization/my-app>
        PARENT_BRANCH: develop
        WORKFLOW_ID: <9999999>
      run: |
        curl -fL --retry 3 -X POST -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ env.CI_TOKEN }}" https://api.github.com/repos/${{ env.PARENT_REPO }}/actions/workflows/${{ env.WORKFLOW_ID }}/dispatches -d '{"ref":"${{ env.PARENT_BRANCH }}"}'

where

  • PARENT_REPO - name of the parent repository as it is in Github (my_org/my_app or just my_app if there is no organization).
  • WORKFLOW_ID - parent Wofklow ID to call via rest API. To find it run curl using your CI_TOKEN:
    curl -X GET -H "Authorization: token $CI_TOKEN" https://api.github.com/repos/$PARENT_REPO/actions/workflows
    

Repeat the workflow creation for every submodule.


P.S. For me it works very stable. Please add information about existing github actions with the above logic if there is any.

Solution 2:[2]

You can achieve this with a single action in the submodule repository:

name: Send submodule updates to parent repo

on:
  push:
    branches: 
      - main

jobs:
  update:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with: 
          repository: org/parent_repository
          token: ${{ secrets.PRIVATE_TOKEN_GITHUB }}

      - name: Pull & update submodules recursively
        run: |
          git submodule update --init --recursive
          git submodule update --recursive --remote
      - name: Commit
        run: |
          git config user.email "[email protected]"
          git config user.name "GitHub Actions - update submodules"
          git add --all
          git commit -m "Update submodules" || echo "No changes to commit"
          git push

You need to:

With this action, every push on the main branch in the submodule repository will result in a commit pulling the update in the parent repository.

Solution 3:[3]

Simple solution

You pull and update the submodules recursively and then commit to the repo.

name: Update submodules

# Controls when the action will run.
on:
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  # This workflow contains a single job called "update"
  update:
    runs-on: ubuntu-latest

    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Pull & update submodules recursively
        run: |
          git submodule update --init --recursive
          git submodule update --recursive --remote

      - name: Commit & push changes
        run: |
          git config --global user.name ${{ secrets.USER_NAME }}
          git config --global user.email ${{ secrets.USER_EMAIL }}
          git commit -am "Update submodules"
          git push

Instead of using Github secrets like ${{ secrets.USER_NAME }} I just hard code my git credentials since I'm lazy, but I figured you might care about security.

Solution 4:[4]

You can compare your GitHub Action source with one like submodule-branch-check, which does make at least a git submodule update.

Check if the update --remote is enough to pull from its own remote origin.

Solution 5:[5]

it working for me, read acticle in here https://zenn.dev/ymmmtym/articles/dc741561759a49

name: Update submodules
on:
  push:
    branches:
      - dev
  pull_request:
    branches:
      - dev
jobs:
  update_submodules:
    name: Update submodules
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        token : ${{secrets.OOG_TOKEN}}
        submodules : true
    - name: Update submodules
      id: update
      run: git submodule update --remote --recursive 
    - name: Run git status
      id: status
      run: echo "::set-output name=status::$(git status -s)"
    - name: Add and commit files
      run: |
        git add .
        git config --local user.email "[email protected]"
        git config --local user.name "GitHub Action"
        git commit -m "Update submodules at $(date "+DATE: %Y-%m-%d TIME: %H:%M:%S")"
      if: ${{ steps.status.outputs.status }}
    - name: Push changes
      uses: ad-m/github-push-action@master
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        branch: dev
      if: ${{ steps.status.outputs.status && github.event_name == 'push' }}

Solution 6:[6]

i try this it working for me

- uses: actions/checkout@v3
      with:
        repository: {owner}/repo
        token: ${{ secrets.PRIVATE_TOKEN_GITHUB }}
        submodules: recursive

    - name: submodules recursively
      run: git submodule update --init --recursive

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Droplet
Solution 3 Nermin
Solution 4 VonC
Solution 5
Solution 6 Mansour Mehidi