diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index f9d2f6c3..a2f210f2 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -36,4 +36,5 @@ jobs: with: go-version: '1.17.x' - name: Run Go tests - run: go test -race ./... + # cannot run tests with race because we are mutating state (setting ENV variables) + run: go test ./... diff --git a/main b/main deleted file mode 100755 index bb0ca6dc..00000000 Binary files a/main and /dev/null differ diff --git a/main.go b/main.go index 0a3cfdfc..f04a578a 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,29 @@ type repositoryInformation struct { Private bool `json:"private"` } +const ( + enableSarif = "ENABLE_SARIF" + enableLicense = "ENABLE_LICENSE" + enableDangerousWorkflow = "ENABLE_DANGEROUS_WORKFLOW" + enabledChecks = "ENABLED_CHECKS" + githubEventPath = "GITHUB_EVENT_PATH" + githubRepository = "GITHUB_REPOSITORY" + //nolint:gosec + githubAuthToken = "GITHUB_AUTH_TOKEN" + inputresultsfile = "INPUT_RESULTS_FILE" + inputresultsformat = "INPUT_RESULTS_FORMAT" + inputpublishresults = "INPUT_PUBLISH_RESULTS" + scorecardBin = "SCORECARD_BIN" + scorecardResultsFormat = "SCORECARD_RESULTS_FORMAT" + scorecardPublishResults = "SCORECARD_PUBLISH_RESULTS" + scorecardPolicyFile = "SCORECARD_POLICY_FILE" + scorecardResultsFile = "SCORECARD_RESULTS_FILE" + scorecardFork = "SCORECARD_IS_FORK" + scorecardDefaultBranch = "SCORECARD_DEFAULT_BRANCH" + scorecardPrivateRepository = "SCORECARD_PRIVATE_REPOSITORY" + sarif = "sarif" +) + // main is the entrypoint for the action. func main() { // TODO - This is a port of the entrypoint.sh script. @@ -53,8 +76,8 @@ func main() { panic(err) } - repository := os.Getenv("GITHUB_REPOSITORY") - token := os.Getenv("GITHUB_AUTH_TOKEN") + repository := os.Getenv(githubRepository) + token := os.Getenv(githubAuthToken) repo, err := getRepositoryInformation(repository, token) if err != nil { @@ -83,12 +106,12 @@ func initalizeENVVariables() error { */ envvars := make(map[string]string) - envvars["ENABLE_SARIF"] = "1" - envvars["ENABLE_LICENSE"] = "1" - envvars["ENABLE_DANGEROUS_WORKFLOW"] = "1" - envvars["SCORECARD_POLICY_FILE"] = "./policy.yml" - envvars["SCORECARD_BIN"] = "/scorecard" - envvars["ENABLED_CHECKS"] = "" + envvars[enableSarif] = "1" + envvars[enableLicense] = "1" + envvars[enableDangerousWorkflow] = "1" + envvars[scorecardPolicyFile] = "./policy.yml" + envvars[scorecardBin] = "/scorecard" + envvars[enabledChecks] = "" for key, val := range envvars { if err := os.Setenv(key, val); err != nil { @@ -96,36 +119,36 @@ func initalizeENVVariables() error { } } - if result, exists := os.LookupEnv("INPUT_RESULTS_FILE"); !exists { + if result, exists := os.LookupEnv(inputresultsfile); !exists { return errInputResultFileNotSet } else { if result == "" { return errInputResultFileEmpty } - if err := os.Setenv("SCORECARD_RESULTS_FILE", result); err != nil { - return fmt.Errorf("error setting SCORECARD_RESULTS_FILE: %w", err) + if err := os.Setenv(scorecardResultsFile, result); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardResultsFile, err) } } - if result, exists := os.LookupEnv("INPUT_RESULTS_FORMAT"); !exists { + if result, exists := os.LookupEnv(inputresultsformat); !exists { return errInputResultFormatNotSet } else { if result == "" { return errInputResultFormatEmtpy } - if err := os.Setenv("SCORECARD_RESULTS_FORMAT", result); err != nil { - return fmt.Errorf("error setting SCORECARD_RESULTS_FORMAT: %w", err) + if err := os.Setenv(scorecardResultsFormat, result); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardResultsFormat, err) } } - if result, exists := os.LookupEnv("INPUT_PUBLISH_RESULTS"); !exists { + if result, exists := os.LookupEnv(inputpublishresults); !exists { return errInputPublishResultsNotSet } else { if result == "" { return errInputPublishResultsEmpty } - if err := os.Setenv("SCORECARD_PUBLISH_RESULTS", result); err != nil { - return fmt.Errorf("error setting SCORECARD_PUBLISH_RESULTS: %w", err) + if err := os.Setenv(scorecardPublishResults, result); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardPublishResults, err) } } @@ -138,7 +161,7 @@ func gitHubEventPath() error { var result string var exists bool - if result, exists = os.LookupEnv("GITHUB_EVENT_PATH"); !exists { + if result, exists = os.LookupEnv(githubEventPath); !exists { return errGitHubEventPathNotSet } @@ -148,7 +171,7 @@ func gitHubEventPath() error { data, err := ioutil.ReadFile(result) if err != nil { - return fmt.Errorf("error reading GITHUB_EVENT_PATH: %w", err) + return fmt.Errorf("error reading %s: %w", githubEventPath, err) } var isFork bool @@ -157,12 +180,12 @@ func gitHubEventPath() error { } if isFork { - if err := os.Setenv("SCORECARD_IS_FORK", "true"); err != nil { - return fmt.Errorf("error setting SCORECARD_IS_FORK: %w", err) + if err := os.Setenv(scorecardFork, "true"); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardFork, err) } } else { - if err := os.Setenv("SCORECARD_IS_FORK", "false"); err != nil { - return fmt.Errorf("error setting SCORECARD_IS_FORK: %w", err) + if err := os.Setenv(scorecardFork, "false"); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardFork, err) } } @@ -194,8 +217,8 @@ func scorecardIsFork(ghEventPath string) (bool, error) { // checkIfRequiredENVSet is a function to check if the required environment variables are set. func checkIfRequiredENVSet() error { envVariables := make(map[string]bool) - envVariables["GITHUB_REPOSITORY"] = true - envVariables["GITHUB_AUTH_TOKEN"] = true + envVariables[githubRepository] = true + envVariables[githubAuthToken] = true for key := range envVariables { if _, exists := os.LookupEnv(key); !exists { @@ -239,25 +262,27 @@ func updateRepositoryInformation(privateRepo bool, defaultBranch string) error { return errEmptyDefaultBranch } - if err := os.Setenv("SCORECARD_PRIVATE_REPOSITORY", strconv.FormatBool(privateRepo)); err != nil { - return fmt.Errorf("error setting SCORECARD_PRIVATE_REPOSITORY: %w", err) + if err := os.Setenv(scorecardPrivateRepository, strconv.FormatBool(privateRepo)); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardPrivateRepository, err) } - if err := os.Setenv("SCORECARD_DEFAULT_BRANCH", defaultBranch); err != nil { - return fmt.Errorf("error setting SCORECARD_DEFAULT_BRANCH: %w", err) + if err := os.Setenv(scorecardDefaultBranch, fmt.Sprintf("refs/heads/%s", defaultBranch)); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardDefaultBranch, err) } return nil } // updateEnvVariables is a function to update the ENV variables based on results format and private repository. func updateEnvVariables() error { - resultsFileFormat := os.Getenv("SCORECARD_RESULTS_FORMAT") - if resultsFileFormat != "sarif" { - os.Unsetenv("SCORECARD_POLICY_FILE") + resultsFileFormat := os.Getenv(scorecardResultsFormat) + if resultsFileFormat != sarif { + if err := os.Unsetenv(scorecardPolicyFile); err != nil { + return fmt.Errorf("error unsetting %s: %w", scorecardPolicyFile, err) + } } - isPrivateRepo := os.Getenv("SCORECARD_PRIVATE_REPOSITORY") + isPrivateRepo := os.Getenv(scorecardPrivateRepository) if isPrivateRepo != "true" { - if err := os.Setenv("SCORECARD_PUBLISH_RESULTS", "false"); err != nil { - return fmt.Errorf("error setting SCORECARD_PUBLISH_RESULTS: %w", err) + if err := os.Setenv(scorecardPublishResults, "false"); err != nil { + return fmt.Errorf("error setting %s: %w", scorecardPublishResults, err) } } return nil diff --git a/main_test.go b/main_test.go index e9ee77d2..f7f037c0 100644 --- a/main_test.go +++ b/main_test.go @@ -14,13 +14,16 @@ package main import ( + "fmt" "io/ioutil" "os" + "strconv" "testing" ) +//not setting t.Parallel() here because we are mutating the env variables +//nolint func Test_scorecardIsFork(t *testing.T) { - t.Parallel() type args struct { ghEventPath string } @@ -63,7 +66,6 @@ func Test_scorecardIsFork(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - t.Parallel() var data []byte var err error if tt.args.ghEventPath != "" { @@ -86,8 +88,10 @@ func Test_scorecardIsFork(t *testing.T) { } } +//not setting t.Parallel() here because we are mutating the env variables +//nolint func Test_initalizeENVVariables(t *testing.T) { - t.Parallel() + //nolint tests := []struct { name string wantErr bool @@ -164,44 +168,234 @@ func Test_initalizeENVVariables(t *testing.T) { for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { - t.Parallel() if tt.inputresultsfileSet { - os.Setenv("INPUT_RESULTS_FILE", tt.inputresultsfile) + defer os.Unsetenv(inputpublishresults) + os.Setenv(inputresultsfile, tt.inputresultsfile) } else { - os.Unsetenv("INPUT_RESULTS_FILE") + os.Unsetenv(inputresultsfile) } if tt.inputresultsFormatSet { - os.Setenv("INPUT_RESULTS_FORMAT", tt.inputresultsFormat) + defer os.Unsetenv(inputresultsformat) + os.Setenv(inputresultsformat, tt.inputresultsFormat) } else { - os.Unsetenv("INPUT_RESULTS_FORMAT") + os.Unsetenv(inputresultsformat) } if tt.inputPublishResultsSet { - os.Setenv("INPUT_PUBLISH_RESULTS", tt.inputPublishResults) + defer os.Unsetenv(inputpublishresults) + os.Setenv(inputpublishresults, tt.inputPublishResults) } else { - os.Unsetenv("INPUT_PUBLISH_RESULTS") + os.Unsetenv(inputpublishresults) } if tt.githubEventPathSet { - os.Setenv("GITHUB_EVENT_PATH", tt.githubEventPath) + defer os.Unsetenv(githubEventPath) + os.Setenv(githubEventPath, tt.githubEventPath) } else { - os.Unsetenv("GITHUB_EVENT_PATH") + os.Unsetenv(githubEventPath) } if err := initalizeENVVariables(); (err != nil) != tt.wantErr { - t.Errorf("initalizeENVVariables() error = %v, wantErr %v", err, tt.wantErr) + t.Errorf("initalizeENVVariables() error = %v, wantErr %v %v", err, tt.wantErr, t.Name()) } envvars := make(map[string]string) - envvars["ENABLE_SARIF"] = "1" - envvars["ENABLE_LICENSE"] = "1" - envvars["ENABLE_DANGEROUS_WORKFLOW"] = "1" - envvars["SCORECARD_POLICY_FILE"] = "./policy.yml" - envvars["SCORECARD_BIN"] = "/scorecard" - envvars["ENABLED_CHECKS"] = "" + envvars[enableSarif] = "1" + envvars[enableLicense] = "1" + envvars[enableDangerousWorkflow] = "1" + envvars[scorecardPolicyFile] = "./policy.yml" + envvars[scorecardBin] = "/scorecard" + envvars[enabledChecks] = "" for k, v := range envvars { if os.Getenv(k) != v { - t.Errorf("%s env var not set correctly", k) + t.Errorf("%s env var not set correctly %s", k, v) } } }) } } + +//not setting t.Parallel() here because we are mutating the env variables +//nolint +func Test_updateEnvVariables(t *testing.T) { + tests := []struct { + name string + outputResultsFormat string + isPrivateRepo bool + wantErr bool + }{ + { + name: "Success - private repo", + outputResultsFormat: "json", + isPrivateRepo: true, + wantErr: false, + }, + { + name: "Success - private repo - sarif", + outputResultsFormat: "sarif", + isPrivateRepo: true, + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if err := updateEnvVariables(); (err != nil) != tt.wantErr { + t.Errorf("updateEnvVariables() error = %v, wantErr %v", err, tt.wantErr) + } + if !tt.wantErr && tt.isPrivateRepo { + if os.Getenv(scorecardPublishResults) != "false" { + t.Errorf("scorecardPublishResults env var should be false") + } + } + + if !tt.wantErr && tt.outputResultsFormat == sarif { + if _, ok := os.LookupEnv(scorecardPolicyFile); ok { + t.Errorf("enableSarif env var should not be set") + } + } + }) + } +} + +//not setting t.Parallel() here because we are mutating the env variables +//nolint +func Test_updateRepoistoryInformation(t *testing.T) { + type args struct { + defaultBranch string + privateRepo bool + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Success - private repo", + args: args{ + defaultBranch: "master", + privateRepo: true, + }, + wantErr: false, + }, + { + name: "Success - public repo", + args: args{ + defaultBranch: "master", + privateRepo: false, + }, + wantErr: false, + }, + { + name: "Success - public repo - no default branch", + args: args{ + defaultBranch: "", + privateRepo: false, + }, + wantErr: true, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + if err := updateRepositoryInformation(tt.args.privateRepo, tt.args.defaultBranch); (err != nil) != tt.wantErr { + t.Errorf("updateRepoistoryInformation() error = %v, wantErr %v", err, tt.wantErr) + } + if tt.args.privateRepo { + if os.Getenv(scorecardPrivateRepository) != strconv.FormatBool(tt.args.privateRepo) { + t.Errorf("scorecardPublishResults env var should be false") + } + } + if tt.args.defaultBranch != "" { + if os.Getenv(scorecardDefaultBranch) != fmt.Sprintf("refs/heads/%s", tt.args.defaultBranch) { + t.Errorf("scorecardDefaultBranch env var should be %s", tt.args.defaultBranch) + } + } + }) + } +} + +//not setting t.Parallel() here because we are mutating the env variables +//nolint +func Test_checkIfRequiredENVSet(t *testing.T) { + tests := []struct { + name string + wantErr bool + }{ + { + name: "Success - all required env vars set", + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + envVariables := make(map[string]bool) + envVariables[githubRepository] = true + envVariables[githubAuthToken] = true + t.Run(tt.name, func(t *testing.T) { + if !tt.wantErr { + for k := range envVariables { + defer os.Unsetenv(k) + if err := os.Setenv(k, "true"); err != nil { + t.Errorf("failed to set env var %s", k) + } + } + } + if err := checkIfRequiredENVSet(); (err != nil) != tt.wantErr { + t.Errorf("checkIfRequiredENVSet() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +//nolint +func Test_gitHubEventPath(t *testing.T) { + tests := []struct { + name string + wantErr bool + shouldgitHubEventPathBeSet bool + gitHubEventPath string + }{ + { + name: "Success - gitHubEventPath set", + wantErr: false, + shouldgitHubEventPathBeSet: true, + gitHubEventPath: "./testdata/fork.json", + }, + { + name: "Success - gitHubEventPath not set", + wantErr: true, + shouldgitHubEventPathBeSet: false, + gitHubEventPath: "", + }, + { + name: "Success - gitHubEventPath is empty", + wantErr: true, + shouldgitHubEventPathBeSet: true, + gitHubEventPath: "", + }, + { + name: "Failure non-existent file", + wantErr: true, + shouldgitHubEventPathBeSet: true, + gitHubEventPath: "./foo.bar.json", + }, + { + name: "Failure non-existent file", + wantErr: true, + shouldgitHubEventPathBeSet: true, + gitHubEventPath: "./testdata/incorrect.json", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if tt.shouldgitHubEventPathBeSet { + if err := os.Setenv(githubEventPath, tt.gitHubEventPath); err != nil { + t.Errorf("failed to set env var %s", githubEventPath) + } + defer os.Unsetenv(githubEventPath) + } + if err := gitHubEventPath(); (err != nil) != tt.wantErr { + t.Errorf("gitHubEventPath() error = %v, wantErr %v %v", err, tt.wantErr, tt.name) + } + }) + } +}