Skip to content
Merged
127 changes: 127 additions & 0 deletions .github/actions/merge-eip-branches/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: Merge EIP Branches
description: Merges multiple EIP branches into a devnet branch, by pushing using --force-with-lease

inputs:
fork:
description: 'Fork name (e.g., amsterdam)'
required: true
devnet_name:
description: 'Devnet name (e.g., amsterdam/1, bal/2, eip-1234/3). Created branch will be `devnets/$devnet_name`'
required: true
eip_numbers:
description: 'Comma-separated list of EIP numbers (e.g., 1234,2345,3456)'
required: true

runs:
using: "composite"
steps:
- name: Configure Git
shell: bash
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Merge EIP branches
shell: bash
env:
FORK: ${{ inputs.fork }}
DEVNET_NAME: ${{ inputs.devnet_name }}
EIP_NUMBERS: ${{ inputs.eip_numbers }}
REMOTE: origin
run: |
set -euo pipefail

echo "FORK=$FORK"
echo "DEVNET_NAME=$DEVNET_NAME"
echo "EIP_NUMBERS=$EIP_NUMBERS"

FORK_BRANCH="forks/${FORK}"
DEVNET_BRANCH="devnets/${DEVNET_NAME}"

# Basic ref-format validation for user-provided pieces
# (git check-ref-format expects full refnames for some checks; --branch is easiest)
git check-ref-format --branch "${DEVNET_BRANCH}" >/dev/null

# Convert comma-separated list to array
IFS=',' read -ra RAW_EIPS <<< "$EIP_NUMBERS"

