Deploying versioned documentation on GitLab with Documenter.jl

One of the things I start to use more and more are private Julia registries, which are really easy to set up and make it much easier to deploy packages which are very experiment specific and not worth to pollute the general registry.

We use our own self-hosted GitLab instance with a heavy multi-rack CI infrastructure with our own GitLab runners and we are very happy with that solution, but…

There is currently no way to host or store version specific documentation generated by e.g. Documenter.jl via the GitLab CI, which means that we can only deploy a single version of the documentation, being it the latest tag or generated from the latest commit. For early prototypes we usually go with the latest commit on the main branch and for more mature Julia packages we restrict it to tags.

The main problem for that is the way the GitLab CI pages deployment works. It simply uploads (and replaces) the folder called public/ in a job which needs to be called pages. That’s it:

pages:
  stage: deploy
  script:
    - mkdir public
    - echo hello world > public/index.html
  artifacts:
    paths:
      - public/

GitLab offers a cache functionality, which allows to store data of a job in a persistent place and it gets extracted every time a job is executed again, so technically one could utilise that, but the problem is that this cache can be invalidated with a single button and it cannot be “protected” whatsoever. There is also no way to wipe the cache for a specific job, so even discipline will not help. The “clear runner caches” clears the caches for all jobs of a projects. It’s needless to say that this button has to be pressed here and there when things break (we use caches to limit traffic to package repositories and computation time by caching build products).

In the GitHub Actions universe, the situation is much nicer. GitHub deals with the deployment of “pages” in a fundamentally different way and maintains an extra branch (usually) called gh-pages like this one: GitHub - JuliaHEP/UnROOT.jl at gh-pages which is modified (by Documenter.jl) each time a deployment is triggered to update versions.js and create a new folder for the tag and replace the symlinks for the latest and stable documentation.

Now my question: does anyone have a working solution or an idea how to bring multiple version doc hosting to the GitLab universe?

I guess the only way is to mimic the extra-branch-approach of GitHub by implementing the procedure in Documenter.jl and then create a GitLab CI job template, but before I dive into that I was curious if anyone has done anything in that direction :wink:

1 Like

Ahhm… I just found a deploy configuration for GitLab: Hosting Documentation · Documenter.jl

I have never seen that before :see_no_evil: let me try that.

OK I few things I have found so far (I have used the PkgTemplates.jl with the GitLab plugin):

  • The default Julia version 1.0 will not work, 1.6+ is needed to do the deployment (building docs works also with 1.0 though)
  • git is not installed in the default julia:1.6 Docker image so it needs to be installed in each job, or better: use another image where git is already pre-installed
  • GitLab does not have a project specific scope for SSH keys, which is needed for the modification of the gh-pages branch to store the versioned docs by Documenter.jl (the base64-encoded private key has to be defined as a CI variable named DOCUMENTER_KEY). This is kind of awkward since it means that one of the users with write-access has to put the public key in their own account. Everyone with maintainer access has access to that SSH key-pair (and therefore to all repos of that user)
  • The default URL for the documentation points to gitlab.io (also the badge in the README.md), so for self-hosted GitLab servers the URL is incorrect. This needs to be changed manually in make.jl and README.md
  • I found that the default branch is still master in a few places, I think those came from Documenter.jl but the errors were clear and the fix was overriding the defaults.

I’ll gather all the issues and try to find time to make PRs to PkgTemplates.jl and Documenter.jl if needed.

For now it seems to work with a bit of fiddling and accepting some serious security issues with the account-bound SSH-keypair :wink:

You can get started by adding deploydocs() to your make.jl:

deploydocs(;
  repo = "git.your-institute.com/username/Project.jl",
  devbranch = "main",
)
1 Like

A tiny update: I still have not managed to get the versions displayed. For whatever reason, the versions.js does only contain dev, so creating version tags has no effect on that. The commits to gh-pages work though via the DOCUMENTER_KEY.

Here is the example project I am working on: https://git.km3net.de/tgal/JuliaGitLabPages.jl

The problem is that even if the commits to gh-pages work, there is no (obvious) way in GitLab to tell pages to use that branch. We would need another .gitlab-ci.yml or so on that branch, since only the pages job is able to deploy the docs by declaring the public/ folder as an artifact.

I created a Git issue to summarise things and try to work on a PR: Deploying docs on GitLab CI with version-selection feature · Issue #2061 · JuliaDocs/Documenter.jl · GitHub

OK, with a bit of fiddling, everything works now. It’s still a manual process but I’ll make a PR to Documenter.jl which makes it a bit easier. You can read the everything in the issue https://github.com/JuliaDocs/Documenter.jl/issues/2061