Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/pr-delete-auto-branches.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: pr-delete-auto-branches

# Description: Deletes auto-generated branches when a pull request is closed (merged or not) if the branch name matches predefined patterns.
#
# This workflow triggers on pull_request closed events and deletes the head branch when it matches any of:
# - update-branch/*
# - chore/update-dev-version-date-*
# - docs/update-version-badge-*
#
# Triggers:
# - pull_request.types: closed
#
# Permissions:
# - contents: write - Required to delete branches

on:
pull_request:
types:
- closed
permissions:
contents: write
jobs:
delete-auto-branches:
name: Delete auto branches
if: |
startsWith(github.event.pull_request.head.ref, 'update-branch/') ||
startsWith(github.event.pull_request.head.ref, 'chore/update-dev-version-date-') ||
startsWith(github.event.pull_request.head.ref, 'docs/update-version-badge-')
runs-on: ubuntu-latest
steps:
- name: Delete branch
uses: breningham/delete-branch@v1.0.0
with:
branch_name: ${{ github.event.pull_request.head.ref }}
github_token: ${{ secrets.GITHUB_TOKEN }}
56 changes: 21 additions & 35 deletions .github/workflows/user-update-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ on:
required: true
type: string
target_branch:
description: 'Target branch (to be updated)'
description: 'Target branch(es) as JSON array string, e.g. ["dev","prod"]'
required: true
type: string
filter:
Expand All @@ -36,6 +36,9 @@ permissions:
jobs:
update-branch:
runs-on: ubuntu-latest
strategy:
matrix:
target_branch: ${{ fromJson(github.event.inputs.target_branch) }}
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
Expand All @@ -57,13 +60,13 @@ jobs:
fi

# Check if target branch exists
if ! git ls-remote --heads origin ${{ github.event.inputs.target_branch }} | grep -q ${{ github.event.inputs.target_branch }}; then
echo "::error::Target branch '${{ github.event.inputs.target_branch }}' does not exist."
if ! git ls-remote --heads origin ${{ matrix.target_branch }} | grep -q ${{ matrix.target_branch }}; then
echo "::error::Target branch '${{ matrix.target_branch }}' does not exist."
exit 1
fi

# Check if branches are the same
if [[ "${{ github.event.inputs.origin_branch }}" == "${{ github.event.inputs.target_branch }}" ]]; then
if [[ "${{ github.event.inputs.origin_branch }}" == "${{ matrix.target_branch }}" ]]; then
echo "::error::Origin and target branches cannot be the same."
exit 1
fi
Expand All @@ -78,15 +81,15 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const filterSuffix = '${{ github.event.inputs.filter }}' ? ` for path ${{ github.event.inputs.filter }}` : '';
const prTitle = `chore(branch): update ${{ github.event.inputs.target_branch }} from ${{ github.event.inputs.origin_branch }}${filterSuffix}`;
const prTitle = `chore(branch): update ${{ matrix.target_branch }} from ${{ github.event.inputs.origin_branch }}${filterSuffix}`;

console.log(`Checking for existing PRs with title: ${prTitle}`);

const prs = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
base: '${{ github.event.inputs.target_branch }}'
base: '${{ matrix.target_branch }}'
});

