Skip to content

Commit

Permalink
🌱 Porting shell script to Go
Browse files Browse the repository at this point in the history
- Porting the shell script to go
- Including additional tests
- Code cleanup for the linter.
  • Loading branch information
naveensrinivasan committed Feb 8, 2022
1 parent 6ef41e4 commit 73e6f16
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 63 deletions.
217 changes: 162 additions & 55 deletions main.go
Expand Up @@ -15,18 +15,59 @@ package main

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
)

var (
errInputResultFileNotSet = errors.New("INPUT_RESULTS_FILE is not set")
errInputResultFileEmpty = errors.New("INPUT_RESULTS_FILE is empty")
errInputResultFormatNotSet = errors.New("INPUT_RESULTS_FORMAT is not set")
errInputResultFormatEmtpy = errors.New("INPUT_RESULTS_FORMAT is empty")
errInputPublishResultsNotSet = errors.New("INPUT_PUBLISH_RESULTS is not set")
errInputPublishResultsEmpty = errors.New("INPUT_PUBLISH_RESULTS is empty")
errRequiredENVNotSet = errors.New("required environment variables are not set")
errGitHubEventPath = errors.New("error getting GITHUB_EVENT_PATH")
errGitHubEventPathEmpty = errors.New("GITHUB_EVENT_PATH is empty")
errGitHubEventPathNotSet = errors.New("GITHUB_EVENT_PATH is not set")
errEmptyDefaultBranch = errors.New("default branch is empty")
)

type repositoryInformation struct {
DefaultBranch string `json:"default_branch"`
Private bool `json:"private"`
}

// main is the entrypoint for the action.
func main() {
// TODO - This is a port of the entrypoint.sh script.
// This is still a work in progress.
if err := initalizeENVVariables(); err != nil {
panic(err)
}
if err := checkIfRequiredENVSet(); err != nil {
panic(err)
}

repository := os.Getenv("GITHUB_REPOSITORY")
token := os.Getenv("GITHUB_AUTH_TOKEN")

repo, err := getRepositoryInformation(repository, token)
if err != nil {
panic(err)
}

if err := updateRepoistoryInformation(repo.Private, repo.DefaultBranch); err != nil {
panic(err)
}

if err := updateEnvVariables(); err != nil {
panic(err)
}
}

