Versioning with mkdocs when not using GitHub

Mike is the go-to tool for versioning MkDocs sites. It allows you to easily manage multiple versions of your site and provides a simple way to deploy them to a static hosting service. However, mike is heavily focused on GitHub Pages, which may not be suitable for all use cases. For example, if you want to host your site on a different platform or use a different versioning strategy, it can get a bit complicated.

Since I am a heavy user of Forgejo/Gitea-based instances, where GitHub Pages is not available (and Codeberg’s pages server can be unreliable at times), I usually prefer pushing to S3 and putting a CDN in front of it. Yet, mike requires the ability to push to a branch named gh-pages in the first place. It doesn’t work locally in the sense that it builds/appends the versioning structure, and one could sync to a different destination from there. After figuring this all out, I thought sharing this in a brief post might help others out there.

This post assumes you have a working mkdocs site and have installed mike.

Run mike list at any time to see the current version structure mike knows about.

Link to this section  Local Deployment

  1. Run mike deploy <version> with the oldest version of your docs you want to deploy. It is usually best to start from the oldest version and move forward, even though you can also deploy older versions retrospectively. Ensure you go to the respective commit back in time (git checkout <tag/commit-hash>) and then run mike deploy <version>. Do this for all versions you want to deploy. It is also common to deploy a rolling “dev” version at the end, which will be updated with each new commit.

    Tip

    You usually only want to use major.minor versioning and leave out versions for patch versions. Instead, patch versions will update the existing minor version.

  2. Tell mike which version is currently the “latest” one by running mike set-default <version> --push. The --push will issue a git push command and push the changes to the remote repository, i.e., the gh-pages branch.

  3. From here, you can now either:

    • Push everything to the pages branch to be picked up by Codeberg pages.
    • Sync the contents to an S3 bucket.

Link to this section  CI Deployment

When running in CI, you must set up the build in a way that it has proper git authentication and is able to push to the gh-pages branch. How this is done depends on your respective CI and is out of scope for this post. However, if you’re running in a containerized way, you can use the following commands in a plain Alpine container:

- apk add --no-cache -q git py3-pip cairo go pngquant
- python3 -m venv venv
- git config --global user.email "<email>"
- git config --global user.name "<username>"
- git remote set-url origin https://<username>:${TOKEN}@<your git domain>/<user>/<repo>.git
# build & deploy
- ./venv/bin/activate && mike deploy <version> --push
Warning

When you deploy a new release version, you want to use mike deploy <tag> latest --push to update the “latest” version reference.

After all of the above, you need to run the following steps:

  1. Clone the gh-pages branch of your repo to a sub-directory: git clone --branch gh-pages --depth 1 <your repo> <some dir>
  2. Perform S3 sync to the destination bucket
You can see a real-time implementation of the above in https://codeberg.org/crowci/crow/src/branch/main/.crow/docs.yaml.