Skip to content

Commit

Permalink
feat: handle merge_group event - get squashed commit (#806)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
YossiSaadi authored and wagoid committed Dec 16, 2024
1 parent 3d28780 commit ef2cd3b
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 0 deletions.
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,66 @@ jobs:
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.

### Using with GitHub Merge Queues

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.

#### Workflow Configuration

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:

```yaml
name: Lint Commit Messages in Merge Queue
on:
merge_group:
types:
- checks_requested
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.sha }}
- uses: wagoid/commitlint-github-action@v6
```

#### Important Note:

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.

Here's a minimal pull_request workflow to satisfy this requirement:

```yaml
name: Placeholder Workflow for Merge Queue
on:
pull_request:
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
```

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**.

### Enabling Merge Queues in Your Repository

Before you can use merge queues, you need to enable the feature in your repository settings:

- Go to your repository's Settings > Branches.
- Under Branch protection rules, edit the rule for your target branch (e.g. master).
- Enable Require merge queue.
- Specify your new job (e.g. commitlint) and any other required status checks, that must pass before merging.

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).

## Inputs

You can supply these inputs to the `wagoid/commitlint-github-action@v6` step.
Expand Down
15 changes: 15 additions & 0 deletions src/action.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { format } from '@commitlint/format'
import load from '@commitlint/load'
import generateOutputs from './generateOutputs.mjs'

const mergeGroupEvent = 'merge_group'
const pullRequestEvent = 'pull_request'
const pullRequestTargetEvent = 'pull_request_target'
const pullRequestEvents = [pullRequestEvent, pullRequestTargetEvent]
Expand Down Expand Up @@ -65,7 +66,21 @@ const getPullRequestEventCommits = async () => {
}))
}

const getMergeGroupEventCommits = async () => {
const { merge_group: mergeGroup } = eventContext.payload

return [
{
message: mergeGroup.head_commit.message,
hash: mergeGroup.head_sha,
},
]
}

const getEventCommits = async () => {
if (GITHUB_EVENT_NAME === mergeGroupEvent) {
return getMergeGroupEventCommits()
}
if (pullRequestEvents.includes(GITHUB_EVENT_NAME)) {
return getPullRequestEventCommits()
}
Expand Down
54 changes: 54 additions & 0 deletions src/action.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { jest, describe, it } from '@jest/globals'
import * as td from 'testdouble'
import {
buildResponseCommit,
createMergeGroupEventPayload,
createPullRequestEventPayload,
createPushEventPayload,
updateMergeGroupEnvVars,
updatePullRequestEnvVars,
updatePushEnvVars,
} from './testUtils.mjs'
Expand Down Expand Up @@ -952,4 +954,56 @@ describe('Commit Linter action', () => {
td.verify(mockCore.setFailed(contains(incorrectCommit.message)))
})
})

describe('when handling merge_group event', () => {
beforeEach(async () => {
cwd = await git.bootstrap('fixtures/conventional', process.cwd())
td.when(mockCore.getInput('configFile')).thenReturn(
'./commitlint.config.mjs',
)

td.replace(process, 'cwd', () => cwd)
td.replace(console, 'log')
})

it('should lint the squashed commit message successfully', async () => {
const mergeGroupData = {
head_sha: 'merge-group-head-sha',
head_commit: {
id: 'merge-group-head-sha',
message: 'feat: add new feature\n\nThis is a detailed description.',
tree_id: 'tree-sha',
},
}

await createMergeGroupEventPayload(cwd, mergeGroupData)
updateMergeGroupEnvVars(cwd)

await runAction()

td.verify(mockCore.setFailed(), { times: 0, ignoreExtraArgs: true })
td.verify(console.log('Lint free! 🎉'))
})

it('should fail if the squashed commit message has linting errors', async () => {
const mergeGroupData = {
head_sha: 'merge-group-head-sha',
head_commit: {
id: 'merge-group-head-sha',
message: 'bad commit message',
tree_id: 'tree-sha',
},
}

await createMergeGroupEventPayload(cwd, mergeGroupData)
updateMergeGroupEnvVars(cwd)

await runAction()

td.verify(
mockCore.setFailed(contains('You have commit messages with errors')),
)
td.verify(mockCore.setFailed(contains('bad commit message')))
})
})
})
29 changes: 29 additions & 0 deletions src/testUtils.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,32 @@ export const buildResponseCommit = (sha, message) => ({
message,
},
})

export const createMergeGroupEventPayload = async (cwd, mergeGroupData) => {
const payload = {
action: 'checks_requested',
merge_group: mergeGroupData,
repository: {
owner: {
login: 'wagoid',
},
name: 'commitlint-github-action',
},
}

const eventPath = path.join(cwd, 'mergeGroupEventPayload.json')

updateEnvVars({
GITHUB_EVENT_PATH: eventPath,
GITHUB_EVENT_NAME: 'merge_group',
GITHUB_REPOSITORY: 'wagoid/commitlint-github-action',
})
await writeFile(eventPath, JSON.stringify(payload), 'utf8')
}

export const updateMergeGroupEnvVars = (cwd) => {
updateEnvVars({
GITHUB_WORKSPACE: cwd,
GITHUB_EVENT_NAME: 'merge_group',
})
}

0 comments on commit ef2cd3b

Please sign in to comment.