50 lines
1.7 KiB
YAML
50 lines
1.7 KiB
YAML
name: Require Cherry-pick to release/*
|
||
on:
|
||
pull_request:
|
||
branches: ['release/**']
|
||
types: [opened, synchronize, reopened]
|
||
|
||
jobs:
|
||
verify:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Checkout PR HEAD with history
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- name: Fetch main
|
||
run: git fetch origin main --quiet
|
||
|
||
- name: Get PR commit SHAs (base..head)
|
||
id: list
|
||
run: |
|
||
echo "COMMITS=$(git log --format=%H origin/${{ github.base_ref }}..HEAD | tr '\n' ' ')" >> $GITHUB_OUTPUT
|
||
|
||
- name: Verify each commit is a cherry-pick from main
|
||
run: |
|
||
set -euo pipefail
|
||
for C in ${{ steps.list.outputs.COMMITS }}; do
|
||
MSG="$(git log -1 --pretty=%B "$C")"
|
||
echo "Checking $C"
|
||
|
||
# 1) 必须含有 -x 生成的 trailer
|
||
if ! echo "$MSG" | grep -qiE 'cherry picked from commit [0-9a-f]{7,40}'; then
|
||
echo "::error::Commit $C lacks 'cherry picked from commit <SHA>' (use 'git cherry-pick -x')."
|
||
exit 1
|
||
fi
|
||
|
||
# 2) 取出来源 SHA
|
||
ORIG=$(printf "%s" "$MSG" | sed -nE 's/.*cherry picked from commit ([0-9a-f]{7,40}).*/\1/ip' | head -n1 | tr -d '[:space:]')
|
||
if [ -z "$ORIG" ]; then
|
||
echo "::error::Cannot parse original commit SHA from $C message."
|
||
exit 1
|
||
fi
|
||
|
||
# 3) 来源必须在 main 上(backport/forward-port 均可换成目标分支)
|
||
if ! git merge-base --is-ancestor "$ORIG" origin/main; then
|
||
echo "::error::Original commit $ORIG not found on origin/main."
|
||
exit 1
|
||
fi
|
||
done
|