Introduction
The way I produce content tends to be rather fractured. I’m often working on 4 or 5 articles at a time, content may need further research or contain images, code, links that require multiple revisions before I consider them fit for public consumption. Not to mention numerous proofreads for the inevitable grammar, spelling mistakes and typos.
For these reasons (and more) I prefer to maintain my content
directory as a separate private submodule. Tania Rascia wrote an excellent tutorial on how to implement this.
Recently I found time to try out Vercel. Vercel’s slogan ‘Develop. Preview. Ship.’ is a succinct summary of what the platform enables developers to achieve. Tight integration with GitHub, GitLab or Bitbucket plus a plethora of features help streamline your development process.
However, while experimenting with the platform I discovered that private submodules are currently unsupported. See below from their site:
Deploying Git submodules with a Git provider is supported as long as the submodule is publicly accessible via the HTTP protocol. Git submodules that are private or requested over SSH will fail during the Build step.
Source: Vercel - Git Submodules
Support for private submodules is forthcoming. In the mean time however I needed a way to deploy my (or any Hugo) site to Vercel while maintaining a private submodule for the content
.
This is where GitHub Actions comes in. GitHub Actions automates your development workflow. Simply put GitHub Actions combines all the manual steps you would take to achieve your goal and automates them. In this case, the deployment of a Hugo site on Vercel’s platform.
This tutorial is a step-by-step guide on how to setup a simple GitHub Actions workflow that accommodates private submodules:
- Develop your Hugo site locally
- Push commits to a
develop
branch on GitHub - GitHub Actions builds your site (with private submodule) and deploys it to Vercel
- Vercel returns a preview URL where you (or your team) can review your site
- If satisfied, you can create a pull request to merge the
develop
branch into amain
branch - Upon merge confirmation GitHub Actions builds your site again and deploys it to Vercel for production
- Vercel returns a production URL where you can view your live site
An additional benefit of using GitHub Actions is that your workflow is no longer restricted to features available only on Vercel’s platform. The GitHub Actions community is extensive, granting you the flexibility to adapt any workflow to your specific needs far beyond the scope of simple access to private submodules.
Prerequisites
- Vercel Account (sign up)
- Hugo & Vercel CLI installed locally
- Basic knowledge of Git & GitHub
Step 1 - Grant GitHub Actions Access to your Private Submodule
In order for GitHub Actions to successfully fetch your private submodule it needs to be granted access. This can be accomplished by configuring a Deploy key in the GitHub repository of the private submodule.
First, generate a new key locally using the ssh-keygen
command:
ssh-keygen -o -a 100 -t ed25519 -f ~/.ssh/submodule_access_deploy_key_ed25519
DO NOT add a passphrase. Leaving the passphrase empty, press return twice.
COMMAND OUTPUT - (click to expand)
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ~/.ssh/submodule_access_deploy_key_ed25519
Your public key has been saved in ~/.ssh/submodule_access_deploy_key_ed25519.pub
The key fingerprint is:
SHA256:rWi6yKn0dyB5kZZWnTyye1kVvtcAP/ZZPyEfI0p8DYg my@DESKTOP-1FTAJ7O
The key's randomart image is:
+--[ED25519 256]--+
| o o oo. |
| o E...+o |
| + o .o.===.|
| * . ...o.=+O|
| + . S +. . =+|
| o o o + . .|
| . o + o |
|...o + . |
|..+.+.. |
+----[SHA256]-----+
The public part of the key pair (submodule_access_deploy_key_ed25519.pub
) can now be uploaded to the submodule repo.
Navigate to your submodule repo on GitHub, Settings > Deploy Keys
and click on Add deploy key
. Choose a title for your new key and enter the public key value:
Leave the
Allow write access
checkbox UNCHECKED!
Click on Add key
to complete the process.
Now navigate to your main/parent repo. Click Settings > Secrets > New repository secret
. Choose a name for your secret/private key and enter the private key value:
Click on Add secret
to finish.
Step 2 - Install Vercel CLI & Create a new Project
GitHub Actions also needs access to your Vercel account in order to push your Hugo site from GitHub to their platform. Three values are required for this.
- Vercel Account Token
- Organisation ID
- Project ID
Generate a Vercel Account Token
Visit https://vercel.com/account/tokens and click on create
to generate a new token (save this token for later):
Obtain your Vercel Organisation & Project ID
To obtain a Vercel Organisation & Project ID a new project needs to be created. For this we’ll use the Vercel CLI. Use either the npm
or yarn
package manager to install the Vercel CLI in your local development environment:
npm
npm i -g vercel
yarn
yarn global add vercel
Now switch to the root of your local Hugo project before using the vercel
command.
Your local file structure should look similar to this
my_hugo_site/
|-- .gitignore
|-- .gitmodules
|-- archetypes/
|-- config.toml
|-- content/
| |-- .git
| `-- posts/
|-- data/
|-- layouts/
|-- public/
|-- resources/
|-- static/
`-- themes/
The
my_hugo_site
directory corresponds to your public parent repo on GitHub while thecontent
directory to your private submodule repo.
Login to Vercel
Login to Vercel by running vercel
or vercel login
at the root of your project. The CLI will send and email to the address registered with your Vercel account. Click on the link in the email to complete login process:
/my_hugo_site$ vercel
Vercel CLI 21.0.1
> No existing credentials found. Please log in:
We sent an email to myemail@example.com. Please follow the steps provided inside it and make sure the security code matches Sunny Moth.
โ Email confirmed
Congratulations! You are now logged in. In order to deploy something, run `vercel`.
๐ก Connect your Git Repositories to deploy every branch push automatically (https://vercel.link/git).
Deploy your site to create a new project on Vercel
Now that you’re logged in run the vercel
command again to configure and deploy your site to Vercel as a new project:
/my_hugo_site$ vercel
Vercel CLI 21.0.1
? Set up and deploy โ~/my-hugo-siteโ? [Y/n] y
? Which scope do you want to deploy to? vercelusername
? Link to existing project? [y/N] n
? Whatโs your projectโs name? my-hugo-site
? In which directory is your code located? ./
Auto-detected Project Settings (Hugo):
- Build Command: `npm run build` or `hugo -D --gc`
- Output Directory: `public` or `publishDir` from the `config` file
- Development Command: hugo server -D -w -p $PORT
? Want to override the settings? [y/N] n
๐ Linked to vercelusername/my-hugo-site (created .vercel and added it to .gitignore)
๐ Inspect: https://vercel.com/vercelusername/my-hugo-site/1rx3k75a7 [2s]
โ
Production: https://my-hugo-site.vercel.app [copied to clipboard] [11s]
๐ Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
๐ก To change the domain or build command, go to https://vercel.com/vercelusername//my-hugo-site/settings
You can accept all the default options presented since the main purpose of running the
vercel
command is to obtain your organisation and project IDs.
Once deployed search the newly generated local .vercel
directory for the project.json
file, it’ll contain your new organisation and project IDs:
{"orgId":"obn4rXWTQ7oc9FjAG9g5klo5","projectId":"prj_3vDZFk6xG1E5ACWMd0nxA264OQVR"}
Return to your main (Hugo) site repository on GitHub and add these three values (Vercel Token, Organisation ID and Project ID) as appropriately named secrets alongside your existing SUBMODULE_CONTENT_DEPLY_KEY
secret.
Step 3 - Update Vercel Project Settings
IMPORTANT: Since GitHub Actions will be responsible for building your Hugo site your new project settings need be updated so that Vercel doesn’t attempt to build your site again once GitHub Actions has pushed your content to Vercel.
In the Vercel dashboard navigate to the Settings
of your new project. Click the switch to override the BUILD COMMAND
. Leave the input field empty. And save your settings:
Step 4 - Create the GitHub Actions Workflow Files
Now that your submodule and parent repositories both have the necessary secrets configured we can proceed to creating the GitHub Action workflow(s) that will deploy your site on Vercel.
If you haven’t already, Create a new (develop
) branch from your main
/master
branch and add the following workflow file(s):
deploy-preview.yaml (click-to-expand)
# deploy-preview.yaml
# Workflow to build and deploy site to Vercel using Hugo
# Name of Workflow
name: deploy-preview
# Controls when the action will run. Triggers the workflow on push
# events but only for the develop branch
on:
push:
branches: [ develop ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "deploy-preview"
deploy-preview:
# The type of runner that the job will run on
runs-on: ubuntu-20.04
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Step 1 - Checks-out your repository under $GITHUB_WORKSPACE
- name: Checkout
uses: actions/checkout@v2
with:
ssh-key: ${{ secrets.SUBMODULE_CONTENT_DEPLOY_KEY }}
submodules: recursive # Fetch private content
# Initiate deployment status
- name: Start Deployment
uses: bobheadxi/deployments@v0.4.3
id: deployment
with:
step: start
token: ${{ secrets.GITHUB_TOKEN }}
env: Preview
# Step 2 - Install Hugo (specific version)
- name: Install Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.79.1'
# Step 3 - Builds the site using Hugo
- name: Build
run: hugo -v
# Step 4 - Push our generated site to Vercel
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
id: vercel-action
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required
#github-token: ${{ secrets.GITHUB_TOKEN }} #Optional
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} #Required
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} #Required
github-comment: false
#vercel-args: '--prod' #Optional
working-directory: public
# Update deployment status
- name: Update Deployment Status
uses: bobheadxi/deployments@v0.4.3
if: always()
with:
step: finish
token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
env_url: ${{ steps.vercel-action.outputs.preview-url }}
deploy-production.yaml (click-to-expand)
# deploy-production.yaml
# Workflow to build and deploy site to Vercel using Hugo
# Name of Workflow
name: deploy-production
# Controls when the action will run. Triggers the workflow on push
# events but only for the main/master branch
on:
push:
branches: [ main ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "deploy-production"
deploy-production:
# The type of runner that the job will run on
runs-on: ubuntu-20.04
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Step 1 - Checks-out your repository under $GITHUB_WORKSPACE
- name: Checkout
uses: actions/checkout@v2
with:
ssh-key: ${{ secrets.SUBMODULE_CONTENT_DEPLOY_KEY }}
submodules: recursive # Fetch private content
# Initiate deployment status
- name: Start Deployment
uses: bobheadxi/deployments@v0.4.3
id: deployment
with:
step: start
token: ${{ secrets.GITHUB_TOKEN }}
env: Production
# Step 2 - Install Hugo (specific version)
- name: Install Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.79.1'
# Step 3 - Builds the site using Hugo
- name: Build
run: hugo -v --minify
# Step 4 - Push our generated Hugo site to Vercel
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
id: vercel-action
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required
#github-token: ${{ secrets.GITHUB_TOKEN }} #Optional
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} #Required
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} #Required
github-comment: false
vercel-args: '--prod'
working-directory: public
# Update deployment status
- name: Update Deployment Status
uses: bobheadxi/deployments@v0.4.3
if: always()
with:
step: finish
token: ${{ secrets.GITHUB_TOKEN }}
status: ${{ job.status }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
env_url: ${{ steps.vercel-action.outputs.preview-url }}
in a .github/workflows
directory at the root of your project:
my_hugo_site/
|-- .github/
| `-- workflows/
| |-- deploy-preview.yaml
| `-- deploy-production.yaml
|-- |
The above workflows are well commented but here are a few additional details on some of the actions used:
-
Line 11: The workflow is triggered when code is pushed to the defined branch. This includes when a pull request is merged into the branch. e.g.
main
<–develop
triggers the push event on themain
branch. -
Line 25, 27: Using your
SUBMODULE_CONTENT_DEPLOY_KEY
secret the actions/checkout action checks out your Hugo and private submodule repository. -
Line 41: The peaceiris/actions-hugo installs Hugo on the virtual machine.
-
Line 51, 54-57: The amondnet/vercel-action action uses your
VERCEL_TOKEN
,VERCEL_ORG_ID
andVERCEL_PROJECT_ID
secrets to authenticate with and push your Hugo site to the Vercel platform. It returns a preview URL generated by Vercel where you can view your site live. -
Line 32, 70, 71: The bobheadxi/deployments action uses the URL returned by the amondnet/vercel-action to create and update a Deployment and Deployment status before, during and after your workflows’ build and push tasks. You can view the status for each deployment by visiting
https://github.com/<your_github_username>/<your_hugo_site_repo>/deployments
:
Clicking View deployment
for either environment will take you to the Preview or Production deployment on Vercel
Step 5 - Publish your ‘develop’ Branch to GitHub
You’ve created a new project on Vercel and your GitHub actions workflow files are done so it’s time to push/publish your develop
branch to GitHub. Once you do, GitHub actions will queue your deploy-preview.yaml
workflow for execution. Go to your site repo on GitHub and click on Actions
. Click the listed workflow to view the results. Below is an example summary of a successfully executed workflow:
vercel-dev
is the name of my ‘develop
’ branch. Also shown are the Status (success
) and the duration the action took to run.
Clicking on deploy-preview
under Jobs will show a summary of the steps in the workflow. Click on a step to view it in more detail:
As mentioned in the previous step, navigate to https://github.com/<your_github_username>/<your_hugo_site_repo>/deployments
and click on View deployment
to see a live preview of your site hosted on Vercel.
Step 6 - Deploy your Hugo Website
If after reviewing the Vercel preview of your develop
branch you wish to go ahead and deploy to production, simply merge your develop
branch into your main
branch via a pull request:
- Merge
vercel-dev
intovercel
(the respective names of my ‘develop
’ and ‘main
’ branches) - The commits that will be merged
- Link to the live Vercel preview deployment of the changes that are to be merged
- Click for details of the workflow
Once the pull request is merged the deploy-production.yaml
workflow will trigger building and deploying your live production site in the same way your preview deployment was ๐.
By default, all deployments on the Vercel platform are assigned a .vercel.app
suffixed domain. If you haven’t already you can add a custom domain to your production deployment.
Summary
You’ve now setup a simple workflow that will accommodate private submodules:
- Make local changes to your Hugo site
- Commit & Push those changes to a remote ‘
develop
’ branch - GitHub Actions builds and deploys your site to Vercel
- Review the Preview of your site on Vercel
- Create a Pull Request to merge your changes from your
develop
tomain
branch - GitHub Actions again builds and deploys your site to Vercel
- View your site in production on Vercel
Keep in mind that this tutorial covers only the basics of what can be achieved through GitHub Actions. All sorts of additional tests can be integrated with your workflows such as LightHouse audits of your Hugo URLs and Visual Testing via Percy. The possibilities are almost limitless.