Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 905
ma1234 Avatar asked Oct 17 '20 21:10

ma1234


Video Answer


4 Answers

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.

like image 182
Artur A Avatar answered Oct 18 '22 21:10

Artur A


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.

like image 21
Nermin Avatar answered Oct 18 '22 22:10

Nermin


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:

  • adjust the name of the parent repository (here, I used org/parent_repository as an example).
  • create a private access token. with sufficient permissions to write in your parent repository and save it as a repository secret (under the name PRIVATE_TOKEN_GITHUB in my example above)

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.

like image 9
Droplet Avatar answered Oct 18 '22 23:10

Droplet


A much better option today is to utilize Dependabot to auto create PRs for submodules.

https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem

A sample that checks daily if a submodule has been updated: In .github/dependabot.yml

version: 2

updates:
  - package-ecosystem: gitsubmodule
    schedule:
        interval: "daily"
    directory: /
like image 5
aknosis Avatar answered Oct 18 '22 23:10

aknosis