Mid 2018 I switched my blog from Wordpress to Hugo. Main reason was performance and that I can use Asciidoctor to write the posts.
What happened the last 18 months? I stayed with the theme I selected 2018, but I tweaked it a little bit. So I added lunr to implement searching, changed all scripts and fonts from CDN to local (privacy and tracking), updated Bootstrap 3 to 4.
Working with Bootstrap was quite fun, I haven’t done a lot of HTML or CSS the last years, but the grid and css classes from Bootstrap are working without checking each change on all browsers and are responsive.
Daily journal #
After reading The Unicorn Project I started writing a daily journal with things I learned or figured out during the day. I tried this several times the last years, but never was happy with the result. This time I just use the same setup as my blog (Hugo, Theme and Asciidoctor), but deploy it to a local Docker container, which is started with podman.
Gitlab CI/CD #
Hugo generates static html pages from Asciidoctor or Markdown sources. The first months I just ran the hugo binary on my local machine and did a rsync of the generated html to my blog and the container.
Updating Hugo, or reinstall my Notebook sometimes delayed a blog post. So I decided to automated the process through Gitlab CI/CD.
.gitmodules
#
I added the theme (which is stored as a seperate git repository) as a submodule (git add submodule …) to the blog content. .gitmodules can handle complete repository URL, or relative ones. The relative URL are easier to checkout in the pipeline, so I changed the file to
.gitmodules
[submodule "themes/stoeps-theme"]
path: themes/stoeps-theme
url: ../stoeps-theme.git - Edit Url and replace with the relative path (I have the theme in the same git group)
Creating .gitlab-ci.yml
#
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- build
- deploy
build:
stage: build
image: "node:alpine"
before_script:
- 'which curl || ( apk update && apk add curl)'
- 'which gem || (apk add ruby)'
- curl -L https://github.com/gohugoio/hugo/releases/download/v0.61.0/hugo_0.61.0_Linux-64bit.tar.gz | tar -xz && mv hugo /usr/local/bin/hugo
- npm install
- gem install asciidoctor
script:
- npx gulp build
only:
refs:
- master
variables:
- $BUILDHTML
changes:
- content/**/*
artifacts:
paths:
- docs
expire_in: 2 hours
deploy:
image: "debian:buster"
stage: deploy
before_script:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- 'which rsync || ( apt-get update -y && apt-get install rsync -y )'
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | base64 --decode | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -t rsa home26617100.1and1-data.host >> ~/.ssh/known_hosts
script:
- rsync -az docs/ p7594620@home26617100.1and1-data.host:/kunden/homepages/13/d26617100/htdocs/stoeps.de --delete
only:
refs:
- master
variables:
- $DEPLOYBLOG
changes:
- content/**/*-
Clone submodules with the main repository
-
Two stages, one builds html, one deploys the code
-
Check if curl is included in the container, if not install it
-
Run build with Gulp (see below)
-
Stage runs only for master-Branch, if variable
BUILDHTMLis set and changed files are in thecontent-tree -
Keep directory
docsas artifacts for the next stage -
I created a seperate SSH key just for the synchronisation, it is stored as a variable in the Gitlab project
Store SSH-Key as variable #
Create Key
ssh-keygenbase64 encode the key and copy to clipboard
base64 -i ~/.ssh/id_gitlab |tr -d '\n' | xclip

Syntax is equal to Linux cron, so the setting of this image will run the pipeline at 23:55 UTC every day. Other option could be hourly at 5 minutes past the full hour: 5 * * * *
I added a scheduler which runs hourly and sets the variables BUILDHTML and DEPLYBLOG, so I can check-in code to gitlab multiple times and the posts will only be build on a scheduled basis.
Just set the variables to true.

Gulp #
The article Continuously Deploy a Hugo Site with GitLab CI added Gulp to minify the built HTML. Cool idea and saves me some megabytes. I added css-minify and build the hugo page with:
npx gulp buildgulpfile.js
var gulp: require("gulp");
var htmlmin: require("gulp-htmlmin");
var cssmin: require("gulp-cssmin");
var shell: require("gulp-shell");
gulp.task("hugo-build", shell.task(["hugo"]));
gulp.task("minify-html", () => {
return gulp.src(["docs/**/*.html"])
.pipe(htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
removeComments: true,
useShortDoctype: true,
}))
.pipe(gulp.dest("./docs"));
});
gulp.task('minify-css', () => {
return gulp.src(["docs/**/*.css"])
.pipe(cssmin())
.pipe(gulp.dest("./docs"));
});
gulp.task("build", gulp.series("hugo-build", "minify-html", "minify-css"));