This article is going live 24th of December in 2024. That’s when we in Finland celebrate Christmas (yes – we celebrate on Christmas Eve, so that we can just chillax on Christmas day, either hungover, playing with our new toys, or both).
I’ll have you know I wrote this article a few days in advance. I’m definitely not working today – I’m frantically wrapping my wife’s presents or watching my kids unwrap some gifts I had no idea my wife got them, depending on whether you’re reading this as it goes live or a few hours later.
And if you’re reading it days, months or years afterwards, just feel free to enjoy the content! Happy holidays / Merry Christmas / Happy Hanukkah!
This article explains how to fix a failing GitHub Actions workflow, in which you’re trying to ninja-merge a branch to another one automatically.
Why? I mean… Maybe for like scheduled publishing of a site on GitHub pages? Or I don’t know, people have all kinds of weird and wild ideas, and apparently I’m not the first or the only one struggling with this.
But let’s take a step back. What am I doing and why?
Background
I wanted to have 2 branches – dev and main. Dev is going to get stuff committed or merged to it after approval, and will be merged to main on a schedule.
Not automatically, not on updates, preferably not manually – but nightly or weekly.
Having frantically googled this on Bing for quite a while, it turns out GitHub Actions doesn’t natively support scheduled merging. And I guess it doesn’t make sense in a lot of cases. But I wanted to make it work.
And after a bit of browsing, I did find this nice GitHub Actions workflow sample on StackOverflow.
name: Automerge
on:
workflow_dispatch:
schedule:
# You can setup schedule here
- cron: '0 0 * * *'
env:
# replace "github_username" with your GitHub username
# replace "github.com/username/repo.git" with your GitHub repo path
# do NOT replace ${{secrets.GITHUB_TOKEN}}, GitHub will take care of it
MY_REPO: https://github_username:${{secrets.GITHUB_TOKEN}}@github.com/koskila/myrepo.git
# replace "long-lived_branch_name" with your branch name
MY_BRANCH: main
# replace it with the path to master repo
MASTER_REPO: https://github.com/koskila/myrepo.git
# replace "master" with your master branch name
MASTER_BRANCH: dev
jobs:
merge:
runs-on: ubuntu-latest
steps:
- name: Merge with master
run: |
git clone ${{env.MY_REPO}} -b ${{env.MY_BRANCH}} tmp
cd tmp
git config user.name "Automerge Bot"
git config user.email "bot@example.com"
git config pull.rebase false
git pull ${{env.MASTER_REPO}} ${{env.MASTER_BRANCH}}
git push
Here I’m merging the dev (MASTER_BRANCH) of my repo (MASTER_REPO) to the main (MY_BRANCH) of, also, my repo (MY_REPO).
… I know the terminology gets a little bit messed up there. But that’s what you get when you copy-paste someone else’s homework, I guess 🤷
This is a pretty good starting point! But it doesn’t work.
Problem
I set it up with my branches, my repo, my desired nightly schedule and fired it off.
And it didn’t work.
Instead of a green disc, I got a red one. Usually not what you want.
Looking a bit closer, my error messages were somewhat like this:
Run git clone ***github.com/koskila/myrepo.git -b dev tmp
git clone ***github.com/koskila/myrepo.git -b dev tmp
cd tmp
git config user.name "Automerge Bot"
git config user.email "bot@example.com"
git config pull.rebase false
git pull https://github.com/koskila/myrepo.git main
git push
shell: /usr/bin/bash -e {0}
env:
MY_REPO: ***github.com/koskila/myrepo.git
MY_BRANCH: dev
MASTER_REPO: https://github.com/koskila/myrepo.git
MASTER_BRANCH: main
Cloning into 'tmp'...
fatal: could not read Username for 'https://github.com': No such device or address
Error: Process completed with exit code 1.
Wait a minute…
fatal: could not read Username for ‘https://github.com’: No such device or address
That doesn’t sound good.
Reason
Ah well. As much as it pains me to admit it, the reason for this one was actually revealed by a StackOverflow answer, that was (as is typical and always so lovely to see on StackOverflow) downvoted because it was too helpful and friendly (I can only assume motivation, of course).
So the issue is that with the syntax/URI structure in the workflow you can not access a private repository.
Bah.
So instead of:
https://github_username:${{secrets.GITHUB_TOKEN}}@github.com/koskila/myrepo.git
I needed to use:
git@github.com:github_username/myrepo.git
But wait a minute… Where does it get the token, then?
Well. It does not. You can’t use the token to authenticate – instead, you need to set up SSH authentication for your GitHub Actions workflow.
Solution
Setting up an SSH authentication isn’t that complicated. Here are the steps.
1. Generate SSH private and public keys
Run this in terminal/PowerShell/your favorite shell:
ssh-keygen
You’ll get a couple of files in your .ssh directory with this – in my case, in directory C:\Users\<username>\.ssh\id_ed25519 I got the following files:
You might want to open both of them in VS Code (or some other text editor):
- “File” – this is your private key
- “.pub” – “Microsoft Publisher Document” – your public key
You’ll need both in just a sec.
2. Add your public key to your GitHub profile
Navigate to this URL: https://github.com/settings/ssh/new
You should see a field that says something like this: “Begins with ‘ssh-rsa’, ‘ecdsa-sha2-nistp256’, ‘ecdsa-sha2-nistp384’, ‘ecdsa-sha2-nistp521’, ‘ssh-ed25519’, ‘sk-ecdsa-sha2-nistp256@openssh.com’, or ‘sk-ssh-ed25519@openssh.com’“
Copy your public key – from the file that ends with .pub – to this field, and save it.
Hit “Save” and you should now see something like this:
Great! On to the next step.
3. Add the private key to your repository
You’ll want to add it as a repository secret. Navigate to the “Settings” of your repository, and open “Secrets and variables” > “Actions”.
Under “Repository secrets” select “New repository secret”, create a new secret called “SSH_PRIVATE_KEY”, and copy the value from the file without a file extension.
Should look like this when you’re done:
Great. Now we’ll need to set it up in your workflow.
4. Get the SSH details from your repository
Open the “<> Code” -button and select “SSH” tab.
You should see something like below:
Copy the SSH url you can see.
5. Set up your worklow
Alright – finally, we’ll get to updating your workflow.
Add the following step before your git steps:
- name: Setup SSH
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
And change this:
MY_REPO: https://github_username:${{secrets.GITHUB_TOKEN}}@github.com/koskila/myrepo.git
To this:
MY_REPO: git@github.com:koskila/myrepo.git
(and note that you might have 2 different repository URLs – you need to change both!)
6. Run your GitHub Actions workflow again
With a bit of luck, you should have something like this:
Alright then. Did it work for you? Let me know in the comments below!
References
- https://stackoverflow.com/questions/35445186/can-github-automatically-merge-branches
- https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent
- https://nts.strzibny.name/how-to-use-ssh-private-keys-with-password/
- https://docs.github.com/en/authentication/connecting-to-github-with-ssh
- Merging on GitHub Actions fails with “could not read Username for ‘https://github.com’: No such device or address”? - December 24, 2024
- How to close the Sidebar in Microsoft Edge - December 17, 2024
- How to stop Surface Headphones from autoplaying audio when you place them on the desk? - December 10, 2024