add: import code
портирован код из старого репозитория https://di9.ru/git/Voomra/Conventional-Commits
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# App
|
||||||
|
target/
|
||||||
|
!target/.gitkeep
|
||||||
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
9
.idea/go-commitlint.iml
generated
Normal file
9
.idea/go-commitlint.iml
generated
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/go-commitlint.iml" filepath="$PROJECT_DIR$/.idea/go-commitlint.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
13
Makefile
Normal file
13
Makefile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!make
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
GOOS=linux go build -o target/commitlint cmd/commitlint/main.go
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
GOOS=windows go build -o target/commitlint.exe cmd/commitlint/main.go
|
||||||
|
|
||||||
|
publish-linux:
|
||||||
|
curl -XPUT --user ${GITEA_USER}:${GITEA_TOKEN} --upload-file target/commitlint ${GITEA_URL}/api/packages/${GITEA_USER}/generic/di9.go.commitlint/1.2/commitlint
|
||||||
|
|
||||||
|
publish-windows:
|
||||||
|
curl -XPUT --user ${GITEA_USER}:${GITEA_TOKEN} --upload-file target/commitlint.exe ${GITEA_URL}/api/packages/${GITEA_USER}/generic/di9.go.commitlint/1.2/commitlint.exe
|
||||||
51
README.MD
Normal file
51
README.MD
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Commit-lint tool
|
||||||
|
|
||||||
|
Программа на Go для проверки описаний коммитов на соответствие [соглашению о коммитах](https://di9.ru/git/Conventional-Commits/specification/src/branch/master/CONVENTIONAL_COMMITS.MD).
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
Добавить git hook `commit-msg`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
commitlint -commitMessage="$1" -config="commitlint.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
| Параметр | Описание | По-умолчанию |
|
||||||
|
|:-----------------|:--------------------------------|-----------------------|
|
||||||
|
| `-commitMessage` | Путь до файла сообщения коммита | `.git/COMMIT_EDITMSG` |
|
||||||
|
| `-config` | Путь до файла настроек | `commitlint.json` |
|
||||||
|
|
||||||
|
### Настройка
|
||||||
|
|
||||||
|
Настройка по-умолчанию считывается из файла `commitlint.json`, который находится в корне репозитория
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"types": [ "build", "docs", "pref", "refac", "revert", "style", "test" ],
|
||||||
|
"contexts": [ "git", "ide" ],
|
||||||
|
"excludes": [ "^wip$" ],
|
||||||
|
"maxLengthLine": 72
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Настройка | Описание |
|
||||||
|
|:----------------|:------------------------------------------|
|
||||||
|
| `types` | Перечисление допустимых типов коммитов |
|
||||||
|
| `contexts` | Перечисление допустимых контекстов |
|
||||||
|
| `excludes` | Перечисление шаблонов для исключений |
|
||||||
|
| `maxLengthLine` | Максимальная длинна первой строки коммита |
|
||||||
|
|
||||||
|
## Сборка
|
||||||
|
|
||||||
|
Для Linux:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make build-linux
|
||||||
|
```
|
||||||
|
|
||||||
|
Для Windows:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
make build-windows
|
||||||
|
```
|
||||||
17
cmd/commitlint/main.go
Normal file
17
cmd/commitlint/main.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"commitlint/internal/commitlint"
|
||||||
|
"flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
commitMessagePath := flag.String("commitMessage", ".git/COMMIT_EDITMSG", "path to commit message file")
|
||||||
|
configPath := flag.String("config", "commitlint.json", "configuration file")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
err := commitlint.EntryPoint(commitMessagePath, configPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
11
go.mod
Normal file
11
go.mod
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module commitlint
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require github.com/stretchr/testify v1.9.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
)
|
||||||
10
go.sum
Normal file
10
go.sum
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
63
internal/commitlint/commitlint.go
Normal file
63
internal/commitlint/commitlint.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package commitlint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"commitlint/internal/commitlint/configuration"
|
||||||
|
"commitlint/internal/commitlint/validator"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func EntryPoint(pCommitMessagePath *string, pConfigPath *string) error {
|
||||||
|
pConfig, err := configuration.CreateConfig(pConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
commitMessage, err := ReadCommitMessage(*pCommitMessagePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pResult := validator.Validate(commitMessage, *pConfig)
|
||||||
|
if pResult != nil {
|
||||||
|
var errMessage string
|
||||||
|
|
||||||
|
switch pResult.Result {
|
||||||
|
case validator.IncorrectPattern:
|
||||||
|
errMessage = "Incorrect commit message format"
|
||||||
|
case validator.UnknownType:
|
||||||
|
errMessage = fmt.Sprintf("Unknown commit type '%s'", pResult.UnknownType)
|
||||||
|
case validator.UnknownContext:
|
||||||
|
errMessage = fmt.Sprintf("Unknown commit context '%s'", pResult.UnknownContext)
|
||||||
|
case validator.OverlongLine:
|
||||||
|
errMessage = fmt.Sprintf("Line number %d exceeds the allowed length", pResult.Line)
|
||||||
|
case validator.BlankLine:
|
||||||
|
errMessage = "Use blank line before BODY"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := fmt.Fprintln(os.Stderr, errMessage)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadCommitMessage(path string) ([]string, error) {
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
_ = file.Close()
|
||||||
|
}(file)
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
lines = append(lines, scanner.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines, err
|
||||||
|
}
|
||||||
35
internal/commitlint/commitlint_test.go
Normal file
35
internal/commitlint/commitlint_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package commitlint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReadCommitMessage(t *testing.T) {
|
||||||
|
createTmpFile := func() string {
|
||||||
|
tmpFile, err := os.CreateTemp("", "COMMIT_EDITMSG")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer func(tmpFile *os.File) {
|
||||||
|
_ = tmpFile.Close()
|
||||||
|
}(tmpFile)
|
||||||
|
|
||||||
|
_, err = tmpFile.WriteString("Line 1\nLine 2\nLine 3")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpFile.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
exceptedContent := []string{"Line 1", "Line 2", "Line 3"}
|
||||||
|
|
||||||
|
message, err := ReadCommitMessage(createTmpFile())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, exceptedContent, message)
|
||||||
|
}
|
||||||
105
internal/commitlint/configuration/config.go
Normal file
105
internal/commitlint/configuration/config.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserConfig struct {
|
||||||
|
Types *[]string `json:"types"`
|
||||||
|
Contexts *[]string `json:"contexts"`
|
||||||
|
Excludes *[]string `json:"excludes"`
|
||||||
|
MaxLengthLine *int `json:"maxLengthLine"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Types []string
|
||||||
|
Contexts []string
|
||||||
|
Excludes []*regexp.Regexp
|
||||||
|
MaxLengthLine int
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateConfig(pPath *string) (*Config, error) {
|
||||||
|
config := Config{
|
||||||
|
Types: []string{"fix", "feat"},
|
||||||
|
Contexts: []string{},
|
||||||
|
Excludes: []*regexp.Regexp{},
|
||||||
|
MaxLengthLine: 72,
|
||||||
|
}
|
||||||
|
|
||||||
|
if pPath != nil && isFileExists(*pPath) {
|
||||||
|
userConfig, err := readUserConfig(*pPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeConfigs(&config, userConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isFileExists(path string) bool {
|
||||||
|
info, err := os.Stat(path)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return !info.IsDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
func readUserConfig(path string) (*UserConfig, error) {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer func(fileJson *os.File) {
|
||||||
|
err := fileJson.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}(file)
|
||||||
|
|
||||||
|
bytes, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var userConfig UserConfig
|
||||||
|
err = json.Unmarshal(bytes, &userConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &userConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeConfigs(config *Config, userConfig *UserConfig) {
|
||||||
|
if userConfig.Types != nil {
|
||||||
|
for _, item := range *(*userConfig).Types {
|
||||||
|
config.Types = append(config.Types, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if userConfig.Contexts != nil {
|
||||||
|
for _, item := range *(userConfig.Contexts) {
|
||||||
|
config.Contexts = append(config.Contexts, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if userConfig.Excludes != nil {
|
||||||
|
for _, item := range *(userConfig.Excludes) {
|
||||||
|
pattern, err := regexp.Compile("(?i)" + item)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Excludes = append(config.Excludes, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if userConfig.MaxLengthLine != nil {
|
||||||
|
config.MaxLengthLine = *(userConfig.MaxLengthLine)
|
||||||
|
}
|
||||||
|
}
|
||||||
69
internal/commitlint/configuration/config_test.go
Normal file
69
internal/commitlint/configuration/config_test.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReadUserConfig(t *testing.T) {
|
||||||
|
createTmpJson := func() string {
|
||||||
|
tmpFile, err := os.CreateTemp("", "config.json")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer func(tmpFile *os.File) {
|
||||||
|
_ = tmpFile.Close()
|
||||||
|
}(tmpFile)
|
||||||
|
|
||||||
|
_, err = tmpFile.WriteString(`{"types": ["type1", "type2"], "contexts": ["ctx1", "ctx2"], "excludes": ["^wip$"], "maxLengthLine": 14}`)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpFile.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedUserConfig := UserConfig{}
|
||||||
|
expectedUserConfig.Types = &([]string{"type1", "type2"})
|
||||||
|
expectedUserConfig.Contexts = &([]string{"ctx1", "ctx2"})
|
||||||
|
expectedUserConfig.Excludes = &([]string{"^wip$"})
|
||||||
|
expectedUserConfig.MaxLengthLine = new(int)
|
||||||
|
*(expectedUserConfig.MaxLengthLine) = 14
|
||||||
|
|
||||||
|
userConfig, err := readUserConfig(createTmpJson())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, expectedUserConfig, *userConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeConfigs(t *testing.T) {
|
||||||
|
config := Config{
|
||||||
|
Types: []string{"fix", "feat"},
|
||||||
|
Contexts: []string{},
|
||||||
|
Excludes: []*regexp.Regexp{},
|
||||||
|
MaxLengthLine: 72,
|
||||||
|
}
|
||||||
|
|
||||||
|
userConfig := UserConfig{}
|
||||||
|
userConfig.Types = &([]string{"type1", "type2"})
|
||||||
|
userConfig.Contexts = &([]string{"ctx1", "ctx2"})
|
||||||
|
userConfig.Excludes = &([]string{"^wip$"})
|
||||||
|
userConfig.MaxLengthLine = new(int)
|
||||||
|
*(userConfig.MaxLengthLine) = 14
|
||||||
|
|
||||||
|
expectedConfig := Config{
|
||||||
|
Types: []string{"fix", "feat", "type1", "type2"},
|
||||||
|
Contexts: []string{"ctx1", "ctx2"},
|
||||||
|
Excludes: []*regexp.Regexp{},
|
||||||
|
MaxLengthLine: 14,
|
||||||
|
}
|
||||||
|
expectedConfig.Excludes = append(expectedConfig.Excludes, regexp.MustCompile("^wip$"))
|
||||||
|
|
||||||
|
mergeConfigs(&config, &userConfig)
|
||||||
|
|
||||||
|
assert.Equal(t, expectedConfig, config)
|
||||||
|
}
|
||||||
90
internal/commitlint/validator/validator.go
Normal file
90
internal/commitlint/validator/validator.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package validator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"commitlint/internal/commitlint/configuration"
|
||||||
|
"regexp"
|
||||||
|
"slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Result int
|
||||||
|
|
||||||
|
const (
|
||||||
|
IncorrectPattern Result = iota
|
||||||
|
UnknownType
|
||||||
|
UnknownContext
|
||||||
|
OverlongLine
|
||||||
|
BlankLine
|
||||||
|
)
|
||||||
|
|
||||||
|
type ValidateError struct {
|
||||||
|
// Тип проблемы
|
||||||
|
Result Result
|
||||||
|
|
||||||
|
// Проблемная строка в коммите. Начинается с 1
|
||||||
|
Line int
|
||||||
|
|
||||||
|
// Переданный не известный тип
|
||||||
|
UnknownType string
|
||||||
|
|
||||||
|
// Переданный не известный контекст
|
||||||
|
UnknownContext string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Validate(commitMessage []string, config configuration.Config) *ValidateError {
|
||||||
|
if pResult := validateFirstLine(commitMessage[0], config); pResult != nil {
|
||||||
|
return pResult
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(commitMessage) > 1 {
|
||||||
|
if pResult := validateBody(commitMessage[1:], config); pResult != nil {
|
||||||
|
return pResult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateFirstLine(line string, config configuration.Config) *ValidateError {
|
||||||
|
for _, pExclude := range config.Excludes {
|
||||||
|
if pExclude.MatchString(line) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commitFirstLine := regexp.MustCompile("^([a-z0-9]+?)!?(?:\\(([a-z0-9]+?)\\))?: .+$")
|
||||||
|
match := commitFirstLine.FindAllStringSubmatch(line, -1)
|
||||||
|
|
||||||
|
if len(match) == 0 {
|
||||||
|
return &ValidateError{Result: IncorrectPattern, Line: 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
commitType := match[0][1]
|
||||||
|
if !slices.Contains(config.Types, commitType) {
|
||||||
|
return &ValidateError{Result: UnknownType, Line: 1, UnknownType: commitType}
|
||||||
|
}
|
||||||
|
|
||||||
|
commitContext := match[0][2]
|
||||||
|
if len(commitContext) > 0 && !slices.Contains(config.Contexts, commitContext) {
|
||||||
|
return &ValidateError{Result: UnknownContext, Line: 1, UnknownContext: commitContext}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(line) > config.MaxLengthLine {
|
||||||
|
return &ValidateError{Result: OverlongLine, Line: 1}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateBody(body []string, config configuration.Config) *ValidateError {
|
||||||
|
if len(body[0]) > 0 {
|
||||||
|
return &ValidateError{Result: BlankLine, Line: 2}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, line := range body[1:] {
|
||||||
|
if len(line) > config.MaxLengthLine {
|
||||||
|
return &ValidateError{Result: OverlongLine, Line: i + 3}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
83
internal/commitlint/validator/validator_test.go
Normal file
83
internal/commitlint/validator/validator_test.go
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package validator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"commitlint/internal/commitlint/configuration"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateFirstLine(t *testing.T) {
|
||||||
|
pConfig, err := configuration.CreateConfig(nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pConfig.Contexts = append(pConfig.Contexts, "git")
|
||||||
|
pConfig.Excludes = append(pConfig.Excludes, regexp.MustCompile("(?i)^wip$"))
|
||||||
|
|
||||||
|
testTab := []struct {
|
||||||
|
line string
|
||||||
|
excepted *ValidateError
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
line: "incorrect line",
|
||||||
|
excepted: &ValidateError{Result: IncorrectPattern, Line: 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line: "zed: message",
|
||||||
|
excepted: &ValidateError{Result: UnknownType, Line: 1, UnknownType: "zed"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line: "fix(zed): message",
|
||||||
|
excepted: &ValidateError{Result: UnknownContext, Line: 1, UnknownContext: "zed"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line: "fix: message",
|
||||||
|
excepted: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line: "fix(git): message",
|
||||||
|
excepted: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line: "WIP",
|
||||||
|
excepted: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testTab {
|
||||||
|
pResult := validateFirstLine(test.line, *pConfig)
|
||||||
|
assert.Equal(t, test.excepted, pResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateBody(t *testing.T) {
|
||||||
|
pConfig, err := configuration.CreateConfig(nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pConfig.MaxLengthLine = 10
|
||||||
|
|
||||||
|
testTab := []struct {
|
||||||
|
lines []string
|
||||||
|
excepted *ValidateError
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
lines: []string{" ", "Some Body"},
|
||||||
|
excepted: &ValidateError{Result: BlankLine, Line: 2},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lines: []string{"", "Some Body 1234567890"},
|
||||||
|
excepted: &ValidateError{Result: OverlongLine, Line: 3},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lines: []string{"", "Some Body"},
|
||||||
|
excepted: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testTab {
|
||||||
|
pResult := validateBody(test.lines, *pConfig)
|
||||||
|
assert.Equal(t, test.excepted, pResult)
|
||||||
|
}
|
||||||
|
}
|
||||||
0
target/.gitkeep
Normal file
0
target/.gitkeep
Normal file
Reference in New Issue
Block a user