From 96c0a7ee5884196c2a62a059bb720aa700573f79 Mon Sep 17 00:00:00 2001 From: Mattia Dal Ben Date: Thu, 7 Aug 2025 11:29:55 +0200 Subject: [PATCH 1/2] ci(workflows): introduce shared force merge workflow --- .github/workflows/_shared-force-merge.yml | 124 ++++++++++++++++++++++ samples/force-merge.yml | 15 +++ 2 files changed, 139 insertions(+) create mode 100644 .github/workflows/_shared-force-merge.yml create mode 100644 samples/force-merge.yml diff --git a/.github/workflows/_shared-force-merge.yml b/.github/workflows/_shared-force-merge.yml new file mode 100644 index 0000000..6036cda --- /dev/null +++ b/.github/workflows/_shared-force-merge.yml @@ -0,0 +1,124 @@ +name: "Force merge automation (shared)" +description: Merge a pull request when N committers post a comment with the command /force-merge + +on: workflow_call + +env: + quorum: 3 + +jobs: + force_merge: + # This job only runs for pull request comments + if: ${{ github.event.issue.pull_request }} + runs-on: ubuntu-latest + + steps: + - name: Check pull request + id: should-run + uses: actions/github-script@v7 + with: + script: | + const issue = await github.rest.issues.get({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }) + + const isClosed = issue.data.closed_at != null + const isDraft = issue.data.draft + + return !isClosed && !isDraft + + - name: Count votes + id: count-votes + if: ${{ steps.should-run.outputs.result == 'true' }} + uses: actions/github-script@v7 + with: + script: | + const comments = await github.rest.issues.listComments({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }) + + // Check if debug mode is enabled by any comment containing "/debug-force-merge" + const debugEnabled = comments.data.some(comment => + comment.body && comment.body.includes('/debug-force-merge') + ); + + // Debug: Print all commenters and their associations (only if debug enabled) + if (debugEnabled) { + console.log("=== All Comments Debug ==="); + for(const comment of comments.data) { + console.log(`User: ${comment.user.login}`); + console.log(`Association: ${comment.author_association}`); + console.log(`Has voting rights: ${comment.author_association === 'MEMBER' || comment.author_association === 'OWNER'}`); + console.log(`Has casted vote: ${comment.body && comment.body.trim() === '/force-merge'}`); + console.log("---"); + } + } + + const votes = new Map(); + for(const comment of comments.data) { + const hasVotingRights = comment.author_association === 'MEMBER' || comment.author_association === 'OWNER' + const hasCastedVote = comment.body && comment.body.trim() === '/force-merge' + + if(hasVotingRights && hasCastedVote) { + votes.set(comment.user.login, comment.author_association); + } + } + + // Display voters and role + console.table(votes) + + return votes.size + + - name: Set lables + if: ${{ steps.should-run.outputs.result == 'true' }} + uses: actions/github-script@v7 + with: + script: | + const labels = await github.rest.issues.listLabelsOnIssue({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo + }) + const labelsToAdd = [] + for(const label of labels.data) { + if(!label.name.startsWith('force-merge-votes-')) { + labelsToAdd.push(label.name) + } + } + + const votes = ${{ steps.count-votes.outputs.result }} + if(votes >= 1 && votes < ${{env.quorum}}) { + labelsToAdd.push("force-merge-votes-" + votes) + } + + const result = github.rest.issues.setLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: labelsToAdd + }) + + - name: Perform merge + if: ${{ (steps.should-run.outputs.result == 'true') && (steps.count-votes.outputs.result >= env.quorum) }} + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.KURA_BOT_GITHUB_TOKEN }} + script: | + github.rest.issues.addLabels({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + labels: ['force-merged'] + }) + + await github.rest.pulls.merge({ + pull_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + merge_method: "squash" + }); + diff --git a/samples/force-merge.yml b/samples/force-merge.yml new file mode 100644 index 0000000..d2b9c15 --- /dev/null +++ b/samples/force-merge.yml @@ -0,0 +1,15 @@ +name: "Force merge automation" +description: Merge a pull request when N committers post a comment with the command /force-merge + +on: + issue_comment: + types: [created, edited, deleted] + +permissions: + contents: write + pull-requests: write + issues: write + +jobs: + call-workflow-in-public-repo: + uses: eclipse-kura/.github/.github/workflows/_shared-force-merge.yml@main From cc3693a33c189b98467e8e5b15d3b66fc6f2376f Mon Sep 17 00:00:00 2001 From: Mattia Dal Ben Date: Thu, 7 Aug 2025 11:33:40 +0200 Subject: [PATCH 2/2] fix: typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Mattia Dal Ben --- .github/workflows/_shared-force-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_shared-force-merge.yml b/.github/workflows/_shared-force-merge.yml index 6036cda..bc0b067 100644 --- a/.github/workflows/_shared-force-merge.yml +++ b/.github/workflows/_shared-force-merge.yml @@ -73,7 +73,7 @@ jobs: return votes.size - - name: Set lables + - name: Set labels if: ${{ steps.should-run.outputs.result == 'true' }} uses: actions/github-script@v7 with: