|
| 1 | +#!/usr/bin/env bash |
| 2 | +# A script to mirror an external contributor's pull request to a maintainer's fork |
| 3 | +# for the purpose of running E2E tests. |
| 4 | +# |
| 5 | +# Prerequisites: |
| 6 | +# 1. GitHub CLI (`gh`) must be installed and authenticated (`gh auth login`). |
| 7 | +# 2. You must have a fork of the repository. |
| 8 | +# 3. You must have a git remote configured for the upstream repository (e.g., "upstream"). |
| 9 | +# |
| 10 | +# Usage: |
| 11 | +# ./mirror-pr.sh <PR_NUMBER> <FORK_REMOTE> |
| 12 | +# |
| 13 | +# Example: |
| 14 | +# ./mirror-pr.sh 1234 my-github-user |
| 15 | +# |
| 16 | +# if no PR number is provided, it will prompt you to select one using `fzf`. |
| 17 | + |
| 18 | +set -eo pipefail |
| 19 | + |
| 20 | +# --- Prerequisite Check --- |
| 21 | + |
| 22 | +if ! command -v gh &>/dev/null; then |
| 23 | + echo "Error: GitHub CLI ('gh') is not installed. Please install it to continue." |
| 24 | + echo "See: https://cli.github.com/" |
| 25 | + exit 1 |
| 26 | +fi |
| 27 | + |
| 28 | +echo "✅ GitHub CLI is installed." |
| 29 | +# --- Configuration and Argument Parsing --- |
| 30 | + |
| 31 | +PR_NUMBER=$1 |
| 32 | +FORK_REMOTE=${GH_FORK_REMOTE:-$2} |
| 33 | +UPSTREAM_REPO=${GH_UPSTREAM_REPO:-openshift-pipelines/pipelines-as-code} |
| 34 | + |
| 35 | +if [[ -z ${PR_NUMBER} ]]; then |
| 36 | + PR_SELECTION=$(gh pr list --repo "$UPSTREAM_REPO" --json number,title,author --template '{{range .}}{{.number}}: {{.title}} (by {{.author.login}}) |
| 37 | +{{end}}' | fzf --prompt="Select PR: ") |
| 38 | + PR_NUMBER=$(echo "$PR_SELECTION" | awk -F: '{print $1}' | xargs) |
| 39 | +fi |
| 40 | + |
| 41 | +if [[ -z $FORK_REMOTE ]]; then |
| 42 | + FORK_REMOTE=$(git remote | awk '{print $1}' | grep -v origin | sort -u | fzf -1 --prompt="Select fork remote: ") |
| 43 | +fi |
| 44 | + |
| 45 | +if [[ -z "$PR_NUMBER" || -z "$FORK_REMOTE" ]]; then |
| 46 | + echo "Usage: $0 <PR_NUMBER> <YOUR_REMOTE_FORK>" |
| 47 | + echo "Example: $0 1234 openshift-pipelines/pipelines-as-code my-github-user" |
| 48 | + exit 1 |
| 49 | +fi |
| 50 | + |
| 51 | +# --- Main Logic --- |
| 52 | + |
| 53 | +echo "🔄 Fetching details for PR #${PR_NUMBER} from ${UPSTREAM_REPO}..." |
| 54 | + |
| 55 | +# Fetch PR title and author using GitHub CLI |
| 56 | +PR_TITLE=$(gh pr view "$PR_NUMBER" --repo "$UPSTREAM_REPO" --json title -q .title) |
| 57 | +PR_AUTHOR=$(gh pr view "$PR_NUMBER" --repo "$UPSTREAM_REPO" --json author -q .author.login) |
| 58 | +PR_URL="https://github.com/${UPSTREAM_REPO}/pull/${PR_NUMBER}" |
| 59 | + |
| 60 | +if [[ -z "$PR_TITLE" ]]; then |
| 61 | + echo "❌ Error: Could not fetch details for PR #${PR_NUMBER}. Please check the PR number and repository." |
| 62 | + exit 1 |
| 63 | +fi |
| 64 | + |
| 65 | +echo " - Title: $PR_TITLE" |
| 66 | +echo " - Author: $PR_AUTHOR" |
| 67 | + |
| 68 | +# 1. Checkout the PR locally |
| 69 | +echo "🔄 Checking out PR #${PR_NUMBER} locally..." |
| 70 | +gh pr checkout "$PR_NUMBER" --repo "$UPSTREAM_REPO" |
| 71 | + |
| 72 | +# 2. Push the branch to your fork |
| 73 | +NEW_BRANCH_NAME="test-pr-${PR_NUMBER}-${PR_AUTHOR}" |
| 74 | + |
| 75 | +echo "🔄 Pushing changes to a new branch '${NEW_BRANCH_NAME}' on your fork (${FORK_REMOTE})..." |
| 76 | +# Force push in case the branch already exists from a previous test run |
| 77 | +git push "$FORK_REMOTE" "HEAD:${NEW_BRANCH_NAME}" -f |
| 78 | + |
| 79 | +# 3. Create a new Pull Request from the fork to the upstream repo |
| 80 | +MIRRORED_PR_TITLE="[MIRRORED] DO NOT MERGE: ${PR_TITLE}" |
| 81 | +MIRRORED_PR_BODY="Mirrors ${PR_URL} to run E2E tests. Original author: @${PR_AUTHOR}" |
| 82 | +DO_NOT_MERGE_LABEL="do-not-merge" # You might need to create this label in your repo if it doesn't exist |
| 83 | + |
| 84 | +echo "🔄 Creating a new mirrored pull request on ${UPSTREAM_REPO}..." |
| 85 | + |
| 86 | +# Create the PR as a draft to prevent accidental merges before tests run. |
| 87 | +# The --head flag specifies the branch in your fork. |
| 88 | +CREATED_PR_URL=$(gh pr create \ |
| 89 | + --repo "$UPSTREAM_REPO" \ |
| 90 | + --title "$MIRRORED_PR_TITLE" \ |
| 91 | + --body "$MIRRORED_PR_BODY" \ |
| 92 | + --head "${FORK_REMOTE}:${NEW_BRANCH_NAME}" \ |
| 93 | + --label "$DO_NOT_MERGE_LABEL" \ |
| 94 | + --draft) # Using --draft is safer |
| 95 | + |
| 96 | +# Check if the PR was created successfully |
| 97 | +if [[ -z "$CREATED_PR_URL" ]]; then |
| 98 | + echo "❌ Error: Failed to create the mirrored pull request." |
| 99 | + exit 1 |
| 100 | +fi |
| 101 | + |
| 102 | +gh pr comment "$PR_NUMBER" --repo "$UPSTREAM_REPO" --body "A mirrored PR has been created for E2E testing: ${CREATED_PR_URL}" |
| 103 | + |
| 104 | +echo "✅ Successfully created mirrored pull request!" |
| 105 | +echo " ${CREATED_PR_URL}" |
| 106 | + |
| 107 | +echo "🚀 Done." |
0 commit comments