Contents

Automate Hugo Deployment with Gitlab CI/CD

Summary:

Having my own gitlab instance I decided to automate the hugo deployment process using gitlabci and each time a new commit is merged to master branch, the site will rebuild using ‘hugo’ command and will be deployed to my server (webhosting provider in my case) using lftp.

In my example ‘gitlab-ci.yaml’ configuration there are 2 stages (test-only & Deploy-Pages)

  • If I’m pushing to a working branch will trigger the pipeline on each commit and will run only the test stage.

  • If I will merge my changes to master or commit to master directly the pipeline will run the Deploy-Pages stage.

Workflow:

Repository structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
├── .git
├── .gitlab-ci.yml
└── MyWebsite
    ├── .hugo_build.lock
    ├── archetypes
    ├── assets
    ├── config.toml
    ├── content
    ├── public
    ├── resources
    ├── static
    └── themes

CI

.gitlab-ci.yml file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#
# Before using this .gitlab-ci.yml:
#
# - This example uses the latest Docker image, but you might want to use the
#   exact version to avoid any broken pipelines.
#   All available Hugo versions are listed under https://gitlab.com/pages/hugo/container_registry.
#
image: registry.gitlab.com/pages/hugo/hugo_extended:latest

# Set this if you intend to use Git submodules
variables:
  HUGO_ENV: production

default:
  before_script:
    - apk add --no-cache lftp
    - cd MyWebsiteFolder


test_only:
  script:
    - hugo
  rules:
    - if: $CI_COMMIT_REF_NAME != $CI_DEFAULT_BRANCH

deploy_Pages:
  script:
    - hugo
    - lftp -e "open $SFTP_SERVER; user $FTP_USER $FTP_PASSWORD; mirror -X .* -X .*/ --reverse --verbose --delete public/ server_public_html/; bye"

#  artifacts:
#    paths:
#      - MyWebsiteFolder/public
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH

SFTP_SERVER, FTP_USER and FTP_PASSWORD are configured as Variables in Settings -> CI/CD -> Variables section.

Tip
I always have my local/repo public folder empty to avoid pollution from old files, public folder contents will be generated during build having always actual/valid content and in sync with the remote server.