# Normalize: trim whitespace, drop empties
EIPS=()
for raw in "${RAW_EIPS[@]}"; do
eip="$(echo "$raw" | xargs)" # trims leading/trailing whitespace
if [[ -n "$eip" ]]; then
# Optional: ensure it looks numeric
if [[ ! "$eip" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid EIP number ${eip}"
exit 1
fi
EIPS+=("$eip")
fi
done

if [[ ${#EIPS[@]} -eq 0 ]]; then
echo "Error: No EIP numbers provided after parsing '${EIP_NUMBERS}'"
exit 1
fi

git fetch "${REMOTE}" --prune

# Build the list of expected remote branches and verify all exist,
# then checkout each branch and rebase it onto the fork branch automatically.
for eip in "${EIPS[@]}"; do
EIP_BRANCH="eips/${FORK}/eip-${eip}"
# Validate ref format for each constructed branch name
git check-ref-format --branch "${EIP_BRANCH}" >/dev/null || {
echo "Error: Computed branch name '${EIP_BRANCH}' is not a valid ref"
exit 1
}

if ! git show-ref --verify --quiet "refs/remotes/${REMOTE}/${EIP_BRANCH}"; then
echo "Error: Missing remote branch ${REMOTE}/${EIP_BRANCH}"
exit 1
fi

git checkout -B "${EIP_BRANCH}" "${REMOTE}/${EIP_BRANCH}"

if git merge-base --is-ancestor "${REMOTE}/${FORK_BRANCH}" "${EIP_BRANCH}"; then
echo "${EIP_BRANCH} is already based on ${FORK_BRANCH}, skipping rebase"
else
if ! git rebase "${REMOTE}/${FORK_BRANCH}"; then
echo "Error: Automatic rebase of ${EIP_BRANCH} onto ${FORK_BRANCH} failed"
git rebase --abort || true
exit 1
else
echo "Rebase of ${EIP_BRANCH} onto ${FORK_BRANCH} successful"
fi
fi
done

# Create (or reset) devnet branch from first EIP
FIRST_EIP="eips/${FORK}/eip-${EIPS[0]}"
echo "Creating branch ${DEVNET_BRANCH} from ${FIRST_EIP}"
git checkout -B "${DEVNET_BRANCH}" "${FIRST_EIP}"

# Merge remaining EIPs
for ((i=1; i<${#EIPS[@]}; i++)); do
EIP_BRANCH="eips/${FORK}/eip-${EIPS[$i]}"
echo "Merging ${EIP_BRANCH}..."

if ! git merge "${EIP_BRANCH}" -m "Merge ${EIP_BRANCH} into ${DEVNET_BRANCH}"; then
echo "Error: Merge conflict occurred while merging ${EIP_BRANCH}"
git merge --abort || true
exit 1
fi
done

echo "All EIP branches merged successfully"

- name: Push devnet branch
shell: bash
env:
DEVNET_NAME: ${{ inputs.devnet_name }}
REMOTE: origin
run: |
DEVNET_BRANCH="devnets/${DEVNET_NAME}"

echo "Force pushing ${DEVNET_BRANCH} to ${REMOTE}"
git push --force-with-lease "${REMOTE}" "${DEVNET_BRANCH}"
71 changes: 71 additions & 0 deletions .github/actions/rebase-eip-branch/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Rebase EIP Branch
description: Rebases an EIP branch onto a fork branch
inputs:
fork:
description: 'Fork name (e.g., amsterdam)'
required: true
eip_number:
description: 'EIP number'
required: true
runs:
using: "composite"
steps:
- name: Configure Git
shell: bash
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Rebase EIP branch (create if missing)
shell: bash
env:
FORK: ${{ inputs.fork }}
EIP_NUMBER: ${{ inputs.eip_number }}
REMOTE: origin
run: |
set -euo pipefail

echo "FORK=$FORK"
echo "EIP_NUMBER=$EIP_NUMBER"
EIP_BRANCH="eips/${FORK}/eip-${EIP_NUMBER}"
FORK_BRANCH="forks/${FORK}"

git fetch "${REMOTE}" --prune

# Sanity: fork base must exist
if ! git show-ref --verify --quiet "refs/remotes/${REMOTE}/${FORK_BRANCH}"; then
echo "Error: Base fork branch ${REMOTE}/${FORK_BRANCH} does not exist"
exit 1
fi

# Create local branch from remote if it exists, else create from fork base
if git show-ref --verify --quiet "refs/remotes/${REMOTE}/${EIP_BRANCH}"; then
echo "Checking out existing ${EIP_BRANCH} (tracking ${REMOTE})"
git checkout -B "${EIP_BRANCH}" "${REMOTE}/${EIP_BRANCH}"
else
echo "Branch ${EIP_BRANCH} does not exist on ${REMOTE}; creating from ${REMOTE}/${FORK_BRANCH}"
git checkout -B "${EIP_BRANCH}" "${REMOTE}/${FORK_BRANCH}"

# First push creates the remote branch (no force needed)
git push -u "${REMOTE}" "${EIP_BRANCH}"
fi

echo "Rebasing ${EIP_BRANCH} onto ${REMOTE}/${FORK_BRANCH}"
if ! git rebase "${REMOTE}/${FORK_BRANCH}"; then
echo "Error: Rebase conflict occurred while rebasing ${EIP_BRANCH} onto ${FORK_BRANCH}"
git rebase --abort || true
exit 1
fi

echo "Rebase successful"

- name: Push rebased branch
shell: bash
env:
FORK: ${{ inputs.fork }}
EIP_NUMBER: ${{ inputs.eip_number }}
REMOTE: origin
run: |
EIP_BRANCH="eips/${FORK}/eip-${EIP_NUMBER}"
echo "Force pushing ${EIP_BRANCH} to ${REMOTE}"
git push --force-with-lease "${REMOTE}" "${EIP_BRANCH}"
36 changes: 36 additions & 0 deletions .github/workflows/eip-rebase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: EIP Rebase Onto Fork Branch

on:
workflow_dispatch:
inputs:
fork:
description: 'Fork name (e.g., amsterdam)'
required: true
type: string
eip_number:
description: 'EIP number'
required: true
type: string

concurrency:
group: ${{ github.workflow }}-${{ github.event.inputs.fork }}-${{ github.event.inputs.eip_number }}
cancel-in-progress: false

permissions:
contents: write

jobs:
rebase-eip:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Rebase EIP branch onto fork
uses: ./.github/actions/rebase-eip-branch
with:
fork: ${{ github.event.inputs.fork }}
eip_number: ${{ github.event.inputs.eip_number }}
44 changes: 44 additions & 0 deletions .github/workflows/update-devnet-branch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Update Devnet Branch

on:
workflow_dispatch:
inputs:
fork:
description: 'Fork name (e.g., amsterdam)'
required: true
type: string
default: 'amsterdam'
devnet_name:
description: 'Devnet name (e.g., amsterdam/1, bal/2, eip-1234/3)'
required: true
type: string
default: 'bal/2'
eip_numbers:
description: 'Comma-separated list of EIP numbers (e.g., 1234,2345,3456)'
required: true
type: string
default: '8024,7843,7708,7778'

concurrency:
group: ${{ github.workflow }}-${{ github.event.inputs.fork || 'amsterdam' }}-${{ github.event.inputs.devnet_name || github.ref }}
cancel-in-progress: false

permissions:
contents: write

jobs:
update-devnet-branch:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Merge EIP branches into devnet
uses: ./.github/actions/merge-eip-branches
with:
fork: ${{ github.event.inputs.fork }}
devnet_name: ${{ github.event.inputs.devnet_name }}
eip_numbers: ${{ github.event.inputs.eip_numbers }}
Loading