TO-SPLIT #15
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Merging-Rebase Automation | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| branch: | |
| description: 'Shears branch to update (seen, next, main, maint, or all)' | |
| required: true | |
| type: choice | |
| options: | |
| - all | |
| - seen | |
| - next | |
| - main | |
| - maint | |
| push: | |
| description: 'Push the result after successful rebase' | |
| required: false | |
| type: boolean | |
| default: false | |
| push: | |
| permissions: | |
| contents: write | |
| models: read | |
| env: | |
| BRANCH: ${{ inputs.branch || 'all' }} | |
| PUSH: ${{ github.event_name == 'schedule' && 'true' || inputs.push || 'false' }} | |
| COPILOT_MODEL: claude-opus-4.5 | |
| jobs: | |
| rebase: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Install Copilot CLI | |
| run: npm install -g @github/copilot | |
| - name: Verify Copilot CLI works | |
| run: | | |
| echo "Testing Copilot CLI authentication..." | |
| copilot -p "What is the current latest Git version according to git-scm.com?" \ | |
| --allow-tool 'web_fetch' --allow-url git-scm.com | |
| echo "Copilot CLI is working!" | |
| env: | |
| GH_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Configure git | |
| run: | | |
| git config user.name "GitHub Actions" | |
| git config user.email "actions@github.com" | |
| - name: Add upstream remote | |
| run: | | |
| git remote add upstream https://github.com/git/git.git || true | |
| git fetch upstream --no-tags | |
| - name: Run rebase (single branch) | |
| id: rebase-single | |
| if: env.BRANCH != 'all' | |
| run: | | |
| case "$BRANCH" in | |
| main) UPSTREAM="upstream/master" ;; | |
| *) UPSTREAM="upstream/$BRANCH" ;; | |
| esac | |
| echo "::group::Fetching shears/$BRANCH" | |
| git fetch origin "shears/$BRANCH" | |
| echo "::endgroup::" | |
| if test 0 = "$(git rev-list --count "origin/shears/$BRANCH..$UPSTREAM")"; then | |
| echo "::notice::Nothing to do for shears/$BRANCH: $UPSTREAM has no new commits" | |
| exit 0 | |
| fi | |
| if ./ci/rebase-branch.sh "shears/$BRANCH" "$UPSTREAM" "$PWD/ci"; then | |
| echo "to_push=shears/$BRANCH" >>"$GITHUB_OUTPUT" | |
| else | |
| echo "failed_worktrees=$PWD/rebase-worktree-$BRANCH" >>"$GITHUB_OUTPUT" | |
| exit 1 | |
| fi | |
| env: | |
| GH_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} | |
| - name: Run rebase (all branches) | |
| id: rebase-all | |
| if: env.BRANCH == 'all' | |
| run: | | |
| to_push="" | |
| failed_worktrees="" | |
| for BRANCH in seen next main maint; do | |
| echo "::group::Fetching shears/$BRANCH" | |
| case "$BRANCH" in | |
| main) UPSTREAM="upstream/master" ;; | |
| *) UPSTREAM="upstream/$BRANCH" ;; | |
| esac | |
| git fetch origin "shears/$BRANCH" | |
| echo "::endgroup::" | |
| if test 0 = "$(git rev-list --count "origin/shears/$BRANCH..$UPSTREAM")"; then | |
| echo "::notice::Nothing to do for shears/$BRANCH: $UPSTREAM has no new commits" | |
| continue | |
| fi | |
| worktree="$PWD/rebase-worktree-$BRANCH" | |
| if ./ci/rebase-branch.sh "shears/$BRANCH" "$UPSTREAM" "$PWD/ci"; then | |
| to_push="${to_push:+$to_push }shears/$BRANCH" | |
| else | |
| echo "::error::Rebase failed for shears/$BRANCH" | |
| failed_worktrees="${failed_worktrees:+$failed_worktrees }$worktree" | |
| fi | |
| done | |
| echo "to_push=$to_push" >>"$GITHUB_OUTPUT" | |
| echo "failed_worktrees=$failed_worktrees" >>"$GITHUB_OUTPUT" | |
| # Fail the step if any rebase failed | |
| test -z "$failed_worktrees" | |
| env: | |
| GH_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} | |
| - name: Create worktree bundles and archives | |
| if: always() | |
| run: | | |
| set -x | |
| mkdir -p upload | |
| # Bundles for successful branches (no worktree needed) | |
| for branch in ${{ steps.rebase-single.outputs.to_push }} ${{ steps.rebase-all.outputs.to_push }}; do | |
| name=${branch##*/} | |
| git bundle create "upload/$name.bundle" "$branch" ^origin/main | |
| done | |
| # Bundles and archives for failed branches | |
| for worktree in ${{ steps.rebase-single.outputs.failed_worktrees }} ${{ steps.rebase-all.outputs.failed_worktrees }}; do | |
| test -d "$worktree" || continue | |
| name=${worktree##*rebase-worktree-} | |
| # Include REBASE_HEAD if it exists | |
| git -C "$worktree" rev-parse --verify REBASE_HEAD && rebase_head_arg=REBASE_HEAD || rebase_head_arg= | |
| git -C "$worktree" for-each-ref --format='%(refname)' | | |
| grep -v '^refs/tags/' | | |
| sed 's,^refs/remotes/origin/,^refs/remotes/origin/,' | | |
| git -C "$worktree" bundle create "../upload/$name.bundle" --stdin HEAD $rebase_head_arg | |
| tar -czf "upload/$name.tar.gz" -C "$worktree" . | |
| done | |
| - name: Upload bundles and worktrees | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bundles-and-worktrees | |
| path: upload/ | |
| if-no-files-found: warn | |
| - name: Push results | |
| if: env.PUSH == 'true' && (steps.rebase-single.outputs.to_push || steps.rebase-all.outputs.to_push) | |
| run: | | |
| git push --force origin ${{ steps.rebase-single.outputs.to_push }} ${{ steps.rebase-all.outputs.to_push }} |