rules

package
v0.8.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 15, 2026 License: EUPL-1.2 Imports: 19 Imported by: 0

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:

  1. Use value receivers (not pointer receivers) for immutability
  2. Accept configuration via constructor when needed (e.g., NewSubjectRule(cfg settings.Config))
  3. Return []domain.ValidationError from Validate method
  4. Use fluent error building with domain.New().WithContextMap().WithHelp()
  5. 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

View Source
const (
	CaseLower    = "lower"
	CaseUpper    = "upper"
	CaseSentence = "sentence"
	CaseAny      = "any"
)

Subject case constants.

Variables

View Source
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.

View Source
var EmailPattern = regexp.MustCompile(`<([^>]+)>`)

EmailPattern extracts email addresses from angle brackets.

View Source
var (
	ErrSubjectNotConventional = errors.New("subject does not match conventional format")
)

Conventional commit validation errors.

View Source
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)
View Source
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

func CreateImperativeSuggestion(stem, originalWord string) string

CreateImperativeSuggestion creates a proper imperative suggestion from a stem, preserving the original word's capitalization pattern.

func IsBaseFormEndingWithED

func IsBaseFormEndingWithED(word string) bool

IsBaseFormEndingWithED checks if a word ending with 'ed' is actually a base form.

func IsBaseFormEndingWithS

func IsBaseFormEndingWithS(word string) bool

IsBaseFormEndingWithS checks if a word ending with 's' is actually a base form.

func IsConventionalLike

func IsConventionalLike(subject string) bool

IsConventionalLike checks if text looks like an attempted conventional commit.

func IsNonImperativeStarter

func IsNonImperativeStarter(word string) bool

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

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) Name

func (r CommitBodyRule) Name() string

Name implements Rule interface.

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

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

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) Name

func (r IdentityRule) Name() string

Name implements Rule interface.

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) Name

func (r SignOffRule) Name() string

Name implements Rule interface.

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).

func (SpellRule) Name

func (r SpellRule) Name() string

Name implements Rule interface.

func (SpellRule) Validate

func (r SpellRule) Validate(commit domain.Commit) []domain.ValidationError

Validate checks commit message text for spelling errors using configured dictionary.

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) Name

func (r SubjectRule) Name() string

Name implements Rule interface.

func (SubjectRule) Validate

func (r SubjectRule) Validate(commit domain.Commit) []domain.ValidationError

Validate validates commit subject requirements.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL