From b3b6e657fbd4c94f57b81ac95885339ff4ee1b59 Mon Sep 17 00:00:00 2001 From: Andrew Rynhard Date: Sat, 11 Apr 2020 10:57:15 -0700 Subject: [PATCH] feat: add spellcheck commit check This adds the ability to spellcheck commits. It supports US, UK, and GB locales. Signed-off-by: Andrew Rynhard --- .conform.yaml | 2 + README.md | 3 ++ go.mod | 1 + go.sum | 2 + internal/policy/commit/check_spelling.go | 68 ++++++++++++++++++++++++ internal/policy/commit/commit.go | 18 ++++--- 6 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 internal/policy/commit/check_spelling.go diff --git a/.conform.yaml b/.conform.yaml index e6a729a1..5429f01c 100644 --- a/.conform.yaml +++ b/.conform.yaml @@ -10,6 +10,8 @@ policies: required: true dco: true gpg: false + spellcheck: + locale: US maximumOfOneCommit: true conventional: types: diff --git a/README.md b/README.md index 1163b34b..40b90d61 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Some of the policies included are: - GPG signature - [Conventional Commits](https://www.conventionalcommits.org) - Imperative mood + - Spell check - Maximum of one commit ahead of `master` - Require a commit body - **License Headers**: Enforce license headers on source code files. @@ -51,6 +52,8 @@ policies: required: true dco: true gpg: false + spellcheck: + locale: US maximumOfOneCommit: true conventional: types: diff --git a/go.mod b/go.mod index 894a6844..e9ceda9b 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/talos-systems/conform require ( github.com/deckarep/golang-set v1.7.1 // indirect github.com/go-git/go-git/v5 v5.0.0 + github.com/golangci/misspell v0.3.4 github.com/google/go-cmp v0.3.1 // indirect github.com/google/go-github v17.0.0+incompatible github.com/google/go-querystring v1.0.0 // indirect diff --git a/go.sum b/go.sum index bbe86fd9..91db48c0 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1 github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg= github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golangci/misspell v0.3.4 h1:kAD5J0611Zo2VirUn9KFP15RjEqkmfEfnFxyIVxZCYg= +github.com/golangci/misspell v0.3.4/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= diff --git a/internal/policy/commit/check_spelling.go b/internal/policy/commit/check_spelling.go new file mode 100644 index 00000000..da21a2ec --- /dev/null +++ b/internal/policy/commit/check_spelling.go @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package commit + +import ( + "fmt" + "strings" + + "github.com/talos-systems/conform/internal/policy" + + "github.com/golangci/misspell" +) + +// SpellCheck represents to spell check policy. +type SpellCheck struct { + Locale string `mapstructure:"locale"` +} + +// SpellingCheck enforces correct spelling. +type SpellingCheck struct { + errors []error +} + +// Name returns the name of the check. +func (h SpellingCheck) Name() string { + return "Spellcheck" +} + +// Message returns to check message. +func (h SpellingCheck) Message() string { + return fmt.Sprintf("Commit contains %d misspellings", len(h.errors)) +} + +// Errors returns any violations of the check. +func (h SpellingCheck) Errors() []error { + return h.errors +} + +// ValidateSpelling checks the spelling. +func (c Commit) ValidateSpelling() policy.Check { + check := &SpellingCheck{} + + r := misspell.Replacer{ + Replacements: misspell.DictMain, + } + + switch strings.ToUpper(c.SpellCheck.Locale) { + case "": + case "US": + r.AddRuleList(misspell.DictAmerican) + case "UK", "GB": + r.AddRuleList(misspell.DictBritish) + case "NZ", "AU", "CA": + check.errors = append(check.errors, fmt.Errorf("unknown locale: %q", c.SpellCheck.Locale)) + } + + r.Compile() + + _, diffs := r.Replace(c.msg) + + for _, diff := range diffs { + check.errors = append(check.errors, fmt.Errorf("`%s` is a misspelling of `%s`", diff.Original, diff.Corrected)) + } + + return check +} diff --git a/internal/policy/commit/commit.go b/internal/policy/commit/commit.go index cb90aea5..bf62acf4 100644 --- a/internal/policy/commit/commit.go +++ b/internal/policy/commit/commit.go @@ -36,6 +36,14 @@ type BodyChecks struct { // Commit implements the policy.Policy interface and enforces commit // messages to conform the Conventional Commit standard. type Commit struct { + // SpellCheck enforces correct spelling. + SpellCheck *SpellCheck `mapstructure:"spellcheck"` + // Conventional is the user specified settings for conventional commits. + Conventional *Conventional `mapstructure:"conventional"` + // Header is the user specified settings for the header of each commit. + Header *HeaderChecks `mapstructure:"header"` + // Header is the user specified settings for the body of each commit. + Body *BodyChecks `mapstructure:"body"` // DCO enables the Developer Certificate of Origin check. DCO bool `mapstructure:"dco"` // GPG enables the GPG signature check. @@ -43,12 +51,6 @@ type Commit struct { // MaximumOfOneCommit enforces that the current commit is only one commit // ahead of a specified ref. MaximumOfOneCommit bool `mapstructure:"maximumOfOneCommit"` - // Conventional is the user specified settings for conventional commits. - Conventional *Conventional `mapstructure:"conventional"` - // Header is the user specified settings for the header of each commit. - Header *HeaderChecks `mapstructure:"header"` - // Header is the user specified settings for the body of each commit. - Body *BodyChecks `mapstructure:"body"` msg string } @@ -113,6 +115,10 @@ func (c *Commit) Compliance(options *policy.Options) (*policy.Report, error) { report.AddCheck(c.ValidateConventionalCommit()) } + if c.SpellCheck != nil { + report.AddCheck(c.ValidateSpelling()) + } + if c.MaximumOfOneCommit { report.AddCheck(c.ValidateNumberOfCommits(g, "refs/heads/master")) }