diff --git a/cmd/main.go b/cmd/main.go index 2d784be..436ed04 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -99,27 +99,34 @@ type TagDetails struct { func checkMatches(content []string, targets []string) bool { contentStr := strings.Join(content, " ") - // Check against blacklist terms first - for _, blacklistTerm := range repo.Blacklist { - if fuzzy.MatchNormalizedFold(contentStr, blacklistTerm) { - logger.Debug(&libpack_logger.LogMessage{ - Message: "Blacklisted term detected, ignoring commit", - Pairs: map[string]interface{}{"content": contentStr, "blacklist_term": blacklistTerm}, - }) - return false - } - } + // First check if any target matches + hasMatch := false for _, tgt := range targets { r := fuzzy.FindNormalizedFold(tgt, content) if len(r) > 0 { + hasMatch = true logger.Debug(&libpack_logger.LogMessage{ Message: "Found match", - Pairs: map[string]interface{}{"target": tgt, "match": strings.Join(r, ","), "content": strings.Join(content, " ")}, + Pairs: map[string]interface{}{"target": tgt, "match": strings.Join(r, ","), "content": contentStr}, }) - return true + break } } - return false + + // If we have a match, check against blacklist + if hasMatch { + for _, blacklistTerm := range repo.Blacklist { + if strings.Contains(strings.ToLower(contentStr), strings.ToLower(blacklistTerm)) { + logger.Debug(&libpack_logger.LogMessage{ + Message: "Blacklisted term detected, ignoring commit", + Pairs: map[string]interface{}{"content": contentStr, "blacklist_term": blacklistTerm}, + }) + return false + } + } + } + + return hasMatch } var extractNumber = regexp.MustCompile("[0-9]+") diff --git a/cmd/main_test.go b/cmd/main_test.go index 16b5c2a..969c660 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -1,18 +1,3 @@ -/* -Copyright © 2021 LUKASZ RACZYLO - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ package cmd import ( @@ -151,6 +136,37 @@ func (suite *Tests) TestSetup_ForcedVersioning() { }, want: "0.0.7", }, + { + name: "All versions set", + fields: fields{ + Force: Force{ + Major: 2, + Minor: 3, + Patch: 4, + }, + }, + want: "2.3.4", + }, + { + name: "Major and Minor set", + fields: fields{ + Force: Force{ + Major: 2, + Minor: 3, + }, + }, + want: "2.3.0", + }, + { + name: "Minor and Patch set", + fields: fields{ + Force: Force{ + Minor: 3, + Patch: 4, + }, + }, + want: "0.3.4", + }, } for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { @@ -165,108 +181,21 @@ func (suite *Tests) TestSetup_ForcedVersioning() { } } -func (suite *Tests) TestSetup_Prepare() { - type fields struct { - RepositoryName string - RepositoryLocalPath string - } - tests := []struct { - name string - fields fields - wantErr bool - }{ - { - name: "Test repository lukaszraczylo/simple-gql-client", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/simple-gql-client", - }, - wantErr: true, - }, - { - name: "Test non-existing repository", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/simple-gql-client-dead", - }, - wantErr: true, - }, - } - for _, tt := range tests { - suite.T().Run(tt.name, func(t *testing.T) { - s := &Setup{ - RepositoryName: tt.fields.RepositoryName, - } - s.Prepare() - if _, err := os.Stat(s.RepositoryLocalPath); os.IsNotExist(err) { - if !tt.wantErr { - assert.NoError(err, "Error should not be present in "+tt.name) - } else { - assert.Error(err, "Error should be present in "+tt.name) - } - } - }) - } -} - -func (suite *Tests) TestSetup_ReadConfig() { - type fields struct { - Wording Wording - Force Force - } - type args struct { - file string - } - tests := []struct { - name string - args args - fields fields - wordingEmpty bool - wantErr bool - }{ - { - name: "Test non-existent config file", - args: args{ - file: "random-file-name.yaml", - }, - wordingEmpty: true, - wantErr: true, - }, - { - name: "Test existing config file", - args: args{ - file: "../config.yaml", - }, - wordingEmpty: false, - wantErr: false, - }, - } - for _, tt := range tests { - suite.T().Run(tt.name, func(t *testing.T) { - s := &Setup{} - err := s.ReadConfig(tt.args.file) - if !tt.wantErr { - assert.NoError(err, "Error should not be present in "+tt.name) - } else { - assert.Error(err, "Error should be present in "+tt.name) - } - assert.Equal(tt.wordingEmpty, pandati.IsZero(s.Wording), "Unexpected wording count "+tt.name+":", s.Wording) - }) - } -} - func (suite *Tests) Test_checkMatches() { type args struct { content []string targets []string } tests := []struct { - name string - args args - want bool + name string + args args + blacklist []string + want bool }{ { name: "No match", args: args{ - content: strings.Fields("Fields splits the string s around each instance of one or more consecutive white space characters, as defined by unicode.IsSpace, returning a slice of substrings of s or an empty slice if s contains only white space"), + content: strings.Fields("Fields splits the string s around each instance of one or more consecutive white space characters"), targets: []string{"github", "repository", "test"}, }, want: false, @@ -274,20 +203,143 @@ func (suite *Tests) Test_checkMatches() { { name: "Match", args: args{ - content: strings.Fields("Fields splits the string s around each instance of one or more consecutive white space characters, as defined by unicode.IsSpace, returning a slice of substrings of s or an empty slice if s contains only white space"), + content: strings.Fields("Fields splits the string s around each instance of one or more consecutive white space characters"), targets: []string{"github", "repository", "instance"}, }, want: true, }, + { + name: "Match but blacklisted", + args: args{ + content: strings.Fields("feat: add new feature with breaking changes"), + targets: []string{"feat", "feature"}, + }, + blacklist: []string{"breaking"}, + want: false, + }, + { + name: "Match with empty blacklist", + args: args{ + content: strings.Fields("feat: add new feature"), + targets: []string{"feat", "feature"}, + }, + blacklist: []string{}, + want: true, + }, + { + name: "No match with blacklist", + args: args{ + content: strings.Fields("chore: update dependencies"), + targets: []string{"feat", "feature"}, + }, + blacklist: []string{"skip-ci"}, + want: false, + }, } for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { + repo.Blacklist = tt.blacklist got := checkMatches(tt.args.content, tt.args.targets) assert.Equal(tt.want, got, "Unexpected result in "+tt.name) }) } } +func (suite *Tests) Test_parseExistingSemver() { + type args struct { + tagName string + } + tests := []struct { + name string + args args + currentSemver SemVer + wantSemanticVersion SemVer + }{ + { + name: "Test parsing existing semver", + args: args{ + tagName: "1.2.3", + }, + currentSemver: SemVer{Major: 1, Minor: 1, Patch: 1}, + wantSemanticVersion: SemVer{ + Major: 1, + Minor: 2, + Patch: 3, + }, + }, + { + name: "Test parsing existing semver with v", + args: args{ + tagName: "v1.2.3", + }, + currentSemver: SemVer{Major: 1, Minor: 1, Patch: 1}, + wantSemanticVersion: SemVer{ + Major: 1, + Minor: 2, + Patch: 3, + }, + }, + { + name: "Test parsing existing semver with rc", + args: args{ + tagName: "1.2.5-rc.7", + }, + currentSemver: SemVer{Major: 1, Minor: 1, Patch: 1}, + wantSemanticVersion: SemVer{ + Major: 1, + Minor: 2, + Patch: 5, + Release: 7, + }, + }, + { + name: "Test invalid semver format", + args: args{ + tagName: "invalid", + }, + currentSemver: SemVer{Major: 2, Minor: 3, Patch: 4}, + wantSemanticVersion: SemVer{ + Major: 2, + Minor: 3, + Patch: 4, + }, + }, + { + name: "Test partial semver", + args: args{ + tagName: "1.2", + }, + currentSemver: SemVer{Major: 2, Minor: 3, Patch: 4}, + wantSemanticVersion: SemVer{ + Major: 2, + Minor: 3, + Patch: 4, + }, + }, + { + name: "Test empty tag", + args: args{ + tagName: "", + }, + currentSemver: SemVer{Major: 2, Minor: 3, Patch: 4}, + wantSemanticVersion: SemVer{ + Major: 2, + Minor: 3, + Patch: 4, + }, + }, + } + for _, tt := range tests { + suite.T().Run(tt.name, func(t *testing.T) { + got := parseExistingSemver(tt.args.tagName, tt.currentSemver) + assert.Equal(tt.wantSemanticVersion.Major, got.Major, "Unexpected MAJOR semver result in "+tt.name) + assert.Equal(tt.wantSemanticVersion.Minor, got.Minor, "Unexpected MINOR semver result in "+tt.name) + assert.Equal(tt.wantSemanticVersion.Patch, got.Patch, "Unexpected PATCH semver result in "+tt.name) + assert.Equal(tt.wantSemanticVersion.Release, got.Release, "Unexpected RELEASE semver result in "+tt.name) + }) + } +} + func (suite *Tests) TestSetup_ListCommits() { type fields struct { RepositoryHandler *git.Repository @@ -357,227 +409,6 @@ func (suite *Tests) TestSetup_ListCommits() { } } -func (suite *Tests) TestSetup_CalculateSemver() { - type fields struct { - RepositoryName string - BranchName string - LocalConfigFile string - Force Force - } - type wantSemver struct { - Major int - Minor int - Patch int - } - tests := []struct { - name string - fields fields - wantSemver wantSemver - strictMatching bool - }{ - { - name: "Test on existing repository", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/semver-generator-test-repo", - LocalConfigFile: "meta.yaml", - BranchName: "main", - }, - strictMatching: false, - wantSemver: wantSemver{ - Major: 0, - Minor: 0, - Patch: 7, - }, - }, - { - name: "Test on existing repository with strict matching", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/semver-generator-test-repo", - LocalConfigFile: "meta.yaml", - BranchName: "main", - }, - strictMatching: true, - wantSemver: wantSemver{ - Major: 2, - Minor: 4, - Patch: 1, - }, - }, - { - name: "Test on existing repository, starting with certain hash", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/semver-generator-test-repo", - LocalConfigFile: "meta.yaml", - BranchName: "main", - Force: Force{ - Major: 1, - Minor: 1, - Commit: "45f9a23cec39e94503841638aee3efecd45111cf", - }, - }, - strictMatching: false, - wantSemver: wantSemver{ - Major: 1, - Minor: 5, - Patch: 1, - }, - }, - { - name: "Test on existing repository, starting with different hash", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/semver-generator-test-repo", - LocalConfigFile: "meta.yaml", - BranchName: "main", - Force: Force{ - Major: 1, - Minor: 1, - Commit: "48564920d88a8a16df607736b438947309ffb8c6", - }, - }, - strictMatching: false, - wantSemver: wantSemver{ - Major: 1, - Minor: 4, - Patch: 1, - }, - }, - { - name: "Test on non-existing repository", - fields: fields{ - RepositoryName: "https://github.com/lukaszraczylo/semver-generator-test-repo-dead", - }, - wantSemver: wantSemver{ - Major: 1, // 1 because config file enforces MAJOR version - Minor: 1, // 1 because config file enforces MINOR version - Patch: 0, - }, - }, - } - for _, tt := range tests { - suite.T().Run(tt.name, func(t *testing.T) { - s := &Setup{} - s.ReadConfig(tt.fields.LocalConfigFile) - s.RepositoryName = tt.fields.RepositoryName - s.RepositoryBranch = tt.fields.BranchName - s.Prepare() - s.ForcedVersioning() - s.Force = tt.fields.Force - s.ListCommits() - params.varStrict = tt.strictMatching - semver := s.CalculateSemver() - assert.Equal(tt.wantSemver.Major, semver.Major, "Unexpected MAJOR semver result in "+tt.name) - assert.Equal(tt.wantSemver.Minor, semver.Minor, "Unexpected MINOR semver result in "+tt.name) - assert.Equal(tt.wantSemver.Patch, semver.Patch, "Unexpected PATCH semver result in "+tt.name) - }) - } -} - -func (suite *Tests) Test_main() { - type vars struct { - varRepoName string - varRepoBranch string - varLocalCfg string - varUseLocal bool - varShowVersion bool - varDebug bool - varUpdate bool - varStrict bool - varGenerateInTest bool - varExisting bool - } - tests := []struct { - name string - vars vars - }{ - { - name: "Test printing version", - vars: vars{ - varShowVersion: true, - }, - }, - { - name: "Test update switch", - vars: vars{ - varUpdate: true, - }, - }, - { - name: "Test main", - vars: vars{ - varGenerateInTest: false, - }, - }, - } - for _, tt := range tests { - suite.T().Run(tt.name, func(t *testing.T) { - params = myParams(tt.vars) - repo = &Setup{} - repo.LocalConfigFile = "../config.yaml" - repo.UseLocal = true - main() - }) - } -} - -func (suite *Tests) Test_parseExistingSemver() { - type args struct { - tagName string - } - tests := []struct { - name string - args args - wantSemanticVersion SemVer - }{ - { - name: "Test parsing existing semver", - args: args{ - tagName: "1.2.3", - }, - wantSemanticVersion: SemVer{ - Major: 1, - Minor: 2, - Patch: 3, - }, - }, - { - name: "Test parsing existing semver with v", - args: args{ - tagName: "v1.2.3", - }, - wantSemanticVersion: SemVer{ - Major: 1, - Minor: 2, - Patch: 3, - }, - }, - { - name: "Test parsing existing semver with rc", - args: args{ - tagName: "1.2.5-rc.7", - }, - wantSemanticVersion: SemVer{ - Major: 1, - Minor: 2, - Patch: 5, - Release: 7, - }, - }, - } - for _, tt := range tests { - suite.T().Run(tt.name, func(t *testing.T) { - got := parseExistingSemver(tt.args.tagName, SemVer{ - Major: 1, - Minor: 1, - Patch: 1, - }) - assert.Equal(tt.wantSemanticVersion.Major, got.Major, "Unexpected MAJOR semver result in "+tt.name) - assert.Equal(tt.wantSemanticVersion.Minor, got.Minor, "Unexpected MINOR semver result in "+tt.name) - assert.Equal(tt.wantSemanticVersion.Patch, got.Patch, "Unexpected PATCH semver result in "+tt.name) - assert.Equal(tt.wantSemanticVersion.Release, got.Release, "Unexpected RELEASE semver result in "+tt.name) - }) - } -} - func (suite *Tests) TestSetup_ListExistingTags() { type fields struct { RepositoryHandler *git.Repository @@ -630,3 +461,50 @@ func (suite *Tests) TestSetup_ListExistingTags() { }) } } + +func (suite *Tests) Test_main() { + type vars struct { + varRepoName string + varRepoBranch string + varLocalCfg string + varUseLocal bool + varShowVersion bool + varDebug bool + varUpdate bool + varStrict bool + varGenerateInTest bool + varExisting bool + } + tests := []struct { + name string + vars vars + }{ + { + name: "Test printing version", + vars: vars{ + varShowVersion: true, + }, + }, + { + name: "Test update switch", + vars: vars{ + varUpdate: true, + }, + }, + { + name: "Test main", + vars: vars{ + varGenerateInTest: false, + }, + }, + } + for _, tt := range tests { + suite.T().Run(tt.name, func(t *testing.T) { + params = myParams(tt.vars) + repo = &Setup{} + repo.LocalConfigFile = "../config.yaml" + repo.UseLocal = true + main() + }) + } +}