Skip to content

Commit

Permalink
Add cherry pick CI workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
ImJeremyHe committed Dec 12, 2024
1 parent 9350aa5 commit 2045b0f
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 0 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/cherry-pick-to-celestia.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Cherry-pick commits and open PR

on:
pull_request:
branches:
- integration
types:
- closed
workflow_dispatch:
inputs:
mode:
description: "Choose operation mode: 'reset' to start fresh, 'continue' to resume from existing branch"
required: true
default: "continue"

jobs:
cherry-pick-and-create-pr:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Fetch all branches
run: git fetch --all

- name: Check if PR already exists
id: check-pr
uses: actions/github-script@v6
with:
script: |
const { data: pulls } = await github.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
head: `${context.repo.owner}:cherry-pick-integration-celestia`
});
if (pulls.length > 0) {
core.setOutput('pr_exists', 'true');
core.setOutput('pr_url', pulls[0].html_url);
} else {
core.setOutput('pr_exists', 'false');
}
- name: Run Cherry-pick Script in reset mode
if: github.event_name == 'pull_request' && github.event.pull_request.merged == true && steps.check-pr.outputs.pr_exists == 'false'
run: |
./scripts/cherry-pick-integration.sh reset
- name: Run Cherry-pick Script in continue mode
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && steps.check-pr.outputs.pr_exists == 'false')
run: |
./scripts/cherry-pick-integration.sh continue
- name: Log existing PR
if: steps.check-pr.outputs.pr_exists == 'true'
run: |
echo "A PR already exists: ${{ steps.check-pr.outputs.pr_url }}. No new PR will be created."
124 changes: 124 additions & 0 deletions scripts/cherry-pick-to-celestia.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#!/usr/bin/env bash

# A script to automate the cherry-picking of commits from the "integration" branch
# into the "celestia-integration" branch with support for conflict resolution.
#
# USAGE:
# ./cherry-pick-integration.sh [MODE]
#
# PARAMETERS:
# MODE:
# - reset:
# - Deletes the existing "cherry-pick-integration-celestia" branch (if it exists).
# - Recreates the branch from the "celestia-integration" branch.
# - Starts cherry-picking commits from the "integration" branch from the beginning.
# - continue:
# - Resumes from the current state of the "cherry-pick-integration-celestia" branch.
# - Skips commits that have already been cherry-picked or resolved.
# - Continues with unprocessed commits.
#
# PROCESS:
# 1. Fetches the latest updates from the remote repository for both branches.
# 2. Depending on the MODE:
# - In "reset" mode:
# - Deletes and recreates the branch "cherry-pick-integration-celestia".
# - In "continue" mode:
# - Uses the existing "cherry-pick-integration-celestia" branch or creates it if missing.
# 3. Cherry-picks all new commits from the "integration" branch to the target branch:
# - Skips already cherry-picked commits by checking commit logs.
# - Pushes unresolved conflicts to the branch for manual resolution.
# - If no conflicts occur, pushes the updated branch automatically.
# 4. Exits with a non-zero status if conflicts are encountered.
#
# ERROR HANDLING:
# - If a conflict occurs during cherry-pick, the script:
# - Aborts the current cherry-pick operation.
# - Stages the conflict state and pushes it to the branch for manual resolution.
# - Exits with an error message instructing the user to resolve the conflicts.
#
# EXAMPLES:
# 1. Start fresh and reapply all commits:
# ./cherry-pick-to-celestia.sh reset
#
# 2. Continue cherry-picking from where it left off:
# ./cherry-pick-to-celestia.sh continue
#

set -e

MODE=$1
BRANCH_NAME="cherry-pick-integration-celestia"
INTEGRATION_BRANCH="integration"
TARGET_BRANCH="celestia-integration"

function is_commit_processed() {
local commit=$1
local marker="Cherry-picked from commit $commit"
git log $BRANCH_NAME --grep="$marker" -q
}

function init_branch() {
if [ "$MODE" == "reset" ]; then
echo "Reset mode: Re-creating branch $BRANCH_NAME from $TARGET_BRANCH"
git branch -D $BRANCH_NAME || echo "Branch $BRANCH_NAME does not exist locally. Skipping deletion."
git checkout origin/$TARGET_BRANCH
git checkout -B $BRANCH_NAME
git push --set-upstream origin $BRANCH_NAME
elif [ "$MODE" == "continue" ]; then
echo "Continue mode: Reusing existing branch $BRANCH_NAME"
git checkout $BRANCH_NAME || {
echo "Branch $BRANCH_NAME does not exist locally. Creating from $TARGET_BRANCH."
git checkout origin/$TARGET_BRANCH
git checkout -B $BRANCH_NAME
}
else
echo "Invalid mode. Use 'reset' or 'continue'."
exit 1
fi
}

function cherry_pick_commits() {
echo "Fetching latest commits from $INTEGRATION_BRANCH and $TARGET_BRANCH"
git fetch origin $INTEGRATION_BRANCH $TARGET_BRANCH

local last_merged_commit=$(git log -1 --pretty=format:"%H" origin/$INTEGRATION_BRANCH)
local pr_commits=$(git log origin/$TARGET_BRANCH..$last_merged_commit --pretty=format:"%H" --)

echo "Cherry-picking commits from $INTEGRATION_BRANCH to $BRANCH_NAME"
for commit in $pr_commits; do
if is_commit_processed $commit; then
echo "Commit $commit already processed. Skipping."
continue
fi

echo "Cherry-picking commit $commit"
if ! git cherry-pick $commit; then
echo "Conflict detected during cherry-pick of $commit."
git status
git cherry-pick --abort

echo "Saving conflict state for manual resolution."
git add .
git commit -m "WIP: Resolve conflicts from cherry-pick of $commit (Cherry-picked from commit $commit)" || echo "No changes to commit."
git push --force origin $BRANCH_NAME

echo "Conflicts pushed to branch $BRANCH_NAME. Exiting for manual resolution."
echo "Don't reset any commit and please resolve conflicts directly. Use \`git commit --amend --no-edit\` after resolving"
exit 1
fi

git commit --amend -m "$(git log -1 --pretty=%B)$'\n\n'Cherry-picked from commit $commit"
done

git push --force origin $BRANCH_NAME
}

function main() {
echo "Running Cherry-pick Script with MODE=$MODE"
init_branch
cherry_pick_commits
echo "Cherry-pick completed successfully."
}

main

0 comments on commit 2045b0f

Please sign in to comment.