Documentation
¶
Overview ¶
Package rules implements commit validation rules for gommitlint.
Rule Interfaces ¶
Rules implement one of two interfaces defined in the domain package:
- domain.CommitRule: For rules that only need commit data (subject, body, author, etc.)
- domain.RepositoryRule: For rules that need repository access (branch comparison, signatures)
Implementation Pattern ¶
All rules follow a consistent pattern:
- Use value receivers (not pointer receivers) for immutability
- Accept configuration via constructor when needed (e.g., NewSubjectRule(cfg settings.Config))
- Return []domain.ValidationError from Validate method
- Use fluent error building with domain.New().WithContextMap().WithHelp()
- Rule enablement is handled by the factory, not internally by the rule
Example implementation:
type MyRule struct {
maxLength int
}
func NewMyRule(cfg settings.Config) MyRule {
return MyRule{maxLength: cfg.Message.Subject.MaxLength}
}
func (r MyRule) Name() string { return "myrule" }
func (r MyRule) Validate(commit domain.Commit) []domain.ValidationError {
if len(commit.Subject) > r.maxLength {
return []domain.ValidationError{
domain.New(r.Name(), domain.ErrSubjectTooLong, "Subject too long").
WithContextMap(map[string]string{
"actual": strconv.Itoa(len(commit.Subject)),
"expected": fmt.Sprintf("max %d", r.maxLength),
}).
WithHelp("Shorten your commit message subject line."),
}
}
return nil
}
Shared Patterns ¶
The patterns.go file contains compiled regex patterns shared across rules:
- SignOffPattern: Validates DCO sign-off format ("Signed-off-by: Name <email>")
- EmailPattern: Extracts email addresses from angle brackets
- TrailerPattern: Matches common Git trailer formats (Signed-off-by, Co-authored-by, Fixes, etc.)
These patterns are compiled once at package initialization for performance.
Rule Categories ¶
CommitRules (validate single commits):
- subject: Subject line length validation
- conventional: Conventional Commits format validation
- imperative: Imperative mood verb checking
- signoff: DCO sign-off validation
- commitbody: Commit body structure validation
- spell: Spelling validation
- jira: JIRA reference validation
- identity: Author identity validation
- linearhistory: Linear history checking (no merge commits)
RepositoryRules (require repository access):
- branchahead: Branch comparison with upstream
- cryptosignature: GPG/SSH signature verification
Index ¶
- Constants
- Variables
- func CreateImperativeSuggestion(stem, originalWord string) string
- func IsBaseFormEndingWithED(word string) bool
- func IsBaseFormEndingWithS(word string) bool
- func IsConventionalLike(subject string) bool
- func IsNonImperativeStarter(word string) bool
- func ValidateWithSimpleRules(wordLower, originalWord, subject, ruleName string) []domain.ValidationError
- type BranchAheadRule
- type CommitBodyRule
- type ConventionalCommitRule
- type CryptoSignatureRule
- type IdentityRule
- type ImperativeValidator
- type JiraReferenceRule
- type KeyIdentity
- type KeyProvider
- type LinearHistoryRule
- type SignOffRule
- type SpellChecker
- type SpellRule
- type SubjectRule
Constants ¶
const ( CaseLower = "lower" CaseUpper = "upper" CaseSentence = "sentence" CaseAny = "any" )
Subject case constants.
Variables ¶
var ( ErrSubjectEmpty = errors.New("subject is empty") ErrMissingSubjectAfterType = errors.New("missing subject after type") ErrInvalidConventionalCommitFmt = errors.New("invalid conventional commit format") ErrInvalidFormat = errors.New("invalid format") ErrNoLetterFound = errors.New("no letter found") )
Subject validation errors.
var EmailPattern = regexp.MustCompile(`<([^>]+)>`)
EmailPattern extracts email addresses from angle brackets.
var (
ErrSubjectNotConventional = errors.New("subject does not match conventional format")
)
Conventional commit validation errors.
var SignOffPattern = regexp.MustCompile(`^Signed-off-by:\s+.+\s+<.+@.+>$`)
SignOffPattern validates DCO (Developer Certificate of Origin) sign-off format. Enforces proper "Name <email@domain>" format as required by DCO specification.
Pattern breakdown:
^Signed-off-by: - Required trailer prefix \s+ - Required whitespace after colon .+ - Name (any characters) \s+ - Required space before email <.+@.+>$ - Email in angle brackets
Valid examples:
✓ "Signed-off-by: John Doe <[email protected]>" ✓ "Signed-off-by: Jane Smith <[email protected]>" ✗ "Signed-off-by:John<[email protected]>" (missing spaces) ✗ "Signed-off-by: John Doe [email protected]" (missing angle brackets)
var TrailerPattern = regexp.MustCompile(`^(Signed-off-by|Co-authored-by|Reviewed-by|Acked-by|Tested-by|Reported-by):\s+.+\s+<.+@.+>$|^(Fixes|Closes|Resolves):\s*(#\d+|https?://[^\s]+).*$`)
TrailerPattern matches common Git trailer formats including: - Sign-off trailers: Signed-off-by, Co-authored-by, Reviewed-by, etc. - Reference trailers: Fixes, Closes, Resolves with issue numbers or URLs
Functions ¶
func CreateImperativeSuggestion ¶
CreateImperativeSuggestion creates a proper imperative suggestion from a stem, preserving the original word's capitalization pattern.
func IsBaseFormEndingWithED ¶
IsBaseFormEndingWithED checks if a word ending with 'ed' is actually a base form.
func IsBaseFormEndingWithS ¶
IsBaseFormEndingWithS checks if a word ending with 's' is actually a base form.
func IsConventionalLike ¶
IsConventionalLike checks if text looks like an attempted conventional commit.
func IsNonImperativeStarter ¶
IsNonImperativeStarter checks if a word is a non-imperative starter.
func ValidateWithSimpleRules ¶
func ValidateWithSimpleRules(wordLower, originalWord, subject, ruleName string) []domain.ValidationError
ValidateWithSimpleRules provides pattern-based imperative validation when stemming fails.
Types ¶
type BranchAheadRule ¶
type BranchAheadRule struct {
// contains filtered or unexported fields
}
BranchAheadRule validates that the current branch is not too many commits ahead of the reference branch.
func NewBranchAheadRule ¶
func NewBranchAheadRule(cfg settings.Config) BranchAheadRule
NewBranchAheadRule creates a new rule for checking commits ahead of a reference branch from settings.
func (BranchAheadRule) Name ¶
func (r BranchAheadRule) Name() string
Name implements Rule interface.
func (BranchAheadRule) Validate ¶
func (r BranchAheadRule) Validate(ctx context.Context, repo domain.Repository, cfg settings.Config) []domain.ValidationError
Validate implements RepositoryRule interface.
type CommitBodyRule ¶
type CommitBodyRule struct {
// contains filtered or unexported fields
}
CommitBodyRule validates commit message bodies.
func NewCommitBodyRule ¶
func NewCommitBodyRule(cfg settings.Config) CommitBodyRule
NewCommitBodyRule creates a new CommitBodyRule from settings.
func (CommitBodyRule) Validate ¶
func (r CommitBodyRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements CommitRule interface.
type ConventionalCommitRule ¶
type ConventionalCommitRule struct {
// contains filtered or unexported fields
}
ConventionalCommitRule validates Conventional Commits specification compliance.
func NewConventionalCommitRule ¶
func NewConventionalCommitRule(cfg settings.Config) ConventionalCommitRule
NewConventionalCommitRule creates a new rule for validating conventional commits from settings.
func (ConventionalCommitRule) Name ¶
func (r ConventionalCommitRule) Name() string
Name implements Rule interface.
func (ConventionalCommitRule) Validate ¶
func (r ConventionalCommitRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements CommitRule interface.
type CryptoSignatureRule ¶
type CryptoSignatureRule struct {
// contains filtered or unexported fields
}
CryptoSignatureRule validates signature presence, format, policy, and trusted key configuration.
This rule validates:
- Signature presence (when required: true)
- Signature format structure (when verify_format: true)
- Signature type matches requirements (require_gpg/require_ssh)
- Trusted keys exist in key_directory (when key_directory is set)
- Keys meet minimum strength requirements (min_rsa_bits/min_ec_bits)
- Keys are not revoked or expired (GPG only)
It does NOT verify that the signature cryptographically matches the commit. Cryptographic verification would require access to the raw Git commit object, which is not currently available in the domain model.
func NewCryptoSignatureRule ¶
func NewCryptoSignatureRule(cfg settings.Config, keyProvider KeyProvider) CryptoSignatureRule
NewCryptoSignatureRule creates a new rule for signature policy validation.
func (CryptoSignatureRule) Name ¶
func (r CryptoSignatureRule) Name() string
Name implements Rule interface.
func (CryptoSignatureRule) Validate ¶
func (r CryptoSignatureRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements CommitRule interface.
type IdentityRule ¶
type IdentityRule struct {
// contains filtered or unexported fields
}
IdentityRule validates that commit authors are in the allowed list. Matching is done by email only (case-insensitive). Supports domain wildcards: "*@company.com" matches any email from that domain.
func NewIdentityRule ¶
func NewIdentityRule(cfg settings.Config) IdentityRule
NewIdentityRule creates a new rule for validating author identity from settings.
func (IdentityRule) Validate ¶
func (r IdentityRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements CommitRule interface.
type ImperativeValidator ¶
type ImperativeValidator struct{}
ImperativeValidator validates imperative mood using Snowball stemming.
func NewImperativeValidator ¶
func NewImperativeValidator() *ImperativeValidator
NewImperativeValidator creates a new imperative validator.
func (*ImperativeValidator) ValidateImperative ¶
func (v *ImperativeValidator) ValidateImperative(text, originalSubject string, isConventional bool, ruleName string) []domain.ValidationError
ValidateImperative checks if text is in imperative mood.
type JiraReferenceRule ¶
type JiraReferenceRule struct {
// contains filtered or unexported fields
}
JiraReferenceRule validates that commit messages reference JIRA issues.
func NewJiraReferenceRule ¶
func NewJiraReferenceRule(cfg settings.Config, isConventionalEnabled bool) JiraReferenceRule
NewJiraReferenceRule creates a new rule for validating JIRA references.
func (JiraReferenceRule) Name ¶
func (r JiraReferenceRule) Name() string
Name implements Rule interface.
func (JiraReferenceRule) Validate ¶
func (r JiraReferenceRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements Rule interface.
type KeyIdentity ¶
type KeyIdentity struct {
Fingerprint string // SHA256 for SSH, hex for GPG
Emails []string // Extracted from User IDs or comments
UserIDs []string // Full User ID strings (GPG) or comment (SSH)
}
KeyIdentity holds all matchable identity forms for a cryptographic key. This allows flexible matching against fingerprints, emails, or full identity strings.
func (KeyIdentity) Matches ¶
func (k KeyIdentity) Matches(allowedSigners []string) bool
Matches checks if any allowed signer matches this key identity. Empty allowedSigners permits all keys.
func (KeyIdentity) PrimaryIdentity ¶
func (k KeyIdentity) PrimaryIdentity() string
PrimaryIdentity returns the best identifier for display purposes.
type KeyProvider ¶
type KeyProvider interface {
// ListKeyFiles returns paths to available key files with specified extensions.
ListKeyFiles(extensions []string) ([]string, error)
// ReadKeyFile reads the contents of a key file.
ReadKeyFile(path string) ([]byte, error)
// ValidateDirectory checks if the key directory exists and is accessible.
ValidateDirectory() error
}
KeyProvider defines the interface for accessing cryptographic keys. This abstraction allows the domain to validate signatures without directly accessing the filesystem, following hexagonal architecture.
type LinearHistoryRule ¶
type LinearHistoryRule struct{}
LinearHistoryRule validates that commits are not merge commits. This enforces a rebase workflow where feature branches are rebased onto the target branch rather than merged. Implements domain.CommitRule interface.
func NewLinearHistoryRule ¶
func NewLinearHistoryRule() LinearHistoryRule
NewLinearHistoryRule creates a new rule for enforcing linear history. The rule is only created by the factory when enabled via configuration, so no internal enabled check is needed.
func (LinearHistoryRule) Name ¶
func (r LinearHistoryRule) Name() string
Name implements CommitRule interface.
func (LinearHistoryRule) Validate ¶
func (r LinearHistoryRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements CommitRule interface. Returns a validation error if the commit is a merge commit.
type SignOffRule ¶
type SignOffRule struct {
// contains filtered or unexported fields
}
SignOffRule validates that commit messages include a sign-off line.
func NewSignOffRule ¶
func NewSignOffRule(cfg settings.Config) SignOffRule
NewSignOffRule creates a new rule for validating commit sign-offs from settings.
func (SignOffRule) Validate ¶
func (r SignOffRule) Validate(commit domain.Commit) []domain.ValidationError
Validate implements CommitRule interface.
type SpellChecker ¶
type SpellChecker interface {
CheckText(text string) []domain.Misspelling
}
SpellChecker defines the interface for spell checking operations. This interface is defined by the consumer (domain), following Go's principle of "accept interfaces, return concrete types".
type SpellRule ¶
type SpellRule struct {
// contains filtered or unexported fields
}
SpellRule validates spelling in commit messages.
func NewSpellRule ¶
func NewSpellRule(cfg settings.Config, checker SpellChecker) SpellRule
NewSpellRule creates a new SpellRule with the provided checker. The SpellChecker interface is defined in factory.go (consumer side).
type SubjectRule ¶
type SubjectRule struct {
// contains filtered or unexported fields
}
SubjectRule validates commit subject length, case, suffix, and imperative mood.
func NewSubjectRule ¶
func NewSubjectRule(cfg settings.Config, isConventionalEnabled bool) SubjectRule
NewSubjectRule creates a new SubjectRule from config with explicit conventional rule dependency.
func (SubjectRule) Validate ¶
func (r SubjectRule) Validate(commit domain.Commit) []domain.ValidationError
Validate validates commit subject requirements.