// initalizeENVVariables is a function to initialize the environment variables required for the action.
Expand All @@ -40,104 +81,98 @@ func initalizeENVVariables() error {
GITHUB_EVENT_NAME contains the event name.
GITHUB_ACTIONS is true in GitHub env.
*/
if err := os.Setenv("ENABLE_SARIF", "1"); err != nil {
return err
}

if err := os.Setenv("ENABLE_LICENSE", "1"); err != nil {
return err
}

if err := os.Setenv("ENABLE_DANGEROUS_WORKFLOW", "1"); err != nil {
return err
}
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"] = ""

if err := os.Setenv("SCORECARD_POLICY_FILE", "/policy.yml"); err != nil {
return err
for key, val := range envvars {
if err := os.Setenv(key, val); err != nil {
return fmt.Errorf("error setting %s: %w", key, err)
}
}

if result, exists := os.LookupEnv("INPUT_RESULTS_FILE"); !exists {
return fmt.Errorf("INPUT_RESULTS_FILE is not set")
return errInputResultFileNotSet
} else {
if result == "" {
return fmt.Errorf("INPUT_RESULTS_FILE is empty")
return errInputResultFileEmpty
}
if err := os.Setenv("SCORECARD_RESULTS_FILE", result); err != nil {
return err
return fmt.Errorf("error setting SCORECARD_RESULTS_FILE: %w", err)
}
}

if result, exists := os.LookupEnv("INPUT_RESULTS_FORMAT"); !exists {
return fmt.Errorf("INPUT_RESULTS_FORMAT is not set")
return errInputResultFormatNotSet
} else {
if result == "" {
return fmt.Errorf("INPUT_RESULTS_FORMAT is empty")
return errInputResultFormatEmtpy
}
if err := os.Setenv("SCORECARD_RESULTS_FORMAT", result); err != nil {
return err
return fmt.Errorf("error setting SCORECARD_RESULTS_FORMAT: %w", err)
}
}

if result, exists := os.LookupEnv("INPUT_PUBLISH_RESULTS"); !exists {
return fmt.Errorf("INPUT_PUBLISH_RESULTS is not set")
return errInputPublishResultsNotSet
} else {
if result == "" {
return fmt.Errorf("INPUT_PUBLISH_RESULTS is empty")
return errInputPublishResultsEmpty
}
if err := os.Setenv("SCORECARD_PUBLISH_RESULTS", result); err != nil {
return err
return fmt.Errorf("error setting SCORECARD_PUBLISH_RESULTS: %w", err)
}
}

if err := os.Setenv("SCORECARD_BIN", "/scorecard"); err != nil {
return err
}

if err := os.Setenv("ENABLED_CHECKS", ""); err != nil {
return err
}
return gitHubEventPath()
}

// gitHubEventPath is a function to get the path to the GitHub event
// and sets the SCORECARD_IS_FORK environment variable.
func gitHubEventPath() error {
if result, exists := os.LookupEnv("GITHUB_EVENT_PATH"); !exists {
return fmt.Errorf("GITHUB_EVENT_PATH is not set")
} else {
if result == "" {
return fmt.Errorf("GITHUB_EVENT_PATH is empty")
}
if err := os.Setenv("GITHUB_EVENT_PATH", result); err != nil {
return err
}
var result string
var exists bool

data, err := ioutil.ReadFile(result)
if err != nil {
return err
}
if result, exists = os.LookupEnv("GITHUB_EVENT_PATH"); !exists {
return errGitHubEventPathNotSet
}

if result == "" {
return errGitHubEventPathEmpty
}

if isFork, err := scorecardIsFork(string(data)); err != nil {
return err
} else {
if isFork {
if err := os.Setenv("SCORECARD_IS_FORK", "true"); err != nil {
return err
}
} else {
if err := os.Setenv("SCORECARD_IS_FORK", "false"); err != nil {
return err
}
}
data, err := ioutil.ReadFile(result)
if err != nil {
return fmt.Errorf("error reading GITHUB_EVENT_PATH: %w", err)
}
var isFork bool

if isFork, err = scorecardIsFork(string(data)); err != nil {
return fmt.Errorf("error checking if scorecard is a fork: %w", err)
}

if isFork {
if err := os.Setenv("SCORECARD_IS_FORK", "true"); err != nil {
return fmt.Errorf("error setting SCORECARD_IS_FORK: %w", err)
}
} else {
if err := os.Setenv("SCORECARD_IS_FORK", "false"); err != nil {
return fmt.Errorf("error setting SCORECARD_IS_FORK: %w", err)
}
}

return nil
}

// scorecardIsFork is a function to check if the current repo is a fork.
func scorecardIsFork(ghEventPath string) (bool, error) {
if ghEventPath == "" {
return false, fmt.Errorf("ghEventPath is empty")
return false, errGitHubEventPath
}
/*
https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#github_repository_is_fork
Expand All @@ -150,8 +185,80 @@ func scorecardIsFork(ghEventPath string) (bool, error) {
}
var r repo
if err := json.Unmarshal([]byte(ghEventPath), &r); err != nil {
return false, err
return false, fmt.Errorf("error unmarshalling ghEventPath: %w", err)
}

return r.Repository.Fork, nil
}

// 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

for key := range envVariables {
if _, exists := os.LookupEnv(key); !exists {
return errRequiredENVNotSet
}
}
return nil
}

// getRepositoryInformation is a function to get the repository information.
// It is decided to not use the golang GitHub library because of the
// dependency on the github.com/google/go-github/github library
// which will in turn require other dependencies.
func getRepositoryInformation(name, githubauthToken string) (repositoryInformation, error) {
//nolint
req, err := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s", name), nil)
if err != nil {
return repositoryInformation{}, fmt.Errorf("error creating request: %w", err)
}
req.Header.Set("Authorization", githubauthToken)

resp, err := http.DefaultClient.Do(req)
if err != nil {
return repositoryInformation{}, fmt.Errorf("error creating request: %w", err)
}
defer resp.Body.Close()
if err != nil {
return repositoryInformation{}, fmt.Errorf("error reading response body: %w", err)
}
var r repositoryInformation
err = json.NewDecoder(resp.Body).Decode(&r)
if err != nil {
return repositoryInformation{}, fmt.Errorf("error decoding response body: %w", err)
}
return r, nil
}

// updateRepoistoryInformation is a function to update the repository information into ENV variables.
func updateRepoistoryInformation(privateRepo bool, defaultBranch string) error {
if defaultBranch == "" {
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("SCORECARD_DEFAULT_BRANCH", defaultBranch); err != nil {
return fmt.Errorf("error setting SCORECARD_DEFAULT_BRANCH: %w", 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")
}
isPrivateRepo := os.Getenv("SCORECARD_PRIVATE_REPOSITORY")
if isPrivateRepo != "true" {
if err := os.Setenv("SCORECARD_PUBLISH_RESULTS", "false"); err != nil {
return fmt.Errorf("error setting SCORECARD_PUBLISH_RESULTS: %w", err)
}
}
return nil
}
26 changes: 18 additions & 8 deletions main_test.go
Expand Up @@ -20,6 +20,7 @@ import (
)

func Test_scorecardIsFork(t *testing.T) {
t.Parallel()
type args struct {
ghEventPath string
}
Expand Down Expand Up @@ -60,7 +61,9 @@ 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 != "" {
Expand All @@ -84,6 +87,7 @@ func Test_scorecardIsFork(t *testing.T) {
}

func Test_initalizeENVVariables(t *testing.T) {
t.Parallel()
tests := []struct {
name string
wantErr bool
Expand Down Expand Up @@ -158,7 +162,9 @@ 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)
} else {
Expand All @@ -183,14 +189,18 @@ func Test_initalizeENVVariables(t *testing.T) {
t.Errorf("initalizeENVVariables() error = %v, wantErr %v", err, tt.wantErr)
}

if os.Getenv("ENABLE_SARIF") == "" && os.Getenv("ENABLE_SARIF") != "1" {
t.Errorf("ENABLE_SARIF is not set")
}
if os.Getenv("ENABLE_LICENSE") == "" && os.Getenv("ENABLE_LICENSE") != "1" {
t.Errorf("ENABLE_LICENSE is not set")
}
if os.Getenv("ENABLE_DANGEROUS_WORKFLOW") == "" && os.Getenv("ENABLE_DANGEROUS_WORKFLOW") != "1" {
t.Errorf("ENABLE_DANGEROUS_WORKFLOW is not set")
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"] = ""

for k, v := range envvars {
if os.Getenv(k) != v {
t.Errorf("%s env var not set correctly", k)
}
}
})
}
Expand Down

0 comments on commit 73e6f16

Please sign in to comment.