diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index e847680..b47f81b 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -1,31 +1,43 @@ -name: "Static Analysis" -on: ["push", "pull_request"] +name: Static Code Analysis +on: + push: + branches: + - "**" + tags-ignore: + - "**" + pull_request: jobs: - Static-Check: + go-analysis: runs-on: ubuntu-latest steps: - - name: Checkout Source - uses: actions/checkout@v3 - - name: Install Go - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 with: go-version: 1.20.x + cache: false + - name: Static Code Analysis - uses: dominikh/staticcheck-action@v1 + uses: golangci/golangci-lint-action@v3 with: - install-go: false + args: | + --timeout 5m --out-${NO_FUTURE}format colored-line-number --enable gosec,errcheck,gosimple,govet,ineffassign,staticcheck,typecheck,unused,gocritic,asasalint,asciicheck,errchkjson,exportloopref,forcetypeassert,makezero,nilerr,unparam,unconvert,wastedassign,usestdlibvars - Go-Sec: + bash-analysis: runs-on: ubuntu-latest steps: - - name: Checkout Source - uses: actions/checkout@v3 - - name: Install Go - uses: actions/setup-go@v3 + - uses: actions/checkout@v4 + + - name: Run ShellCheck + uses: ludeeus/action-shellcheck@master with: - go-version: 1.20.x - - name: Install gosec - run: curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $(go env GOPATH)/bin - - name: Run gosec - # Temporary ignoring G301,G302,G306 - run: gosec -exclude=G204,G301,G302,G304,G306 -exclude-dir=\.*test\.* ./... + ignore_paths: "*test*" + + check-spelling: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check spelling + uses: crate-ci/typos@master diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml index e36268d..541512e 100644 --- a/.github/workflows/cla.yml +++ b/.github/workflows/cla.yml @@ -14,16 +14,16 @@ jobs: id: sign-or-recheck with: text: ${{ github.event.comment.body }} - regex: '\s*(I have read the CLA Document and I hereby sign the CLA)|(recheckcla)\s*' - + regex: '\s*(I have read the CLA Document and I hereby sign the CLA)|(recheck)\s*' + - name: "CLA Assistant" if: ${{ steps.sign-or-recheck.outputs.match != '' || github.event_name == 'pull_request_target' }} # Alpha Release - uses: cla-assistant/github-action@v2.1.1-beta + uses: cla-assistant/github-action@v2.3.0 env: - # Generated and maintained by github + # Generated and maintained by GitHub GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # JFrog organization secret + # JFrog's organization secret PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_SIGN_TOKEN }} with: path-to-signatures: 'signed_clas.json' diff --git a/.github/workflows/frogbot-fix-go.yml b/.github/workflows/frogbot-fix-go.yml deleted file mode 100644 index 84c550e..0000000 --- a/.github/workflows/frogbot-fix-go.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: "Frogbot Scan and Fix" -on: - push: - # Creating fix pull requests will be triggered by any push to one of the these branches. - # You can add or replace to any branch you want to open fix pull requests for. - branches: - - "dev" -permissions: - contents: write - pull-requests: write -jobs: - create-fix-pull-requests: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - # Install prerequisites - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: 1.20.x - - - uses: jfrog/frogbot@v2 - env: - # [Mandatory] - # JFrog platform URL (This functionality requires version 3.29.0 or above of Xray) - JF_URL: ${{ secrets.FROGBOT_URL }} - - # [Mandatory if JF_USER and JF_PASSWORD are not provided] - # JFrog access token with 'read' permissions on Xray service - JF_ACCESS_TOKEN: ${{ secrets.FROGBOT_ACCESS_TOKEN }} - - # [Mandatory] - # The GitHub token automatically generated for the job - JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/frogbot-scan-pr-go.yml b/.github/workflows/frogbot-scan-pr-go.yml deleted file mode 100644 index 87f618e..0000000 --- a/.github/workflows/frogbot-scan-pr-go.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: "Frogbot Scan Pull Requests" -on: - pull_request_target: - types: [opened, synchronize] -permissions: - pull-requests: write -jobs: - scan-pull-request: - runs-on: ubuntu-latest - # A pull request needs to be approved, before Frogbot scans it. Any GitHub user who is associated with the - # "frogbot" GitHub environment can approve the pull request to be scanned. - environment: frogbot - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - # Install prerequisites - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: 1.20.x - - - uses: jfrog/frogbot@v2 - env: - # [Mandatory] - # JFrog platform URL - JF_URL: ${{ secrets.FROGBOT_URL }} - - # [Mandatory if JF_USER and JF_PASSWORD are not provided] - # JFrog access token with 'read' permissions on Xray service - JF_ACCESS_TOKEN: ${{ secrets.FROGBOT_ACCESS_TOKEN }} - - # [Mandatory] - # The GitHub token automatically generated for the job - JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/frogbot-scan-pull-request.yml b/.github/workflows/frogbot-scan-pull-request.yml new file mode 100644 index 0000000..998c8c9 --- /dev/null +++ b/.github/workflows/frogbot-scan-pull-request.yml @@ -0,0 +1,119 @@ +name: "Frogbot Scan Pull Request" +on: + pull_request_target: + types: [ opened, synchronize ] +permissions: + pull-requests: write + contents: read +jobs: + scan-pull-request: + runs-on: ubuntu-latest + # A pull request needs to be approved before Frogbot scans it. Any GitHub user who is associated with the + # "frogbot" GitHub environment can approve the pull request to be scanned. + environment: frogbot + steps: + - uses: jfrog/frogbot@v2 + env: + JFROG_CLI_LOG_LEVEL: "DEBUG" + # [Mandatory] + # JFrog platform URL (This functionality requires version 3.29.0 or above of Xray) + JF_URL: ${{ secrets.FROGBOT_URL }} + + # [Mandatory if JF_USER and JF_PASSWORD are not provided] + # JFrog access token with 'read' permissions on Xray service + JF_ACCESS_TOKEN: ${{ secrets.FROGBOT_ACCESS_TOKEN }} + + # [Mandatory] + # The GitHub token is automatically generated for the job + JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # [Optional, default: https://api.github.com] + # API endpoint to GitHub + # JF_GIT_API_ENDPOINT: https://github.example.com + + # [Optional] + # By default, the Frogbot workflows download the Frogbot executable as well as other tools + # needed from https://releases.jfrog.io + # If the machine that runs Frogbot has no access to the internet, follow these steps to allow the + # executable to be downloaded from an Artifactory instance, which the machine has access to: + # + # 1. Login to the Artifactory UI, with a user who has admin credentials. + # 2. Create a Remote Repository with the following properties set. + # Under the 'Basic' tab: + # Package Type: Generic + # URL: https://releases.jfrog.io + # Under the 'Advanced' tab: + # Uncheck the 'Store Artifacts Locally' option + # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. + # JF_RELEASES_REPO: "" + + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + JF_SMTP_SERVER: ${{ secrets.JF_SMTP_SERVER }} + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + JF_SMTP_USER: ${{ secrets.JF_SMTP_USER }} + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + JF_SMTP_PASSWORD: ${{ secrets.JF_SMTP_PASSWORD }} + + # [Optional] + # List of comma separated email addresses to receive email notifications about secrets + # detected during pull request scanning. The notification is also sent to the email set + # in the committer git profile regardless of whether this variable is set or not. + JF_EMAIL_RECEIVERS: "eco-system@jfrog.com" + + ########################################################################## + ## If your project uses a 'frogbot-config.yml' file, you can define ## + ## the following variables inside the file, instead of here. ## + ########################################################################## + + # [Mandatory if the two conditions below are met] + # 1. The project uses yarn 2, NuGet or .NET Core to download its dependencies + # 2. The `installCommand` variable isn't set in your frogbot-config.yml file. + # + # The command that installs the project dependencies (e.g "nuget restore") + # JF_INSTALL_DEPS_CMD: "" + + # [Optional, default: "."] + # Relative path to the root of the project in the Git repository + # JF_WORKING_DIR: path/to/project/dir + + # [Optional] + # Xray Watches. Learn more about them here: https://www.jfrog.com/confluence/display/JFROG/Configuring+Xray+Watches + # JF_WATCHES: ,... + + # [Optional] + # JFrog project. Learn more about it here: https://www.jfrog.com/confluence/display/JFROG/Projects + # JF_PROJECT: + + # [Optional, default: "FALSE"] + # Displays all existing vulnerabilities, including the ones that were added by the pull request. + # JF_INCLUDE_ALL_VULNERABILITIES: "TRUE" + + # [Optional, default: "TRUE"] + # Fails the Frogbot task if any security issue is found. + # JF_FAIL: "FALSE" + + # [Optional] + # Frogbot will download the project dependencies if they're not cached locally. To download the + # dependencies from a virtual repository in Artifactory, set the name of the repository. There's no + # need to set this value, if it is set in the frogbot-config.yml file. + # JF_DEPS_REPO: "" + + # [Optional, Default: "FALSE"] + # If TRUE, Frogbot creates a single pull request with all the fixes. + # If false, Frogbot creates a separate pull request for each fix. + # JF_GIT_AGGREGATE_FIXES: "FALSE" + + # [Optional, Default: "FALSE"] + # Handle vulnerabilities with fix versions only + # JF_FIXABLE_ONLY: "TRUE" + + # [Optional] + # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests + # The following values are accepted: Low, Medium, High or Critical + # JF_MIN_SEVERITY: "" \ No newline at end of file diff --git a/.github/workflows/frogbot-scan-repository.yml b/.github/workflows/frogbot-scan-repository.yml new file mode 100644 index 0000000..2342d4d --- /dev/null +++ b/.github/workflows/frogbot-scan-repository.yml @@ -0,0 +1,125 @@ +name: "Frogbot Scan Repository" +on: + workflow_dispatch: + schedule: + # The repository will be scanned once a day at 00:00 GMT. + - cron: "0 0 * * *" +permissions: + contents: write + pull-requests: write + security-events: write +jobs: + scan-repository: + runs-on: ubuntu-latest + strategy: + matrix: + # The repository scanning will be triggered periodically on the following branches. + branch: [ "master" ] + steps: + - uses: jfrog/frogbot@v2 + env: + JFROG_CLI_LOG_LEVEL: "DEBUG" + # [Mandatory] + # JFrog platform URL (This functionality requires version 3.29.0 or above of Xray) + JF_URL: ${{ secrets.FROGBOT_URL }} + + # [Mandatory if JF_USER and JF_PASSWORD are not provided] + # JFrog access token with 'read' permissions on Xray service + JF_ACCESS_TOKEN: ${{ secrets.FROGBOT_ACCESS_TOKEN }} + + # [Mandatory if JF_ACCESS_TOKEN is not provided] + # JFrog username with 'read' permissions for Xray. Must be provided with JF_PASSWORD + # JF_USER: ${{ secrets.JF_USER }} + + # [Mandatory if JF_ACCESS_TOKEN is not provided] + # JFrog password. Must be provided with JF_USER + # JF_PASSWORD: ${{ secrets.JF_PASSWORD }} + + # [Mandatory] + # The GitHub token is automatically generated for the job + JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # [Mandatory] + # The name of the branch on which Frogbot will perform the scan + JF_GIT_BASE_BRANCH: ${{ matrix.branch }} + + # [Optional, default: https://api.github.com] + # API endpoint to GitHub + # JF_GIT_API_ENDPOINT: https://github.example.com + + # [Optional] + # By default, the Frogbot workflows download the Frogbot executable as well as other tools + # needed from https://releases.jfrog.io + # If the machine that runs Frogbot has no access to the internet, follow these steps to allow the + # executable to be downloaded from an Artifactory instance, which the machine has access to: + # + # 1. Login to the Artifactory UI, with a user who has admin credentials. + # 2. Create a Remote Repository with the following properties set. + # Under the 'Basic' tab: + # Package Type: Generic + # URL: https://releases.jfrog.io + # Under the 'Advanced' tab: + # Uncheck the 'Store Artifacts Locally' option + # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. + # JF_RELEASES_REPO: "" + + ########################################################################## + ## If your project uses a 'frogbot-config.yml' file, you can define ## + ## the following variables inside the file, instead of here. ## + ########################################################################## + + # [Optional, default: "."] + # Relative path to the root of the project in the Git repository + # JF_WORKING_DIR: path/to/project/dir + + # [Optional] + # Xray Watches. Learn more about them here: https://www.jfrog.com/confluence/display/JFROG/Configuring+Xray+Watches + # JF_WATCHES: ,... + + # [Optional] + # JFrog project. Learn more about it here: https://www.jfrog.com/confluence/display/JFROG/Projects + # JF_PROJECT: + + # [Optional, default: "TRUE"] + # Fails the Frogbot task if any security issue is found. + # JF_FAIL: "FALSE" + + # [Optional] + # Frogbot will download the project dependencies, if they're not cached locally. To download the + # dependencies from a virtual repository in Artifactory, set the name of the repository. There's no + # need to set this value, if it is set in the frogbot-config.yml file. + # JF_DEPS_REPO: "" + + # [Optional] + # Template for the branch name generated by Frogbot when creating pull requests with fixes. + # The template must include ${BRANCH_NAME_HASH}, to ensure that the generated branch name is unique. + # The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. + # JF_BRANCH_NAME_TEMPLATE: "frogbot-${IMPACTED_PACKAGE}-${BRANCH_NAME_HASH}" + + # [Optional] + # Template for the commit message generated by Frogbot when creating pull requests with fixes + # The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. + # JF_COMMIT_MESSAGE_TEMPLATE: "Upgrade ${IMPACTED_PACKAGE} to ${FIX_VERSION}" + + # [Optional] + # Template for the pull request title generated by Frogbot when creating pull requests with fixes. + # The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. + # JF_PULL_REQUEST_TITLE_TEMPLATE: "[🐸 Frogbot] Upgrade ${IMPACTED_PACKAGE} to ${FIX_VERSION}" + + # [Optional, Default: "FALSE"] + # If TRUE, Frogbot creates a single pull request with all the fixes. + # If FALSE, Frogbot creates a separate pull request for each fix. + # JF_GIT_AGGREGATE_FIXES: "FALSE" + + # [Optional, Default: "FALSE"] + # Handle vulnerabilities with fix versions only + # JF_FIXABLE_ONLY: "TRUE" + + # [Optional] + # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests + # The following values are accepted: Low, Medium, High or Critical + # JF_MIN_SEVERITY: "" + + # [Optional, Default: eco-system+frogbot@jfrog.com] + # Set the email of the commit author + # JF_GIT_EMAIL_AUTHOR: "" \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8377cfe..95f7889 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,23 +1,21 @@ -name: Tests - -on: [push, pull_request] - +name: Test +on: + push: + branches: + - "**" + tags-ignore: + - "**" + # pull_request: jobs: test: - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.os }}-latest strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - env: - GOPROXY: direct + os: [ubuntu, windows, macOS] steps: - - uses: actions/checkout@v3 - - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.20.x + - name: Checkout Source + uses: actions/checkout@v4 - name: Go Cache uses: actions/cache@v3 @@ -27,8 +25,11 @@ jobs: restore-keys: | ${{ runner.os }}-go- - - name: Go Vet - run: go vet ./... + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: 1.20.x + cache: false - name: Tests - run: go test ./... -v -race + run: go test -v -race -covermode atomic -coverprofile=covprofile ./... diff --git a/.gitignore b/.gitignore index 335d6a8..54b01ba 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,11 @@ _testmain.go *.exe *.test *.prof + +# IDEs +.vscode +.idea +*.iml + +# IOS +*.DS_Store \ No newline at end of file diff --git a/crypto/key_generator.go b/crypto/key_generator.go index 573b62c..9c6e7ea 100644 --- a/crypto/key_generator.go +++ b/crypto/key_generator.go @@ -31,6 +31,6 @@ func GenerateKeyId(key string) (string, error) { } h := sha256.New() h.Write([]byte(key)) - sha256 := fmt.Sprintf("%x", (h.Sum(nil))) + sha256 := fmt.Sprintf("%x", h.Sum(nil)) return sha256[:6], nil } diff --git a/io/cmd.go b/io/cmd.go index 0f6cc3c..39b227a 100644 --- a/io/cmd.go +++ b/io/cmd.go @@ -62,7 +62,8 @@ func RunCmd(config CmdConfig) error { // If the command fails to run or doesn't complete successfully ExitError is returned. // We would like to return a regular error instead of ExitError, // because some frameworks (such as codegangsta used by JFrog CLI) automatically exit when this error is returned. - if _, ok := err.(*exec.ExitError); ok { + var exitError *exec.ExitError + if errors.As(err, &exitError) { err = errors.New(err.Error()) } @@ -135,14 +136,15 @@ func RunCmdWithOutputParser(config CmdConfig, prompt bool, regExpStruct ...*CmdO return } exitOk = true - if _, ok := err.(*exec.ExitError); ok { + var exitError *exec.ExitError + if errors.As(err, &exitError) { // The program has exited with an exit code != 0 exitOk = false } return } -// Run all of the input regExpStruct array on the input stdout or stderr line. +// Run all the input regExpStruct array on the input stdout or stderr line. // If an error occurred, add it to the error channel. // regExpStruct - Array of command output patterns to process the line // line - string line from stdout or stderr @@ -195,7 +197,7 @@ type CmdConfig interface { } // RegExp - The regexp that the line will be searched upon. -// MatchedResults - The slice result that was found by the regex +// MatchedResults - The slice result that was found by the regexp // Line - The output line from the external process // ExecFunc - The function to execute type CmdOutputPattern struct { diff --git a/lru/lru.go b/lru/lru.go index 1543cf3..fb49393 100644 --- a/lru/lru.go +++ b/lru/lru.go @@ -53,7 +53,7 @@ func (c *Cache) Get(key string) (value interface{}, ok bool) { return c.cache.Get(key) } -// Updates element's value without updating it's "Least-Recently-Used" status +// Updates element's value without updating its "Least-Recently-Used" status func (c *Cache) UpdateElement(key string, value interface{}) { if !c.noSync { c.lock.Lock() diff --git a/lru/lru_base.go b/lru/lru_base.go index 55db5c6..2f7a4ee 100644 --- a/lru/lru_base.go +++ b/lru/lru_base.go @@ -65,7 +65,7 @@ func (c *cacheBase) Get(key string) (value interface{}, ok bool) { return nil, false } -// Updates element's value without updating it's "Least-Recently-Used" status +// Updates element's value without updating its "Least-Recently-Used" status func (c *cacheBase) UpdateElement(key string, value interface{}) { if ee, ok := c.cache[key]; ok { ee.Value.(*entry).value = value diff --git a/parallel/bounded_runner_test.go b/parallel/bounded_runner_test.go index 1711ec7..a13ca9d 100644 --- a/parallel/bounded_runner_test.go +++ b/parallel/bounded_runner_test.go @@ -207,7 +207,7 @@ func createSuccessfulFlowTaskFunc(num int, result chan int) TaskFunc { func createTaskWithErrorFunc(num int, result chan int) TaskFunc { return func(threadId int) error { if num > 50 { - return fmt.Errorf("num: %d, above 50 going to stop.", num) + return fmt.Errorf("num: %d, above 50 going to stop", num) } result <- num time.Sleep(time.Millisecond * time.Duration(rand.Intn(50))) diff --git a/parallel/runner.go b/parallel/runner.go index d051412..48e0947 100644 --- a/parallel/runner.go +++ b/parallel/runner.go @@ -80,7 +80,7 @@ type runner struct { // Create a new capacity runner - a runner we can add tasks to without blocking as long as the capacity is not reached. // maxParallel - number of go routines for task processing, maxParallel always will be a positive number. -// acceptBeforeBlocking - number of tasks that can be added until a free processing goruntine is needed. +// acceptBeforeBlocking - number of tasks that can be added until a free processing goroutine is needed. // failFast - is set to true the will stop on first error. func NewRunner(maxParallel int, capacity uint, failFast bool) *runner { consumers := maxParallel diff --git a/version/version.go b/version/version.go index 01c934b..e042d09 100644 --- a/version/version.go +++ b/version/version.go @@ -69,7 +69,7 @@ func compareTokens(ver1Token, ver2Token string) int { return 0 } - // Ignoring error because we strip all the non numeric values in advance. + // Ignoring error because we strip all the non-numeric values in advance. ver1Number, ver1Suffix := splitNumberAndSuffix(ver1Token) ver1TokenInt, _ := strconv.Atoi(ver1Number) ver2Number, ver2Suffix := splitNumberAndSuffix(ver2Token)