Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ignore-on-exit flag to control the error code #162

Merged
merged 28 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9fdbd5a
Addded ignore-secret flag to all plugins (relevant sub-commands)
Aug 6, 2023
db979d9
Added ignore-on-exit flag to all sub commands
Aug 8, 2023
a17f2ae
Merge branch 'Checkmarx:master' into issue_155
nirmo Aug 8, 2023
b5860fb
changed IgnoreOnExitFlag var to ignoreOnExitFlag
Aug 8, 2023
06373e6
Merge branch 'issue_155' of https://github.com/nirmo/2ms into issue_155
Aug 8, 2023
6f4361a
issue 155 - add ignore-on-exit flag and change exit code logic
Aug 11, 2023
61ffa53
Merge branch 'Checkmarx:master' into issue_155
nirmo Aug 11, 2023
c5a866f
Merge branch 'Checkmarx:master' into issue_155
nirmo Aug 11, 2023
48ed7c0
Merge branch 'issue_155' of https://github.com/nirmo/2ms into issue_155
Aug 11, 2023
7b35e70
Issue 155 - minor changes
Aug 11, 2023
f74f216
Issue155 - added error channel and removed log fatal(s)
Aug 18, 2023
b399c8b
moved errorChan check after sleep wait
Aug 18, 2023
193afd6
merging changes from master
Aug 24, 2023
3b56fc8
sync with main
Sep 2, 2023
a3e131c
simplfying showError, removing comments and adding error channel check
Sep 2, 2023
dfcad26
modified ShowError and getFiles funcs
Sep 4, 2023
2eb264d
Merge pull request #2 from nirmo/master
nirmo Sep 4, 2023
40342fb
make the ignore-on-exit to be enum flag
Sep 27, 2023
417451f
refactor: reduce main size
Sep 27, 2023
7cc6483
move error decide to exit_handler
Sep 27, 2023
2785d3b
refactor: listen for errors
Sep 27, 2023
75a159a
one exit point
Sep 27, 2023
4d8a234
Merge remote-tracking branch 'origin/master' into pr/nirmo/162-1
Sep 27, 2023
060fde0
update README
Sep 27, 2023
2d328a7
Merge remote-tracking branch 'origin/master' into pr/nirmo/162-1
Sep 28, 2023
c880867
avoid using log.Fatal
Sep 28, 2023
1cbb777
remove comment
Sep 28, 2023
4a268a9
simplify the cmd.Error
Sep 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,21 @@ Additional Commands:
rules List all rules

Flags:
--add-special-rule strings special (non-default) rules to apply.
This list is not affected by the --rule and --ignore-rule flags.
--config string config file path
-h, --help help for 2ms
--ignore-result strings ignore specific result by id
--ignore-rule strings ignore rules by name or tag
--log-level string log level (trace, debug, info, warn, error, fatal) (default "info")
--regex stringArray custom regexes to apply to the scan, must be valid Go regex
--report-path strings path to generate report files. The output format will be determined by the file extension (.json, .yaml, .sarif)
--rule strings select rules by name or tag to apply to this scan
--stdout-format string stdout output format, available formats are: json, yaml, sarif (default "yaml")
-v, --version version for 2ms
--add-special-rule strings special (non-default) rules to apply.
This list is not affected by the --rule and --ignore-rule flags.
--config string config file path
-h, --help help for 2ms
--ignore-on-exit ignoreOnExit defines which kind of non-zero exits code should be ignored
accepts: all, results, errors, none
example: if 'results' is set, only engine errors will make 2ms exit code different from 0 (default none)
--ignore-result strings ignore specific result by id
--ignore-rule strings ignore rules by name or tag
--log-level string log level (trace, debug, info, warn, error, fatal) (default "info")
--regex stringArray custom regexes to apply to the scan, must be valid Go regex
--report-path strings path to generate report files. The output format will be determined by the file extension (.json, .yaml, .sarif)
--rule strings select rules by name or tag to apply to this scan
--stdout-format string stdout output format, available formats are: json, yaml, sarif (default "yaml")
-v, --version version for 2ms

