@@ -3,7 +3,7 @@ name: Check Conventional Commits format
3
3
on :
4
4
pull_request_target :
5
5
branches :
6
- - main
6
+ - main
7
7
types :
8
8
- opened
9
9
- edited
14
14
types : [checks_requested]
15
15
16
16
permissions :
17
- pull-requests : read
17
+ pull-requests : write
18
18
19
19
jobs :
20
20
main :
23
23
# The action does not support running on merge_group events,
24
24
# but if the check succeeds in the PR there is no need to check it again.
25
25
if : github.event_name == 'pull_request_target'
26
+ outputs :
27
+ # Whether the PR title indicates a breaking change.
28
+ breaking : ${{ steps.breaking.outputs.breaking }}
29
+ # Whether the PR body contains a "BREAKING CHANGE:" footer describing the breaking change.
30
+ has_breaking_footer : ${{ steps.breaking.outputs.has_breaking_footer }}
26
31
steps :
27
- - uses : amannn/action-semantic-pull-request@v5
32
+ - name : Validate the PR title format
33
+ uses : amannn/action-semantic-pull-request@v5
34
+ id : lint_pr_title
28
35
env :
29
36
GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
30
37
with :
69
76
# labels change, you might want to use the `labeled` and `unlabeled`
70
77
# event triggers in your workflow.
71
78
ignoreLabels : |
72
- ignore-semantic-pull-request
79
+ ignore-semantic-pull-request
80
+
81
+ # `action-semantic-pull-request` does not parse the title, so it cannot
82
+ # detect if it is marked as a breaking change.
83
+ #
84
+ # Since at this point we know the PR title is a valid conventional commit,
85
+ # we can use a simple regex that looks for a '!:' sequence. It could be
86
+ # more complex, but we don't care about false positives.
87
+ - name : Check for breaking change flag
88
+ id : breaking
89
+ run : |
90
+ if [[ "${PR_TITLE}" =~ ^.*\!:.*$ ]]; then
91
+ echo "breaking=true" >> $GITHUB_OUTPUT
92
+ else
93
+ echo "breaking=false" >> $GITHUB_OUTPUT
94
+ fi
95
+
96
+ # Check if the PR comment has a "BREAKING CHANGE:" footer describing
97
+ # the breaking change.
98
+ if [[ "${PR_BODY}" != *"BREAKING CHANGE:"* ]]; then
99
+ echo "has_breaking_footer=false" >> $GITHUB_OUTPUT
100
+ else
101
+ echo "has_breaking_footer=true" >> $GITHUB_OUTPUT
102
+ fi
103
+ env :
104
+ PR_TITLE : ${{ github.event.pull_request.title }}
105
+ PR_BODY : ${{ github.event.pull_request.body }}
106
+
107
+ # Post a help comment if the PR title indicates a breaking change but does
108
+ # not contain a "BREAKING CHANGE:" footer.
109
+ - name : Require "BREAKING CHANGE:" footer for breaking changes
110
+ id : breaking-comment
111
+ if : ${{ steps.breaking.outputs.breaking == 'true' && steps.breaking.outputs.has_breaking_footer == 'false' }}
112
+ uses : marocchino/sticky-pull-request-comment@v2
113
+ with :
114
+ header : pr-title-lint-error
115
+ message : |
116
+ Hey there and thank you for opening this pull request! 👋🏼
117
+
118
+ It looks like your proposed title indicates a breaking change. If that's the case,
119
+ please make sure to include a "BREAKING CHANGE:" footer in the body of the pull request
120
+ describing the breaking change and any migration instructions.
121
+ GITHUB_TOKEN : ${{ secrets.HUGRBOT_PAT }}
122
+ - name : Fail if the footer is required but missing
123
+ if : ${{ steps.breaking.outputs.breaking == 'true' && steps.breaking.outputs.has_breaking_footer == 'false' }}
124
+ run : exit 1
125
+
126
+ - name : Post a comment if the PR badly formatted
127
+ uses : marocchino/sticky-pull-request-comment@v2
128
+ # When the previous steps fails, the workflow would stop. By adding this
129
+ # condition you can continue the execution with the populated error message.
130
+ if : always() && (steps.lint_pr_title.outputs.error_message != null)
131
+ with :
132
+ header : pr-title-lint-error
133
+ message : |
134
+ Hey there and thank you for opening this pull request! 👋🏼
135
+
136
+ We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/)
137
+ and it looks like your proposed title needs to be adjusted.
138
+
139
+ Your title should look like this. The scope field is optional.
140
+ ```
141
+ <type>(<scope>): <description>
142
+ ```
143
+
144
+ If the PR includes a breaking change, mark it with an exclamation mark:
145
+ ```
146
+ <type>!: <description>
147
+ ```
148
+ and include a "BREAKING CHANGE:" footer in the body of the pull request.
149
+
150
+ Details:
151
+ ```
152
+ ${{ steps.lint_pr_title.outputs.error_message }}
153
+ ```
154
+ GITHUB_TOKEN : ${{ secrets.HUGRBOT_PAT }}
155
+
156
+ # Delete previous comments when the issues have been resolved
157
+ # This step doesn't run if any of the previous checks fails.
158
+ - name : Delete previous comments
159
+ uses : marocchino/sticky-pull-request-comment@v2
160
+ with :
161
+ header : pr-title-lint-error
162
+ delete : true
163
+ GITHUB_TOKEN : ${{ secrets.HUGRBOT_PAT }}
0 commit comments