-
Notifications
You must be signed in to change notification settings - Fork 76
ci: add workflow to auto-rebase feature branches #2290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
bde1fb1
c90324e
dfaae16
0870e98
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,274 @@ | ||||
| name: Auto Rebase Feature Branches | ||||
| # Long-running feature branches should be added to the corresponding repository ruleset: | ||||
| # - PRs should be squash merged into the feature branch | ||||
| # - This workflow will keep the feature branch rebased against main | ||||
| # - It will only ever do auto rebase when there are no conflicts. It will trigger a slack notification if there is a conflict that requires manual resolution. | ||||
|
|
||||
| on: | ||||
| push: | ||||
| branches: | ||||
| - main | ||||
|
|
||||
| permissions: | ||||
| contents: write | ||||
|
|
||||
| jobs: | ||||
| rebase: | ||||
| runs-on: | ||||
| - runs-on=${{ github.run_id }}/runner=1cpu-linux-x64 | ||||
| steps: | ||||
| # This step exchanges your app credentials for a temporary token | ||||
| - name: Generate GitHub App Token | ||||
| id: app_token | ||||
| uses: actions/[email protected] | ||||
| with: | ||||
| app-id: ${{ secrets.REBASE_APP_ID }} | ||||
| private-key: ${{ secrets.REBASE_APP_PRIVATE_KEY }} | ||||
|
|
||||
| # Use the generated token for git operations | ||||
| - uses: actions/[email protected] | ||||
| with: | ||||
| fetch-depth: 0 | ||||
| token: ${{ steps.app_token.outputs.token }} | ||||
|
|
||||
| - name: Configure Git | ||||
| run: | | ||||
| git config user.name "branch-rebase-bot[bot]" | ||||
| git config user.email "branch-rebase-bot[bot]@users.noreply.github.com" | ||||
|
|
||||
| - name: Rebase Feature Branches | ||||
| run: | | ||||
| # List of feature branches to maintain | ||||
| FEATURE_BRANCHES=("develop-v2" "develop-v1.5.0" "develop-v1.6.0") | ||||
|
|
||||
| FAILED_BRANCHES=() | ||||
| SUCCEEDED_BRANCHES=() | ||||
| BACKED_UP_BRANCHES=() | ||||
|
|
||||
| # Generate timestamp for backups | ||||
| TIMESTAMP=$(date +%Y%m%d-%H%M%S) | ||||
|
|
||||
| for branch in "${FEATURE_BRANCHES[@]}"; do | ||||
| echo "Processing $branch..." | ||||
|
|
||||
| # Fetch latest | ||||
| git fetch origin "$branch" || { | ||||
| echo "Failed to fetch $branch, skipping..." | ||||
| continue | ||||
| } | ||||
|
|
||||
| # Check if branch exists | ||||
| if ! git rev-parse --verify "origin/$branch" >/dev/null 2>&1; then | ||||
| echo "Branch $branch does not exist, skipping..." | ||||
| continue | ||||
| fi | ||||
|
|
||||
| # Store the original commit hash | ||||
| ORIGINAL_COMMIT=$(git rev-parse "origin/$branch") | ||||
| echo "Original commit for $branch: $ORIGINAL_COMMIT" | ||||
|
|
||||
| # Checkout and rebase | ||||
| git checkout "$branch" | ||||
|
|
||||
| if git rebase origin/main; then | ||||
| echo "✓ Rebase successful for $branch" | ||||
|
|
||||
| # Get the new commit hash after rebase | ||||
| NEW_COMMIT=$(git rev-parse HEAD) | ||||
| echo "New commit for $branch: $NEW_COMMIT" | ||||
|
|
||||
| # Check if rebase actually changed anything | ||||
| if [ "$ORIGINAL_COMMIT" != "$NEW_COMMIT" ]; then | ||||
| echo "⚠️ Rebase changed history, creating backup..." | ||||
|
|
||||
| # Create backup branch from the original commit | ||||
| BACKUP_BRANCH="${branch}-backup-${TIMESTAMP}" | ||||
| git branch "$BACKUP_BRANCH" "$ORIGINAL_COMMIT" | ||||
|
|
||||
| # Push backup branch | ||||
| if git push origin "$BACKUP_BRANCH"; then | ||||
| echo "✓ Backup created: $BACKUP_BRANCH" | ||||
| BACKED_UP_BRANCHES+=("$branch → $BACKUP_BRANCH") | ||||
|
|
||||
| # Only force push the rebased branch if backup succeeded | ||||
| if git push origin "$branch" --force-with-lease; then | ||||
| echo "✓ Force push successful for $branch" | ||||
| SUCCEEDED_BRANCHES+=("$branch") | ||||
| else | ||||
| echo "✗ Push failed for $branch" | ||||
| FAILED_BRANCHES+=("$branch (push failed)") | ||||
| fi | ||||
| else | ||||
| echo "✗ Failed to create backup for $branch - ABORTING force push" | ||||
| FAILED_BRANCHES+=("$branch (backup creation failed - not force pushed)") | ||||
| # Restore original state since we can't safely force push | ||||
| git checkout "$branch" | ||||
|
||||
| git checkout "$branch" |
jonathanpwang marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Dec 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String truncation with bash substring syntax ${COMMIT_MSG:0:100} may not work correctly inside the jq --arg parameter. The variable substitution happens before jq receives it, but this bash syntax needs to be evaluated in a bash context.
Consider truncating before passing to jq:
COMMIT_MSG_TRUNCATED="${COMMIT_MSG:0:100}"
SLACK_PAYLOAD=$(jq -n \
--arg commit_msg "$COMMIT_MSG_TRUNCATED" \
...
)
Uh oh!
There was an error while loading. Please reload this page.