Access private submodules in GitHub Actions
Using submodules can be a simple solution to make some parts of a public repo private. For example I have separated the actual content of this blog to a private repo. Not because it's something secret (you are reading it now anyway) but it's fun to play around with and also if someone forks this blog the content is probably something they should write themselves.
A problem I encountered is that my GitHub Actions flow didn't really play nice with fetching the private submodule during build. The parent (blog) repo didn't have access to other repos (like content), for good reasons. Here is my solution for accessing the private submodule during build.
- The parent repo
blog
is public on GitHub - The submodule repo
content
is private on GitHub
First we need to generate a new key locally to be used on our CI/CD for read permissions to our submodule repository.
ssh-keygen -t rsa -b 4096 -C "an optional comment"
Don't add a password and you can save it to a temporary place for now, let's say the desktop.
Then we need to add the public part of the key to our submodule repo. You do that under submodule repo -> Settings -> Deploy keys -> Add deploy key
. Give it a descriptive title, paste the public part of the key and keep it read-only.
Next step is to add the private part of the key to the repository using the submodule, the parent blog repo in our example. Navigate to parent repo -> Setting -> Settings -> Secrets -> New secrets
and give it a name and paste the key.
The last step is to use the secret to authorize against our submodule repo when checking out the project in an Action.
A simple workflow to build the blog could look like this:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '14.x'
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Do stuff
run: yarn do-stuff
The functionality already exists in the checkout action, you only need to enable it using the key by adding this to the checkout step:
ssh-key: ${{ secrets.SUBMODULE_CONTENT_PULL_KEY }}
submodules: 'recursive'
This is what the updated flow will look like
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ssh-key: ${{ secrets.SUBMODULE_CONTENT_PULL_KEY }}
submodules: 'recursive'
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '14.x'
- name: Install dependencies
run: yarn --frozen-lockfile
- name: Do stuff
run: yarn do-stuff
The build will use the SUBMODULE_CONTENT_PULL_KEY
for checking out both the parent and the submodule, but since the parent is a public repo that's no problem. If both are private the key needs to have access to both repos.