Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 96 additions & 57 deletions .github/scripts/create-pr-body-multiarch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
# [--kselftest-passed N --kselftest-failed N --kselftest-status TEXT]
# [--ltp-passed N --ltp-failed N --ltp-status TEXT]
# [--arch ...] --run-id ID --repo REPO --compared-against BRANCH
# [--ltp-details TEXT] [--commit-file FILE]
# [--ltp-details TEXT] [--commit-file FILE] [--ci-skipped]
#
# --ci-skipped produces an abbreviated PR body for pr_only-mode runs where
# build/boot/test stages didn't execute. The build/test sections are
# replaced with a "CI was skipped" notice. --build-time / --total-time /
# --kselftest-* / --ltp-* args are not required (and ignored) in this mode.

set -euo pipefail

Expand All @@ -17,6 +22,7 @@ REPO=""
COMMIT_MESSAGE_FILE=""
COMPARED_AGAINST=""
LTP_DETAILS=""
CI_SKIPPED=false

CURRENT_ARCH=""

Expand Down Expand Up @@ -55,6 +61,8 @@ while [[ $# -gt 0 ]]; do
LTP_DETAILS="$2"; shift 2 ;;
--commit-file)
COMMIT_MESSAGE_FILE="$2"; shift 2 ;;
--ci-skipped)
CI_SKIPPED=true; shift ;;
*)
echo "Error: Unknown option: $1" >&2; exit 1 ;;
esac
Expand All @@ -70,10 +78,13 @@ if [ ! -f "$COMMIT_MESSAGE_FILE" ]; then
exit 1
fi

for arch in "${ARCHS[@]}"; do
[[ -z "${ARCH_DATA[${arch}_build_time]:-}" ]] && { echo "Error: Missing --build-time for $arch" >&2; exit 1; }
[[ -z "${ARCH_DATA[${arch}_total_time]:-}" ]] && { echo "Error: Missing --total-time for $arch" >&2; exit 1; }
done
# build-time / total-time only required when build actually ran
if [ "$CI_SKIPPED" != "true" ]; then
for arch in "${ARCHS[@]}"; do
[[ -z "${ARCH_DATA[${arch}_build_time]:-}" ]] && { echo "Error: Missing --build-time for $arch" >&2; exit 1; }
[[ -z "${ARCH_DATA[${arch}_total_time]:-}" ]] && { echo "Error: Missing --total-time for $arch" >&2; exit 1; }
done
fi

