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 117
|
name: ✒️ Conventional Commits
on:
pull_request_target:
paths-ignore:
- 'doc/**'
- '*.md'
branches:
- master
- release/**
permissions:
contents: read
pull-requests: write
jobs:
conventional-commits:
name: 📜 Parse PR commits
runs-on: ubuntu-latest
steps:
- name: 🔎 Check PR commit messages follow Conventional Commits
uses: actions/github-script@v8
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const pull_number = context.payload.pull_request.number;
const marker = "<!-- conventional-commits-check -->";
// Conventional Commits v1.0.0 summary line regex
const re = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([^)]+\))?(!)?:\s\S.+/;
const commits = await github.paginate(
github.rest.pulls.listCommits,
{ owner, repo, pull_number, per_page: 100 }
);
const invalid = [];
for (const c of commits) {
const summary = c.commit.message.split("\n")[0];
if (!re.test(summary)) {
invalid.push({
sha: c.sha.substring(0, 7),
message: summary,
});
}
}
// Find existing bot comment (if any)
const comments = await github.paginate(
github.rest.issues.listComments,
{ owner, repo, issue_number: pull_number }
);
const existing = comments.find(
c => c.user?.type === "Bot" && c.body?.includes(marker)
);
if (invalid.length > 0) {
const body =
`${marker}
### ❌ Conventional Commits check failed
One or more commit messages in this PR do **not** follow the
[Conventional Commits v1.0.0](https://www.conventionalcommits.org/en/v1.0.0/) specification.
**Invalid commits:**
${invalid.map(i => `- \`${i.sha}\` — ${i.message}`).join("\n")}
**Expected format**
\`\`\`
type(scope?)!?: subject
\`\`\`
**Examples**
- \`feat: add user login\`
- \`fix(api): handle null response\`
- \`chore!: drop node 16 support\`
Please fix the commit messages (e.g. via \`git rebase -i\`) and push again.`;
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner,
repo,
issue_number: pull_number,
body,
});
}
core.setFailed(
`${invalid.length} commit(s) do not follow Conventional Commits`
);
} else {
// If previously failed, clean up the comment
if (existing) {
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existing.id,
body: `${marker}
### ✅ Conventional Commits check passed
All commit messages in this PR now follow the Conventional Commits specification. 🎉`,
});
}
core.info(`All ${commits.length} commit(s) follow Conventional Commits.`);
}
|