In this blog post, I’ll show you how to setup your Hugo blog for automatic deployment to Google Firebase Hosting .
I’ll assume that you already have
- a Github account with a repository setup to sync your blog
- setup firebase hosting via
firebase init hosting
to publish the blog via the CLI
We will add a Github Actions workflow for CI/CD, so the blog is automatically built and published whenever we push to it.
If you setup your Hugo blog to host in Render, CloudFlare Pages, or Azure, they should have already setup a Github Action workflow using a framework/build preset. In that case, you do not need to do anything extra. If, like me, you use Firebase which is framework-agnostic, then there is an additional step after you finished setting up hosting with its CLI. There are some hiccups from the Firebase CLI and I think that my bad experience motivates me to write a post to share all my mistakes, so you don’t waste as much time as I did!
What’s the problem?
When some steps during firebase init hosting
asked if you want to
- setup automatic builds and deploys with Github (Q6-9 in official doc)
- authenticate your Firebase account
- setup a Github workflow
I made the assumption that they have setup CI/CD. In fact, firebase init hosting
merely takes care of its own hosting by creating firebase.json
and .firebaserc
files to store configuration and project settings. Nothing about github is done!
Since Firebase is framework-agnostic, we need to perform an additional step after hosting is configured. Here’s how:
The right steps
We need to run firebase init hosting:github
after firebase init hosting
is completed.
note: When I setup a new Hugo blog, I thought I could shoot one bird with 2 stones just by doing
firebase init hosting:github
. This will fail as it needs to look upfirebase.json
and.firebaserc
(created byfirebase init hosting
) for project information to work on.
Specify your Github repository
CLI will automatically creates a Firebase project Service account with deploy permission, and authenticate with GitHub to upload this service account JSON to the repo’s secrets store.
The CLI now detects I’ve added a predeploy script
"predeploy": "hugo",
tofirebase.json
, and prompts me to use it in the new workflow.note: This is the place where we should specify the workflow to do
hugo
to build our files. Don’t believe it! Just press ENTER to accept the default. I notice that it really doesn’t matter what you input, as it will default back to building for node.js. Don’t worry, we will edit this value in step 5.Say yes to the remaining options. It will finally create 2
yaml
files for both merge (firebase-hosting-merge.yml
) and PR (firebase-hosting-pull-request.yml
) workflows in the.github/workflows/
folder. These will automate build and deploy whenever there is a push or pull request in your Github repository. Both use the official FirebaseExtended action to deploy.Let’s look at
firebase-hosting-merge.yml
. What the script does is- checkout the repo files
- build (using npm)
- deploy to Firebase
name: Deploy to Firebase Hosting on merge 'on': push: branches: - main jobs: build_and_deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci && npm run build - uses: FirebaseExtended/action-hosting-deploy@v0 with: repoToken: '${{ secrets.GITHUB_TOKEN }}' firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_YOUR-FIREBASE-PROJECTID }}' channelId: live projectId: YOUR-FIREBASE-PROJECTID
Since it ignores what we enter in step 3, we will edit the workflow file to take care of Hugo builds
We might be tempted to just swap out the
run: npm ci
and replace it withrun: hugo
to build our files and call it a day. I did that and it was not still missing parts!A proper workflow is
- check out repo files
- setup the Hugo environment
- Build Hugo site
- Deploy
Clearly what’s missing from Firebase CLI’s default workflow is 2 and 3. So let’s patch our yml with the following
- name: Setup Hugo uses: peaceiris/actions-hugo@v2.5.0 # Action to set up Hugo environment with: hugo-version: 'latest' # Specifies the Hugo version to use - name: Build Hugo site run: hugo --minify # Runs the Hugo build command with minification
Now recall how you acquired your Hugo theme. You can check its readme or github.
- Is it by
git clone
? Then it’s ok, please jump to the next step. - Is it by using a submodule? (check the existence of
.gitmodules
file in your project root folder) If so, make sure you specify the yml with- uses: actions/checkout@v4 # Updated to v4 with: submodules: true # Added for Hugo themes that are Git submodules
This is another mistake I made. Without this, the checkout process will not fetch layouts and css from the theme’s original repo, and the build will not complete. My old process was building and deploying locally (which contains all the submodule theme files) so this is new to me Worst yet, Github Action status will show everything green and checked, with the errors hidden as mere warnings. For your first few pushes, make sure to go to Github/Actions/click the workflow run, click
build_and_deploy
job and expandBuild Hugo Site
to check if the files are successfully built. You can see that the layouts are missing. If you just glance at the top level Action status, everything looks good.- Is it by
For your theme, does it use SCSS and SASS? Again confirm with its readme. If so, make sure
extended
is added to the Setup Hugo step, like- name: Setup Hugo uses: peaceiris/actions-hugo@v2.5.0 # Action to set up Hugo environment with: hugo-version: 'latest' # Specifies the Hugo version to use extended: true # <--- ADD THIS LINE TO USE THE EXTENDED HUGO VERSION
Commit and push the new files to your repo.
Let’s test editing some .md files in your desktop and push to Github. Verify that the updates are properly deployed to Firebase.
Now we’re all done and we can use both desktop or mobile Github clients to sync our blog to Github, wherever we are.
Comments