From 863ce675c66c784d29da8a1928be9bcaf357ff44 Mon Sep 17 00:00:00 2001 From: Luis Chamberlain Date: Tue, 18 Mar 2025 22:56:12 +0000 Subject: [PATCH 1/3] adding ci files Update: Daniel Gomez kdevops-init.yml: use debug callback plugin In preparation to commit [1], configure the Ansible callback plugin via cli adn set it debug (instead of the new default dense). This ensures we keep the verbosity in CI. [1]: https://lore.kernel.org/all/20250206-ansible_cfg3-v3-2-4588c8c07e22@samsung.com/ Signed-off-by: Daniel Gomez --- .github/workflows/kdevops-cleanup.yml | 60 ++++++++ .github/workflows/kdevops-generic.yml | 37 +++++ .github/workflows/kdevops-init.yml | 192 ++++++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 .github/workflows/kdevops-cleanup.yml create mode 100644 .github/workflows/kdevops-generic.yml create mode 100644 .github/workflows/kdevops-init.yml diff --git a/.github/workflows/kdevops-cleanup.yml b/.github/workflows/kdevops-cleanup.yml new file mode 100644 index 00000000000000..d7e69ac48e6c92 --- /dev/null +++ b/.github/workflows/kdevops-cleanup.yml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# This can be used towards the end of your action. All tasks here run even if +# any of the previous tasks failed. + +name: Kdevops cleanup workflow + +on: + workflow_call: # Makes this workflow reusable + +jobs: + cleanup: + name: Archive results and cleanup + runs-on: [self-hosted, Linux, X64] + steps: + - name: Set Linux kdevops development path + if: ${{ job.status != 'cancelled' }} + run: echo "LINUX_KDEVOPS_PATH=$GITHUB_WORKSPACE" >> $GITHUB_ENV + + - name: Get systemd journal files + if: ${{ job.status != 'cancelled' }} + run: | + if [[ ! -d kdevops ]]; then + exit 0 + fi + cd kdevops + make journal-dump + + - name: Start SSH Agent + if: ${{ job.status != 'cancelled' }} + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Build our kdevops archive results + if: ${{ job.status != 'cancelled' }} + run: | + if [[ ! -d kdevops ]]; then + exit 0 + fi + cd kdevops + make ci-archive + + - name: Upload our kdevops results archive + if: ${{ job.status != 'cancelled' }} + uses: actions/upload-artifact@v4 + with: + name: kdevops-ci-results + path: ${{ env.LINUX_KDEVOPS_PATH }}/kdevops/archive/*.zip + + - name: Run kdevops make destroy + if: always() + run: | + if [[ ! -d kdevops ]]; then + exit 0 + fi + cd kdevops + make destroy + cd .. + rm -rf kdevops diff --git a/.github/workflows/kdevops-generic.yml b/.github/workflows/kdevops-generic.yml new file mode 100644 index 00000000000000..8ca2006c1e1d22 --- /dev/null +++ b/.github/workflows/kdevops-generic.yml @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Most simple Linux kernel subsystems can be tested with this target +# test setup. For more elaborates tests look for a topic branch under the +# kdevops-ci tree. For example to test a filesystem look at the fstests +# branch. + +name: Run generic kdevops CI tests + +on: + push: + branches: ['**'] + pull_request: + branches: ['**'] + workflow_dispatch: # Allow manual triggering + +jobs: + setup: + uses: ./.github/workflows/kdevops-init.yml + secrets: inherit + + run-tests: + needs: setup + name: Run CI tests + runs-on: [self-hosted, Linux, X64] + steps: + - name: Run CI tests + run: | + cd kdevops + make ci-test + echo "ok" > ci.result + + cleanup: + needs: [run-tests, setup] # Add setup as a dependency to ensure proper ordering + if: always() # This ensures cleanup runs even if run-tests fails + uses: ./.github/workflows/kdevops-cleanup.yml + secrets: inherit diff --git a/.github/workflows/kdevops-init.yml b/.github/workflows/kdevops-init.yml new file mode 100644 index 00000000000000..022683eba3ec95 --- /dev/null +++ b/.github/workflows/kdevops-init.yml @@ -0,0 +1,192 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# This can be used as a initialization workflow for most Linux kernel +# development environments. This takes care of: +# +# - Checks out and re-using a local mirror for your kernel tree +# - Looks for a defconfig in kdevops to use for your kernel tree +# - Sets up CI metadata for kdevops-results-archive +# - Ensures your kernel tree at least builds with defconfig +# - Brings up target DUTs nodes +# - Installs your Linux kernel tree on them +# - Builds all of your test requirements for your Linux kernel tree + +name: Base kdevops workflow + +on: + workflow_call: # Makes this workflow reusable + inputs: + kdevops_defconfig: + required: false + type: string + +jobs: + setup: + name: Setup kdevops environment + runs-on: [self-hosted, Linux, X64] + steps: + - name: Verify we won't expect user input interactions on the host key + run: | + mkdir -p ~/.ssh + if ! grep -q "StrictHostKeyChecking no" ~/.ssh/config 2>/dev/null; then + echo "StrictHostKeyChecking no" >> ~/.ssh/config + fi + + - name: Start SSH Agent for initial test + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + # Modify the repo here if you have a custom or private URL for the archive + # This can also just be a repo variable later. + - name: Verify our ssh connection will work + run: | + if ! git ls-remote git@github.com:linux-kdevops/kdevops-results-archive.git HEAD; then + echo "Cannot access kdevops-results-archive repository" + exit 1 + fi + + - name: Configure git + run: | + git config --global --add safe.directory '*' + git config --global user.name "kdevops" + git config --global user.email "kdevops@lists.linux.dev" + + - name: Checkout kdevops + run: | + rm -rf kdevops + git clone /mirror/kdevops.git kdevops + + - name: Make sure our repo kdevops defconfig exists + run: | + cd kdevops + if [[ -z "${{ inputs.kdevops_defconfig }}" ]]; then + KDEVOPS_DEFCONFIG=$(basename ${{ github.repository }}) + else + KDEVOPS_DEFCONFIG="${{ inputs.kdevops_defconfig }}" + fi + + if [[ ! -f defconfigs/$KDEVOPS_DEFCONFIG ]]; then + echo "kdevops lacks a defconfig for this repository, expected to find: defconfigs/$KDEVOPS_DEFCONFIG" + exit 1 + fi + + echo "KDEVOPS_DEFCONFIG=$KDEVOPS_DEFCONFIG" >> $GITHUB_ENV + + - name: Checkout custom branch with delta on kdevops/linux + run: | + LINUX_TREE="https://github.com/${{ github.repository }}" + LINUX_TREE_REF="${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}" + cd kdevops + git clone $LINUX_TREE --reference /mirror/linux.git/ --depth=5 linux + cd linux + git fetch origin $LINUX_TREE_REF + git checkout $LINUX_TREE_REF + git log -1 + + - name: Initialize CI metadata for kdevops-results-archive for linux + run: | + cd kdevops/linux + echo "$(basename ${{ github.repository }})" > ../ci.trigger + + # This supports using kdevops github actions using two different + # approaches: + # + # 1) Commit the .github/ directory onto a Linux tree before your + # kernel changes. This approach is used for example for + # testing patches posted on the mailing list with patchwork, + # this is the strategy kernel-patch-deaemon uses. Since the + # patches are ephemeral there is not important git history to + # maintain. + # + # 2) Merge the .github/ directory at the end of your development + # tree. This is useful for kernel developers wishing to test + # existing trees. + # + # So this checks to see if the last commit (top of the tree) *added* + # the .github directory. If the last commit added it, then we assume + # the commit prior to it was the one we'd like to document as the main + # test point. + if git diff-tree --no-commit-id --name-only --diff-filter=A -r HEAD | grep -q "^\.github/"; then + git log -2 --skip=1 --pretty=format:"%s" -1 > ../ci.subject + git describe --exact-match --tags HEAD^ 2>/dev/null || git rev-parse --short HEAD^ > ../ci.ref + else + git log -1 --pretty=format:"%s" > ../ci.subject + git describe --exact-match --tags HEAD 2>/dev/null || git rev-parse --short HEAD > ../ci.ref + fi + + RELEVANT_GIT_TAG=$(cat ../ci.ref) + RELEVANT_GIT_REF=$(git rev-parse --short=12 $RELEVANT_GIT_TAG) + + echo "LINUX_GIT_REF=$RELEVANT_GIT_REF" >> $GITHUB_ENV + echo "LINUX_GIT_TAG=$RELEVANT_GIT_TAG" >> $GITHUB_ENV + + # Start out pessimistic + echo "unknown" > ../ci.result + echo "Nothing to write home about." > ../ci.commit_extra + + - name: Run a quick Linux kernel defconfig build test + run: | + cd kdevops/linux + git reset --hard ${{ env.LINUX_GIT_TAG }} + make defconfig + make -j$(nproc) + + - name: Run kdevops make defconfig-repo + run: | + LINUX_TREE="https://github.com/${{ github.repository }}" + LINUX_TREE_REF="${{ env.LINUX_GIT_TAG }}" + + # We make the compromise here to use a relevant git tag for the + # host prefix so that folks can easily tell what exact kernel tree + # is being tested by using the relevant git ref. That is, if you + # pushed a tree with the .github/ directory as the top of the tree, + # that commit will not be used, we'll use the last one as that is + # the relevant git ref we want to annotate a test for. + # + # The compromise here we use special KDEVOPS to separete the + # commit ID and github.run_id. Exotic things likes UTF characters + # and dots have problems. + KDEVOPS_HOSTS_PREFIX="${{ env.LINUX_GIT_REF }}KDEVOPS${{ github.run_id }}" + + echo "Going to use defconfig-${{ env.KDEVOPS_DEFCONFIG }}" + + echo "Linux tree: $LINUX_TREE" + echo "Linux trigger ref: $LINUX_TREE_REF" + echo "Linux tag: ${{ env.LINUX_GIT_TAG }}" + echo "Runner ID: ${{ github.run_id }}" + echo "kdevops host prefix: $KDEVOPS_HOSTS_PREFIX" + echo "kdevops defconfig: defconfig-${{ env.KDEVOPS_DEFCONFIG }}" + + KDEVOPS_ARGS="\ + KDEVOPS_HOSTS_PREFIX=$KDEVOPS_HOSTS_PREFIX \ + LINUX_TREE=$LINUX_TREE \ + LINUX_TREE_REF=$LINUX_TREE_REF \ + ANSIBLE_CFG_CALLBACK_PLUGIN="debug" \ + defconfig-${{ env.KDEVOPS_DEFCONFIG }}" + echo "Going to run:" + echo "make $KDEVOPS_ARGS" + + cd kdevops + make $KDEVOPS_ARGS + + - name: Run kdevops make + run: | + cd kdevops + make -j$(nproc) + + - name: Run kdevops make bringup + run: | + cd kdevops + ls -ld linux + make bringup + + - name: Build linux and boot test nodes on test kernel + run: | + cd kdevops + make linux + + - name: Build required ci tests + run: | + cd kdevops + make ci-build-test From 3ba0d07f06e0d096fedfaac0080b5c7b39d7ab0f Mon Sep 17 00:00:00 2001 From: Daniel Gomez Date: Mon, 23 Jun 2025 07:39:41 +0000 Subject: [PATCH 2/3] .github/workflows: add autorebase support Automatically rebase default branch repository with latest upstream kernel's tag (from torvalds repository). Use a deploy key method: https://github.com/orgs/community/discussions/ 25305#discussioncomment-10901083 Note: GitHub App token method did not work: https://github.com/orgs/community/discussions/ 25305#discussioncomment-8256560 May be because the GitHub App Token is not correctly authenticated when trying to bypass the protected ref rule and so, it fails at pushing a protected ref. Signed-off-by: Daniel Gomez --- .github/workflows/autorebase.yml | 77 ++++++++++++++++++++++++++ scripts/github_output.sh | 9 ++++ scripts/korg-releases.py | 92 ++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 .github/workflows/autorebase.yml create mode 100755 scripts/github_output.sh create mode 100755 scripts/korg-releases.py diff --git a/.github/workflows/autorebase.yml b/.github/workflows/autorebase.yml new file mode 100644 index 00000000000000..f3eb921a180b59 --- /dev/null +++ b/.github/workflows/autorebase.yml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: GPL-2.0 +--- +name: Autorebase + +on: + workflow_dispatch: + schedule: + - cron: '0 14 * * *' + +jobs: + rebase: + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 1 + ssh-key: ${{ secrets.DEPLOY_KEY }} + + - name: Configure git + run: | + git config --local user.email "github-actions@github.com" + git config --local user.name "GitHub Actions" + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Get latest mainline tag + id: mainline + run: | + tag=$(./scripts/korg-releases.py --moniker mainline) + "${{ github.workspace }}/scripts/github_output.sh" mainline_tag "$tag" + + - name: Get current kernel version + id: localver + run: | + version=$(make kernelversion) + tag="v${version/.0/}" + "${{ github.workspace }}/scripts/github_output.sh" local_tag "$tag" + + - name: Check if tags match + id: check + run: | + set -euxo pipefail + if [ "${{ steps.mainline.outputs.mainline_tag }}" = \ + "${{ steps.localver.outputs.local_tag }}" ]; then + echo "Tags are the same. Skipping rebase." + exit 0 + fi + echo "Rebase \ + ${{ steps.localver.outputs.local_tag }} -> \ + ${{ steps.mainline.outputs.mainline_tag }}" + + - name: Unshallow (get full history for rebase) + run: | + git fetch --unshallow + + - name: Add torvalds remote + run: | + git remote add torvalds \ + https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git + git fetch torvalds + + - name: Rebase master onto new mainline + run: | + set -euxo pipefail + git checkout ${{ github.event.repository.default_branch }} + git rebase --onto ${{ steps.mainline.outputs.mainline_tag }} \ + ${{ steps.localver.outputs.local_tag }} \ + ${{ github.event.repository.default_branch }} + + - name: Push rebased branch + run: | + git push origin ${{ github.event.repository.default_branch }} --force diff --git a/scripts/github_output.sh b/scripts/github_output.sh new file mode 100755 index 00000000000000..711306c38cb5ff --- /dev/null +++ b/scripts/github_output.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# +# Usage: ./github_output.sh key value +set -euxo pipefail + +key="$1" +value="$2" + +echo "$key=$value" >> "$GITHUB_OUTPUT" diff --git a/scripts/korg-releases.py b/scripts/korg-releases.py new file mode 100755 index 00000000000000..bce182e28d7926 --- /dev/null +++ b/scripts/korg-releases.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: copyleft-next-0.3.1 +import sys +import logging +import argparse +import json +import urllib.request +import socket +import re + + +def parser(): + parser = argparse.ArgumentParser(description="kernel.org/releases.json checker") + parser.add_argument("--debug", action="store_true", help="debug") + parser.add_argument( + "--moniker", + help="moniker (mainline, stable, longterm or linux-next)", + required=True, + ) + parser.add_argument( + "--pname", + help="project name for User-Agent request", + default="kdevops", + ) + parser.add_argument( + "--pversion", + help="project version for User-Agent request", + default="5.0.2", + ) + return parser + + +def _check_connection(host, port, timeout=2): + try: + with socket.create_connection((host, port), timeout): + logging.debug(f"Connection to {host} on port {port} succeeded!") + return True + except (socket.timeout, socket.error) as e: + logging.debug(f"Connection to {host} on port {port} failed: {e}") + return False + + +def kreleases(args) -> None: + """Get the latest kernel releases from kernel.org/releases.json""" + + reflist = [] + if _check_connection("kernel.org", 80): + _url = "https://www.kernel.org/releases.json" + req = urllib.request.Request( + _url, + headers={ + "User-Agent": f"{args.pname}/{args.pversion} (kdevops@lists.linux.dev)" + }, + ) + with urllib.request.urlopen(req) as url: + data = json.load(url) + + for release in data["releases"]: + if release["moniker"] == args.moniker: + # Check if release.json is aa.bb.cc type + if re.compile(r'^\d+\.\d+(\.\d+|-rc\d+)?$').match(release["version"]): + reflist.append("v" + release["version"]) + else: + reflist.append(release["version"]) + + logging.debug(f"{reflist}") + for r in reflist: + print(r) + + +def main() -> None: + """Kconfig choice generator for git refereces""" + log = logging.getLogger() + log.setLevel(logging.INFO) + p = parser() + args, _ = p.parse_known_args() + if args.debug: + log.setLevel(logging.DEBUG) + + kreleases(args) + + +if __name__ == "__main__": + ret = 0 + try: + main() + except Exception: + ret = 1 + import traceback + + traceback.print_exc() + sys.exit(ret) From 1288994407c2218de7228ac27654eae715ae2008 Mon Sep 17 00:00:00 2001 From: Daniel Gomez Date: Sat, 28 Jun 2025 17:38:46 +0000 Subject: [PATCH 3/3] .github/workflows: increase kmod timeout 165 -> 175 From v6.13 -> v6.14 the selftests kmod takes around 10s longer to run. Use KMOD_TIMEOUT Makefile cli variable to increase the default 165s timeout to 175s. Output: ok 1 selftests: kmod: kmod.sh real 2m47.077s user 0m0.062s sys 0m0.235s kdevops@dani-kmod:/data/selftests/kselftest/kselftest_install$ uname -a Linux dani-kmod 6.14.0 #3 SMP PREEMPT_DYNAMIC Fri Jun 27 18:28:16 UTC 2025 x86_64 GNU/Linux ok 1 selftests: kmod: kmod.sh real 2m41.456s user 0m0.068s sys 0m0.241s kdevops@dani-kmod:/data/selftests/kselftest/kselftest_install$ uname -a Linux dani-kmod 6.13.0 #2 SMP PREEMPT_DYNAMIC Fri Jun 27 17:13:42 UTC 2025 x86_64 GNU/Linux Signed-off-by: Daniel Gomez --- .github/workflows/kdevops-init.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/kdevops-init.yml b/.github/workflows/kdevops-init.yml index 022683eba3ec95..51bef753cc85ba 100644 --- a/.github/workflows/kdevops-init.yml +++ b/.github/workflows/kdevops-init.yml @@ -163,6 +163,7 @@ jobs: LINUX_TREE=$LINUX_TREE \ LINUX_TREE_REF=$LINUX_TREE_REF \ ANSIBLE_CFG_CALLBACK_PLUGIN="debug" \ + KMOD_TIMEOUT="175" \ defconfig-${{ env.KDEVOPS_DEFCONFIG }}" echo "Going to run:" echo "make $KDEVOPS_ARGS"