convert_time() {
local seconds="${1%s}"
Expand All @@ -85,10 +96,14 @@ convert_time() {
MULTIARCH=false
[ ${#ARCHS[@]} -gt 1 ] && MULTIARCH=true

for arch in "${ARCHS[@]}"; do
ARCH_DATA["${arch}_build_time_readable"]=$(convert_time "${ARCH_DATA[${arch}_build_time]}")
ARCH_DATA["${arch}_total_time_readable"]=$(convert_time "${ARCH_DATA[${arch}_total_time]}")
done
# Only convert build/total time when build actually ran. In CI-skipped mode
# these values aren't set and aren't rendered.
if [ "$CI_SKIPPED" != "true" ]; then
for arch in "${ARCHS[@]}"; do
ARCH_DATA["${arch}_build_time_readable"]=$(convert_time "${ARCH_DATA[${arch}_build_time]}")
ARCH_DATA["${arch}_total_time_readable"]=$(convert_time "${ARCH_DATA[${arch}_total_time]}")
done
fi

# Check if any arch has kselftest or LTP data
HAS_KSELFTEST=false
Expand All @@ -98,91 +113,115 @@ for arch in "${ARCHS[@]}"; do
[ -n "${ARCH_DATA[${arch}_ltp_passed]:-}" ] && HAS_LTP=true
done

cat << EOF
if [ "$CI_SKIPPED" = "true" ]; then
cat << EOF
## Summary
This PR was created with CI intentionally skipped (\`-pr-only\` branch suffix).
**No build or test results are available.** Please review the patch carefully
before merging.

## Commit Message(s)

EOF
else
cat << EOF
## Summary
This PR has been automatically created after successful completion of all CI stages.

## Commit Message(s)

EOF
fi

cat "$COMMIT_MESSAGE_FILE"
echo ""

cat << EOF
if [ "$CI_SKIPPED" = "true" ]; then
cat << EOF

## CI Status

⚠️ **CI was skipped for this PR.** Build, boot, kselftest, and LTP stages
did not run. The PR was created via the \`-pr-only\` branch suffix.

- [View workflow run](https://github.com/${REPO}/actions/runs/${RUN_ID})
EOF
else
cat << EOF

## Test Results

### ✅ Build Stage
EOF

if [ "$MULTIARCH" = true ]; then
echo ""
echo "| Architecture | Build Time | Total Time |"
echo "|--------------|------------|------------|"
for arch in "${ARCHS[@]}"; do
echo "| ${arch} | ${ARCH_DATA[${arch}_build_time_readable]} | ${ARCH_DATA[${arch}_total_time_readable]} |"
done
else
ARCH1="${ARCHS[0]}"
echo "- Status: Passed (${ARCH1})"
echo "- Build Time: ${ARCH_DATA[${ARCH1}_build_time_readable]}"
echo "- Total Time: ${ARCH_DATA[${ARCH1}_total_time_readable]}"
fi
if [ "$MULTIARCH" = true ]; then
echo ""
echo "| Architecture | Build Time | Total Time |"
echo "|--------------|------------|------------|"
for arch in "${ARCHS[@]}"; do
echo "| ${arch} | ${ARCH_DATA[${arch}_build_time_readable]} | ${ARCH_DATA[${arch}_total_time_readable]} |"
done
else
ARCH1="${ARCHS[0]}"
echo "- Status: Passed (${ARCH1})"
echo "- Build Time: ${ARCH_DATA[${ARCH1}_build_time_readable]}"
echo "- Total Time: ${ARCH_DATA[${ARCH1}_total_time_readable]}"
fi

echo ""
echo "- [View build logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"
echo ""
echo "- [View build logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"

cat << EOF
cat << EOF

### ✅ Boot Verification
EOF

if [ "$MULTIARCH" = true ]; then
echo "- Status: Passed (all architectures)"
else
echo "- Status: Passed (${ARCHS[0]})"
fi
echo "- [View boot logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"
if [ "$MULTIARCH" = true ]; then
echo "- Status: Passed (all architectures)"
else
echo "- Status: Passed (${ARCHS[0]})"
fi
echo "- [View boot logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"

if [ "$HAS_KSELFTEST" = true ]; then
cat << EOF
if [ "$HAS_KSELFTEST" = true ]; then
cat << EOF

### ✅ Kernel Selftests

| Architecture | Passed | Failed | Compared Against | Status |
|--------------|--------|--------|-----------------|--------|
EOF
for arch in "${ARCHS[@]}"; do
passed="${ARCH_DATA[${arch}_kselftest_passed]:-N/A}"
failed="${ARCH_DATA[${arch}_kselftest_failed]:-N/A}"
status="${ARCH_DATA[${arch}_kselftest_status]:-⚠️ No baseline available}"
echo "| ${arch} | ${passed} | ${failed} | ${COMPARED_AGAINST:-N/A} | ${status} |"
done
echo ""
echo "- [View kselftest logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"
fi
for arch in "${ARCHS[@]}"; do
passed="${ARCH_DATA[${arch}_kselftest_passed]:-N/A}"
failed="${ARCH_DATA[${arch}_kselftest_failed]:-N/A}"
status="${ARCH_DATA[${arch}_kselftest_status]:-⚠️ No baseline available}"
echo "| ${arch} | ${passed} | ${failed} | ${COMPARED_AGAINST:-N/A} | ${status} |"
done
echo ""
echo "- [View kselftest logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"
fi

if [ "$HAS_LTP" = true ]; then
cat << EOF
if [ "$HAS_LTP" = true ]; then
cat << EOF

### ✅ LTP Results

| Architecture | Passed | Failed | Compared Against | Status |
|--------------|--------|--------|-----------------|--------|
EOF
for arch in "${ARCHS[@]}"; do
ltp_passed="${ARCH_DATA[${arch}_ltp_passed]:-N/A}"
ltp_failed="${ARCH_DATA[${arch}_ltp_failed]:-N/A}"
ltp_status="${ARCH_DATA[${arch}_ltp_status]:-⚠️ No baseline available}"
echo "| ${arch} | ${ltp_passed} | ${ltp_failed} | ${COMPARED_AGAINST:-N/A} | ${ltp_status} |"
done
echo ""
echo "- [View LTP logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"

if [ -n "$LTP_DETAILS" ]; then
for arch in "${ARCHS[@]}"; do
ltp_passed="${ARCH_DATA[${arch}_ltp_passed]:-N/A}"
ltp_failed="${ARCH_DATA[${arch}_ltp_failed]:-N/A}"
ltp_status="${ARCH_DATA[${arch}_ltp_status]:-⚠️ No baseline available}"
echo "| ${arch} | ${ltp_passed} | ${ltp_failed} | ${COMPARED_AGAINST:-N/A} | ${ltp_status} |"
done
echo ""
echo "$LTP_DETAILS"
echo "- [View LTP logs](https://github.com/${REPO}/actions/runs/${RUN_ID})"

if [ -n "$LTP_DETAILS" ]; then
echo ""
echo "$LTP_DETAILS"
fi
fi
fi

Expand Down
78 changes: 78 additions & 0 deletions .github/workflows/kernel-build-and-test-multiarch-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,66 @@ jobs:
SKIP_LTP=true
fi

# Branch-name suffix parsing for skip directives.
#
# Suffixes (each strippable, can stack in any order):
# -no-kselftest skip kselftest execution + comparison
# -no-ltp skip LTP execution + comparison
# -no-tests skip both kselftest and LTP
# -no-pr run full pipeline but don't create the PR
# -pr-only skip build/boot/tests, only create the PR
#
# Pick source explicitly based on event:
# - push event: use PUSH_REF (github.ref_name = branch name)
# - pull_request event: use HEAD_REF (github.head_ref = source branch)
# We can't just `${PUSH_REF:-$HEAD_REF}` because on PR events
# github.ref_name is the synthetic "N/merge" ref, which would cause
# us to look for suffixes in the wrong string.
#
# Examples:
# {shreeya}_ciqlts9_2-no-ltp → skip LTP only
# {shreeya}_ciqlts9_2-no-tests-no-pr → skip both tests AND skip PR
# {shreeya}_rlc-10/6.12.0-211.16.1.el10_2-pr-only → just open PR, no build
#
# Strip from the end; record each flag; what's left is the base for
# downstream extraction. The closed vocabulary means no ambiguity.
PR_ONLY=false
NO_PR=false
if [[ "$IS_PR" == "true" ]]; then
SKIP_CI_RAW="$HEAD_REF"
else
SKIP_CI_RAW="$PUSH_REF"
fi
while :; do
case "$SKIP_CI_RAW" in
*-no-kselftest) SKIP_KSELFTESTS=true; SKIP_CI_RAW="${SKIP_CI_RAW%-no-kselftest}" ;;
*-no-ltp) SKIP_LTP=true; SKIP_CI_RAW="${SKIP_CI_RAW%-no-ltp}" ;;
*-no-tests) SKIP_KSELFTESTS=true; SKIP_LTP=true; SKIP_CI_RAW="${SKIP_CI_RAW%-no-tests}" ;;
*-no-pr) NO_PR=true; SKIP_CI_RAW="${SKIP_CI_RAW%-no-pr}" ;;
*-pr-only) PR_ONLY=true; SKIP_KSELFTESTS=true; SKIP_LTP=true; SKIP_CI_RAW="${SKIP_CI_RAW%-pr-only}" ;;
*) break ;;
esac
done

# Reject contradictions
if [ "$PR_ONLY" = "true" ] && [ "$NO_PR" = "true" ]; then
echo "❌ Branch name contains both -pr-only and -no-pr (contradictory)"
exit 1
fi

if [ "$PR_ONLY" = "true" ]; then
echo "⏭️ -pr-only suffix detected — only create-pr will run"
fi
if [ "$NO_PR" = "true" ]; then
echo "⏭️ -no-pr suffix detected — PR will not be created/updated"
fi

# The remote branch name (PUSH_REF / HEAD_REF) keeps the suffix,
# because `gh pr list --head ...` needs to match the actual remote
# branch. SKIP_CI_RAW holds the stripped form for downstream
# base-branch extraction; we save it as HEAD_REF_BASE in metadata.
HEAD_REF_BASE="$SKIP_CI_RAW"

# On push events there is no PR context; BASE_REF is empty string
# It will be deduced automatically in a later worklow
if [[ "$IS_PR" == "false" ]]; then
Expand Down Expand Up @@ -164,6 +224,16 @@ jobs:
exit 1
fi

# Validate pr_only / no_pr - must be exactly 'true' or 'false'
if ! [[ "$PR_ONLY" =~ ^(true|false)$ ]]; then
echo "❌ Invalid pr_only value: $PR_ONLY"
exit 1
fi
if ! [[ "$NO_PR" =~ ^(true|false)$ ]]; then
echo "❌ Invalid no_pr value: $NO_PR"
exit 1
fi

# Pass validated values to environment
echo "IS_PR=$IS_PR" >> "$GITHUB_ENV"
echo "BASE_REF=$BASE_REF" >> "$GITHUB_ENV"
Expand All @@ -173,6 +243,9 @@ jobs:
echo "SKIP_KABI=$SKIP_KABI" >> "$GITHUB_ENV"
echo "SKIP_KSELFTESTS=$SKIP_KSELFTESTS" >> "$GITHUB_ENV"
echo "SKIP_LTP=$SKIP_LTP" >> "$GITHUB_ENV"
echo "PR_ONLY=$PR_ONLY" >> "$GITHUB_ENV"
echo "NO_PR=$NO_PR" >> "$GITHUB_ENV"
echo "HEAD_REF_BASE=$HEAD_REF_BASE" >> "$GITHUB_ENV"

- name: Clone base branch
if: github.event_name == 'pull_request'
Expand Down Expand Up @@ -222,6 +295,11 @@ jobs:
echo "$SKIP_KABI" > pr_metadata/skip_kabi.txt
echo "$SKIP_KSELFTESTS" > pr_metadata/skip_kselftests.txt
echo "$SKIP_LTP" > pr_metadata/skip_ltp.txt
echo "$PR_ONLY" > pr_metadata/pr_only.txt
echo "$NO_PR" > pr_metadata/no_pr.txt
# head_ref_base is head_ref with any skip-suffix stripped, used by
# downstream base-branch extraction. Equals head_ref when no suffix.
echo "$HEAD_REF_BASE" > pr_metadata/head_ref_base.txt
echo "$IS_PR" > pr_metadata/is_pr.txt

# Create a checksum of metadata for integrity verification
Expand Down
Loading
Loading