Skip to content

Check Conventional Commits format #21

Check Conventional Commits format

Check Conventional Commits format #21

Workflow file for this run

name: Check Conventional Commits format
on:
# Allow this workflow to be called by another workflow
workflow_call:
secrets:
GITHUB_PAT:
description: 'The github token for the user that will post comments.'
required: true
# The caller should use these triggers on their workflow file
pull_request_target:
branches:
- main
types:
- opened
- edited
- synchronize
- labeled
- unlabeled
# The action does not support running on merge_group events,
# but if the check succeeds in the PR there is no need to check it again.
merge_group:
types: [checks_requested]
jobs:
main:
name: Validate Conventional Commit PR title
runs-on: ubuntu-latest
env:
# We use a HUGRBOT_PAT secret locally.
GITHUB_TOKEN: ${{ secrets.GITHUB_PAT || secrets.HUGRBOT_PAT }}
outputs:
# Whether the PR title indicates a breaking change.
breaking: ${{ steps.breaking.outputs.breaking }}
# Whether the PR body contains a "BREAKING CHANGE:" footer describing the breaking change.
has_breaking_footer: ${{ steps.breaking.outputs.has_breaking_footer }}
# The following steps are only run on pull_request_target events. We add the
# `if` statements to each individual step since we want the job to still
# succeed in merge queues. Skipping the job completely doesn't seem to work
# when called as a reusable workflow (the worker is never started, and the
# queued job just hangs there).
steps:
- name: Fail if the GITHUB_PAT input is not set
if: env.GITHUB_TOKEN == ''
run: |
echo "The `GITHUB_PAT` input is required."
exit 1
- name: Validate the PR title format
uses: amannn/action-semantic-pull-request@v5
if: github.event_name == 'pull_request_target'
id: lint_pr_title
with:
# Configure which types are allowed (newline-delimited).
# Default: https://github.com/commitizen/conventional-commit-types
types: |
feat
fix
docs
style
refactor
perf
test
ci
chore
revert
# Configure which scopes are allowed (newline-delimited).
# These are regex patterns auto-wrapped in `^ $`.
#scopes: |
# .*
# Configure that a scope must always be provided.
requireScope: false
# Configure which scopes are disallowed in PR titles (newline-delimited).
# For instance by setting the value below, `chore(release): ...` (lowercase)
# and `ci(e2e,release): ...` (unknown scope) will be rejected.
# These are regex patterns auto-wrapped in `^ $`.
#disallowScopes: |
# release
# [A-Z]+
# Configure additional validation for the subject based on a regex.
# This example ensures the subject doesn't start with an uppercase character.
#subjectPattern: ^(?![A-Z]).+$
# If `subjectPattern` is configured, you can use this property to override
# the default error message that is shown when the pattern doesn't match.
# The variables `subject` and `title` can be used within the message.
#subjectPatternError: |
# The subject "{subject}" found in the pull request title "{title}"
# didn't match the configured pattern. Please ensure that the subject
# doesn't start with an uppercase character.
# If the PR contains one of these newline-delimited labels, the
# validation is skipped. If you want to rerun the validation when
# labels change, you might want to use the `labeled` and `unlabeled`
# event triggers in your workflow.
ignoreLabels: |
ignore-semantic-pull-request
# `action-semantic-pull-request` does not parse the title, so it cannot
# detect if it is marked as a breaking change.
#
# Since at this point we know the PR title is a valid conventional commit,
# we can use a simple regex that looks for a '!:' sequence. It could be
# more complex, but we don't care about false positives.
- name: Check for breaking change flag
if: github.event_name == 'pull_request_target'
id: breaking
run: |
if [[ "${PR_TITLE}" =~ ^.*\!:.*$ ]]; then
echo "breaking=true" >> $GITHUB_OUTPUT
else
echo "breaking=false" >> $GITHUB_OUTPUT
fi
# Check if the PR comment has a "BREAKING CHANGE:" footer describing
# the breaking change.
if [[ "${PR_BODY}" != *"BREAKING CHANGE:"* ]]; then
echo "has_breaking_footer=false" >> $GITHUB_OUTPUT
else
echo "has_breaking_footer=true" >> $GITHUB_OUTPUT
fi
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_BODY: ${{ github.event.pull_request.body }}
# Post a help comment if the PR title indicates a breaking change but does
# not contain a "BREAKING CHANGE:" footer.
- name: Require "BREAKING CHANGE:" footer for breaking changes
id: breaking-comment
if: ${{ github.event_name == 'pull_request_target' && steps.breaking.outputs.breaking == 'true' && steps.breaking.outputs.has_breaking_footer == 'false' }}
uses: marocchino/sticky-pull-request-comment@v2
with:
header: pr-title-lint-error
message: |
Hey there and thank you for opening this pull request! 👋
It looks like your proposed title indicates a breaking change. If that's the case,
please make sure to include a "BREAKING CHANGE:" footer in the body of the pull request
describing the breaking change and any migration instructions.
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}
- name: Fail if the footer is required but missing
if: ${{ github.event_name == 'pull_request_target' && steps.breaking.outputs.breaking == 'true' && steps.breaking.outputs.has_breaking_footer == 'false' }}
run: exit 1
- name: Post a comment if the PR badly formatted
uses: marocchino/sticky-pull-request-comment@v2
# When the previous steps fails, the workflow would stop. By adding this
# condition you can continue the execution with the populated error message.
if: always() && github.event_name == 'pull_request_target' && (steps.lint_pr_title.outputs.error_message != null)
with:
header: pr-title-lint-error
message: |
Hey there and thank you for opening this pull request! 👋
We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/)
and it looks like your proposed title needs to be adjusted.
Your title should look like this. The scope field is optional.
```
<type>(<scope>): <description>
```
If the PR includes a breaking change, mark it with an exclamation mark:
```
<type>!: <description>
```
and include a "BREAKING CHANGE:" footer in the body of the pull request.
Details:
```
${{ steps.lint_pr_title.outputs.error_message }}
```
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}
# Delete previous comments when the issues have been resolved
# This step doesn't run if any of the previous checks fails.
- name: Delete previous comments
uses: marocchino/sticky-pull-request-comment@v2
if: github.event_name == 'pull_request_target'
with:
header: pr-title-lint-error
delete: true
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}