Skip to content
Open
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
191 changes: 159 additions & 32 deletions .github/scripts/create-pr-body.sh
Original file line number Diff line number Diff line change
@@ -1,39 +1,106 @@
#!/bin/bash

# Script to create PR body
# Arguments: build_time total_time passed failed run_id comparison_section repo commit_message_file
# Script to create PR body using named arguments
# Usage: create-pr-body.sh --arch ARCH --build-time TIME --total-time TIME --passed N --failed N [--arch ...] --run-id ID --comparison SECTION --repo REPO [--commit-file FILE]

set -euo pipefail

# Check number of arguments
if [ $# -lt 7 ] || [ $# -gt 8 ]; then
echo "Error: Expected 7 or 8 arguments, got $#" >&2
echo "Usage: $0 <build_time> <total_time> <passed> <failed> <run_id> <comparison_section> <repo> [commit_message_file]" >&2
exit 1
fi

BUILD_TIME="$1"
TOTAL_TIME="$2"
PASSED="$3"
FAILED="$4"
RUN_ID="$5"
COMPARISON_SECTION="$6"
REPO="$7"
COMMIT_MESSAGE_FILE="${8:-/tmp/commit_message.txt}"

# Validate required arguments are not empty
if [ -z "$BUILD_TIME" ] || [ -z "$TOTAL_TIME" ] || [ -z "$PASSED" ] || [ -z "$FAILED" ] || [ -z "$RUN_ID" ] || [ -z "$COMPARISON_SECTION" ] || [ -z "$REPO" ]; then
echo "Error: One or more required arguments are empty" >&2
echo "Usage: $0 <build_time> <total_time> <passed> <failed> <run_id> <comparison_section> <repo> [commit_message_file]" >&2
exit 1
fi
# Arrays to track architectures and their data
declare -a ARCHS=()
declare -A ARCH_DATA

# Global parameters
RUN_ID=""
COMPARISON_SECTION=""
REPO=""
COMMIT_MESSAGE_FILE=""

CURRENT_ARCH=""

while [[ $# -gt 0 ]]; do
case "$1" in
--arch)
[[ $# -lt 2 ]] && { echo "Error: --arch requires a value" >&2; exit 1; }
CURRENT_ARCH="$2"
# Only add to ARCHS array if not already present
if [[ ! " ${ARCHS[@]:-} " =~ " ${CURRENT_ARCH} " ]]; then
ARCHS+=("$CURRENT_ARCH")
fi
shift 2
Comment on lines 20 to 29
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

Option parsing assumes every flag has a following value (e.g., CURRENT_ARCH="$2") but doesn’t check that $2 exists. With set -u, a malformed invocation will crash with an unbound variable rather than a controlled usage error. Add explicit validation for missing option arguments (e.g., ensure [[ $# -ge 2 ]] before reading $2).

Copilot uses AI. Check for mistakes.
;;
--build-time)
[[ $# -lt 2 ]] && { echo "Error: --build-time requires a value" >&2; exit 1; }
[[ -z "$CURRENT_ARCH" ]] && { echo "Error: --arch must be specified before --build-time" >&2; exit 1; }
ARCH_DATA["${CURRENT_ARCH}_build_time"]="$2"
shift 2
;;
--total-time)
[[ $# -lt 2 ]] && { echo "Error: --total-time requires a value" >&2; exit 1; }
[[ -z "$CURRENT_ARCH" ]] && { echo "Error: --arch must be specified before --total-time" >&2; exit 1; }
ARCH_DATA["${CURRENT_ARCH}_total_time"]="$2"
shift 2
;;
--passed)
[[ $# -lt 2 ]] && { echo "Error: --passed requires a value" >&2; exit 1; }
[[ -z "$CURRENT_ARCH" ]] && { echo "Error: --arch must be specified before --passed" >&2; exit 1; }
ARCH_DATA["${CURRENT_ARCH}_passed"]="$2"
shift 2
;;
--failed)
[[ $# -lt 2 ]] && { echo "Error: --failed requires a value" >&2; exit 1; }
[[ -z "$CURRENT_ARCH" ]] && { echo "Error: --arch must be specified before --failed" >&2; exit 1; }
ARCH_DATA["${CURRENT_ARCH}_failed"]="$2"
shift 2
;;
--run-id)
[[ $# -lt 2 ]] && { echo "Error: --run-id requires a value" >&2; exit 1; }
RUN_ID="$2"
shift 2
;;
--comparison)
[[ $# -lt 2 ]] && { echo "Error: --comparison requires a value" >&2; exit 1; }
COMPARISON_SECTION="$2"
shift 2
;;
--repo)
[[ $# -lt 2 ]] && { echo "Error: --repo requires a value" >&2; exit 1; }
REPO="$2"
shift 2
;;
--commit-file)
[[ $# -lt 2 ]] && { echo "Error: --commit-file requires a value" >&2; exit 1; }
COMMIT_MESSAGE_FILE="$2"
shift 2
;;
*)
echo "Error: Unknown option: $1" >&2
echo "Usage: $0 --arch ARCH --build-time TIME --total-time TIME --passed N --failed N [--arch ...] --run-id ID --comparison SECTION --repo REPO [--commit-file FILE]" >&2
exit 1
;;
esac
done

# Validate required parameters
[[ ${#ARCHS[@]} -eq 0 ]] && { echo "Error: At least one --arch required" >&2; exit 1; }
[[ -z "$RUN_ID" ]] && { echo "Error: --run-id required" >&2; exit 1; }
[[ -z "$COMPARISON_SECTION" ]] && { echo "Error: --comparison required" >&2; exit 1; }
[[ -z "$REPO" ]] && { echo "Error: --repo required" >&2; exit 1; }
[[ -z "$COMMIT_MESSAGE_FILE" ]] && COMMIT_MESSAGE_FILE="/tmp/commit_message.txt"

# Check if commit message file exists
if [ ! -f "$COMMIT_MESSAGE_FILE" ]; then
echo "Error: Commit message file not found: $COMMIT_MESSAGE_FILE" >&2
exit 1
fi

# Validate each arch has all required data
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; }
[[ -z "${ARCH_DATA[${arch}_passed]:-}" ]] && { echo "Error: Missing --passed for $arch" >&2; exit 1; }
[[ -z "${ARCH_DATA[${arch}_failed]:-}" ]] && { echo "Error: Missing --failed for $arch" >&2; exit 1; }
done

# Convert seconds to minutes for better readability
convert_time() {
local seconds="${1%s}" # Remove 's' suffix if present
Expand All @@ -42,9 +109,19 @@ convert_time() {
echo "${minutes}m ${remaining_seconds}s"
}
Comment on lines 104 to 110
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

convert_time assumes the input is numeric seconds and will exit the script on values like N/A (arithmetic expansion fails under set -e). Since the workflow can emit non-numeric fallbacks, make convert_time resilient (e.g., detect non-numeric input and return it unchanged) or ensure callers always pass a valid integer number of seconds.

Copilot uses AI. Check for mistakes.

BUILD_TIME_READABLE=$(convert_time "$BUILD_TIME")
TOTAL_TIME_READABLE=$(convert_time "$TOTAL_TIME")
# Determine if multi-arch
MULTIARCH=false
if [ ${#ARCHS[@]} -gt 1 ]; then
MULTIARCH=true
fi

# Convert times for all architectures
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

# Generate PR body
cat << EOF
## Summary
This PR has been automatically created after successful completion of all CI stages.
Expand All @@ -61,18 +138,68 @@ cat << EOF
## Test Results

### ✅ Build Stage
- Status: Passed
- Build Time: ${BUILD_TIME_READABLE}
- Total Time: ${TOTAL_TIME_READABLE}
EOF

# Build Stage - conditional formatting
if [ "$MULTIARCH" = true ]; then
cat << EOF

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

cat << EOF

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

### ✅ Boot Verification
- Status: Passed
EOF

# Boot Verification - conditional formatting
if [ "$MULTIARCH" = true ]; then
echo "- Status: Passed (all architectures)"
else
echo "- Status: Passed (${ARCHS[0]})"
fi

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

### ✅ Kernel Selftests
- **Passed:** ${PASSED}
- **Failed:** ${FAILED}
EOF

# Kernel Selftests - conditional formatting
if [ "$MULTIARCH" = true ]; then
cat << EOF

| Architecture | Passed | Failed |
|--------------|---------|--------|
EOF
for arch in "${ARCHS[@]}"; do
echo "| ${arch} | ${ARCH_DATA[${arch}_passed]} | ${ARCH_DATA[${arch}_failed]} |"
done
else
ARCH1="${ARCHS[0]}"
cat << EOF
(${ARCH1})
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

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

In the single-architecture case, the selftest section prints the architecture as a standalone parenthesized line ((${ARCH1})) without a bullet, and with an extra leading space. This renders oddly in Markdown; consider formatting it consistently with the build stage (e.g., include the arch in the status line or as a bullet).

Suggested change
(${ARCH1})
- **Architecture:** ${ARCH1}

Copilot uses AI. Check for mistakes.
- **Passed:** ${ARCH_DATA[${ARCH1}_passed]}
- **Failed:** ${ARCH_DATA[${ARCH1}_failed]}
EOF
fi

cat << EOF

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

${COMPARISON_SECTION}
Expand Down
Loading