From 9090da59256226294a773e8fa71c397dcc3ea4a5 Mon Sep 17 00:00:00 2001 From: Rafi-Microsoft Date: Fri, 23 May 2025 14:31:27 +0530 Subject: [PATCH] Updated Dependabot config to group PRs and added workflow for scheduled auto-merge --- .github/dependabot.yml | 84 ++++++---- .../scheduled-Dependabot-PRs-Auto-Merge.yml | 152 ++++++++++++++++++ 2 files changed, 203 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/scheduled-Dependabot-PRs-Auto-Merge.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 508a62b..de9bbbb 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -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: + - "*" \ No newline at end of file diff --git a/.github/workflows/scheduled-Dependabot-PRs-Auto-Merge.yml b/.github/workflows/scheduled-Dependabot-PRs-Auto-Merge.yml new file mode 100644 index 0000000..1cfc097 --- /dev/null +++ b/.github/workflows/scheduled-Dependabot-PRs-Auto-Merge.yml @@ -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." \ No newline at end of file