Skip to content

[CLK] Embed dist-git in source branch #24

[CLK] Embed dist-git in source branch

[CLK] Embed dist-git in source branch #24

name: LT Rebase Merge
on:
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to merge'
required: true
type: number
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
jobs:
lt-rebase-merge:
# Only run on PRs when comment starts with /lt_rebase_merge, or when manually dispatched
if: |
github.event_name == 'workflow_dispatch' ||
(github.event.issue.pull_request && startsWith(github.event.comment.body, '/lt_rebase_merge'))
runs-on: ubuntu-latest
container:
image: rockylinux:9
steps:
- name: Generate GitHub App token
id: generate-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
repositories: |
kernel-src-tree
kernel-src-tree-tools
- name: Install system dependencies
run: |
dnf install -y git jq
# Install GitHub CLI
dnf install 'dnf-command(config-manager)' -y
dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
dnf install gh -y
- name: Validate commenter has write access
if: github.event_name == 'issue_comment'
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
COMMENTER: ${{ github.event.comment.user.login }}
REPOSITORY: ${{ github.repository }}
run: |
set -e
# Check if commenter has write or admin permission on the repository
PERMISSION=$(gh api "/repos/$REPOSITORY/collaborators/$COMMENTER/permission" --jq '.permission' 2>/dev/null || echo "none")
echo "User $COMMENTER has permission level: $PERMISSION"
if [[ "$PERMISSION" == "admin" || "$PERMISSION" == "write" ]]; then
echo "✅ User $COMMENTER has sufficient permissions"
else
echo "❌ User $COMMENTER does not have write or admin access to $REPOSITORY"
echo "Only users with write or admin access can trigger lt_rebase_merge"
exit 1
fi
- name: Get PR details and verify approvals
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
run: |
set -e
# Validate PR number is actually a number
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "❌ Security: Invalid PR number format: $PR_NUMBER"
exit 1
fi
# Validate PR number is reasonable (1 to 7 digits)
if [ "$PR_NUMBER" -lt 1 ] || [ "$PR_NUMBER" -gt 9999999 ]; then
echo "❌ Security: PR number out of range: $PR_NUMBER"
exit 1
fi
# Validate repository format (owner/repo)
if ! [[ "$REPOSITORY" =~ ^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$ ]]; then
echo "❌ Security: Invalid repository format: $REPOSITORY"
exit 1
fi
# Validate repository name length
if [ ${#REPOSITORY} -gt 100 ]; then
echo "❌ Security: Repository name too long"
exit 1
fi
echo "✅ All input validation passed"
# Get PR details
PR_DATA=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json number,headRefName,baseRefName,title,reviews)
# Extract branch names and PR title
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
# Validate PR title to prevent injection via GITHUB_ENV
if [ ${#PR_TITLE} -gt 500 ]; then
echo "❌ Security: PR title too long (${#PR_TITLE} > 500)"
exit 1
fi
# Validate branch names to prevent injection via GITHUB_ENV
BRANCH_REGEX='^[a-zA-Z0-9/_.{}-]+$'
MAX_BRANCH_LENGTH=255
for BR_VAR in HEAD_BRANCH BASE_BRANCH; do
BR_VALUE=${!BR_VAR}
if [ -z "$BR_VALUE" ]; then
echo "❌ $BR_VAR is empty, aborting."
exit 1
fi
if ! [[ "$BR_VALUE" =~ $BRANCH_REGEX ]]; then
echo "❌ Security: Invalid branch name in $BR_VAR: $BR_VALUE"
exit 1
fi
if [ ${#BR_VALUE} -gt $MAX_BRANCH_LENGTH ]; then
echo "❌ Security: Branch name in $BR_VAR too long (${#BR_VALUE} > $MAX_BRANCH_LENGTH)"
exit 1
fi
done
echo "✅ Branch name validation passed"
echo "HEAD_BRANCH=$HEAD_BRANCH" >> $GITHUB_ENV
echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV
# Count approvals based on the latest review state per reviewer
APPROVALS=$(echo "$PR_DATA" | jq '[.reviews
| sort_by(.author.login, .submittedAt)
| group_by(.author.login)[]
| last
| select(.state == "APPROVED")
] | length')
echo "PR #$PR_NUMBER has $APPROVALS approvals"
if [ "$APPROVALS" -lt 2 ]; then
echo "❌ PR requires at least 2 approvals to merge. Current approvals: $APPROVALS"
exit 1
fi
echo "✅ PR has sufficient approvals ($APPROVALS)"
- name: Extract LT version from PR
run: |
set -e
# Extract version from head branch name
# Expected patterns: {automation_tmp}_ciq-6.XX.y-next or similar
if [[ "$HEAD_BRANCH" =~ ciq-([0-9]+)\.([0-9]+)\.y ]]; then
LT_MAJOR="${BASH_REMATCH[1]}"
LT_MINOR="${BASH_REMATCH[2]}"
echo "Extracted version from branch: $LT_MAJOR.$LT_MINOR"
else
echo "❌ Could not extract LT version from branch name '$HEAD_BRANCH'"
echo "Branch name must match pattern: ciq-X.Y.y"
exit 1
fi
echo "LT_MAJOR=$LT_MAJOR" >> $GITHUB_ENV
echo "LT_MINOR=$LT_MINOR" >> $GITHUB_ENV
echo "LT_VERSION=$LT_MAJOR.$LT_MINOR" >> $GITHUB_ENV
# Construct branch names
echo "AUTOMATION_TMP_BRANCH={automation_tmp}_ciq-${LT_MAJOR}.${LT_MINOR}.y-next" >> $GITHUB_ENV
echo "NEXT_BRANCH=ciq-${LT_MAJOR}.${LT_MINOR}.y-next" >> $GITHUB_ENV
echo "TARGET_BRANCH=ciq-${LT_MAJOR}.${LT_MINOR}.y" >> $GITHUB_ENV
echo "✅ LT Version: $LT_MAJOR.$LT_MINOR"
- name: Validate PR target branch
run: |
set -e
# Verify BASE_BRANCH matches expected pattern (ciq-X.Y.y-next)
if ! echo "$BASE_BRANCH" | grep -qE '^ciq-[0-9]+\.[0-9]+\.y-next$'; then
echo "❌ PR base branch '$BASE_BRANCH' does not match expected pattern 'ciq-X.Y.y-next'"
exit 1
fi
# Verify BASE_BRANCH matches the version extracted from HEAD_BRANCH
EXPECTED_BASE="ciq-${LT_MAJOR}.${LT_MINOR}.y-next"
if [ "$BASE_BRANCH" != "$EXPECTED_BASE" ]; then
echo "❌ PR base branch '$BASE_BRANCH' does not match expected '$EXPECTED_BASE'"
echo "HEAD_BRANCH version: $LT_MAJOR.$LT_MINOR"
exit 1
fi
echo "✅ PR base branch is correct: $BASE_BRANCH"
- name: Checkout kernel-src-tree
uses: actions/checkout@v4
with:
repository: ctrliq/kernel-src-tree
token: ${{ steps.generate-token.outputs.token }}
path: kernel-src-tree
fetch-depth: 0
persist-credentials: true
- name: Checkout kernel-src-tree-tools
uses: actions/checkout@v4
with:
repository: ctrliq/kernel-src-tree-tools
token: ${{ steps.generate-token.outputs.token }}
path: kernel-src-tree-tools
persist-credentials: true
- name: Configure git
run: |
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
- name: Setup branch references and execute lt_rebase_merge.sh
run: |
set -e
cd kernel-src-tree
# Get local references to the required branches
echo "Fetching required branches..."
for branch in "$AUTOMATION_TMP_BRANCH" "$NEXT_BRANCH" "$TARGET_BRANCH"; do
if ! git fetch origin "$branch:$branch"; then
echo "❌ Failed to fetch branch: $branch"
exit 1
fi
done
echo "✅ Branch references set up"
echo "Branches:"
echo " - Automation Tmp: $AUTOMATION_TMP_BRANCH"
echo " - Next: $NEXT_BRANCH"
echo " - Target: $TARGET_BRANCH"
# Execute the lt_rebase_merge.sh script
echo "Executing lt_rebase_merge.sh..."
if ! OUTPUT=$(../kernel-src-tree-tools/lt_rebase_merge.sh "$AUTOMATION_TMP_BRANCH" "$TARGET_BRANCH" 2>&1); then
echo "❌ lt_rebase_merge.sh failed with output:"
echo "$OUTPUT"
exit 1
fi
echo "✅ lt_rebase_merge.sh completed successfully"
- name: Comment on PR with result
if: always()
env:
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
JOB_STATUS: ${{ job.status }}
run: |
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
if [ -z "${LT_VERSION:-}" ]; then
EMOJI="❌"
TITLE="LT Rebase Merge failed"
MESSAGE="Could not determine LT version, rebase merge aborted. Please check the workflow run for details."
elif [ "$JOB_STATUS" == "success" ]; then
EMOJI="✅"
TITLE="LT Rebase Merge completed successfully"
MESSAGE="Successfully completed LT $LT_VERSION rebase merge"
else
EMOJI="❌"
TITLE="LT Rebase Merge failed"
MESSAGE="Failed to complete LT $LT_VERSION rebase merge. Please check the workflow run for details."
fi
if gh pr comment "$PR_NUMBER" \
--body "$EMOJI **$TITLE**
$MESSAGE
Workflow run: $RUN_URL" \
--repo "$REPOSITORY"; then
echo "✅ Successfully commented on PR #$PR_NUMBER"
else
echo "❌ Failed to comment on PR #$PR_NUMBER"
echo "Comment posting failure is non-fatal, but PR status may not be visible"
fi