Build Typst doc in GitLab CI with Guix

2026-10-08 published | 2026-10-09 edited

In the Git repo with Typst documents, we have this manifest.scm:

(specifications->manifest
  (list "typst"
        "typstyle"
        ; The following we need to build docker image:
        "bash-minimal" ; bash
        "git-minimal" ; git
        "nss-certs" ; git with TLS, I guess
        "coreutils-minimal" ; mkdir
        "make" ; make
        ))

From this file, we can create a Docker image typst-at-guix:

docker load < $(guix pack -m manifest.scm -f docker -S /bin=bin --image-tag=typst-at-guix)

To get Typst packages we use git with --sparse argument so we cannot simply use git-download from Guix (yet). And that is sole reason for using “intermediate” Dockerfile:

FROM typst-at-guix

# Get Typst packages we use -- we need just two, therefore such mummery:

WORKDIR /.local/share/

# Clone limited history only (without blobs, i.e., files):
RUN git clone \
  --sparse --no-checkout --filter=tree:0 \
  --single-branch --branch main \
  https://github.com/typst/packages.git typst

WORKDIR /.local/share/typst/

# Specify only what files to checkout:
RUN git sparse-checkout set \
  packages/preview/diagraph/0.3.7 \
  packages/preview/cheq/0.3.1

# And checkout them:
RUN git checkout

Now build docker image from that:

docker build -t registry.gitlab.com/qeef/foo .

Nope, there is no repo qeef/foo on GitLab, but the idea is clear, isn’t it?

Push the image to GitLab registry when you are ready (authenticated):

docker push registry.gitlab.com/qeef/foo

Now, we can use the image from .gitlab-ci.yaml:

image: registry.gitlab.com/qeef/foo

stages:
- build
- check

typst:
  stage: build
  script:
    - typst compile what.typ what.pdf
  artifacts:
    paths:
      - "*.pdf"

typstyle:
  stage: check
  allow_failure: true
  script:
    - typstyle --check *.typ
go back | CC0 1.0