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
124 changes: 124 additions & 0 deletions .github/workflows/_shared-force-merge.yml
Original file line number Diff line number Diff line change
@@ -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 labels
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 }}
Comment thread
mattdibi marked this conversation as resolved.
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"
});

15 changes: 15 additions & 0 deletions samples/force-merge.yml
Original file line number Diff line number Diff line change
@@ -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