Skip to content
Björn Töpel edited this page Sep 28, 2023 · 3 revisions

RISC-V Linux Github Patchwork CI

Introduction

This document describes what the RISC-V Linux Github Patchwork CI (pw-ci) is, how, and where it is run, and how to use it.

Patchwork is "a web-based patch tracking system designed to facilitate the contribution and management of contributions to an open-source project". It crawls the RISC-V Linux mailing list, and exposes the patches in a convenient UI (https://patchwork.kernel.org/project/linux-riscv/list/), and also a REST API for managing the patches.

All patches that end up on the RISC-V patchwork instance, are picked up by a CI service, which tries to apply the series a corresponding RISC-V git tree, and build/run checks for/test the series for a number of configuraions.

The CI service is described here.

The top-level view

This is the flow a series, from submission to status reported on patchwork.

  1. A developer submits a series to the RISC-V Linux mailing list.
  2. Patchwork picks up the series. The series is now available on the patchwork system.
  3. The KPD (Kernel Patches Daemon) monitors patchwork, and the RISC-V git trees. When a new series appeears, the service will pull the series from patchwork and try to apply the Github build files (.github), and the series on top of the RISC-V trees.
  4. KPD creates a Github pull request on github.com/linux-riscv/linux-riscv repository.
  5. Github triggers the Github Action Workflow for the pull request, and the workflow is run on the self-hosted runners.
  6. The results for the run is reported back to Github.
  7. KPD fetches the run results for the series, and reports back to patchwork.

Components

Kernel Patches Daemon

KPD is a python-based service originally authored by Meta, and orignally used for the BPF subsystem.

A RISC-V KPD fork has been adapted to support the RISC-V PW test suite.

RISC-V fork: https://github.com/linux-riscv/kernel-patches-daemon Meta upstream: https://github.com/facebookincubator/kernel-patches-daemon

Installation/setup

git clone https://github.com/facebookincubator/kernel-patches-daemon
pipx install poetry
cd kernel-patches-daemon
python -m venv .venv
poetry install

Configuration files:

pwsyncher@rise-kernel-ci-1:~$ cat .kernel-patches/config.json 
{
  "version": 3,
  "patchwork": {
    "server": "patchwork.kernel.org",
    "project": "linux-riscv",
    "search_patterns": [
      {
        "archived": false,
        "project": 377
      }
    ],
    "lookback": 7
  },
  "tag_to_branch_mapping": {
      "fixes" : [ "fixes" ],
      "for-next" : [ "for-next" ],
      "__DEFAULT__" : [ "for-next", "fixes" ]
  },
  "branches": {
       "for-next": {
            "github_oauth_token": "github_pat_SECRET",
            "repo": "https://github.com/linux-riscv/linux-riscv",
            "upstream": "git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git",
            "upstream_branch": "for-next",
            "ci_repo": "https://github.com/linux-riscv/github-ci.git",
            "ci_branch": "main"
        },
        "fixes": {
            "github_oauth_token": "github_pat_SECRET",
            "repo": "https://github.com/linux-riscv/linux-riscv",
            "upstream": "git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git",
            "upstream_branch": "fixes",
            "ci_repo": "https://github.com/linux-riscv/github-ci.git",
            "ci_branch": "main"
        }
   },
  "base_directory": "/disk-1/var/lib/kpd"
}

pwsyncher@rise-kernel-ci-1:~$ cat .kernel-patches/metric_logger.sh 
#!/bin/bash

d=$(dirname "${BASH_SOURCE[0]}")

cat > /dev/null
pwsyncher@rise-kernel-ci-1:~$ 


pwsyncher@rise-kernel-ci-1:~$ cat /etc/systemd/system/pwsyncher.service
# /etc/systemd/system/pwsyncher.service

[Unit]
Description=Kernel Patches Daemon
After=network.target

[Service]
User=pwsyncher
WorkingDirectory=/disk-1/share/kpd
ExecStart=/bin/bash -c 'PATH=${PATH}:/home/pwsyncher/.local/bin poetry run python -m kernel_patches_daemon --config ~/.kernel-patches/config.json --label-color configs/labels.json'
KillMode=process
KillSignal=SIGTERM
TimeoutStopSec=5min
Restart=on-success
RestartSec=120s

[Install]
WantedBy=multi-user.target

Note that the github_oauth_token token has to be generated via the https://github.com/linux-riscv/ settings.

Instance

Host: rise-kernel-ci-1 User: pwsyncher Run: systemd service: pwsyncher.service Logs: journalctl -f -u pwsyncher.service

Github self-hosted runner

The self-hosted runners are arm64 based running Debian 12. The runners are run in "ephemeral" mode with containers, which means that the builds are done in a Docker container, and that the docker container is clean on each run.

Installation/setup

mkdir -p /disk-1/share/gh-runner && cd /disk-1/share/gh-runner
curl -O -L https://github.com/actions/runner/releases/download/v2.309.0/actions-runner-linux-arm64-2.309.0.tar.gz
tar xzf ./actions-runner-linux-arm64-2.309.0.tar.gz

# Create this file
cat /disk-1/share/gh-runner/ghrunner.sh
#!/bin/bash

# Tokens in clear text... XD
ghtoken="bjoto:github_pat_SECRET"

cd /disk-1/share/gh-runner
while true; do
    token=$(curl -s -u "$ghtoken"  -X POST -H "Accept: application/vnd.github.v3+json" \
		 "https://api.github.com/repos/linux-riscv/linux-riscv/actions/runners/registration-token" |
		jq ".token" -r)
    
    if [[ "$token" != "null" ]]; then
	echo "token is $token"
	./config.sh --unattended --url https://github.com/linux-riscv/linux-riscv --ephemeral --token "$token" --name $(hostname) && ./run.sh
    else
	echo "ERROR: Could not get token"
    fi
    
    sleep 2
done

# Create this file
cat /etc/systemd/system/ghrunner.service 
# /etc/systemd/system/ghrunner.service

[Unit]
Description=GitHub Runner
After=network.target

[Service]
User=ghrunner
ExecStart=/bin/bash /disk-1/share/gh-runner/ghrunner.sh
KillMode=process
KillSignal=SIGTERM
TimeoutStopSec=5min

[Install]
WantedBy=multi-user.target

Instances

Host: rise-kernel-ci-1 Host: rise-kernel-ci-3 User: ghrunner Run: systemd service: ghrunner.service Logs: journalctl -f -u ghrunner.service

Github workflow files

The Github CI files reside in a separate repository: https://github.com/linux-riscv/github-ci

The files in this repo are applied as a single commit to the pull request. The actual workflow is very simple:

...snip
     - name: Run checks
        run: |
          bash .github/scripts/patches.sh

It simply calls into a shell script. This is to make it simple to run the tests locally (outside the Github framework).

To run the test suite locally:

docker pull ghcr.io/linux-riscv/pw-builder:latest
cd /linux/repo
# Fetch the PR, e.g.
git fetch https://github.com/linux-riscv/linux-riscv.git 'series/785424=>for-next'
git branch -B mypr FETCH_HEAD
docker run -it --volume "$PWD":/workspace ghcr.io/linux-riscv/pw-builder bash -l
bash .github/scripts/patches.sh

Docker build container

Each workflow is run in a docker container, which is stored on github. The docker container resides at https://github.com/linux-riscv/docker. To build, and push the container:

git clone https://github.com/linux-riscv/docker linux-riscv-docker
cd linux-riscv-docker
docker login ghcr.io -u USER
docker buildx build --platform=linux/arm64 --progress=plain -t pw-builder .
docker tag pw-builder:latest ghcr.io/linux-riscv/pw-builder:latest
docker push ghcr.io/linux-riscv/pw-builder:latest

The docker container assumes that the ccache directory is "/ccache", which is stored on the host.

docker run -it --volume "$PWD":/workspace  --volume /tmp/ccache:/ccache pw-builder