This is an automated email from the ASF dual-hosted git repository.

roryqi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new f077ce8421 [#12277] fix(ci): Guard cherry-pick conflict PRs with 
title, label, and CI check (#12276)
f077ce8421 is described below

commit f077ce84211fedfa925ae40c1b76dcb8f942e1e6
Author: MaSai <[email protected]>
AuthorDate: Fri Jul 31 09:39:19 2026 +0800

    [#12277] fix(ci): Guard cherry-pick conflict PRs with title, label, and CI 
check (#12276)
    
    ### What changes were proposed in this pull request?
    
    Improve handling of auto cherry-pick PRs that contain unresolved
    conflicts:
    
    1. **CI check** (`.github/workflows/conflict-marker-check.yml`)
       - Fail when a PR/push introduces unresolved git conflict markers
         (`<<<<<<< ` / whole-line `=======` / `>>>>>>> `).
       - Standalone workflow so `build.yml` path filters cannot skip it.
    
    2. **Cherry-pick PR signaling**
    (`.github/workflows/cherry-pick-branch.yml`)
       - On conflict: prefix the PR title with `[DO NOT MERGE]`.
    - On conflict: add a `cherry-pick-conflict` label (created if missing).
       - Keep opening the PR so humans can still resolve conflicts in place.
    
    ### Why are the changes needed?
    
    When auto cherry-pick fails, `cherry-pick-branch.yml` commits conflict
    markers and opens a PR. Today only the PR body says there are conflicts.
    GitHub mergeability stays clean, and existing CI can stay green for
    docs/conf/shell conflicts.
    
    Maintainers asked for clearer signaling (title + label, similar to the
    enterprise conflict flow) plus a CI check so these PRs are hard to merge
    by mistake.
    
    Fix: #12277
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. CI / automation only. No API, configuration, or runtime behaviour
    changes.
    
    ### How was this patch tested?
    
    Locally ran `git diff --check`: commits with conflict markers fail,
    clean commits pass.
    
    ---------
    
    Co-authored-by: Cursor <[email protected]>
---
 .github/workflows/cherry-pick-branch.yml    | 56 ++++++++++++++++----
 .github/workflows/conflict-marker-check.yml | 82 +++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/cherry-pick-branch.yml 
b/.github/workflows/cherry-pick-branch.yml
index e685d6bd0e..3b5aaa8d41 100644
--- a/.github/workflows/cherry-pick-branch.yml
+++ b/.github/workflows/cherry-pick-branch.yml
@@ -39,6 +39,10 @@ jobs:
   cherry-pick:
     runs-on: ubuntu-latest
     name: Cherry-pick to ${{ inputs.target-branch }}
+    permissions:
+      contents: write
+      pull-requests: write
+      issues: write
     steps:
       - name: Checkout
         uses: actions/checkout@v4
@@ -99,7 +103,8 @@ jobs:
         run: |
           # Use original commit message with branch prefix
           TITLE="[Cherry-pick to ${TARGET_BRANCH}] ${COMMIT_MESSAGE}"
-          
+          LABELS=(cherry-pick)
+
           # Prepare body with cherry-pick info
           if [ "${SUCCESS}" = "true" ]; then
             BODY=$(cat <<'EOF'
@@ -110,25 +115,54 @@ jobs:
           EOF
           )
           else
+            # Make conflicts visible in the PR list (title + label), not only 
in the body.
+            TITLE="[DO NOT MERGE] ${TITLE}"
+            LABELS+=(cherry-pick-conflict)
+
             BODY=$(cat <<'EOF'
           **Cherry-pick Information:**
           - Original commit: ${COMMIT_SHA}
           - Target branch: `${TARGET_BRANCH}`
           - Status: ⚠️ **Has conflicts - manual resolution required**
-          
+
+          **Do not merge** until conflict markers are resolved and the
+          `cherry-pick-conflict` label is removed.
+
           Please review and resolve the conflicts before merging.
           EOF
           )
           fi
-          
+
           # Replace placeholders with actual values
           BODY="${BODY//\$\{COMMIT_SHA\}/${COMMIT_SHA}}"
           BODY="${BODY//\$\{TARGET_BRANCH\}/${TARGET_BRANCH}}"
-          
-          gh pr create \
-            --title "$TITLE" \
-            --body "$BODY" \
-            --base ${{ inputs.target-branch }} \
-            --head ${{ steps.cherry-pick.outputs.branch-name }} \
-            --label cherry-pick \
-            --reviewer jerryshao || echo "Failed to create PR, may already 
exist"
+
+          # Ensure labels exist (forks may not have them yet).
+          gh label create cherry-pick \
+            --description "Automatically opened cherry-pick PR" \
+            --color 1D76DB \
+            --force >/dev/null 2>&1 || true
+          if [ "${SUCCESS}" != "true" ]; then
+            gh label create cherry-pick-conflict \
+              --description "Cherry-pick has conflicts; needs human resolution 
before merge" \
+              --color B60205 \
+              --force >/dev/null 2>&1 || true
+          fi
+
+          LABEL_ARGS=()
+          for label in "${LABELS[@]}"; do
+            LABEL_ARGS+=(--label "$label")
+          done
+
+          CREATE_ARGS=(
+            --title "$TITLE"
+            --body "$BODY"
+            --base "${{ inputs.target-branch }}"
+            --head "${{ steps.cherry-pick.outputs.branch-name }}"
+            "${LABEL_ARGS[@]}"
+          )
+          # Reviewer is only valid on apache/gravitino.
+          if [ "${{ github.repository }}" = "apache/gravitino" ]; then
+            CREATE_ARGS+=(--reviewer jerryshao)
+          fi
+          gh pr create "${CREATE_ARGS[@]}" || echo "Failed to create PR, may 
already exist"
diff --git a/.github/workflows/conflict-marker-check.yml 
b/.github/workflows/conflict-marker-check.yml
new file mode 100644
index 0000000000..7b14e9cc7b
--- /dev/null
+++ b/.github/workflows/conflict-marker-check.yml
@@ -0,0 +1,82 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+name: Conflict Marker Check
+
+# Standalone workflow so path filters on build.yml cannot skip this check.
+# Catches cherry-pick / sync PRs that commit unresolved git conflict markers.
+on:
+  pull_request:
+    branches: ["main", "branch-*"]
+  push:
+    branches: ["main", "branch-*"]
+
+permissions:
+  contents: read
+
+concurrency:
+  group: conflict-marker-check-${{ github.event.pull_request.number || 
github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  conflict-marker-check:
+    name: conflict-marker-check
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Fail if unresolved git conflict markers are introduced
+        run: |
+          set -euo pipefail
+
+          if [ "${{ github.event_name }}" = "pull_request" ]; then
+            BASE_SHA="${{ github.event.pull_request.base.sha }}"
+            HEAD_SHA="${{ github.event.pull_request.head.sha }}"
+          else
+            BASE_SHA="${{ github.event.before }}"
+            HEAD_SHA="${{ github.sha }}"
+            # First push / force-push edge case: before may be all zeros.
+            if [ -z "${BASE_SHA}" ] || [[ "${BASE_SHA}" =~ ^0+$ ]]; then
+              BASE_SHA="$(git rev-parse "${HEAD_SHA}^")"
+            fi
+          fi
+
+          echo "Checking range ${BASE_SHA}...${HEAD_SHA}"
+
+          # git's built-in check for conflict markers introduced in the diff.
+          git diff --check "${BASE_SHA}...${HEAD_SHA}"
+
+          # Explicit line-start scan on changed files (======= must be a whole 
line).
+          failed=0
+          while IFS= read -r f; do
+            [ -f "$f" ] || continue
+            if grep -nE '^(<<<<<<< |>>>>>>> |=======$)' "$f"; then
+              echo "::error file=${f}::Unresolved conflict markers remain in 
${f}"
+              failed=1
+            fi
+          done < <(git diff --name-only --diff-filter=ACMR 
"${BASE_SHA}...${HEAD_SHA}")
+
+          if [ "${failed}" -ne 0 ]; then
+            echo "Unresolved git conflict markers found. Resolve them before 
merging."
+            exit 1
+          fi
+
+          echo "No unresolved conflict markers found."

Reply via email to