Skip to content

Commit ef2cd3b

Browse files
YossiSaadiwagoid
authored andcommitted
feat: handle merge_group event - get squashed commit (#806)
* feat: handle merge_group event - get squashed commit * test: merge_group event * chore: temporarily change docker image * Revert "chore: temporarily change docker image" This reverts commit 39350ef. * docs: update merge_group event support
1 parent 3d28780 commit ef2cd3b

File tree

4 files changed

+158
-0
lines changed

4 files changed

+158
-0
lines changed

README.md

+60
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,66 @@ jobs:
2424
2525
Alternatively, you can run on other event types such as `on: [push]`. In that case the action will lint the push event's commit(s) instead of linting commits from a pull request. You can also combine `push` and `pull_request` together in the same workflow.
2626

27+
### Using with GitHub Merge Queues
28+
29+
GitHub's [merge queue](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue) is a feature that allows you to queue pull requests for merging once they meet certain criteria. When using merge queues, you need to ensure that your workflows are set up to handle the merge_group event, which is triggered when pull requests are added to the merge queue.
30+
31+
#### Workflow Configuration
32+
33+
To use the commitlint-github-action with merge queues, you need to set up a workflow that listens to the merge_group event. Here's an example of how to configure your workflow:
34+
35+
```yaml
36+
name: Lint Commit Messages in Merge Queue
37+
38+
on:
39+
merge_group:
40+
types:
41+
- checks_requested
42+
43+
jobs:
44+
commitlint:
45+
runs-on: ubuntu-latest
46+
steps:
47+
- uses: actions/checkout@v3
48+
with:
49+
ref: ${{ github.sha }}
50+
51+
- uses: wagoid/commitlint-github-action@v6
52+
```
53+
54+
#### Important Note:
55+
56+
To ensure that the merge_group event triggers correctly, you need to have **at least one workflow that responds to the pull_request event** with a job named the same as the one in your merge_group workflow (**commitlint** in this example). This is necessary because the merge queue relies on the existence of status checks from the pull request context.
57+
58+
Here's a minimal pull_request workflow to satisfy this requirement:
59+
60+
```yaml
61+
name: Placeholder Workflow for Merge Queue
62+
63+
on:
64+
pull_request:
65+
66+
jobs:
67+
commitlint:
68+
runs-on: ubuntu-latest
69+
steps:
70+
- name: Checkout Repository
71+
uses: actions/checkout@v3
72+
```
73+
74+
This workflow can also be a meaningful one that checks out the commits in your PR and runs other checks, but it must have a job named **commitlint**.
75+
76+
### Enabling Merge Queues in Your Repository
77+
78+
Before you can use merge queues, you need to enable the feature in your repository settings:
79+
80+
- Go to your repository's Settings > Branches.
81+
- Under Branch protection rules, edit the rule for your target branch (e.g. master).
82+
- Enable Require merge queue.
83+
- Specify your new job (e.g. commitlint) and any other required status checks, that must pass before merging.
84+
85+
For more information on configuring merge queues, refer to the [GitHub documentation on managing a merge queue](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue).
86+
2787
## Inputs
2888

2989
You can supply these inputs to the `wagoid/commitlint-github-action@v6` step.

src/action.mjs

+15
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { format } from '@commitlint/format'
77
import load from '@commitlint/load'
88
import generateOutputs from './generateOutputs.mjs'
99

10+
const mergeGroupEvent = 'merge_group'
1011
const pullRequestEvent = 'pull_request'
1112
const pullRequestTargetEvent = 'pull_request_target'
1213
const pullRequestEvents = [pullRequestEvent, pullRequestTargetEvent]
@@ -65,7 +66,21 @@ const getPullRequestEventCommits = async () => {
6566
}))
6667
}
6768

