Skip to content

github-actions: Add LT rebase merge automation workflow#922

Open
bmastbergen wants to merge 1 commit intomainfrom
{bmastbergen}_clk-rebase-ltrm
Open

github-actions: Add LT rebase merge automation workflow#922
bmastbergen wants to merge 1 commit intomainfrom
{bmastbergen}_clk-rebase-ltrm

Conversation

@bmastbergen
Copy link
Collaborator

Introduce automated workflow for merging CLK PRs using the lt_rebase_merge process. The workflow can be triggered via /lt_rebase_merge comment on PRs or manual workflow dispatch.

Key features:

  • Validates PR has at least 2 approvals before merging
  • Verifies commenter has write/admin permissions
  • Extracts LT version from branch name (ciq-X.Y.y pattern)
  • Validates PR target branch matches expected -next branch
  • Executes lt_rebase_merge.sh script from kernel-src-tree-tools
  • Posts success/failure comment on PR with workflow run link

I've tested the workflow logic with manual dispatch to merge the last couple of CLK rebase PRs:
#903
#902

Unfortunately the comment trigger can't be tested until the workflow is on the main branch. So I'll have to test it on the next automatically generated CLK rebase PRs after this PR is merged.

@bmastbergen bmastbergen requested a review from a team February 25, 2026 19:11
Copilot AI review requested due to automatic review settings February 25, 2026 19:11
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an automated workflow for merging CLK (Custom Linux Kernel) PRs using the lt_rebase_merge process from the kernel-src-tree-tools repository. The workflow can be triggered either via a /lt_rebase_merge comment on PRs (by users with write/admin permissions) or through manual workflow dispatch. It validates that PRs have at least 2 approvals, extracts the LT version from the branch name, validates the target branch, and executes the merge script.

