diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4e88c49c..afdd2951 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -15,6 +15,11 @@ # - /Labs/Potemkin/app (Potemkin experimental app) # - /Labs/Potemkin/moral_reasoner (Potemkin moral reasoner) # +# Grouping policy: +# - patch and minor updates are grouped into a single PR per directory +# (auto-merged by the dependabot-auto-merge workflow) +# - major updates remain as individual PRs and require manual review +# version: 2 updates: # Cyrano main package @@ -27,6 +32,11 @@ updates: labels: - "dependencies" - "cyrano" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" # Cyrano auth-server - package-ecosystem: "npm" @@ -39,6 +49,11 @@ updates: - "dependencies" - "cyrano" - "auth-server" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" # LexFiat app - package-ecosystem: "npm" @@ -50,6 +65,11 @@ updates: labels: - "dependencies" - "lexfiat" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" # Arkiver app - package-ecosystem: "npm" @@ -61,6 +81,11 @@ updates: labels: - "dependencies" - "arkiver" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" # Arkiver frontend - package-ecosystem: "npm" @@ -72,6 +97,11 @@ updates: labels: - "dependencies" - "arkiver" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" # Labs - Potemkin app - package-ecosystem: "npm" @@ -84,6 +114,11 @@ updates: - "dependencies" - "labs" - "potemkin" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" # Labs - Potemkin moral_reasoner - package-ecosystem: "npm" @@ -96,3 +131,8 @@ updates: - "dependencies" - "labs" - "potemkin" + groups: + non-breaking-deps: + update-types: + - "patch" + - "minor" diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 812bee93..922bbe76 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -2,7 +2,7 @@ name: Dependabot Auto-Merge on: pull_request: - types: [opened, synchronize, reopened] + types: [opened, synchronize, reopened, ready_for_review] permissions: contents: write @@ -19,28 +19,79 @@ jobs: with: github-token: "${{ secrets.GITHUB_TOKEN }}" - - name: Auto-approve PR - run: gh pr review --approve "$PR_URL" + - name: Check for breaking changes + id: breaking + env: + UPDATE_TYPE: ${{ steps.metadata.outputs.update-type }} + PR_TITLE: ${{ github.event.pull_request.title }} + PR_BODY: ${{ github.event.pull_request.body }} + run: | + IS_BREAKING="false" + REASON="" + + # Major version bump is always treated as a potential breaking change + if [[ "$UPDATE_TYPE" == "version-update:semver-major" ]]; then + IS_BREAKING="true" + REASON="major version bump" + fi + + # Check PR title and body for breaking change keywords + if echo "$PR_TITLE $PR_BODY" | grep -qiE "breaking[[:space:]_-]?changes?|BREAKING[[:space:]_-]?CHANGE:?|incompatible change|breaking update"; then + IS_BREAKING="true" + if [[ -n "$REASON" ]]; then + REASON="${REASON}, breaking change keyword detected in PR text" + else + REASON="breaking change keyword detected in PR text" + fi + fi + + echo "is_breaking=${IS_BREAKING}" >> $GITHUB_OUTPUT + echo "reason=${REASON}" >> $GITHUB_OUTPUT + echo "update_type=${UPDATE_TYPE}" >> $GITHUB_OUTPUT + + - name: Auto-approve non-breaking update + if: steps.breaking.outputs.is_breaking == 'false' + run: | + gh pr review --approve "$PR_URL" \ + --body "✅ Auto-approved: non-breaking \`${{ steps.breaking.outputs.update_type }}\` dependency update." env: PR_URL: ${{ github.event.pull_request.html_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Enable auto-merge for patch and minor updates - if: | - steps.metadata.outputs.update-type == 'version-update:semver-patch' || - steps.metadata.outputs.update-type == 'version-update:semver-minor' - run: gh pr merge --auto --squash "$PR_URL" + - name: Merge non-breaking update immediately + if: steps.breaking.outputs.is_breaking == 'false' + run: gh pr merge --squash --admin "$PR_URL" env: PR_URL: ${{ github.event.pull_request.html_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Auto-merge security patches (any severity) - if: steps.metadata.outputs.package-ecosystem != '' + - name: Notify maintainer of blocked breaking-change PR + if: steps.breaking.outputs.is_breaking == 'true' + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BLOCK_REASON: ${{ steps.breaking.outputs.reason }} run: | - if [[ "${{ steps.metadata.outputs.severity }}" != "" ]]; then - echo "Security patch detected - enabling auto-merge" - gh pr merge --auto --squash "$PR_URL" - fi + cat <<'COMMENT_EOF' > /tmp/block-comment.md + ⚠️ **Auto-merge blocked** — potential breaking change detected. + + **Reason:** BLOCK_REASON_PLACEHOLDER + + This PR requires manual review and approval before merging. Please: + 1. Review the upstream changelog for breaking changes + 2. Update any affected code in the repository to accommodate the new version + 3. Merge manually once compatibility is verified + + --- + *Automated check by the Dependabot Auto-Merge workflow.* + COMMENT_EOF + sed -i "s|BLOCK_REASON_PLACEHOLDER|${BLOCK_REASON}|g" /tmp/block-comment.md + gh pr comment "$PR_URL" --body-file /tmp/block-comment.md + + - name: Label breaking-change PR for manual review + if: steps.breaking.outputs.is_breaking == 'true' + run: gh pr edit "$PR_URL" --add-label "breaking-change" env: PR_URL: ${{ github.event.pull_request.html_url }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true