I finally got around to publishing my new website design this week. It is not 100% done, but it is a good basis that I can build from.
My previous site was built on Gatsby with all my posts stored in Strapi. This made scheduling posts relatively simple with a script that published the post on Strapi and then call to GitHub trigger my website build.
I am now using eleventy (11ty) for my new website, so I needed a new way of scheduling my posts.
If you Google how to do this, you will get a lot of people mention the GitHub Action gr2m/merge-schedule-action
which allows you to merge a PR automatically if it has /schedule 2024-05-12T12:00:00Z
in the comment.
This sounded like a great solution, unfortunately the GitHub Action no longer seems to work. I am guessing GitHub changed something with their permissions and I ended up with the same error shown in one of the open issues.
Luckily GitHub has a pretty extensive API so writing a quick script to do this was the easiest option.
This script needed to do the following:
- Get a list of open pull requests for my blog repo.
- Loop through each PR looking for a string that matches
/schedule <date_string>
of the form/schedule 2024-05-12T12:00:00Z
somewhere in the comment. - Check to see if the date is either now or in the past.
- If it is, then comment on the PR and merge it into
main
.
I then a have a GitHub Action when something is merged into main that builds and deploys my website.
This is the script that I came up with:
#!/bin/bash
# This script checks for open pull requests and merges them based on
# a "/schedule 2024-05-02T08:00:00Z" comment in your PR.
#
# Script requires the package jq
# GITHUB_TOKEN can be supplied using .env file
#
# Token should be a fine grained token with Read and write access to
# Contents - needed to merge
# Pull Requests - needed to post a comment
#
# Read access is also required to Metadata which is given by default.
# Runs script in local directory to pick up .env file
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
cd "$parent_path"
# Import variables
set -a
source .env
set +a
OWNER=alexhyett # Your GitHub Username
REPO=alexhyett-website # The repo for your website.
# Get list of open PRs for repo
response=$(curl -L -s -w "\n%{http_code}" \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$OWNER/$REPO/pulls)
response=(${response[@]})
status_code=${response[*]: -1}
pull_requests=${response[@]::${#response[@]}-1}
if [ $status_code -ne 200 ];
then
echo "Unable to get pull requests. Status Code: $status_code"
exit 1
fi
# Should match /schedule 2024-05-02T08:00:00Z or /schedule 2024-05-02T08:00:00
regex='\/schedule ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z?)'
echo $pull_requests | jq -c '.[]' | while read pr; do
body=$(echo $pr | jq -c '.body')
pull_number=$(echo $pr | jq -c '.number')
title=$(echo $pr | jq -c '.title')
if [[ $body =~ $regex ]]
then
date="${BASH_REMATCH[1]}"
now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Alphabetical string match
if [[ $date < $now || $date = $now ]];
then
# Add a merge comment
status_code=$(curl -L -w '%{http_code}' -s -o /dev/null \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$OWNER/$REPO/issues/$pull_number/comments \
-d '{"body":"Automatically merging PR on schedule"}')
if [ $status_code -eq 201 ];
then
# Merge Pull Request
status_code=$(curl -L -w '%{http_code}' -s -o /dev/null \
-X PUT \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/$OWNER/$REPO/pulls/$pull_number/merge \
-d '{"commit_title":'"$title"',"commit_message":"Automatically merged"}')
if [ $status_code -ne 200 ];
then
echo "Failed to merge pull request. Status code: $status_code"
fi
else
echo "Failed to post comment. Status code: $status_code"
fi
fi
fi
done
To use this script you will need to create a fine-grained GitHub personal access token with the following read & write permissions to your repository:
- Contents - needed to merge the pull request.
- Pull Requests - needed to add a comment to your pull request.
This token should be saved to a .env
file in the same directory using the variable GITHUB_TOKEN
e.g.
GITHUB_TOKEN=github_pat_11Ajdi9s9383h7sdsFGGDs839290jds_s73w9s9w9dshSSDDg
I then run this script on my home server every 15 minutes using cron. If you don't have a home server you could run this on a free Oracle VM instead.
The hardest part of this script was just working out how to get curl to output the response as well as the status code, which you can see in the first curl
command.
I wrote this script using bash, so it could mostly run anywhere, but it does have a few dependencies. In addition to curl
which you mostly likely already have installed you will also need jq
installed for parsing the json
response from the APIs.
❤️ Picks of the Week #
📝 Article - Should you self-host Google Fonts? - I am using the Atkinson Hyperlegible font on my new site. I did wonder whether it is worth self-hosting but after reading this it turns out Google are doing a lot of optimisations that it is just not worth the effort.
📝 Article - Programming mantras are proverbs - It is easy to take things like SOLID and YAGNI as rules that need to be obeyed. Really they are more like intelligent suggestions and they aren't always the right choice.
📝 Article - Wait the Piña Colada song is about what?! - This made me laugh. I think the last time I heard this song is in the film "Guardians of the Galaxy" and it was likely only the chorus. I never realised what the song was actually about.
📝 Article - Why you need TDD - I always use TDD when I am fixing a bug, but I have never got into it for normal coding. I probably should and this post gives quite a compelling argument too.
📝 Article - Rebuilding my website with Eleventy - It looks like I am not the only one who has been rebuilding my website with Eleventy. I might introduce a like button and a link to Mastodon in future as well. Search is another topic I need to tackle as well.
🎬 Video - Apple's message falls flat - I am not sure what Apple were thinking when they made the new iPad advert. They are usually very good with their adverts but destroying all the things that creatives love in order to promote the iPad is not a great way to go.
📝 Article - Stack Overflow Upset Over Users Deleting Answers After OpenAI Partnership - Stack Overflow is going to get a lot less useful if people start deleting content. I can see why though, the same happened with Reddit.
👨💻 Latest from me #
As I mentioned in this week's post, my new website is live. I still have a few optimizations to do, but most pages are already under my 100 Kb target. I will probably discuss some of the design decisions and tweaks in one of my later posts.
If you didn't know you can also subscribe to my website (and this newsletter) using RSS as well. I know we all get a lot of emails already so if you use RSS check out my RSS Feed.
I also wrote a blog post this week on setting up my Windows gaming VM on my Unraid server, if that sort of thing interests you.
💬 Quote of the Week #
Don’t let comparison be the thief of your joy. Live your life the way you want to and spend time on things and activities you enjoy. That will lead you to a long-term state of happiness.
From the article Material Things Will Never Make You Happy – Here’s Why