Use "2ms [command] --help" for more information about a command.
```
Expand Down
57 changes: 57 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package cmd

import (
"fmt"
"path/filepath"
"regexp"
"strings"

"github.com/checkmarx/2ms/lib"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
)

func initialize() {
configFilePath, err := rootCmd.Flags().GetString(configFileFlag)
if err != nil {
cobra.CheckErr(err)
}
cobra.CheckErr(lib.LoadConfig(vConfig, configFilePath))
cobra.CheckErr(lib.BindFlags(rootCmd, vConfig, envPrefix))

logLevel := zerolog.InfoLevel
switch strings.ToLower(logLevelVar) {
case "trace":
logLevel = zerolog.TraceLevel
case "debug":
logLevel = zerolog.DebugLevel
case "info":
logLevel = zerolog.InfoLevel
case "warn":
logLevel = zerolog.WarnLevel
case "err", "error":
logLevel = zerolog.ErrorLevel
case "fatal":
logLevel = zerolog.FatalLevel
}
zerolog.SetGlobalLevel(logLevel)
log.Logger = log.Logger.Level(logLevel)
}

func validateFormat(stdout string, reportPath []string) error {
r := regexp.MustCompile(outputFormatRegexpPattern)
if !(r.MatchString(stdout)) {
return fmt.Errorf(`invalid output format: %s, available formats are: json, yaml and sarif`, stdout)
}

for _, path := range reportPath {
fileExtension := filepath.Ext(path)
format := strings.TrimPrefix(fileExtension, ".")
if !(r.MatchString(format)) {
return fmt.Errorf(`invalid report extension: %s, available extensions are: json, yaml and sarif`, format)
}
}

return nil
}
37 changes: 37 additions & 0 deletions cmd/enum_flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cmd

import (
"flag"
"fmt"
)

type ignoreOnExit string

const (
ignoreOnExitNone ignoreOnExit = "none"
ignoreOnExitAll ignoreOnExit = "all"
ignoreOnExitResults ignoreOnExit = "results"
ignoreOnExitErrors ignoreOnExit = "errors"
)

// verify that ignoreOnExit implements flag.Value interface
// https://github.com/uber-go/guide/blob/master/style.md#verify-interface-compliance
var _ flag.Value = (*ignoreOnExit)(nil)

func (i *ignoreOnExit) String() string {
return string(*i)
}

func (i *ignoreOnExit) Set(value string) error {
switch value {
case "none", "all", "results", "errors":
*i = ignoreOnExit(value)
return nil
default:
return fmt.Errorf("invalid value %s", value)
}
}

func (i *ignoreOnExit) Type() string {
return "ignoreOnExit"
}
53 changes: 53 additions & 0 deletions cmd/exit_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cmd

import (
"os"
)

const (
errorCode = 1
resultsCode = 2
)

func isNeedReturnErrorCodeFor(kind ignoreOnExit) bool {
if ignoreOnExitVar == ignoreOnExitNone {
return true
}

if ignoreOnExitVar == ignoreOnExitAll {
return false
}

if ignoreOnExitVar != ignoreOnExit(kind) {
return true
}

return false
}

func exitCodeIfError(err error) int {
if err != nil && isNeedReturnErrorCodeFor("errors") {
return errorCode
}

return 0
}

func exitCodeIfResults(resultsCount int) int {
if resultsCount > 0 && isNeedReturnErrorCodeFor("results") {
return resultsCode
}

return 0
}

func Exit(resultsCount int, err error) {
os.Exit(exitCodeIfError(err) + exitCodeIfResults(resultsCount))
}

func listenForErrors(errors chan error) {
go func() {
err := <-errors
Exit(0, err)
}()
}
73 changes: 73 additions & 0 deletions cmd/exit_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cmd

import (
"fmt"
"testing"
)

func TestExitHandler_IsNeedReturnErrorCode(t *testing.T) {

var onErrorsTests = []struct {
userInput ignoreOnExit
expectedResult bool
}{
{
userInput: ignoreOnExitNone,
expectedResult: true,
},
{
userInput: ignoreOnExitAll,
expectedResult: false,
},
{
userInput: ignoreOnExitResults,
expectedResult: true,
},
{
userInput: ignoreOnExitErrors,
expectedResult: false,
},
}

for idx, testCase := range onErrorsTests {
t.Run(fmt.Sprintf("Print test case %d", idx), func(t *testing.T) {
ignoreOnExitVar = testCase.userInput
result := isNeedReturnErrorCodeFor("errors")
if result != testCase.expectedResult {
t.Errorf("Expected %v, got %v", testCase.expectedResult, result)
}
})
}

var onResultsTests = []struct {
userInput ignoreOnExit
expectedResult bool
}{
{
userInput: ignoreOnExitNone,
expectedResult: true,
},
{
userInput: ignoreOnExitAll,
expectedResult: false,
},
{
userInput: ignoreOnExitResults,
expectedResult: false,
},
{
userInput: ignoreOnExitErrors,
expectedResult: true,
},
}

for idx, testCase := range onResultsTests {
t.Run(fmt.Sprintf("Print test case %d", idx), func(t *testing.T) {
ignoreOnExitVar = testCase.userInput
result := isNeedReturnErrorCodeFor("results")
if result != testCase.expectedResult {
t.Errorf("Expected %v, got %v", testCase.expectedResult, result)
}
})
}
}
Loading
Loading