[LTP] [PATCH v2 2/4] ci: add patchwork-ci script

Andrea Cervesato andrea.cervesato@suse.de
Thu Apr 10 20:21:11 CEST 2025


From: Andrea Cervesato <andrea.cervesato@suse.com>

Add a script to communicate with patchwork. Available commands are:

- verify: will print a list of new patch-series which has not been
  tested in the past hour (by default)
- apply: apply a patch-series to the current git branch using git-am
- check: send a tests report to patchwork

The script can be configured defining:

- PATCHWORK_URL: patchwork url to communicate with
- PATCHWORK_SINCE: timespan in seconds where we want to fetch
  patch-series

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 ci/patchwork-ci.sh | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)

diff --git a/ci/patchwork-ci.sh b/ci/patchwork-ci.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f363055578c831f9426564cd8530348a8f9f76e2
--- /dev/null
+++ b/ci/patchwork-ci.sh
@@ -0,0 +1,164 @@
+#!/bin/sh -ex
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2025 Andrea Cervesato <andrea.cervesato@suse.com>
+
+if [ -z "$PATCHWORK_URL" ]; then
+        PATCHWORK_URL="https://patchwork.ozlabs.org"
+fi
+
+if [ -z "$PATCHWORK_SINCE" ]; then
+        PATCHWORK_SINCE=3600
+fi
+
+fetch_series() {
+        local current_time=$(date +%s)
+        local since_time=$(expr $current_time - $PATCHWORK_SINCE)
+        local date=$(date -u -d @$since_time +"%Y-%m-%dT%H:%M:%SZ")
+
+        curl -k -G "$PATCHWORK_URL/api/events/" \
+                --data "category=series-completed" \
+                --data "project=ltp" \
+                --data "state=new" \
+                --data "since=$date" \
+                --data "archive=no" |
+                jq -r '.[] | "\(.payload.series.id):\(.payload.series.mbox)"'
+}
+
+get_patches() {
+        local series_id="$1"
+
+        curl -k -G "$PATCHWORK_URL/api/patches/" \
+                --data "project=ltp" \
+                --data "series=$series_id" |
+                jq -r '.[] | "\(.id)"'
+}
+
+set_patch_state() {
+        local patch_id="$1"
+        local state="$2"
+
+        curl -k -X PATCH \
+                -H "Authorization: Token $PATCHWORK_TOKEN" \
+                -F "state=$state" \
+                "$PATCHWORK_URL/api/patches/$patch_id/"
+}
+
+set_series_state() {
+        local series_id="$1"
+        local state="$2"
+
+        get_patches "$series_id" | while IFS= read -r patch_id; do
+                if [ -n "$patch_id" ]; then
+                        set_patch_state "$patch_id" "$state"
+                fi
+        done
+}
+
+get_checks() {
+        local patch_id="$1"
+
+        curl -k -G "$PATCHWORK_URL/api/patches/$patch_id/checks/" |
+                jq -r '.[] | "\(.id)"'
+}
+
+already_tested() {
+        local series_id="$1"
+
+        get_patches "$series_id" | while IFS= read -r patch_id; do
+                if [ ! -n "$patch_id" ]; then
+                        continue
+                fi
+
+                get_checks "$patch_id" | while IFS= read -r check_id; do
+                        if [ -n "$check_id" ]; then
+                                echo "$check_id"
+                                return
+                        fi
+                done
+        done
+}
+
+verify_new_patches() {
+        local output="output.txt"
+
+        fetch_series | while IFS=: read -r series_id series_mbox; do
+                if [ ! -n "$series_id" ]; then
+                        continue
+                fi
+
+                tested=$(already_tested "$series_id")
+                if [ -n "$tested" ]; then
+                        continue
+                fi
+
+                echo -n "$series_id:$series_mbox;" >>"$output"
+        done
+
+        if [ -e "$output" ]; then
+                cat "$output"
+        fi
+}
+
+apply_series() {
+        local series_id="$1"
+        local series_mbox="$2"
+
+        git config --global user.name 'GitHub CI'
+        git config --global user.email 'patchwork.tester@example.org'
+        git config --global --add safe.directory $GITHUB_WORKSPACE
+
+        curl -k "$series_mbox" | git am
+
+        # we set patch state after applying it, so
+        # the next triggering won't take patch into account
+        set_series_state "$series_id" "needs-review-ack"
+}
+
+send_results() {
+        local series_id="$1"
+        local target_url="$2"
+
+        local context=$(echo "$3" | sed 's/:/_/g; s/\//_/g')
+        if [ -n "$CC" ]; then
+                context="${context}_${CC}"
+        fi
+
+        if [ -n "$ARCH" ]; then
+                context="${context}_${ARCH}"
+        fi
+
+        local result="$4"
+        if [ "$result" = "cancelled" ]; then
+                return
+        fi
+
+        local state="fail"
+        if [ "$result" = "success" ]; then
+                state="success"
+        fi
+
+        get_patches "$series_id" | while IFS= read -r patch_id; do
+                if [ -n "$patch_id" ]; then
+                        curl -k -X POST \
+                                -H "Authorization: Token $PATCHWORK_TOKEN" \
+                                -F "state=$state" \
+                                -F "context=$context" \
+                                -F "target_url=$target_url" \
+                                -F "description=$result" \
+                                "$PATCHWORK_URL/api/patches/$patch_id/checks/"
+                fi
+        done
+}
+
+run="$1"
+
+if [ -z "$run" -o "$run" = "verify" ]; then
+        verify_new_patches
+elif [ -z "$run" -o "$run" = "apply" ]; then
+        apply_series "$2" "$3"
+elif [ -z "$run" -o "$run" = "check" ]; then
+        send_results "$2" "$3" "$4" "$5"
+else
+        echo "Available commands: apply, check, verify"
+        exit 1
+fi

-- 
2.43.0



More information about the ltp mailing list