A GitHub Action that validates Pull Request titles against the Conventional Commits specification.
- Full support for Conventional Commits v1.0.0 specification
- Validates PR title format:
<type>[optional scope][optional !]: <description> - Supports breaking change markers (
!) - Configurable strict mode for enhanced validation
- Clear, actionable error messages with examples
- No external dependencies beyond GitHub Actions toolkit
Create a .github/workflows/pr-title-checker.yml file in your repository:
name: PR Title Lint
on:
pull_request:
types: [opened, edited, synchronize, reopened]
jobs:
check-title:
name: Check PR Title
runs-on: ubuntu-latest
steps:
- name: Validate PR Title
uses: openGemini/pr-title-checker@main- name: Validate PR Title
uses: openGemini/pr-title-checker@main
with:
strict: 'true' # Enable strict mode (default)
max_description_length: '72' # Set max description length to 72 characters (default: 50)<type>[optional scope][optional !]: <description>
Required. Must be one of the following (lowercase only):
feat- A new featurefix- A bug fixdocs- Documentation changesstyle- Code style changes (formatting, missing semicolons, etc.)refactor- Code refactoring (neither fixes a bug nor adds a feature)perf- Performance improvementstest- Adding or updating testsbuild- Build system or external dependency changesci- CI configuration changeschore- Other changes that don't modify src or test filesrevert- Reverting a previous commit
Optional. Indicates the area of change. If provided:
- Must be enclosed in parentheses:
(scope) - Can only contain lowercase letters, numbers, hyphens, and underscores
- Cannot be empty (use no scope instead of
())
Examples:
feat(auth): add loginfix(api): handle timeoutdocs(readme): update usage
Optional. Use ! to indicate a breaking change:
- Must be placed after the scope (or type if no scope)
- Must be before the colon
Examples:
feat!: breaking changefeat(api)!: breaking API change
Required. A brief description of the change:
- Maximum length is configurable (default: 50 characters)
- Must have exactly one space after the colon
- Cannot start or end with spaces
- Must contain only displayable ASCII characters (range: 32-126)
When strict mode is enabled (default), the description must also:
- Start with a lowercase letter
- Not end with a period
- Use imperative mood (e.g., "add" not "added" or "adds")
feat: add user authentication
fix: resolve memory leak
docs: update installation guide
style: format code with prettier
refactor: simplify error handling
perf: optimize database queries
test: add unit tests for api
build: update webpack config
ci: configure github actions
chore: update dependencies
revert: undo breaking change
feat(auth): add oauth2 support
fix(api): handle timeout errors
docs(readme): clarify usage examples
feat(api)!: breaking change in api
fix!: critical security fix
Feature: add something # Invalid type
feat : add something # Space before colon
feat:add something # Missing space after colon
feat: Add something # Uppercase start (strict mode)
feat: add something. # Period at end (strict mode)
feat: added something # Past tense (strict mode)
feat(): add something # Empty scope
feat(API): add endpoint # Uppercase in scope (strict mode)
feat: 这是中文 # Non-ASCII characters
feat: add user authentication that is very long description exceeding limit # Too long (>50 chars)
| Input | Description | Required | Default |
|---|---|---|---|
strict |
Enable strict mode validation | No | true |
max_description_length |
Maximum length for the description part | No | 50 |
When enabled (default), strict mode enforces additional rules:
- Description must start with a lowercase letter
- Description must not end with a period
- Description should use imperative mood
To disable strict mode:
- name: Validate PR Title
uses: openGemini/pr-title-checker@main
with:
strict: 'false'By default, the description is limited to 50 characters (following Conventional Commits best practices). You can customize this limit:
- name: Validate PR Title
uses: openGemini/pr-title-checker@main
with:
max_description_length: '72' # Allow up to 72 charactersCommon length limits:
50- Conventional Commits default (recommended for commit messages)72- Git commit message standard100- Relaxed limit for longer descriptions
-
"Type must be lowercase"
- Use
featnotFeatorFEAT
- Use
-
"Description must start with lowercase letter"
- Use
feat: add featurenotfeat: Add feature - Disable strict mode if you prefer uppercase
- Use
-
"Description should use imperative mood"
- Use
feat: add featurenotfeat: added featureorfeat: adds feature - Think of completing the sentence: "This commit will..."
- Use
-
"Scope format is incorrect"
- Use lowercase, numbers, hyphens, or underscores only
feat(user-auth): ...is validfeat(User Auth): ...is invalid
-
"Breaking change marker must be placed after scope"
- Use
feat(api)!: changenotfeat!(api): change
- Use
npm install
npm run buildnpm testYou can test the action locally by running:
npm run build
node dist/index.jsApache-2.0
Contributions are welcome! Please feel free to submit a Pull Request.