const existingPR = prs.data.find(pr =>
Expand All @@ -111,19 +114,19 @@ jobs:
- name: Exit if PR exists
if: fromJSON(steps.check-existing-pr.outputs.result).exists == true
run: |
echo "::warning::An open PR already exists for updating ${{ github.event.inputs.target_branch }} from ${{ github.event.inputs.origin_branch }}. See PR #$(echo '${{ steps.check-existing-pr.outputs.result }}' | jq -r .pr_number) at $(echo '${{ steps.check-existing-pr.outputs.result }}' | jq -r .pr_url)"
echo "::warning::An open PR already exists for updating ${{ matrix.target_branch }} from ${{ github.event.inputs.origin_branch }}. See PR #$(echo '${{ steps.check-existing-pr.outputs.result }}' | jq -r .pr_number) at $(echo '${{ steps.check-existing-pr.outputs.result }}' | jq -r .pr_url)"
exit 0
shell: bash

- name: Create temporary branch
id: create-temp-branch
run: |
# Create a unique branch name
TEMP_BRANCH="update-branch/${{ github.event.inputs.target_branch }}-from-${{ github.event.inputs.origin_branch }}"
TEMP_BRANCH="update-branch/${{ matrix.target_branch }}-from-${{ github.event.inputs.origin_branch }}"
echo "temp_branch=$TEMP_BRANCH" >> $GITHUB_OUTPUT

# Checkout target branch
git checkout ${{ github.event.inputs.target_branch }}
git checkout ${{ matrix.target_branch }}

# Create temporary branch from target
git checkout -b $TEMP_BRANCH
Expand All @@ -133,9 +136,10 @@ jobs:

- name: Attempt merge
id: attempt-merge
continue-on-error: true
run: |
ORIGIN=${{ github.event.inputs.origin_branch }}
TARGET=${{ github.event.inputs.target_branch }}
TARGET=${{ matrix.target_branch }}
FILTER=${{ github.event.inputs.filter }}

# Function to check for file suppressions
Expand Down Expand Up @@ -236,23 +240,8 @@ jobs:
fi
shell: bash

- name: Push changes if no conflicts
id: push-changes
if: steps.attempt-merge.outputs.merge_status == 'success'
run: |
# Try to push changes directly to target branch
if git push origin ${{ steps.create-temp-branch.outputs.temp_branch }}:${{ github.event.inputs.target_branch }}; then
echo "push_status=success" >> $GITHUB_OUTPUT
echo "Successfully updated ${{ github.event.inputs.target_branch }} with changes from ${{ github.event.inputs.origin_branch }}."
else
echo "push_status=failed" >> $GITHUB_OUTPUT
echo "Direct push failed. Branch may be protected. Will create a PR instead."
fi
shell: bash
continue-on-error: true

- name: Create PR if conflicts or protected branch
if: steps.attempt-merge.outputs.merge_status == 'conflict' || steps.push-changes.outputs.push_status == 'failed'
if: steps.attempt-merge.outcome == 'failure' || steps.attempt-merge.outputs.merge_status == 'conflict' || steps.attempt-merge.outputs.merge_status == 'success'
Copy link

Copilot AI Apr 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including 'merge_status' equal to 'success' in the condition for creating a PR could lead to unnecessary PRs when a merge successfully occurs. Consider removing this case so that a PR is created only when the merge fails or there is a conflict.

Suggested change
if: steps.attempt-merge.outcome == 'failure' || steps.attempt-merge.outputs.merge_status == 'conflict' || steps.attempt-merge.outputs.merge_status == 'success'
if: steps.attempt-merge.outcome == 'failure' || steps.attempt-merge.outputs.merge_status == 'conflict'

Copilot uses AI. Check for mistakes.
id: create-pr
uses: actions/github-script@v7.0.1
with:
Expand All @@ -263,11 +252,11 @@ jobs:
execSync('git push origin ${{ steps.create-temp-branch.outputs.temp_branch }}');

const filterSuffix = '${{ github.event.inputs.filter }}' ? ` for path ${{ github.event.inputs.filter }}` : '';
const prTitle = `chore(branch): update ${{ github.event.inputs.target_branch }} from ${{ github.event.inputs.origin_branch }}${filterSuffix}`;
const prTitle = `chore(branch): update ${{ matrix.target_branch }} from ${{ github.event.inputs.origin_branch }}${filterSuffix}`;

let prBody = `## Branch Update

This PR updates \`${{ github.event.inputs.target_branch }}\` with changes from \`${{ github.event.inputs.origin_branch }}\`${filterSuffix ? ` for the path \`${filterSuffix.substring(10)}\`` : ''}.`;
This PR updates \`${{ matrix.target_branch }}\` with changes from \`${{ github.event.inputs.origin_branch }}\`${filterSuffix ? ` for the path \`${filterSuffix.substring(10)}\`` : ''}.`;

if ('${{ steps.attempt-merge.outputs.merge_status }}' === 'conflict') {
prBody += `
Expand All @@ -280,7 +269,7 @@ jobs:

### ℹ️ Protected Branch

This PR was created because \`${{ github.event.inputs.target_branch }}\` is a protected branch that requires changes through pull requests.`;
This PR was created because \`${{ matrix.target_branch }}\` is a protected branch that requires changes through pull requests.`;
}

prBody += `
Expand All @@ -299,7 +288,7 @@ jobs:
title: prTitle,
body: prBody,
head: '${{ steps.create-temp-branch.outputs.temp_branch }}',
base: '${{ github.event.inputs.target_branch }}'
base: '${{ matrix.target_branch }}'
});

console.log(`PR created: ${pr.data.html_url}`);
Expand All @@ -316,11 +305,8 @@ jobs:

- name: Output results
run: |
if [[ "${{ steps.attempt-merge.outputs.merge_status }}" == "success" && "${{ steps.push-changes.outputs.push_status }}" == "success" ]]; then
echo "✅ Successfully updated ${{ github.event.inputs.target_branch }} with changes from ${{ github.event.inputs.origin_branch }}."
elif [[ "${{ steps.attempt-merge.outputs.merge_status }}" == "success" && "${{ steps.push-changes.outputs.push_status }}" == "failed" ]]; then
echo "ℹ️ Branch is protected. Created PR #$(echo '${{ steps.create-pr.outputs.result }}' | jq -r .pr_number) for review."
echo "PR URL: $(echo '${{ steps.create-pr.outputs.result }}' | jq -r .pr_url)"
if [[ "${{ steps.attempt-merge.outputs.merge_status }}" == "success" ]]; then
echo "✅ Successfully updated ${{ matrix.target_branch }} with changes from ${{ github.event.inputs.origin_branch }}."
elif [[ "${{ steps.attempt-merge.outputs.merge_status }}" == "no_changes" ]]; then
echo "ℹ️ No changes to merge. Branches are already in sync."
elif [[ "${{ steps.attempt-merge.outputs.merge_status }}" == "conflict" ]]; then
Expand Down
Loading