simfish:

Blogging

This document provides a development environment and a build script for my personal blog, simfish.dev

cover image
If you build it, they will come

Introduction

This documents describes a development environment and deployment pipeline used by this website, simfish.dev.

The site is built using Emacs/org-mode and Hugo. And, it is deployed as a Gitlab pages. The rest of this document describes the development and build process of this website using litdoc and gitlab.

Getting Started

The following requirements are assumed: git, guix, litdoc

clone the site repo locally,

git clone https://gitlab.com/aarongile/blog

And load the development environment using the following litdoc command:

cd blog
litdoc site load dev.simfish

Once the environment is loaded, the following commands are available.

site_up use this command for starting a local hugo web server. After launching this command, visit http://localhost:1313 and start hacking as usual hugo website.

site_up() {

       plz clean
       pushd ./scripts
       python3 resource-server.py &
       [ $? -eq 0 ] || {
           echo "failed to start asset server"
           exit 1
       }
       popd
       sleep 3
       plz build
       pushd ./site || {
         log_error "failed to enter directory"
         exit 1
       }
       hugo server --config="config.toml" \
                   --environment="staging"\
                   --buildDrafts  \
                   --buildExpired \
                   --buildFuture  \
                   --cleanDestinationDir \
                   --logLevel=debug\
                   --gc \
                   --ignoreCache || {
           log_error "failed to launch hugo server"
           exit $?
       }
       popd
       kill %1 || :
       return 0
  }

site_build: is a command for building this repo without running hugo server. This is used internally when deploying the page to gitlab pages.

site_build() {
    plz clean
    cd ./scripts/
    python3 resource-server.py &
    sleep 3
    cd -
    plz build --config=dbg "//:simfish.dev"
    exit_code=$?
    kill % || :
    return ${exit_code}
}

site_deploy is a utility for deploying this repo as a Gitlab page. It registers a Gitlab runner and optionally triggers a CI/CD pipeline run. To behave as expected the command expects the hosting environment to be configured with the following environmental variables,

GL_TOEKN= ***** # this is a gitlab API token, it is used for rendering project information.
GL_PROJECT_ID= ***** # the gitlab project ID(for this blog)
GL_RUNNER_TRIGGER_TOEKN= ***** # token for manually(API based) triggering of build pipeline(optional)

The command implementation is as follows,

site_deploy() {

    gitlab-runner  register \
                   --non-interactive \
                   --url https://gitlab.com \
                   --token ${GL_RUNNER_TOKEN} \
                   --executor shell
    curl -X POST --fail -F token="${GL_RUNNER_TRIGGER_TOKEN}" -F ref=main \
         https://gitlab.com/api/v4/projects/${GL_PROJECT_ID}/trigger/pipeline

    local build_dir="${HOME}/.cache/litdoc/simfish.dev/builds"
    mkdir -p "${build_dir}"
    gitlab-runner run --working-directory="${build_dir}"
    return 0
}

The entry point for the build script is shown below.

case  "${1}" in
    up)
       site_up
    ;;
    build)
       site_build || {
          echo "failed to build site"
          exit 1
       }
       exit 0
       ;;
    deploy)
       site_deploy || {
         echo "failed to deploy site"
         exit 1
       }
       exit 0
       ;;
    ,*)
        echo   "simfish.dev development environment"
        echo   "available commands:"
        echo   "- site_up: start local hugo site development server"
        echo   "- site_build:  build the site"
        echo   "- site_deploy: deploy website to Gitlab pages"
        exec bash "${@}"
        ;;
esac

echo "ERROR: unexpected error"
exit 1

The important bit is that, loading the development environment and running the build commands can be combined. For example, instead of loading the development environment and executing site_up, run

litdoc site run simfish.dev up

Packages

The development environment is configured with the following Guix package manifest:

(specifications->manifest
 '(
   "curl"
   "openssl"
   "bash"
   "coreutils"
   "guix"
   "git"
   "gitlab-runner"
   "go"
   "hugo"
   "python"
   "python-matplotlib"
   "python-pandas"
   "python-requests"
   "python-twisted"
   "python-bottle"
   "please-build"
   "brotli"
   "gzip"
   "gcc-toolchain"
   "tar"
   "xz"
   "gettext"
   "optipng"
   "jpegoptim"))

Appendix

Hugo

This module provides Hugo binary for 64bit Linux systems running Guix.

(define-module (nongnu packages hugo)
  #:use-module (gnu packages)
  #:use-module (gnu packages gcc)
  #:use-module (guix)
  #:use-module (guix packages)
  #:use-module (guix build-system copy)
  #:use-module (guix download)
  #:use-module (ice-9 format)
  #:use-module ((guix licenses) #:prefix license:))

(define hugo-repo-url-format
  "https://github.com/gohugoio/hugo/releases/download/v~a/hugo_extended_~a_~a.tar.gz")

(define-public hugo
  (package (name "hugo")
           (version "0.128.2")
           (build-system   copy-build-system)
           (source (origin (method url-fetch)
                           (uri (format #f hugo-repo-url-format version version "Linux-64bit"))
                           (sha256 (base32 "1i8jqhw9rra3xjkxzzyj6liqrg52wdi5cdzf3dzijv6pap0m6cm8"))))
           (inputs `(("gcc:lib" ,gcc-5 "lib")))
           (arguments
           (let*  ((src_file    "hugo")
                   (out_file    `(lambda _ (chmod ,src_file #o777))))
          `(#:install-plan  '((,src_file "bin/hugo"))
            #:validate-runpath? #f
            #:phases        (modify-phases %standard-phases (add-after 'unpack 'out_file ,out_file)))))
           (home-page "https://please.build")
           (synopsis "Please is a cross-language build system." )
           (description
            (string-append
             "Please is a cross-language build system with an emphasis on high performance,"
             "extensibility and reproducibility. It supports a number of popular languages "
             "and can automate nearly any aspect of your build process."))
           (license  license:asl2.0)))

Gitlab Runner

Configuration settings

(define-module (nongnu packages gitlab-runner)
  #:use-module (gnu packages)
  #:use-module (gnu packages gcc)
  #:use-module (guix)
  #:use-module (guix packages)
  #:use-module (guix build-system copy)
  #:use-module (guix download)
  #:use-module (ice-9 format)
  #:use-module ((guix licenses) #:prefix license:))

(define url-for-x86-64
  "https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/latest/binaries/gitlab-runner-linux-amd64")

(define-public gitlab-runner
  (package (name "gitlab-runner")
           (version "0.1")
           (build-system   copy-build-system)
           (source (origin (method url-fetch)
                           (uri url-for-x86-64)
                           (sha256 (base32 "0y1yncsd4y3vjdbfd3ps8qjg7aaf9kraalngy5ciqalfala4nlv7"))))
           (inputs `(("gcc:lib" ,gcc-5 "lib")))
           (arguments
            (let*  ((src_file    "gitlab-runner-linux-amd64")
                    (out_file    `(lambda _ (chmod ,src_file #o777))))
              `(#:install-plan  '((,src_file "bin/gitlab-runner"))
                #:validate-runpath? #f
                #:phases        (modify-phases %standard-phases (add-after 'unpack 'out_file ,out_file)))))
           (home-page "https://please.build")
           (synopsis "GitLab Runner runs the CI/CD jobs that are defined in GitLab." )
           (description
            "GitLab Runner is the open source project that is used to run your CI/CD jobs and send the results back to GitLab")
           (license  license:expat)))