How to automate previews for Github Pages
I host my website on Github Pages because it’s simple, I don’t need serverside stuff for a humble static website, I’m already in Github all day errday, and it was a top quality option when I set it up a billion technological years ago.
A feature of modern hosting platforms (e.g. Vercel) that I miss with GH Pages is getting automatic site previews on each PR, which is nice for showing other people your WIPs, or (if you’re lone-wolfing it) quickly checking if things are broken without bothering with your local dev server.
So I thought I’d clobber something together using Github Actions and taking advantage of the directory structure of static sites :D
>How it works
To publish my website, I use a github action to compile each commit to the main
branch, then push that output to the gh-pages
branch.
Adding a PR preview is similar: build the site on each commit to a pull request, and push the result to the /pull/{pr-number}
folder on the gh-pages
branch. This means the preview can be accessed at https://github.io/username/project/pull/{pr-number}
. Seems simple enough, right?
>Walkthrough
The end result is found here (spoiler alert): https://github.com/daiyi/gh-pages-pr-previews.
>Create a new static site
For this tutorial I’m starting with a fresh Hugo site, but you can use whatever static site generator you fancy.
1 | # create new site |
>Host your site on github pages and automate deploy with github actions
Now it’s time to tell Github about it. Create a repo at https://github.com/new (I initialised it as blank). Then,
1 | # create first commit |
To automate publishing your site to gh pages on every commit to main
, add the following to the .github/workflows/gh-pages.yml
file then push the change to github (source here):
1 | # .github/workflows/gh-pages.yml |
Once the file is in main
, you should see the workflow running in the Actions tab: https://github.com/daiyi/gh-pages-pr-previews/actions.
When that’s done, activate github pages by going to Settings -> Pages
and picking the gh-pages
branch under “Source”. Click “Save”. Checking “Enforce HTTPS” is recommended.
The github pages site should be live! I am using a custom domain so mine is at https://daiyi.co/gh-pages-pr-previews/. The default should look like: https://daiyi.github.io/gh-pages-pr-previews/.
If you look at your new site, you’ll see that there’s no posts, because your post was a draft :'D You can make it live by removing draft: true
in /content/posts/pr-previews-for-gh-pages.md
:
1 | --- |
If you commit and push this change, you’ll see another github action kick off. It will take a minute for your site to reflect the new content, but if you keep refreshing the post will appear :D
>Automate static site previews on pull requests
Now we get to the finale. Modify the gh-pages.yml
workflow to also compile the site on every commit to a pull request (file source here):
1 | diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml |
It’s nice to clean up after ourselves, so create a new github action file .github/workflows/pr-close.yml
that deletes previews when PRs are closed (source here):
1 | # .github/workflows/pr-close.yml |
Let’s test this out on a PR :D
1 | git checkout -b pr-previews |
Go to github and open a pull request for that branch. A friendly robot will let you know they’re working on your request:
The comment will update with preview urls once the preview is ready:
Check out the link in the preview. It should contain a site that is exactly like the site at main
, since we haven’t made changes to it. If everything looks good, merge that PR, upon which the robots will come in and clean up:
Here’s a demo of an open pull request where I add a new blog post:
The preview for that PR: https://daiyi.github.io/gh-pages-pr-previews/pull/2/.
And the source: https://github.com/daiyi/gh-pages-pr-previews/tree/gh-pages/pull/2/.
Nice! It works!
>Considerations
I haven’t thought too hard about if this is too jank for a Serious Website™, but it should be fine for low-key stuff like blogs, portfolios, or documentation.
The preview urls shouldn’t interfere with your site unless the /pull
subdirectory is already occupied with a web page. And the preview pages also won’t appear on your production sitemap/rss feeds/other generated indeces since the static site generator doesn’t know about it while compiling the production version of the site. If you’re worried about that, it may be prudent to use ENV flags to conditionally toggle off production stuff in the PR preview sites, like web crawler indexing (noindex,nofollow
, robots.txt
, etc). In my example, I set HUGO_ENV: production
for main
and HUGO_ENV: staging
for PRs. You can look into if your static site generator/theme supports that.
Also I am not compelled to spend the energy to become a workflow configuration language expert and I’m sure it could be written with more elegance, if that is a concept that can be applied to yaml files. Feel free to make a PR and show me how it should be done :D
Let me know if you use this strategy! I found someone else’s attempt at implementing this idea but thought I’d try my own hand at it (and also completing the “delete preview on PR close” feature). I’m curious if someone else out there wants to make PR previews for gh pages for some weird reason \o/
Comments
No comments at the moment. Hey, you could write one \o/