Skip to content

Conversation

@shreeya-patel98
Copy link
Collaborator

Add automated kernel CI workflow with kselftest and PR creation
Implements a 5-stage GitHub Actions pipeline for automated kernel testing and PR creation.
Uses kernel-container-build automated-testing-v1 branch for build/test tooling.

Stage 1: Build (15-30 min)

  • Checkout kernel source + kernel-container-build repo (automated-testing-v1)
  • Build kernel in CIQ builder container with kABI checking
  • Convert built container to QCOW2 VM image
  • Upload: kernel-build.log, QCOW2 image

Stage 2: Boot Verification (2-5 min)

  • Download QCOW2 image
  • Boot kernel in QEMU (KVM or TCG) and validate login prompt appears
  • Upload: boot logs

Stage 3: Kernel Selftests (40-60 min)

  • Download QCOW2 image
  • Execute comprehensive kselftests in QEMU with dual serial consoles
  • Upload: kselftest TAP logs, dmesg output

Stage 4: Compare Results (1-2 min)
Purpose: Detect test regressions by comparing against base branch

Steps:

  1. Checkout with full history (fetch-depth: 0) for git merge-base ops
  2. Download current kselftest logs
  3. Smart base branch detection:
    • For PRs: Uses PR's target branch
    • For pushes: Sorts branches by commit date, checks 30 most recent,
      finds closest common ancestor via git merge-base
    • For force-pushes: Doesn't do the detection again, instead uses the
      same base branch as detected during the first PR creation and also
      compares the result against that base branch only
    • Outputs: base_branch (reused by PR stage)
  4. Download baseline logs from base branch (searches last 5 successful runs)
  5. Compare results:
    • Counts passing/failing tests (before/after)
    • Fails if >±3 tests changed
    • Outputs: comparison_status, comparison_message

Stage 5: Create Pull Request (1-2 min)
Purpose: Auto-create/update PR after all tests pass

Prerequisites: Only runs if build + boot + kselftest passed, no regressions detected

Steps:

  1. Check all stages passed and comparison_status != failed
  2. Checkout (shallow: fetch-depth: 50) for commit messages
  3. Download all artifacts (build/boot/test logs)
  4. Extract statistics (pass/fail counts, build times)
  5. Get commit info:
    • Single commit: Use commit message
    • Multiple commits: Create summary
  6. Create/Update PR:
    • Reuses base_branch from compare-results (no duplication!)
    • Generate PR body with test results via create-pr-body.sh
    • Creates new PR or updates existing one in case of force pushes

Note :-
To skip this github action workflow, add [ci skip] or [skip ci]
into the head commit when pushing the patches.

Implements a 5-stage GitHub Actions pipeline for automated kernel testing and PR creation.
Uses kernel-container-build automated-testing-v1 branch for build/test tooling.

Stage 1: Build (15-30 min)
- Checkout kernel source + kernel-container-build repo (automated-testing-v1)
- Build kernel in CIQ builder container with kABI checking
- Convert built container to QCOW2 VM image
- Upload: kernel-build.log, QCOW2 image

Stage 2: Boot Verification (2-5 min)
- Download QCOW2 image
- Boot kernel in QEMU (KVM or TCG) and validate login prompt appears
- Upload: boot logs

Stage 3: Kernel Selftests (40-60 min)
- Download QCOW2 image
- Execute comprehensive kselftests in QEMU with dual serial consoles
- Upload: kselftest TAP logs, dmesg output

Stage 4: Compare Results (1-2 min)
Purpose: Detect test regressions by comparing against base branch

Steps:
1. Checkout with full history (fetch-depth: 0) for git merge-base ops
2. Download current kselftest logs
3. Smart base branch detection:
   - For PRs: Uses PR's target branch
   - For pushes: Sorts branches by commit date, checks 30 most recent,
     finds closest common ancestor via git merge-base
   - For force-pushes: Doesn't do the detection again, instead uses the
     same base branch as detected during the first PR creation and also
     compares the result against that base branch only
   - Outputs: base_branch (reused by PR stage)
