GitLab CI/CD Overview

Continuous Integration (CI) is a way to automatically test, build, and validate your code whenever changes are made.

GitLab provides built-in CI/CD features through its .gitlab-ci.yml file. This file, placed in the root of your repository, tells GitLab how to build and test your project. It defines stages and scripts that are run in a clean environment every time changes are pushed.

This document outlines how GitLab CI/CD works, including the role of the .gitlab-ci.yml file, shell scripts, and external tools like Meson and Ninja. The Artbox CI system has been specifically aligned with the official GIMP master CI approach for consistency and reproducibility.

For detailed technical documentation of the Artbox CI build process, see README-CI.md in the repository.

GitLab CI/CD Basics

The CI is controlled by a file named .gitlab-ci.yml. This file defines:

  • Stages: Ordered groups of jobs (e.g., build-this, build-that, package-up)
  • Jobs: Individual tasks to run within each stage
  • Scripts: Shell commands executed for each job
  • Runners: Computers that GitLab uses to run jobs defined in the pipeline.

Container-Based Builds

The Artbox pipeline uses containerization for consistent builds:

  1. Creating the Build Container: The first stage uses Kaniko to create a Docker image with all dependencies
  2. Using the Container: Subsequent stages run inside this container, ensuring consistent environment
  3. Reproducible Builds: Container isolation guarantees the same results across different runners

This approach ensures that builds work the same way across any GitLab runner and provides a controlled environment for complex build processes.

Role of Shell Scripts

Jobs in .gitlab-ci.yml typically invoke shell commands directly. Complex operations are often moved into separate scripts stored in the repository.

The Artbox CI uses modular shell scripts to organize build logic:

Example of script invocation:

script:
  - bash build/linux/appimage/artbox-goappimage.sh > appimage_creation.log 2>&1

Benefits of this approach:

  • Clean YAML: Keeps the .gitlab-ci.yml file focused on job structure
  • Maintainability: Complex logic is easier to debug and modify in shell scripts
  • Reusability: Scripts can be used in different contexts or environments
  • Modularity: Different aspects of the build can be separated into focused scripts

This keeps the CI configuration clean while allowing sophisticated build processes.

Integration with Build Systems

Artbox uses Meson and Ninja to prepare and then build the code.

For example:

script:
  - meson setup _build-${CI_RUNNER_TAG}
  - ninja -C _build-${CI_RUNNER_TAG}

Here:

  • meson setup prepares the build directory and generates build.ninja
  • ninja runs the build commands as defined

Meson Build System Structure

The Meson build system uses a root meson.build file placed at the project’s root directory. This file defines the top-level build configuration and entry point for the build process.

  • The root meson.build is typically located in the same directory as .gitlab-ci.yml
  • From there, it cascades recursively into subdirectories, each of which may have its own meson.build file
  • These subdirectory files define targets, sources, dependencies, and build instructions relevant to that directory

Environment Variables

Key variables in the Artbox pipeline include:

variables:
  DEBIAN_FRONTEND: "noninteractive"  # Prevents interactive prompts
  DEB_VERSION: "bookworm"            # Debian version for consistency
  CI_RUNNER_TAG: "x86_64"            # Architecture specification

Job-specific variables:

build-artbox:
  variables:
    COMPILER: "clang"                                    # Compiler selection
    GIMP_PREFIX: "${CI_PROJECT_DIR}/_install-${CI_RUNNER_TAG}"  # Installation path
    MESON_OPTIONS: "-Drelocatable-bundle=yes -Dvector-icons=true"  # Build configuration

These variables control build behavior and ensure consistency across different stages and runners.

Example Structure

project-root/
├── .gitlab-ci.yml
├── meson.build              <-- Root Meson file
├── src/
│   ├── meson.build          <-- Subdirectory Meson file
│   └── some_source.c
├── data/
│   ├── meson.build
│   └── icons/

In this structure:

  • The root meson.build file configures the overall build environment
  • Subdirectory meson.build files handle compilation details for specific components or modules
  • This hierarchical layout keeps build logic modular and maintainable

Artifacts Between Stages

Artifacts are files generated by jobs that are needed in subsequent stages:

build-artbox:
  # ...job configuration...
  artifacts:
    paths:
      - "${GIMP_PREFIX}/"      # Installation files
      - _build-${CI_RUNNER_TAG}/meson-logs/meson-log.txt  # Build logs

Pipeline Stages and Dependencies

The Artbox pipeline consists of three main stages:

  1. Dependencies: Creates a containerized build environment with all required tools and libraries
  2. Build Artbox: Compiles Artbox using Meson and Ninja in the prepared environment
  3. AppImage: Packages the built application into a distributable AppImage format

Stage Dependencies:

build-artbox:
  needs: [deps-debian]  # Waits for dependency container

artbox-appimage:
  needs: [build-artbox] # Waits for application build

Each stage runs only after its dependencies complete successfully, ensuring proper build order and artifact availability.

Summary

  • .gitlab-ci.yml defines the structure and logic of the pipeline
  • Jobs contain shell commands or external scripts
  • Tools like Meson and Ninja are used inside jobs as part of the build process

Artbox uses the GitLab CI to automatically build its AppImage for Debian based platforms. Here is the Artbox .gitlab-ci.yml to view.

For comprehensive technical details about the Artbox CI build process, including environment setup, script architecture, and troubleshooting, refer to README-CI.md.