-
Notifications
You must be signed in to change notification settings - Fork 46
116 lines (97 loc) · 4.18 KB
/
semantic-pull-request.yml
File metadata and controls
116 lines (97 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Linter to enforce semantic pull request titles (see https://www.conventionalcommits.org/)
---
name: 🔍 Semantic PR Validation
on:
pull_request_target:
branches:
- main
types:
- opened
- edited
- reopened
- ready_for_review
permissions:
issues: write
jobs:
check_pr_title:
name: Check Pull Request Title
runs-on: ubuntu-latest
steps:
- name: Run Semantic PR Validation
id: validation
uses: actions/github-script@v6
with:
script: |
const prTitle = context.payload.pull_request.title;
const regex = /^(feat|fix|docs|style|refactor|perf|test|chore|build|ci|revert)(\([^)]+\))?(!?): .+/;
if (!regex.test(prTitle)) {
core.setFailed('Pull request title does not follow Conventional Commits specification. See PR comment for details.');
}
- name: Handle Invalid Title
if: failure()
uses: actions/github-script@v6
with:
script: |
const commentMarker = '<!-- semantic-pr-comment -->';
const { data: comments } = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
const existingComment = comments.find(comment => comment.body.includes(commentMarker));
if (!existingComment) {
const message = `<!-- semantic-pr-comment -->
Hey there and thank you for your contribution! 👋🏼
We require pull request titles to follow the [Conventional Commits](https://www.conventionalcommits.org/) specification and it looks like your proposed title needs to be adjusted.
A valid title has the format: \`type(scope): subject\`
**type**: Must be one of the following:
- \`feat\`: A new feature
- \`fix\`: A bug fix
- \`docs\`: Documentation only changes
- \`style\`: Changes that do not affect the meaning of the code (e.g., formatting)
- \`refactor\`: A code change that neither fixes a bug nor adds a feature
- \`perf\`: A code change that improves performance
- \`test\`: Adding missing tests or correcting existing tests
- \`chore\`: Changes to the build process or auxiliary tools
- \`build\`: Changes that affect the build system or external dependencies
- \`ci\`: Changes to CI configuration files and scripts
- \`revert\`: Reverts a previous commit
**scope** (optional): A noun describing a section of the codebase.
**subject**: A short description of the code changes.
Examples:
- \`feat(api): add new endpoint for users\`
- \`fix: incorrect type check in cp command\`
- \`docs(readme): update installation instructions\`
Please update your pull request title to match this format.`;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message
});
}
await github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['invalid']
});
- name: Handle Valid Title
if: success()
uses: actions/github-script@v6
with:
script: |
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const invalidLabel = labels.find(label => label.name === 'invalid');
if (invalidLabel) {
await github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: 'invalid',
});
}