Skip to content

Commit c2026c8

Browse files
authored
build: add commit message validation workflow (#1219)
1 parent e9f7cae commit c2026c8

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

.github/workflows/auto-label.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
name: 'Auto Label PR'
2+
3+
on:
4+
pull_request:
5+
types: [ opened, synchronize, reopened ]
6+
7+
jobs:
8+
label-pr:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
with:
13+
fetch-depth: 0
14+
15+
- name: Auto Label PR Based on Commits
16+
uses: actions/github-script@v7
17+
with:
18+
github-token: ${{ secrets.GITHUB_TOKEN }}
19+
script: |
20+
const { issue: { number: issue_number }, repo: { owner, repo } } = context;
21+
22+
// Get commits in the PR
23+
const { data: commits } = await github.rest.pulls.listCommits({
24+
owner,
25+
repo,
26+
pull_number: issue_number
27+
});
28+
29+
// Define valid types and their corresponding labels
30+
const typeToLabel = {
31+
'feat': 'type: new feature',
32+
'fix': 'type: bug',
33+
'docs': 'type: doc',
34+
'test': 'type: test',
35+
'chore': 'type: chore',
36+
'enhance': 'type: enhancement',
37+
'amend': 'type: amend',
38+
'style': 'type: chore',
39+
'refactor': 'type: enhancement',
40+
'perf': 'type: enhancement',
41+
'build': 'type: chore'
42+
};
43+
44+
const validTypes = Object.keys(typeToLabel);
45+
const pattern = new RegExp(`^(${validTypes.join('|')})(\(.+\))?!?: .+`);
46+
47+
let isValid = true;
48+
let invalidCommits = [];
49+
50+
// Check each commit
51+
for (const commit of commits) {
52+
const message = commit.commit.message.split('\n')[0]; // Get first line
53+
if (!pattern.test(message)) {
54+
isValid = false;
55+
invalidCommits.push(message);
56+
}
57+
}
58+
59+
// Get the first valid commit to determine the type
60+
const firstValidCommit = commits.find(commit => {
61+
const message = commit.commit.message.split('\n')[0];
62+
return pattern.test(message);
63+
});
64+
65+
// Get existing type labels
66+
const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
67+
owner,
68+
repo,
69+
issue_number
70+
});
71+
72+
if (isValid && firstValidCommit) {
73+
// Extract type from first valid commit
74+
const type = firstValidCommit.commit.message.match(pattern)[1];
75+
const labelToAdd = typeToLabel[type];
76+
77+
// Check if the label already exists
78+
const labelExists = currentLabels.some(label => label.name === labelToAdd);
79+
80+
if (!labelExists) {
81+
// Remove other type labels if they exist
82+
for (const label of currentLabels) {
83+
if (label.name.startsWith('type:') && label.name !== labelToAdd) {
84+
await github.rest.issues.removeLabel({
85+
owner,
86+
repo,
87+
issue_number,
88+
name: label.name
89+
});
90+
}
91+
}
92+
93+
// Add the new label
94+
await github.rest.issues.addLabels({
95+
owner,
96+
repo,
97+
issue_number,
98+
labels: [labelToAdd]
99+
});
100+
}
101+
} else {
102+
// Create error comment
103+
const errorMessage = `
104+
❌ Some commit messages don't follow the conventional format.
105+
106+
Invalid commits:
107+
${invalidCommits.map(msg => `- \`${msg}\``).join('\n')}
108+
109+
Please update your commits to follow the format:
110+
\`\`\`
111+
type: description
112+
113+
Valid types:
114+
- feat: New feature (type: new feature)
115+
- fix: Bug fix (type: bug)
116+
- docs: Documentation changes (type: doc)
117+
- test: Adding/updating tests (type: test)
118+
- chore: Maintenance tasks (type: chore)
119+
- enhance: Enhancement to existing features (type: enhancement)
120+
- amend: Small amendments (type: amend)
121+
- style: Code formatting (type: chore)
122+
- refactor: Code restructuring (type: enhancement)
123+
- perf: Performance improvements (type: enhancement)
124+
- build: Build system changes (type: chore)
125+
\`\`\`
126+
127+
You can update your commit messages using:
128+
\`\`\`bash
129+
git rebase -i HEAD~n # where n is the number of commits to edit
130+
# Change 'pick' to 'reword' for commits you want to edit
131+
\`\`\`
132+
`;
133+
134+
await github.rest.issues.createComment({
135+
owner,
136+
repo,
137+
issue_number,
138+
body: errorMessage
139+
});
140+
}

0 commit comments

Comments
 (0)