Skip to content

chore: Updated Dependabot config to group PRs and added workflow for scheduled auto-merge #107

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

Merged
merged 1 commit into from
May 27, 2025
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
84 changes: 51 additions & 33 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,56 @@
version: 2
updates:
# GitHub Actions dependencies
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 100
# GitHub Actions dependencies (grouped)
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 10
groups:
all-actions:
patterns:
- "*"

- package-ecosystem: "pip"
directory: "/src/backend"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 100
# Python dependencies (grouped)
- package-ecosystem: "pip"
directory: "/src/backend"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 10
groups:
all-backend-deps:
patterns:
- "*"

- package-ecosystem: "pip"
directory: "/src/frontend"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 100
- package-ecosystem: "pip"
directory: "/src/frontend"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 10
groups:
all-backend-deps:
patterns:
- "*"

- package-ecosystem: "npm"
directory: "/src/frontend"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 100
# npm dependencies (grouped)
- package-ecosystem: "npm"
directory: "/src/frontend"
schedule:
interval: "monthly"
commit-message:
prefix: "build"
target-branch: "dependabotchanges"
open-pull-requests-limit: 10
groups:
all-frontend-deps:
patterns:
- "*"
152 changes: 152 additions & 0 deletions .github/workflows/scheduled-Dependabot-PRs-Auto-Merge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# ------------------------------------------------------------------------------
# Scheduled Dependabot PRs Auto-Merge Workflow
#
# Purpose:
# - Automatically detect, rebase (if needed), and merge Dependabot PRs targeting
# the `dependabotchanges` branch, supporting different merge strategies.
#
# Features:
# ✅ Filters PRs authored by Dependabot and targets the specific base branch
# ✅ Rebases PRs with conflicts and auto-resolves using "prefer-theirs" strategy
# ✅ Attempts all three merge strategies: merge, squash, rebase (first success wins)
# ✅ Handles errors gracefully, logs clearly
#
# Triggers:
# - Scheduled daily run (midnight UTC)
# - Manual trigger (via GitHub UI)
#
# Required Permissions:
# - contents: write
# - pull-requests: write
# ------------------------------------------------------------------------------

name: Scheduled Dependabot PRs Auto-Merge

on:
schedule:
- cron: '0 0 * * *' # Runs once a day at midnight UTC
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
merge-dependabot:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install GitHub CLI
run: |
sudo apt update
sudo apt install -y gh
- name: Fetch & Filter Dependabot PRs
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "🔍 Fetching all Dependabot PRs targeting 'dependabotchanges'..."
> matched_prs.txt
pr_batch=$(gh pr list --state open --json number,title,author,baseRefName,url \
--jq '.[] | "\(.number)|\(.title)|\(.author.login)|\(.baseRefName)|\(.url)"')
while IFS='|' read -r number title author base url; do
author=$(echo "$author" | xargs)
base=$(echo "$base" | xargs)
if [[ "$author" == "app/dependabot" && "$base" == "dependabotchanges" ]]; then
echo "$url" >> matched_prs.txt
echo "✅ Matched PR #$number - $title"
else
echo "❌ Skipped PR #$number - $title (Author: $author, Base: $base)"
fi
done <<< "$pr_batch"
echo "👉 Matched PRs:"
cat matched_prs.txt || echo "None"
- name: Rebase PR if Conflicts Exist
if: success()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [[ ! -s matched_prs.txt ]]; then
echo "⚠️ No matching PRs to process."
exit 0
fi
while IFS= read -r pr_url; do
pr_number=$(basename "$pr_url")
echo "🔁 Checking PR #$pr_number for conflicts..."
mergeable=$(gh pr view "$pr_number" --json mergeable --jq '.mergeable')
if [[ "$mergeable" == "CONFLICTING" ]]; then
echo "⚠️ Merge conflicts detected. Performing manual rebase for PR #$pr_number..."
head_branch=$(gh pr view "$pr_number" --json headRefName --jq '.headRefName')
base_branch=$(gh pr view "$pr_number" --json baseRefName --jq '.baseRefName')
git fetch origin "$base_branch":"$base_branch"
git fetch origin "$head_branch":"$head_branch"
git checkout "$head_branch"
git config user.name "github-actions"
git config user.email "action@github.com"
# Attempt rebase with 'theirs' strategy
if git rebase --strategy=recursive -X theirs "$base_branch"; then
echo "✅ Rebase successful. Pushing..."
git push origin "$head_branch" --force
else
echo "❌ Rebase failed. Aborting..."
git rebase --abort || true
fi
else
echo "✅ PR #$pr_number is mergeable. Skipping rebase."
fi
done < matched_prs.txt

- name: Auto-Merge PRs using available strategy
if: success()
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
if [[ ! -s matched_prs.txt ]]; then
echo "⚠️ No matching PRs to process."
exit 0
fi
while IFS= read -r pr_url; do
pr_number=$(basename "$pr_url")
echo "🔍 Checking mergeability for PR #$pr_number"
attempt=0
max_attempts=8
mergeable=""
sleep 5 # Let GitHub calculate mergeable status
while [[ $attempt -lt $max_attempts ]]; do
mergeable=$(gh pr view "$pr_number" --json mergeable --jq '.mergeable' 2>/dev/null || echo "UNKNOWN")
echo "🔁 Attempt $((attempt+1))/$max_attempts: mergeable=$mergeable"
if [[ "$mergeable" == "MERGEABLE" ]]; then
success=0
for strategy in rebase squash merge; do
echo "🚀 Trying to auto-merge PR #$pr_number using '$strategy' strategy..."
set -x
merge_output=$(gh pr merge --auto --"$strategy" "$pr_url" 2>&1)
merge_status=$?
set +x
echo "$merge_output"
if [[ $merge_status -eq 0 ]]; then
echo "✅ Auto-merge succeeded using '$strategy'."
success=1
break
else
echo "❌ Auto-merge failed using '$strategy'. Trying next strategy..."
fi
done
if [[ $success -eq 0 ]]; then
echo "❌ All merge strategies failed for PR #$pr_number"
fi
break
elif [[ "$mergeable" == "CONFLICTING" ]]; then
echo "❌ Cannot merge due to conflicts. Skipping PR #$pr_number"
break
else
echo "🕒 Waiting for GitHub to determine mergeable status..."
sleep 15
fi
((attempt++))
done
if [[ "$mergeable" != "MERGEABLE" && "$mergeable" != "CONFLICTING" ]]; then
echo "❌ Mergeability undetermined after $max_attempts attempts. Skipping PR #$pr_number"
fi
done < matched_prs.txt || echo "⚠️ Completed loop with some errors, but continuing gracefully."