Changes:

  • Added new GitHub Actions workflow for LT rebase merge automation with comment-based and manual triggers
  • Implements permission checks, approval validation, version extraction, and branch validation
  • Posts success/failure comments on PRs with workflow run links

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 211 to 218
if [ "$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."
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The LT_VERSION environment variable is referenced in the comment step (lines 214 and 218) but may not be set if the "Extract LT version from PR" step fails. Since the comment step uses "if: always()", it will run even when earlier steps fail. Consider adding a check to use a default message when LT_VERSION is not set, or use a conditional to only include the version in the message when it's available.

Suggested change
if [ "$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."
# Derive a label for LT that is safe even if LT_VERSION is unset
if [ -n "${LT_VERSION:-}" ]; then
LT_LABEL="LT $LT_VERSION"
else
LT_LABEL="LT"
fi
if [ "$JOB_STATUS" == "success" ]; then
EMOJI="✅"
TITLE="LT Rebase Merge completed successfully"
MESSAGE="Successfully completed $LT_LABEL rebase merge"
else
EMOJI="❌"
TITLE="LT Rebase Merge failed"
MESSAGE="Failed to complete $LT_LABEL rebase merge. Please check the workflow run for details."

Copilot uses AI. Check for mistakes.
Comment on lines 71 to 77
PR_NUMBER: ${{ github.event_name == 'workflow_dispatch' && inputs.pr_number || github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
run: |
set -e

# Get PR details
PR_DATA=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json number,headRefName,baseRefName,title,reviews)
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The PR_NUMBER and REPOSITORY variables should be validated before use, following the defense-in-depth security pattern used in validate-kernel-commits-comment.yml. Even though these values come from GitHub Actions context (github.event.issue.number, github.repository) or typed inputs (type: number), validating them with regex patterns and range checks provides an additional security layer. PR_NUMBER should be validated as a positive integer within a reasonable range, and REPOSITORY should match the owner/repo format with length checks.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I litterally don't know what this is talking about these checks exist?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

They didn't exist when this comment was made, but do now. I'm not sure why this copilot comment isn't marked as outdated like the others. I probably should have marked it as resolved anyways.

Comment on lines 88 to 89
# Count approvals
APPROVALS=$(echo "$PR_DATA" | jq '[.reviews[] | select(.state == "APPROVED")] | length')
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The approval counting logic counts all reviews with state "APPROVED", which may not accurately reflect the current approval state. If a reviewer approves and then later submits a "CHANGES_REQUESTED" or "COMMENTED" review, both reviews are returned by the API. The jq filter should group reviews by author and only count the most recent review state from each unique reviewer. This prevents overcounting approvals and ensures only the latest review state from each reviewer is considered.

Suggested change
# Count approvals
APPROVALS=$(echo "$PR_DATA" | jq '[.reviews[] | select(.state == "APPROVED")] | length')
# 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')

Copilot uses AI. Check for mistakes.
Comment on lines 79 to 87
# Extract branch names
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')

echo "HEAD_BRANCH=$HEAD_BRANCH" >> $GITHUB_ENV
echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV

Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

Branch names extracted from the GitHub API (HEAD_BRANCH and BASE_BRANCH) should be validated before being stored in GITHUB_ENV and used in subsequent steps. Consider adding validation similar to the pattern used in validate-kernel-commits-comment.yml (lines 98-108), which validates branch names against a regex pattern and checks length limits. This prevents potential command injection if the API returns unexpected values or if the repository is compromised.

Suggested change
# Extract branch names
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
echo "HEAD_BRANCH=$HEAD_BRANCH" >> $GITHUB_ENV
echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV
# 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 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}" -gt "$MAX_BRANCH_LENGTH" ]; then
echo "❌ $BR_VAR is too long (>${MAX_BRANCH_LENGTH} characters), aborting."
exit 1
fi
if ! [[ "$BR_VALUE" =~ $BRANCH_REGEX ]]; then
echo "❌ $BR_VAR contains invalid characters, aborting."
exit 1
fi
done
# Sanitize PR title to avoid breaking GITHUB_ENV (remove newlines)
PR_TITLE_CLEAN=$(printf '%s' "$PR_TITLE" | tr '\n\r' ' ')
echo "HEAD_BRANCH=$HEAD_BRANCH" >> "$GITHUB_ENV"
echo "BASE_BRANCH=$BASE_BRANCH" >> "$GITHUB_ENV"
echo "PR_TITLE=$PR_TITLE_CLEAN" >> "$GITHUB_ENV"

Copilot uses AI. Check for mistakes.
Comment on lines 77 to 86
PR_DATA=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json number,headRefName,baseRefName,title,reviews)

# Extract branch names
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')

echo "HEAD_BRANCH=$HEAD_BRANCH" >> $GITHUB_ENV
echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

The PR_TITLE variable is extracted and stored in GITHUB_ENV but is never used in the workflow. Consider removing line 82 (extraction) and line 86 (storage) to simplify the code and reduce unnecessary API data retrieval.

Suggested change
PR_DATA=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json number,headRefName,baseRefName,title,reviews)
# Extract branch names
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
PR_TITLE=$(echo "$PR_DATA" | jq -r '.title')
echo "HEAD_BRANCH=$HEAD_BRANCH" >> $GITHUB_ENV
echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV
PR_DATA=$(gh pr view "$PR_NUMBER" --repo "$REPOSITORY" --json number,headRefName,baseRefName,reviews)
# Extract branch names
HEAD_BRANCH=$(echo "$PR_DATA" | jq -r '.headRefName')
BASE_BRANCH=$(echo "$PR_DATA" | jq -r '.baseRefName')
echo "HEAD_BRANCH=$HEAD_BRANCH" >> $GITHUB_ENV
echo "BASE_BRANCH=$BASE_BRANCH" >> $GITHUB_ENV

Copilot uses AI. Check for mistakes.
@bmastbergen
Copy link
Collaborator Author

There is some decent copilot feedback here. Working through it.

Introduce automated workflow for merging CLK PRs using the lt_rebase_merge
process. The workflow can be triggered via /lt_rebase_merge comment on PRs
or manual workflow dispatch.

Key features:
- Validates PR has at least 2 approvals before merging
- Verifies commenter has write/admin permissions
- Extracts LT version from branch name (ciq-X.Y.y pattern)
- Validates PR target branch matches expected -next branch
- Executes lt_rebase_merge.sh script from kernel-src-tree-tools
- Posts success/failure comment on PR with workflow run link
@bmastbergen bmastbergen force-pushed the {bmastbergen}_clk-rebase-ltrm branch from 7e64e46 to ab74bfe Compare February 25, 2026 20:28
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_ENV

# Count approvals based on the latest review state per reviewer
APPROVALS=$(echo "$PR_DATA" | jq '[.reviews
Copy link
Collaborator

Choose a reason for hiding this comment

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

right now this is mostly just us doing the reviews and approval we may want to take note that it requires x number of 'code owners'

This is non-blocking but something we have to be careful about.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yea, good call. I focused more on the comentor having the correct permissions, but some amount of approver validation would be good too

Copy link
Collaborator

Choose a reason for hiding this comment

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

thats a fair counter point, we shouldn't be adding that a comment unless we also have validated it.

Copy link
Collaborator

@PlaidCat PlaidCat left a comment

Choose a reason for hiding this comment

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

:shipit:

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