diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index e847680..5a9f30c 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -1,31 +1,42 @@ -name: "Static Analysis" -on: ["push", "pull_request"] +name: Static Code Analysis +on: + push: + branches: + - "**" + tags-ignore: + - "**" + pull_request: jobs: Static-Check: runs-on: ubuntu-latest steps: - name: Checkout Source uses: actions/checkout@v3 + - name: Install Go uses: actions/setup-go@v3 with: go-version: 1.20.x + - 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 errcheck,gosimple,govet,ineffassign,staticcheck,typecheck,unused,gocritic,asasalint,asciicheck,errchkjson,exportloopref,makezero,nilerr,unparam,unconvert,wastedassign,usestdlibvars + Go-Sec: runs-on: ubuntu-latest steps: - name: Checkout Source uses: actions/checkout@v3 + - name: Install Go uses: actions/setup-go@v3 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\.* ./... + + - name: Run Gosec Security Scanner + uses: securego/gosec@master + with: + args: -exclude G204,G304,G404,G401,G505 -tests -exclude-dir \.*test\.* ./... \ No newline at end of file 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/aes_encryption.go b/crypto/aes_encryption.go index 3cc52f0..4c5aa98 100644 --- a/crypto/aes_encryption.go +++ b/crypto/aes_encryption.go @@ -75,8 +75,8 @@ func Decrypt(formattedCipherText, key, keyId string) (string, error) { if !strings.Contains(formattedCipherText, formatEncryption) { return "", errors.New("cipher text is not well formatted") } - //keep cipher text only - cipherText := strings.Replace(formattedCipherText, formatEncryption, "", -1) + // keep cipher text only + cipherText := strings.ReplaceAll(formattedCipherText, formatEncryption, "") // hex decoding of key and text KeyByte, err := hex.DecodeString(key) if err != nil { @@ -99,7 +99,7 @@ func IsTextEncrypted(formattedCipherText, key, keyId string) (bool, error) { return false, errors.New("cipher text is not well formatted") } // Keep cipher text only - cipherText := strings.Replace(formattedCipherText, formatEncryption, "", -1) + cipherText := strings.ReplaceAll(formattedCipherText, formatEncryption, "") // hex decoding of key and text keyByte, err := hex.DecodeString(key) if err != nil { diff --git a/crypto/aes_encryption_test.go b/crypto/aes_encryption_test.go index fd4f0e4..1bf7d33 100644 --- a/crypto/aes_encryption_test.go +++ b/crypto/aes_encryption_test.go @@ -16,7 +16,7 @@ func init() { panic("Failed to generate signingKey") } h := sha256.New() - sha256 := fmt.Sprintf("%x", (h.Sum(nil))) + sha256 := fmt.Sprintf("%x", h.Sum(nil)) keyId = sha256[:6] } @@ -42,8 +42,8 @@ func TestDecryptUnformattedCipherText(t *testing.T) { t.Fatal(err) } formatEncryption := keyId + "$" + "aes256" + "$" - //keep cipher text only - cipherText := strings.Replace(FormattedCipherText, formatEncryption, "", -1) + // Keep cipher text only + cipherText := strings.ReplaceAll(FormattedCipherText, formatEncryption, "") _, err = Decrypt(cipherText, signingKey, keyId) if err == nil || (err != nil && err.Error() != "cipher text is not well formatted") { t.Fatal("Expect error Cipher text is not well formatted") @@ -53,7 +53,7 @@ func TestDecryptUnformattedCipherText(t *testing.T) { func TestIsTextEncrypted(t *testing.T) { var text = "Text to encrypt with very long text" formatEncryption := keyId + "$" + "aes256" + "$" + text - //keep cipher text only + // Keep cipher text only isEncrypted, err := IsTextEncrypted(formatEncryption, signingKey, keyId) if isEncrypted { t.Fatal(err) 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/fanout/readall_reader.go b/fanout/readall_reader.go index aa4bc80..068df54 100644 --- a/fanout/readall_reader.go +++ b/fanout/readall_reader.go @@ -45,7 +45,7 @@ func NewReadAllReader(reader io.Reader, consumers ...ReadAllConsumer) *ReadAllRe pipeWriters := make([]*io.PipeWriter, procLen) done := make(chan *readerResult, procLen) errs := make(chan error, procLen) - //Create pipe r/w for each reader + // Create pipe r/w for each reader for i := 0; i < procLen; i++ { pr, pw := io.Pipe() pipeReaders[i] = pr diff --git a/fanout/reader.go b/fanout/reader.go index 978f4d3..7cb168c 100644 --- a/fanout/reader.go +++ b/fanout/reader.go @@ -28,7 +28,7 @@ func NewReader(reader io.Reader, consumers ...Consumer) *Reader { procLen := len(consumers) pipeReaders := make([]*io.PipeReader, procLen) pipeWriters := make([]*io.PipeWriter, procLen) - //Create pipe r/w for each reader + // Create pipe r/w for each reader for i := 0; i < procLen; i++ { pr, pw := io.Pipe() pipeReaders[i] = pr @@ -52,10 +52,10 @@ func (r *Reader) Read(p []byte) (int, error) { go func() { defer wg.Done() defer r.close() - //Read from reader and fan out to the writers + // Read from reader and fan out to the writers n, err := r.reader.Read(p) if err != nil { - //Do not wrap the read err or EOF will not be handled + // Do not wrap the read err or EOF will not be handled e = err } else { _, err = r.multiWriter.Write(p[:n]) diff --git a/fanout/reader_test.go b/fanout/reader_test.go index 5301853..cbe6b25 100644 --- a/fanout/reader_test.go +++ b/fanout/reader_test.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "encoding/hex" "errors" + "github.com/stretchr/testify/assert" "io" "strings" "testing" @@ -28,7 +29,7 @@ func TestFanoutRead(t *testing.T) { return hash.Sum(nil), nil } - //Using a closure argument instead of results + // Using a closure argument instead of results var sum3 []byte proc1 := func(r io.Reader) (rt interface{}, er error) { hash := sha256.New() @@ -46,15 +47,17 @@ func TestFanoutRead(t *testing.T) { if err != nil { t.Error(err) } - sum1 := results[0].([]byte) - sum2 := results[1].([]byte) + sum1, ok := results[0].([]byte) + assert.True(t, ok) + sum2, ok := results[1].([]byte) + assert.True(t, ok) sum1str := hex.EncodeToString(sum1) sum2str := hex.EncodeToString(sum2) sum3str := hex.EncodeToString(sum3) - if !(sum1str == sum2str && sum1str == sum3str) { - t.Errorf("Sum1 %s and sum2 %s and sum3 %s are not the same", sum1str, sum2str, sum3str) + if sum1str != sum2str || sum1str != sum3str { + t.Errorf("Sum1 %s, Sum2 %s, and Sum3 %s are not all the same", sum1str, sum2str, sum3str) } if sum1str != sha2sum { @@ -156,5 +159,5 @@ func TestSyncReadOnError(t *testing.T) { } pfr := NewReadAllReader(strings.NewReader("someNotTooShortString"), ReadAllConsumerFunc(proc1), ReadAllConsumerFunc(proc2)) - pfr.ReadAll() + _, _ = pfr.ReadAll() } diff --git a/go.mod b/go.mod index 4988110..a60ea6b 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,22 @@ module github.com/jfrog/gofrog go 1.20 require ( - github.com/jfrog/archiver/v3 v3.5.3 + github.com/jfrog/archiver/v3 v3.6.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.4 ) require ( - github.com/andybalholm/brotli v1.0.1 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect - github.com/golang/snappy v0.0.2 // indirect - github.com/klauspost/compress v1.11.4 // indirect - github.com/klauspost/pgzip v1.2.5 // indirect - github.com/nwaples/rardecode v1.1.0 // indirect - github.com/pierrec/lz4/v4 v4.1.2 // indirect + github.com/dsnet/compress v0.0.1 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/pgzip v1.2.6 // indirect + github.com/nwaples/rardecode v1.1.3 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/ulikunitz/xz v0.5.9 // indirect + github.com/ulikunitz/xz v0.5.11 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 499ef73..b9baeb6 100644 --- a/go.sum +++ b/go.sum @@ -1,43 +1,36 @@ -github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= -github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= -github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= -github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/jfrog/archiver/v3 v3.5.3 h1:Udz6+z/YIhTFmcEp1TeW2DEwNyo7JSAnrGUsrbL2FZI= -github.com/jfrog/archiver/v3 v3.5.3/go.mod h1:/MbmBhPzkliu9PtweAg9lCYHGcKdapwMMZS/QS09T5c= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/jfrog/archiver/v3 v3.6.0 h1:OVZ50vudkIQmKMgA8mmFF9S0gA47lcag22N13iV3F1w= +github.com/jfrog/archiver/v3 v3.6.0/go.mod h1:fCAof46C3rAXgZurS8kNRNdSVMKBbZs+bNNhPYxLldI= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU= -github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= -github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= -github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= -github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= +github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc= +github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= -github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= +github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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/io/fileutils.go b/io/fileutils.go index 95b93ba..75fa724 100644 --- a/io/fileutils.go +++ b/io/fileutils.go @@ -21,7 +21,7 @@ const buflen = 4096 var src = rand.NewSource(time.Now().UnixNano()) -// #nosec G404 - No cryptographic level encription is needed in random file +// #nosec G404 - No cryptographic level encryption is needed in random file var rnd = rand.New(src) func CreateRandomLenFile(maxLen int, filesDir string, prefix string) string { @@ -33,7 +33,7 @@ func CreateRandomLenFile(maxLen int, filesDir string, prefix string) string { panic(err) } defer created.Close() - //Check that the files were created with expected len + // Check that the files were created with expected len if created.Info.Size() != int64(len) { panic(fmt.Errorf("unexpected file length. Expected: %d, Got %d", created.Info.Size(), len)) } 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..8522b51 100644 --- a/lru/lru_base.go +++ b/lru/lru_base.go @@ -38,8 +38,10 @@ func (c *cacheBase) Add(key string, value interface{}) { } if ee, ok := c.cache[key]; ok { c.ll.MoveToFront(ee) - ee.Value.(*entry).value = value - ee.Value.(*entry).timeInsert = epochNow + if ent, entOk := ee.Value.(*entry); entOk { + ent.value = value + ent.timeInsert = epochNow + } return } ele := c.ll.PushFront(&entry{key, value, epochNow}) @@ -65,7 +67,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..0126dca 100644 --- a/parallel/bounded_runner_test.go +++ b/parallel/bounded_runner_test.go @@ -139,10 +139,10 @@ func TestFailFastOnTaskError(t *testing.T) { wg.Wait() checkResult(expectedTotal, results, t) - //TODO: Fix this test - //This test is fragile since 1 or more goroutines may be executing and failing fast in parallel, - //calling the error handler and increasing the result. So we cannot use accurate comparison. - //Here we only take care of uo to 1 additional concurrent failfast. + // TODO: Fix this test + // This test is fragile since 1 or more goroutines may be executing and failing fast in parallel, + // calling the error handler and increasing the result. So we cannot use accurate comparison. + // Here we only take care of uo to 1 additional concurrent failfast. errTotal := 0 for { err := errorsQueue.GetError() @@ -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/parallel/runner_test.go b/parallel/runner_test.go index b3e0293..bf2433a 100644 --- a/parallel/runner_test.go +++ b/parallel/runner_test.go @@ -15,9 +15,10 @@ var errTest = errors.New("some error") func TestIsStarted(t *testing.T) { runner := NewBounedRunner(1, false) - runner.AddTask(func(i int) error { + _, err := runner.AddTask(func(i int) error { return nil }) + assert.NoError(t, err) runner.Done() runner.Run() assert.True(t, runner.IsStarted()) @@ -41,7 +42,7 @@ func TestAddTask(t *testing.T) { results <- x time.Sleep(time.Millisecond * time.Duration(rand.Intn(50))) if float64(x) > float64(count)/2 { - return fmt.Errorf("Second half value %d not counted", x) + return fmt.Errorf("second half value %d not counted", x) } return nil }) diff --git a/stringutils/wildcards.go b/stringutils/wildcards.go index 79c3c38..ae0b0e5 100644 --- a/stringutils/wildcards.go +++ b/stringutils/wildcards.go @@ -19,7 +19,7 @@ func MatchWildcardPattern(pattern string, str string) (matched bool, err error) func WildcardPatternToRegExp(localPath string) string { localPath = EscapeSpecialChars(localPath) var wildcard = ".*" - localPath = strings.Replace(localPath, "*", wildcard, -1) + localPath = strings.ReplaceAll(localPath, "*", wildcard) if strings.HasSuffix(localPath, "/") || strings.HasSuffix(localPath, "\\") { localPath += wildcard } @@ -30,7 +30,7 @@ func EscapeSpecialChars(path string) string { // We don't replace other special characters (like parenthesis) because they're used in the placeholders logic of the JFrog CLI. var specialChars = []string{".", "^", "$", "+", "[", "]"} for _, char := range specialChars { - path = strings.Replace(path, char, "\\"+char, -1) + path = strings.ReplaceAll(path, char, "\\"+char) } return path } diff --git a/version/version.go b/version/version.go index 01c934b..c047939 100644 --- a/version/version.go +++ b/version/version.go @@ -25,11 +25,12 @@ func (v *Version) SetVersion(version string) { // If ver1 > version returns 1 // If ver1 < version returns -1 func (v *Version) Compare(ver1 string) int { - if ver1 == v.version { + switch { + case ver1 == v.version: return 0 - } else if ver1 == "development" { + case ver1 == "development": return 1 - } else if v.version == "development" { + case v.version == "development": return -1 } @@ -69,7 +70,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)