Exporting Godot with GitLab CI/CD

Exporting Godot with GitLab CI/CD

One of the great features about Godot is the ability to export to multiple platforms, either through the engine's UI or through the command line. As a software engineer by trade, I wondered how I could export my Godot games in an automated fashion. Here is how I went about setting up a basic automated deployment pipeline with GitLab CI/CD for my game.

Exporting Godot games

Exporting projects in Godot is rather straightforward when following their documentation, especially for PC.

The main requirements are as follows:

  1. Download Godot's export templates, available at Godot's official download page.
  2. Generate an export preset with saved configurations for the target platform. (I'll be using Windows in my example.)

Export presets have many configurations, but I used mostly default settings.

godot_export_preset_windows.png

Once the export templates and preset were ready, exporting through the command line was a simple command. All I have to do was specify the export preset (which had to be in the working directory), the path to the Godot project (optional since it was also in the working directory), and the target file.

godot --export "windows_pck" --path ".\project.godot" ".exports\AMonthAway.exe"

GitLab CI/CD

I decided to use GitLab CI/CD because when I created my repository, GitHub didn't have free private repositories and I'm pretty sure GitHub Actions didn't exist yet either. With my project already in GitLab, GitLab CI/CD was the naturally convenient choice.

GitLab CI/CD is configured with a .gitlab-ci.yml file, so after going through GitLab's CI/CD documentation, I set up a pipeline with my yml looking something like this:

build-job:
  stage: build
  script:
    - echo "Downloading Godot executable"
    - curl -o godot_linux_64.zip https://downloads.tuxfamily.org/godotengine/3.2.3/Godot_v3.2.3-stable_x11.64.zip
    - unzip godot_linux_64.zip -d godot
    - godot/Godot_v3.2.3-stable_x11.64 --version

To quickly test that Godot can run, this pipeline downloads the Godot v3.2.3 release, unzips the downloaded file, and then attempts to get the Godot version. Unfortunately, this quickly resulted in a failure:

godot_gitlab_cicid_failure.png

Since GitLab CI/CD runs on Kubernetes and uses Linux containers, I had tried using the Godot Linux release, but I discovered the default Docker image ruby:2.5 wasn't properly configured to run Godot. I then realized that creating my own custom Docker image with Godot pre-installed could save time during deployment and reduce the likelihood of hitting the 400 CI/CD minute limit of GitLab's free tier.

Docker

godot_gitlab_cicd_docker.png

To have Godot ready to export any project file, both the Godot engine and export templates need to be available.

Here is the Dockerfile for my jetpackgone/godot-gitlab-cicd image to export a Windows executable for my game:

FROM ubuntu

RUN apt-get update \
  && apt-get install -y git unzip wget

ENV GODOT_VERSION "3.2.3"

RUN wget -nv https://downloads.tuxfamily.org/godotengine/${GODOT_VERSION}/Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip \
    && wget -nv https://downloads.tuxfamily.org/godotengine/${GODOT_VERSION}/Godot_v${GODOT_VERSION}-stable_export_templates.tpz \
    && unzip Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip \
    && unzip Godot_v${GODOT_VERSION}-stable_export_templates.tpz \
    && mkdir ~/.cache \
    && mkdir -p ~/.config/godot \
    && mkdir -p ~/.local/share/godot/templates/${GODOT_VERSION}.stable \
    && mv Godot_v${GODOT_VERSION}-stable_linux_headless.64 /usr/local/bin/godot \
    && mv templates/* ~/.local/share/godot/templates/${GODOT_VERSION}.stable \
    && rm -f Godot_v${GODOT_VERSION}-stable_export_templates.tpz Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip

Starting from the ubuntu image, I install git, unzip, and wget with apt-get.

FROM ubuntu

RUN apt-get update \
  && apt-get install -y git unzip wget

With this alone, I could build the image locally in Docker Desktop and open a shell in the container, where I could test exporting my Godot project:

docker build -t godot-gitlab-cicd .
docker run -it godot-gitlab-cicd

After verifying that my project could indeed be exported with this image locally, I added the following to the Dockerfile:

ENV GODOT_VERSION "3.2.3"

RUN wget -nv https://downloads.tuxfamily.org/godotengine/${GODOT_VERSION}/Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip \
    && wget -nv https://downloads.tuxfamily.org/godotengine/${GODOT_VERSION}/Godot_v${GODOT_VERSION}-stable_export_templates.tpz \
    && unzip Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip \
    && unzip Godot_v${GODOT_VERSION}-stable_export_templates.tpz \
    && mkdir ~/.cache \
    && mkdir -p ~/.config/godot \
    && mkdir -p ~/.local/share/godot/templates/${GODOT_VERSION}.stable \
    && mv Godot_v${GODOT_VERSION}-stable_linux_headless.64 /usr/local/bin/godot \
    && mv templates/* ~/.local/share/godot/templates/${GODOT_VERSION}.stable \
    && rm -f Godot_v${GODOT_VERSION}-stable_export_templates.tpz Godot_v${GODOT_VERSION}-stable_linux_headless.64.zip

This portion was heavily inspired by the Barichello/godot-ci repository. This not only downloads and unzips the Godot engine and export templates, but also allows Godot to be called in the command line with just godot.

After building, tagging, and pushing this image to DockerHub, it was ready to use in GitLab CI/CD.

docker build -t godot-gitlab-cicd .
docker tag godot-gitlab-cicd jetpackgone/godot-gitlab-cicd
docker push jetpackgone/godot-gitlab-cicd

GitLab CI/CD (again)

With my custom Docker image ready in DockerHub, I modified my .gitlab-ci.yml to use the image and run the Godot export process.

image: jetpackgone/godot-gitlab-cicd

build-job:
  stage: build
  only:
    refs:
      - master
  script:
    - mkdir -p exports/windows
    - cd ./src
    - godot --export "windows_pck" --path ./project.godot "../exports/windows/AMonthAway.exe"
  artifacts:
    name: amonthaway-windows
    paths:
      - $CI_PROJECT_DIR/exports/windows

I also updated the pipeline to publish artifacts found at $CI_PROJECT_DIR/exports/windows, the target export directory. I included $CI_PROJECT_DIR in the path since GitLab CI/CD searches for artifacts relative to this directory, not the working directory.

Note: I also had to remove export_presets.cfg from my .gitignore so that it would be available in GitLab CI/CD for Godot to use when exporting.

With these changes, my pipeline finally ran successfully and published the exported Godot game, which I could download and run!

godot_gitlab_cicd.png

Next Steps

Now that the Windows export is setup, exporting for iOS and Linux should be straightforward as separate export presets and CI/CD jobs.

I also intend to publish these exports to Steam and itch.io when playable releases are available.

Resources

The jetpackgone/godot-gitlab-cicd Docker image is publicly available on DockerHub for use on MIT license.