4. Download baseline logs from base branch (searches last 5 successful runs)
5. Compare results:
   - Counts passing/failing tests (before/after)
   - Fails if >±3 tests changed
   - Outputs: comparison_status, comparison_message

Stage 5: Create Pull Request (1-2 min)
Purpose: Auto-create/update PR after all tests pass

Prerequisites: Only runs if build + boot + kselftest passed, no regressions detected

Steps:
1. Check all stages passed and comparison_status != failed
2. Checkout (shallow: fetch-depth: 50) for commit messages
3. Download all artifacts (build/boot/test logs)
4. Extract statistics (pass/fail counts, build times)
5. Get commit info:
   - Single commit: Use commit message
   - Multiple commits: Create summary
6. Create/Update PR:
   - Reuses base_branch from compare-results (no duplication!)
   - Generate PR body with test results via create-pr-body.sh
   - Creates new PR or updates existing one in case of force pushes

Note :-
To skip this github action workflow, add [ci skip] or [skip ci]
into the head commit when pushing the patches.

Signed-off-by: Shreeya Patel <spatel@ciq.com>
Script to generate detailed PR descriptions with kselftest results.

Signed-off-by: Shreeya Patel <spatel@ciq.com>
RUN_ID="$5"
COMPARISON_SECTION="$6"
REPO="$7"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor, but just to be sure, I would check if nb of arguments is as expected.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either number or args OR qualify each.

fi

if [ -z "$BASE_BRANCH" ]; then
echo "::warning::Could not determine base branch for comparison - no common ancestor found"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would put error here, not warning.

And exit 1 or sth else, not 0.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# Only check the 30 most recently updated branches for performance
I think this is the reason its set as a warning rather than as an error.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in private, this does not work because we also have personal branches pushed.
As seen here #683.

We can extract the base branch based on the branch, or we can ignore the branches with '{}', or we can keep a list of the branches that are bases. This is anyway the idea to move forward for automation. Keeping this list in a yaml file would be the norm, so I don't see it as an issue here that we "hardcode" this.

id: commit_msg
run: |
# Count commits since origin/main (or appropriate base branch)
BASE_BRANCH="main"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the same as Determine base branch for comparison?

\`\`\`
EOF

cat /tmp/commit_message.txt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is created outside of this script, can you add a check and fail before this section ... just in case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally this is hardcoded in two separate files we should probably make this an input parameter

REPO="$7"

# Convert seconds to minutes for better readability
convert_time() {
Copy link
Collaborator

@PlaidCat PlaidCat Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally there are not issues here but we should validate the BUILD_TIME and TOTAL_TIME here or at script input validation.

Mostly concerned about accidental drift.

name: kselftest-logs-x86_64
path: |
output/kselftests-*.log
output/dmesg-*.log
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we didn't need the dmesg logs could we keep these for like 60 days?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PlaidCat We have a bigger problem actually which I wanted to discuss. All the logs will only be there for 7 days in github. Unfortunately that's the policy of github if we use their runners.

sudo apt-get install -y gh
fi

- name: Determine base branch for comparison
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole step seems overly complicated

name: Automated kernel build and test (x86_64)
on:
  push:
    branches:
      - '*_ciqlts9_2'

We're only allowing this to run on specific patterns, if that is built into the branch name it should be pretty easy to create a map and validate that the HEAD of the base branch is contained in this branch?

Then maybe use an error.

For a completely generic case this might work but also requires relatively recent updates.

If i'm missing something here please correct me.


- name: Download baseline kselftest logs from base branch
if: steps.base_branch.outputs.base_branch != ''
uses: dawidd6/action-download-artifact@v3
Copy link
Collaborator

@PlaidCat PlaidCat Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this appear to be a user action, we should do a code audit of this.

@bmastbergen has mentioned this before too, maybe as CIQ we should be authoring our own sort of actions like this so that we can contribute to additional community members and we know a company is behind an action code we're running

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants