Building the Linux Kernel in a GitLab Runner

Git Lab provides a mechanism to run workloads triggered by a git commit. We try to let the automation do as much work as possible before interrupting a human code reviewer. We want to know if the code is right in as objective a manner as possible before we take the expensive context switch to perform a code review.

We can think of the set of tasks in a three step process. The first step is fast up front checks. The second is long programmatic correctness checks. The final is regression tests. There is a natural ordering between these, and they also progress in an increasing order of time and resource commitments.

The Linux Kernel is a C program, and the long, programmatic correctness check is the compile and link processes. It is worthwhile to think in terms of the third level tests, though, and package up the result of the compilation for later install on a wide array of systems based on a binary packaging format, either RPM or .DEB. We’re testing on Fedora, so we need an rpm.

While GitLab allows you to post images back to the server, it turns out the images produced by the Linux Kernel build process are a bit too large. Instead, we upload them to an S3-type Bucket. We use MinIO.

default:
  interruptible: true
  tags:
    - pe-arm64

stages:
  - compile

variables:
  # Set LANG so that lolcat will work
  LANG: "C"
compilation:
  stage: compile
  image:
    name: registry.fedoraproject.org/fedora:latest
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
  script:

    - dnf install -y kernel-headers bc xz cpio openssl dwarves rpm-build elfutils-libelf-devel openssl-devel bison flex gcc make rpm-build kernel-devel rsync
    - dnf install -y https://dl.min.io/client/mc/release/linux-arm64/mcli-20211007041958.0.0.aarch64.rpm
    - make olddefconfig 
    - mkdir -p rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
    - make -j 16 rpm-pkg
    - mkdir ./artifacts
    - cp /root/rpmbuild/SRPMS/* ./artifacts/
    - cp /root/rpmbuild/RPMS/aarch64/* ./artifacts/
    - echo http://10.76.142.35:9000/minio/cki/public/$CI_COMMIT_TIMESTAMP  >> artifacts-link.txt
    - /usr/local/bin/mcli alias set minio http://10.76.142.35:9000/ cki $AMPERE_MINIO_KEY --api S3v4
    - /usr/local/bin/mcli mb minio/cki/public/$CI_COMMIT_TIMESTAMP
    - /usr/local/bin/mcli cp artifacts/*  minio/cki/public/$CI_COMMIT_TIMESTAMP
  artifacts:
    paths:
      - ./.config
      - ./kernel.spec
      - ./artifacts-link.txt
    expire_in: 1 week
  timeout: 2h

For the Key we define a variable in the project (could be group or instance as well). We mask the variable as it is used for authentication.

Masked for a modicum of secrecy.

Note that the masking of the variable is, in this case, not sufficient to provide actual security from a malicious or inattentive participant that decided to echo the variable’s content out: it would be visible in the log.

One final step is to create artifacts-link.txt, a file that gets uploaded to GitLab that points to the location of the completed uploads. That will match the code review to the artifacts. It is not the cleanest of integrations. Ideally, there would be a way to attach a URL to the build. But this ensures at least that there is some way to link the merge request version to the artifacts.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.