69+
const getMergeGroupEventCommits = async () => {
70+
const { merge_group: mergeGroup } = eventContext.payload
71+
72+
return [
73+
{
74+
message: mergeGroup.head_commit.message,
75+
hash: mergeGroup.head_sha,
76+
},
77+
]
78+
}
79+
6880
const getEventCommits = async () => {
81+
if (GITHUB_EVENT_NAME === mergeGroupEvent) {
82+
return getMergeGroupEventCommits()
83+
}
6984
if (pullRequestEvents.includes(GITHUB_EVENT_NAME)) {
7085
return getPullRequestEventCommits()
7186
}

src/action.test.mjs

+54
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import { jest, describe, it } from '@jest/globals'
55
import * as td from 'testdouble'
66
import {
77
buildResponseCommit,
8+
createMergeGroupEventPayload,
89
createPullRequestEventPayload,
910
createPushEventPayload,
11+
updateMergeGroupEnvVars,
1012
updatePullRequestEnvVars,
1113
updatePushEnvVars,
1214
} from './testUtils.mjs'
@@ -952,4 +954,56 @@ describe('Commit Linter action', () => {
952954
td.verify(mockCore.setFailed(contains(incorrectCommit.message)))
953955
})
954956
})
957+
958+
describe('when handling merge_group event', () => {
959+
beforeEach(async () => {
960+
cwd = await git.bootstrap('fixtures/conventional', process.cwd())
961+
td.when(mockCore.getInput('configFile')).thenReturn(
962+
'./commitlint.config.mjs',
963+
)
964+
965+
td.replace(process, 'cwd', () => cwd)
966+
td.replace(console, 'log')
967+
})
968+
969+
it('should lint the squashed commit message successfully', async () => {
970+
const mergeGroupData = {
971+
head_sha: 'merge-group-head-sha',
972+
head_commit: {
973+
id: 'merge-group-head-sha',
974+
message: 'feat: add new feature\n\nThis is a detailed description.',
975+
tree_id: 'tree-sha',
976+
},
977+
}
978+
979+
await createMergeGroupEventPayload(cwd, mergeGroupData)
980+
updateMergeGroupEnvVars(cwd)
981+
982+
await runAction()
983+
984+
td.verify(mockCore.setFailed(), { times: 0, ignoreExtraArgs: true })
985+
td.verify(console.log('Lint free! 🎉'))
986+
})
987+
988+
it('should fail if the squashed commit message has linting errors', async () => {
989+
const mergeGroupData = {
990+
head_sha: 'merge-group-head-sha',
991+
head_commit: {
992+
id: 'merge-group-head-sha',
993+
message: 'bad commit message',
994+
tree_id: 'tree-sha',
995+
},
996+
}
997+
998+
await createMergeGroupEventPayload(cwd, mergeGroupData)
999+
updateMergeGroupEnvVars(cwd)
1000+
1001+
await runAction()
1002+
1003+
td.verify(
1004+
mockCore.setFailed(contains('You have commit messages with errors')),
1005+
)
1006+
td.verify(mockCore.setFailed(contains('bad commit message')))
1007+
})
1008+
})
9551009
})

src/testUtils.mjs

+29
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,32 @@ export const buildResponseCommit = (sha, message) => ({
7777
message,
7878
},
7979
})
80+
81+
export const createMergeGroupEventPayload = async (cwd, mergeGroupData) => {
82+
const payload = {
83+
action: 'checks_requested',
84+
merge_group: mergeGroupData,
85+
repository: {
86+
owner: {
87+
login: 'wagoid',
88+
},
89+
name: 'commitlint-github-action',
90+
},
91+
}
92+
93+
const eventPath = path.join(cwd, 'mergeGroupEventPayload.json')
94+
95+
updateEnvVars({
96+
GITHUB_EVENT_PATH: eventPath,
97+
GITHUB_EVENT_NAME: 'merge_group',
98+
GITHUB_REPOSITORY: 'wagoid/commitlint-github-action',
99+
})
100+
await writeFile(eventPath, JSON.stringify(payload), 'utf8')
101+
}
102+
103+
export const updateMergeGroupEnvVars = (cwd) => {
104+
updateEnvVars({
105+
GITHUB_WORKSPACE: cwd,
106+
GITHUB_EVENT_NAME: 'merge_group',
107+
})
108+
}

0 commit comments

Comments
 (0)