Skip to content
Merged
238 changes: 238 additions & 0 deletions .github/workflows/validate-kernel-commits.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
name: Validate Kernel Commits

on:
workflow_call:
# No inputs needed - uses github context from caller

permissions:
contents: read
pull-requests: write

jobs:
validate-kernel-commits:
runs-on: ubuntu-latest
timeout-minutes: 120

steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.head_ref }}

- name: Checkout base branch
run: |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }}

- name: Checkout kernel-src-tree-tools
uses: actions/checkout@v4
with:
repository: ctrliq/kernel-src-tree-tools
ref: 'mainline'
path: kernel-src-tree-tools

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'

- name: Run upstream fixes check
id: check-kernel-commits
working-directory: kernel-src-tree-tools
run: |
set +e # Don't exit on error, we want to capture the output
set -o pipefail # Capture exit code from python script, not tee
python3 check_kernel_commits.py \
--repo .. \
--pr_branch "${{ github.head_ref }}" \
--base_branch "${{ github.base_ref }}" \
--markdown \
--check-cves | tee ../ckc_result.txt
EXIT_CODE=$?

# Check if the script failed
if [ $EXIT_CODE -ne 0 ]; then
echo "❌ Kernel commits check failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi

# Check for findings:
# 1. Verify the success message exists
# 2. If it exists, check if there are any OTHER lines (which would indicate issues)
# 3. If success message doesn't exist, that's also a finding
if grep -q "All referenced commits exist upstream and have no Fixes: tags." ../ckc_result.txt; then
# Success message found, check if there are any other lines
LINE_COUNT=$(wc -l < ../ckc_result.txt)
if [ "$LINE_COUNT" -gt 1 ]; then
echo "has_findings=true" >> $GITHUB_OUTPUT
else
echo "has_findings=false" >> $GITHUB_OUTPUT
fi
else
# Success message not found, there must be findings
echo "has_findings=true" >> $GITHUB_OUTPUT
fi

set -e # Re-enable exit on error

- name: Comment on PR if issues found
if: steps.check-kernel-commits.outputs.has_findings == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
if ! gh pr comment ${{ github.event.pull_request.number }} \
--body-file ckc_result.txt \
--repo ${{ github.repository }}; then
echo "❌ Failed to post check-kernel-commits comment to PR"
exit 1
fi

- name: Install build dependencies for patchutils
run: |
sudo apt-get update
sudo apt-get install -y build-essential autoconf automake libtool gnulib

- name: Clone and build custom patchutils
run: |
git clone https://github.com/kerneltoast/patchutils.git --depth=1 --revision=32e5f1df96920f1d24beb910346f01acab8b0bd8
cd patchutils
./bootstrap
./configure
make -j$(nproc)

- name: Run interdiff check
id: interdiff
working-directory: kernel-src-tree-tools
run: |
set +e # Don't exit on error, we want to capture the output
set -o pipefail # Capture exit code from python script, not tee
python3 run_interdiff.py \
--repo .. \
--pr_branch "${{ github.head_ref }}" \
--base_branch "${{ github.base_ref }}" \
--markdown \
--interdiff ../patchutils/src/interdiff | tee ../interdiff_result.txt
EXIT_CODE=$?

# Check if the script failed
if [ $EXIT_CODE -ne 0 ]; then
echo "❌ Interdiff check failed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi

# Check for differences:
# 1. Verify the success message exists
# 2. If it exists, check if there are any OTHER lines (which would indicate differences)
# 3. If success message doesn't exist, that's also a difference
if grep -q "All backported commits match their upstream counterparts." ../interdiff_result.txt; then
# Success message found, check if there are any other lines
LINE_COUNT=$(wc -l < ../interdiff_result.txt)
if [ "$LINE_COUNT" -gt 1 ]; then
echo "has_differences=true" >> $GITHUB_OUTPUT
else
echo "has_differences=false" >> $GITHUB_OUTPUT
fi
else
# Success message not found, there must be differences
echo "has_differences=true" >> $GITHUB_OUTPUT
fi

set -e # Re-enable exit on error

- name: Comment on PR if interdiff differences found
if: steps.interdiff.outputs.has_differences == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
if ! gh pr comment ${{ github.event.pull_request.number }} \
--body-file interdiff_result.txt \
--repo ${{ github.repository }}; then
echo "❌ Failed to post interdiff comment to PR"
exit 1
fi

- name: Install JIRA PR Check dependencies
run: |
python -m pip install --upgrade pip
pip install jira

- name: Mask JIRA credentials
run: |
echo "::add-mask::${{ secrets.JIRA_API_TOKEN }}"
echo "::add-mask::${{ secrets.JIRA_API_USER }}"
echo "::add-mask::${{ secrets.JIRA_URL }}"

- name: Run JIRA PR Check
id: jira_check
continue-on-error: true # Allow PR comments to be posted before failing workflow
env:
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
JIRA_API_USER: ${{ secrets.JIRA_API_USER }}
JIRA_URL: ${{ secrets.JIRA_URL }}
working-directory: kernel-src-tree-tools
run: |
# Run script and capture output, ensuring credentials are never echoed
set +x # Disable command echo to prevent credential exposure
set +e # Don't exit on error, we want to capture the output
OUTPUT=$(python3 jira_pr_check.py \
--kernel-src-tree .. \
--merge-target ${{ github.base_ref }} \
--pr-branch ${{ github.head_ref }} 2>&1)
EXIT_CODE=$?

# Filter out any potential credential leaks from output
FILTERED_OUTPUT=$(echo "$OUTPUT" | grep -v "jira-user\|jira-key\|basic_auth\|Authorization\|$JIRA_API_TOKEN")

echo "$FILTERED_OUTPUT"
echo "output<<'EOF'" >> $GITHUB_OUTPUT
echo "$FILTERED_OUTPUT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Check if there are any issues based on output patterns
if echo "$FILTERED_OUTPUT" | grep -q "❌ Errors:"; then
echo "has_issues=true" >> $GITHUB_OUTPUT

# Check specifically for LTS mismatch errors
if echo "$FILTERED_OUTPUT" | grep -q "expects branch"; then
echo "has_lts_mismatch=true" >> $GITHUB_OUTPUT
else
echo "has_lts_mismatch=false" >> $GITHUB_OUTPUT
fi
elif echo "$FILTERED_OUTPUT" | grep -q "⚠️ Warnings:"; then
echo "has_issues=true" >> $GITHUB_OUTPUT
echo "has_lts_mismatch=false" >> $GITHUB_OUTPUT
else
echo "has_issues=false" >> $GITHUB_OUTPUT
echo "has_lts_mismatch=false" >> $GITHUB_OUTPUT
fi

# Exit with the script's exit code
exit $EXIT_CODE

- name: Comment PR with JIRA issues
if: steps.jira_check.outputs.has_issues == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
if ! gh pr comment ${{ github.event.pull_request.number }} \
--body "${{ steps.jira_check.outputs.output }}" \
--repo ${{ github.repository }}; then
echo "❌ Failed to post JIRA check comment to PR"
exit 1
fi

- name: Request changes if LTS mismatch
if: steps.jira_check.outputs.has_lts_mismatch == 'true'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr review ${{ github.event.pull_request.number }} \
--request-changes \
--body "⚠️ This PR contains VULN tickets that do not match the target LTS product. Please review the JIRA ticket assignments and ensure they match the merge target branch." \
--repo ${{ github.repository }}

- name: Fail workflow if JIRA errors found
if: steps.jira_check.outcome == 'failure'
run: |
echo "❌ JIRA PR check failed - errors were found in one or more commits"
exit 1