Proof is in the pudding, Hugo is working since it published this blog post. I’m going to detail here what was required to get it all working. I blame Ivan Pepelnjak for this.
GitHub
I have a github account here. You can see that it has a pretty interesting mix of content, but Hugo integrates with github so I figured I’d use it. My first attempt was just creating a blog repo, and using the Hugo setup documents try to get it working. It did work, but my understanding of github pages was incorrect and everything was a subdirectory of my repo. I wanted a pretty domain, so I started over.
First step, create a new repo to hold the blog code and back-end. This is a private repo called blog. I use a mac and I use vscode on that mac. Using Ports I installed hugo. I created a local folder on my mac and initialized hugo on that folder.
I won’t go into the github specifics of creating a repo, but here’s what I did locally to link my folder to github. All of this was run in terminal, inside the folder that Hugo was initialized on.
git init
git add .
git commit -m "Initial Commit"
git remote add origin https://github.com/<USERNAME>/<REPO>.git
git push --set-upstream origin master
This works and everything is pushed to the blog repo I created. If you’ve never setup git on the workstation you’re using, you likely need to add other options like your username and email. Also vscode has github integration which is really nice.
The repo is private however, which means github pages can’t work on it. This is by design, as I want the blog back-end itself private in case I want to tinker without affecting the public content. I’m going to use hugo’s static site content so when I create those pages, I want that content pushed to a public site.
Hugo can generate static pages that publish in the ./public folder. With that in mind, I create another repo in my github account called jrmann1999.github.io.
When you create a github repo in this format, USERNAME.github.io, github automatically assumes that’s going to be a pages site, and enables it for public website hosting. Perfect for my use-case here. Now the question is how do you get the content from the private repo, to sync to the public repo.
Hugo has the ability to link to a github action, and publish content. I wasn’t ready to tackle that at this point so with some googling I came up with git submodules. The public folder can be a submodule of a different repo, in this case my public jrmann1999.github.io repo. Credit to this site for the idea. Look at the Hosting on GitHub section.
This worked, however it did rely on my running a couple of actions on my mac everytime I generated the public site. The process boiled down to this.
hugo
cd public
git add .
git commit -m "Post ###"
git push
The blog I referenced mentions doing this with a shell script, but since earlier I mentioned hugo supports github actions natively, I’d rather just create a post, push it to github, and let that system do all the work.
Github workflows are the actions component of this whole shebang. First I started by creating a .github/workflows folder in my blog repo. Within that I created a gh-pages.yml. This is mostly detailed in the setup article for Hugo I referenced earlier. Copying that code and committing it to the blog folder I synced up to github. Github found the workflow and executed it, and promptly failed.
The failure was due to git submodules, both the public submodule I had created, but also the theme module that hugo suggests you install. After some googling I came up with the needed fixes. Enter .gitmodules, a file you create (or can be created for you with git submodule command, mine did not). This gives git the necessary information to link the remote repos to your submodules. Here is my .gitmodule contents
[submodule "public"]
path = public
url = https://github.com/jrmann1999/jrmann1999.github.io.git
[submodule "PaperMod"]
path = themes/PaperMod
url = https://github.com/adityatelange/hugo-PaperMod.git
I use papermod as my theme, so that’s why the link to that module. After adding committing and pushing this to git, the runner succeeded! However the default configuration for that runner is to push the static content to a new branch in the current repo. Remember, my blog repo is private, so github pages can’t run on it. The runner doesn’t do the work listed above of cd’ing into the public folder and committing that, so the public repo wasn’t updating either.
Going to documentation I found what I needed. The provided module supports publishing to a remote repo as part of the Deployment stage. Here are the rough steps to set that up.
- Create a new SSH key, this is specific to the Runner that Github uses.
- Add that public key to the Public Repo (jrmann1999.github.io)
- Add the private key to the Private repo (my blog repo). You add this under the Secrets, and name it ACTIONS_DEPLOY_KEY if you’re following the official documentation
- Update the gh-pages.yml to reference this key, and to tell it to push changes when deploying to the public repo
Here is the section of gh-pages.yml that i used for my deployment
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.ref == 'refs/heads/master'
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
publish_dir: ./public
external_repository: jrmann1999/jrmann1999.github.io
Once I did this add, commit, push to the private repo. The runner succeeded! It successfully updated the public repo too.
I reloaded my site, and saw no changes. Why? By default the runner script publishes to a branch named gh-pages. However the default github pages repo is main or master. The simple fix for me was to change pages to reference the gh-pages branch. This would allow me to create other branches if I want to for other things in the future.
Once all of this was setup I published a test blog post Submodule and commited/pushed to my repo. The public repo was updated and the post was published a few minutes later (github pages takes a few minutes to update changes).
Hopefully some of this helps, as I had to do quite a bit of googling to piece this together.
What I need to do at this point is likely remove the submodule for my public folder since my runner is doing the work, however keeping it seems like a decent idea. If I ever want to just push the content directly from my mac, I can without involving github’s runner.