diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f12648cd4..04664fe9b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,16 +1,33 @@ +--- version: 2 updates: -- package-ecosystem: gomod - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 -- package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 -- package-ecosystem: "docker" - directory: "/" - schedule: - interval: weekly + - package-ecosystem: gomod + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 + groups: + gomod: + update-types: + - "patch" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 + groups: + actions: + update-types: + - "patch" + - "minor" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: weekly + groups: + docker: + update-types: + - "patch" + - "minor" diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5aa9e321d..d7ae0a094 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -6,42 +6,49 @@ on: pull_request: branches: - '*' + +permissions: {} + jobs: build: runs-on: ubuntu-latest + + permissions: + contents: read + steps: - name: checkout - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 + persist-credentials: false - name: shellcheck uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 - name: Setup go - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: - go-version-file: './go.mod' + go-version: '1.25' check-latest: true + cache: false - - uses: azure/setup-helm@5119fcb9089d432beecbf79bb2c7915207344b78 # v3.5 - with: - version: v3.11.2 + - uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1 - name: Install GoReleaser - uses: goreleaser/goreleaser-action@f82d6c1c344bcacabba2c841718984797f664a6b # v4.2.0 + uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 with: install-only: true - name: Install cosign - uses: sigstore/cosign-installer@c3667d99424e7e6047999fb6246c0da843953c65 # v3.0.1 + uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0 - name: Install syft - uses: anchore/sbom-action/download-syft@448520c4f19577ffce70a8317e619089054687e3 # v0.14.0 + uses: anchore/sbom-action/download-syft@62ad5284b8ced813296287a0b63906cb364b73ee # v0.22.0 - name: Install k8s Kind - uses: helm/kind-action@d8ccf8fb623ce1bb360ae2f45f323d9d5c5e9f00 # v1.3.0 + uses: helm/kind-action@92086f6be054225fa813e0a4b13787fc9088faab # v1.3.0 with: install_only: true @@ -65,10 +72,10 @@ jobs: git diff --exit-code - name: Set up QEMU - uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Build run: | @@ -81,12 +88,20 @@ jobs: check-docs: name: check-docs runs-on: ubuntu-latest + + permissions: + contents: read + steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - go-version-file: './go.mod' + persist-credentials: false + + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version: '1.25' check-latest: true + cache: false - name: generate docs run: | @@ -102,13 +117,22 @@ jobs: golangci: name: lint runs-on: ubuntu-latest + + permissions: + contents: read + steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 - - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - go-version-file: './go.mod' + persist-credentials: false + + - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version: '1.25' check-latest: true + cache: false + - name: golangci-lint - uses: golangci/golangci-lint-action@08e2f20817b15149a52b5b3ebe7de50aff2ba8c5 # v3 + uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0 with: - version: v1.52.1 + version: v2.7 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 98edc7584..2ece1c36b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -6,6 +6,8 @@ on: description: Version required: true +permissions: {} + jobs: build: runs-on: ubuntu-latest @@ -17,7 +19,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 # v3.5.0 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -25,21 +27,22 @@ jobs: uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 - name: Setup go - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: - go-version-file: './go.mod' + go-version: '1.25' check-latest: true + cache: false - name: Install GoReleaser - uses: goreleaser/goreleaser-action@f82d6c1c344bcacabba2c841718984797f664a6b # v4.2.0 + uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 with: install-only: true - name: Install cosign - uses: sigstore/cosign-installer@c3667d99424e7e6047999fb6246c0da843953c65 # v3.0.1 + uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0 - name: Install syft - uses: anchore/sbom-action/download-syft@448520c4f19577ffce70a8317e619089054687e3 # v0.14.0 + uses: anchore/sbom-action/download-syft@62ad5284b8ced813296287a0b63906cb364b73ee # v0.22.0 - name: Install tools run: | @@ -53,13 +56,13 @@ jobs: git diff --exit-code - name: Set up QEMU - uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 + uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Login to registry - uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: quay.io username: ${{ secrets.DOCKER_USERNAME }} diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml new file mode 100644 index 000000000..fc024373e --- /dev/null +++ b/.github/workflows/stale.yaml @@ -0,0 +1,28 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '30 1 * * *' + +permissions: {} + +jobs: + stale: + runs-on: ubuntu-latest + + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + with: + stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' + stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.' + close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.' + close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.' + days-before-issue-stale: 30 + days-before-pr-stale: 45 + days-before-issue-close: 5 + days-before-pr-close: 5 + exempt-issue-labels: 'frozen' + exempt-pr-labels: 'frozen' diff --git a/.golangci.yml b/.golangci.yml index 36164d663..0955ce238 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,32 +1,42 @@ +--- +version: "2" +run: + issues-exit-code: 1 linters: enable: - asciicheck - - depguard - - errcheck - errorlint - - gofmt - - goimports - - gosec - gocritic + - gosec - importas + - misspell - prealloc - revive - - misspell - - stylecheck + - staticcheck - unconvert - - unused - whitespace -output: - uniq-by-line: false + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ issues: - exclude-rules: - - path: _test\.go - linters: - - errcheck - - gosec - - revive max-issues-per-linter: 0 max-same-issues: 0 -run: - issues-exit-code: 1 - timeout: 10m + uniq-by-line: false +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/.goreleaser.yml b/.goreleaser.yml index b358d187e..e63a6f6f1 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,4 +1,5 @@ project_name: chart-testing +version: 2 env: - COSIGN_YES=true @@ -23,6 +24,9 @@ builds: - linux - darwin - windows + ignore: + - goarch: arm + goos: windows flags: - -trimpath mod_timestamp: '{{ .CommitTimestamp }}' @@ -33,10 +37,10 @@ builds: -X github.com/helm/chart-testing/v3/ct/cmd.BuildDate={{ .Date }} archives: - - rlcp: true - format_overrides: + - format_overrides: - goos: windows - format: zip + formats: + - zip files: - LICENSE - README.md @@ -47,60 +51,27 @@ checksum: name_template: 'checksums.txt' snapshot: - name_template: "{{ .Tag }}-next" + version_template: "{{ .Tag }}-next" -dockers: - - skip_push: false - use: buildx - dockerfile: Dockerfile - image_templates: - - quay.io/helmpack/chart-testing:{{ .Tag }}-amd64 - - quay.io/helmpack/chart-testing:latest-amd64 - build_flag_templates: - - --platform=linux/amd64 - - --label=org.opencontainers.image.version={{ .Version }} - - --label=org.opencontainers.image.revision={{ .Commit }} - - --label=org.opencontainers.image.title={{ .ProjectName }} - - --label=org.opencontainers.image.created={{ .Date }} - - --label=org.opencontainers.image.description=ct - The chart testing tool - - --label=org.opencontainers.image.vendor=Helm - - --label=org.opencontainers.image.licenses=Apache-2.0 - - --label=org.opencontainers.image.source=https://github.com/helm/chart-testing - - --label=org.opencontainers.image.authors=The Helm Authors +dockers_v2: + - images: + - "quay.io/helmpack/chart-testing" + tags: + - "{{ .Tag }}" + - "latest" + labels: + "org.opencontainers.image.version": "{{ .Version }}" + "org.opencontainers.image.revision": "{{ .Commit }}" + "org.opencontainers.image.title": "{{ .ProjectName }}" + "org.opencontainers.image.created": "{{ .Date }}" + "org.opencontainers.image.description": "ct - The chart testing tool" + "org.opencontainers.image.vendor": "Helm" + "org.opencontainers.image.licenses": "Apache-2.0" + "org.opencontainers.image.source": "https://github.com/helm/chart-testing" + "org.opencontainers.image.authors": "The Helm Authors" extra_files: - etc/chart_schema.yaml - etc/lintconf.yaml - - skip_push: false - goarch: arm64 - use: buildx - dockerfile: Dockerfile - image_templates: - - quay.io/helmpack/chart-testing:{{ .Tag }}-arm64 - - quay.io/helmpack/chart-testing:latest-arm64 - build_flag_templates: - - --platform=linux/arm64 - - --label=org.opencontainers.image.version={{ .Version }} - - --label=org.opencontainers.image.revision={{ .Commit }} - - --label=org.opencontainers.image.title={{ .ProjectName }} - - --label=org.opencontainers.image.created={{ .Date }} - - --label=org.opencontainers.image.description=ct - The chart testing tool - - --label=org.opencontainers.image.vendor=Helm - - --label=org.opencontainers.image.licenses=Apache-2.0 - - --label=org.opencontainers.image.source=https://github.com/helm/chart-testing - - --label=org.opencontainers.image.authors=The Helm Authors - extra_files: - - etc/chart_schema.yaml - - etc/lintconf.yaml - -docker_manifests: - - name_template: quay.io/helmpack/chart-testing:latest - image_templates: - - quay.io/helmpack/chart-testing:latest-amd64 - - quay.io/helmpack/chart-testing:latest-arm64 - - name_template: quay.io/helmpack/chart-testing:{{ .Tag }} - image_templates: - - quay.io/helmpack/chart-testing:{{ .Tag }}-amd64 - - quay.io/helmpack/chart-testing:{{ .Tag }}-arm64 signs: - id: all @@ -114,7 +85,6 @@ docker_signs: - id: images cmd: cosign args: ["sign", "${artifact}"] - artifacts: manifests changelog: use: github-native diff --git a/Dockerfile b/Dockerfile index 25d1bc390..9e402e1b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,37 +1,38 @@ -FROM alpine:3.17 +FROM alpine:3.23 RUN apk --no-cache add \ bash \ - curl>7.77.0-r0 \ + curl \ git \ libc6-compat \ openssh-client \ py3-pip \ py3-wheel \ - python3 && \ - pip install --upgrade pip==21.0.1 - -# Install a YAML Linter -ARG yamllint_version=1.29.0 -LABEL yamllint_version=$yamllint_version -RUN pip install "yamllint==$yamllint_version" + python3 \ + yamllint # Install Yamale YAML schema validator -ARG yamale_version=4.0.4 -LABEL yamale_version=$yamale_version -RUN pip install "yamale==$yamale_version" +ARG yamale_version=6.0.0 +LABEL yamale-version=$yamale_version +RUN pip install --break-system-packages "yamale==$yamale_version" ARG TARGETPLATFORM # Install kubectl -ARG kubectl_version=v1.26.2 -LABEL kubectl_version=$kubectl_version -RUN curl -LO "https://storage.googleapis.com/kubernetes-release/release/$kubectl_version/bin/$TARGETPLATFORM/kubectl" && \ - chmod +x kubectl && \ - mv kubectl /usr/local/bin/ +ARG kubectl_version=v1.32.0 +LABEL kubectl-version=$kubectl_version +RUN targetArch=$(echo $TARGETPLATFORM | cut -f2 -d '/') \ + && if [ ${targetArch} = "amd64" ]; then \ + HELM_ARCH="linux/amd64"; \ +elif [ ${targetArch} = "arm64" ]; then \ + HELM_ARCH="linux/arm64"; \ +fi \ + && curl -LO "dl.k8s.io/$kubectl_version/bin/$HELM_ARCH/kubectl" \ + && chmod +x kubectl \ + && mv kubectl /usr/local/bin/ # Install Helm -ARG helm_version=v3.11.2 -LABEL helm_version=$helm_version +ARG helm_version=v3.16.4 +LABEL helm-version=$helm_version RUN targetArch=$(echo $TARGETPLATFORM | cut -f2 -d '/') \ && if [ ${targetArch} = "amd64" ]; then \ HELM_ARCH="linux-amd64"; \ @@ -46,6 +47,7 @@ fi \ COPY ./etc/chart_schema.yaml /etc/ct/chart_schema.yaml COPY ./etc/lintconf.yaml /etc/ct/lintconf.yaml -COPY ct /usr/local/bin/ct +ARG TARGETPLATFORM +COPY $TARGETPLATFORM/ct /usr/local/bin/ct # Ensure that the binary is available on path and is executable RUN ct --help diff --git a/README.md b/README.md index 8d6a8201c..2209b29e5 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Go Report Card](https://goreportcard.com/badge/github.com/helm/chart-testing)](https://goreportcard.com/report/github.com/helm/chart-testing) -![ci](https://github.com/helm/chart-testing/workflows/ci/badge.svg) +[![ci](https://github.com/helm/chart-testing/workflows/ci/badge.svg)](https://github.com/helm/chart-testing/actions/workflows/ci.yaml) -`ct` is the the tool for testing Helm charts. +`ct` is the tool for testing Helm charts. It is meant to be used for linting and testing pull requests. It automatically detects charts changed against the target branch. @@ -12,7 +12,7 @@ It automatically detects charts changed against the target branch. ### Prerequisites -It is recommended to use the provided Docker image which can be [found on Quay](https://quay.io/helmpack/chart-testing/). +It is recommended to use the provided Docker image which can be [found on Quay](https://quay.io/repository/helmpack/chart-testing). It comes with all necessary tools installed. * [Helm](http://helm.sh) @@ -93,7 +93,7 @@ If you have a chart in current directory and ct installed on the host then you c With docker it works with: - docker run -it --network host --workdir=/data --volume ~/.kube/config:/root/.kube/config:ro --volume $(pwd):/data quay.io/helmpack/chart-testing:v3.7.1 ct install --chart-dirs . --charts . + docker run -it --network host --workdir=/data --volume ~/.kube/config:/root/.kube/config:ro --volume $(pwd):/data quay.io/helmpack/chart-testing:v3.14.0 ct install --chart-dirs . --charts . Notice that `workdir` param is important and must be the same as volume mounted. @@ -131,6 +131,7 @@ Notice that if no config file is specified, then `ct.yaml` (or any of the suppor #### Using private chart repositories When adding chart-repos you can specify additional arguments for the `helm repo add` command using `helm-repo-extra-args` on a per-repo basis. +You can also specify OCI registries which will be added using the `helm registry login` command, they also support the `helm-repo-extra-args` for authentication. This could for example be used to authenticate a private chart repository. `config.yaml`: @@ -140,6 +141,7 @@ chart-repos: - incubator=https://incubator.io - basic-auth=https://private.com - ssl-repo=https://self-signed.ca + - oci-registry=oci://nice-oci-registry.pt helm-repo-extra-args: - ssl-repo=--ca-file ./my-ca.crt ``` @@ -193,7 +195,7 @@ Here's a previous one for reference: https://github.com/helm/chart-testing/pull/ ### Create Release The release workflow is [dispatched from github actions](https://github.com/helm/chart-testing/actions) -Versions must start with a lower-case `v`, e. g. `v3.7.1`. +Versions must start with a lower-case `v`, e. g. `v3.14.0`. ## Supported versions diff --git a/build.sh b/build.sh index 9e31e37f3..499255d56 100755 --- a/build.sh +++ b/build.sh @@ -67,7 +67,7 @@ main() { fi if [[ -z "$release" ]]; then - goreleaser_args+=(--snapshot --skip-sign) + goreleaser_args+=(--snapshot --skip=sign) fi pushd "$SCRIPT_DIR" > /dev/null diff --git a/code-of-conduct.md b/code-of-conduct.md index 91ccaf035..74c5cb7aa 100644 --- a/code-of-conduct.md +++ b/code-of-conduct.md @@ -1,3 +1,3 @@ # Community Code of Conduct -Helm follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). +Helm follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/ct/cmd/install.go b/ct/cmd/install.go index 96523f3c2..4afeb8186 100644 --- a/ct/cmd/install.go +++ b/ct/cmd/install.go @@ -61,9 +61,6 @@ func addInstallFlags(flags *flag.FlagSet) { An optional, arbitrary identifier that is added to the name of the namespace a chart is installed into. In a CI environment, this could be the build number or the ID of a pull request. If not specified, the name of the chart is used`)) - flags.String("helm-extra-args", "", heredoc.Doc(` - Additional arguments for Helm. Must be passed as a single quoted string - (e.g. "--timeout 500s"`)) flags.Bool("upgrade", false, heredoc.Doc(` Whether to test an in-place upgrade of each chart from its previous revision if the current version should not introduce a breaking change according to the SemVer spec`)) @@ -74,6 +71,9 @@ func addInstallFlags(flags *flag.FlagSet) { flags.String("namespace", "", heredoc.Doc(` Namespace to install the release(s) into. If not specified, each release will be installed in its own randomly generated namespace`)) + flags.String("release-name", "", heredoc.Doc(` + Name for the release. If not specified, is set to the chart name and a random + identifier.`)) flags.String("release-label", "app.kubernetes.io/instance", heredoc.Doc(` The label to be used as a selector when inspecting resources created by charts. This is only used if namespace is specified`)) @@ -96,11 +96,7 @@ func install(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed loading configuration: %w", err) } - extraSetArgs, err := cmd.Flags().GetString("helm-extra-set-args") - if err != nil { - return err - } - testing, err := chart.NewTesting(*configuration, extraSetArgs) + testing, err := chart.NewTesting(*configuration) if err != nil { fmt.Println(err) } diff --git a/ct/cmd/lint.go b/ct/cmd/lint.go index c5b015cc9..73e6a8349 100644 --- a/ct/cmd/lint.go +++ b/ct/cmd/lint.go @@ -54,26 +54,28 @@ func newLintCmd() *cobra.Command { func addLintFlags(flags *flag.FlagSet) { flags.String("lint-conf", "", heredoc.Doc(` - The config file for YAML linting. If not specified, 'lintconf.yaml' - is searched in the current directory, '$HOME/.ct', and '/etc/ct', in - that order`)) + The config file for YAML linting. If not specified, 'lintconf.yaml' + is searched in the current directory, '$HOME/.ct', and '/etc/ct', in + that order`)) flags.String("chart-yaml-schema", "", heredoc.Doc(` - The schema for chart.yml validation. If not specified, 'chart_schema.yaml' - is searched in the current directory, '$HOME/.ct', and '/etc/ct', in - that order.`)) + The schema for chart.yml validation. If not specified, 'chart_schema.yaml' + is searched in the current directory, '$HOME/.ct', and '/etc/ct', in + that order.`)) flags.Bool("validate-maintainers", true, heredoc.Doc(` - Enable validation of maintainer account names in chart.yml. - Works for GitHub, GitLab, and Bitbucket`)) + Enable validation of maintainer account names in chart.yml. + Works for GitHub, GitLab, and Bitbucket`)) flags.Bool("check-version-increment", true, "Activates a check for chart version increments") flags.Bool("validate-chart-schema", true, heredoc.Doc(` - Enable schema validation of 'Chart.yaml' using Yamale`)) + Enable schema validation of 'Chart.yaml' using Yamale`)) flags.Bool("validate-yaml", true, heredoc.Doc(` - Enable linting of 'Chart.yaml' and values files`)) + Enable linting of 'Chart.yaml' and values files`)) + flags.Bool("skip-helm-dependencies", false, heredoc.Doc(` + Skip running 'helm dependency build' before linting`)) flags.StringSlice("additional-commands", []string{}, heredoc.Doc(` - Additional commands to run per chart (default: []) - Commands will be executed in the same order as provided in the list and will - be rendered with go template before being executed. - Example: "helm unittest --helm3 -f tests/*.yaml {{ .Path }}"`)) + Additional commands to run per chart (default: []) + Commands will be executed in the same order as provided in the list and will + be rendered with go template before being executed. + Example: "helm unittest --helm3 -f tests/*.yaml {{ .Path }}"`)) } func lint(cmd *cobra.Command, _ []string) error { @@ -88,8 +90,7 @@ func lint(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed loading configuration: %w", err) } - emptyExtraSetArgs := "" - testing, err := chart.NewTesting(*configuration, emptyExtraSetArgs) + testing, err := chart.NewTesting(*configuration) if err != nil { return err } diff --git a/ct/cmd/lintAndInstall.go b/ct/cmd/lintAndInstall.go index d885033ca..760a883dc 100644 --- a/ct/cmd/lintAndInstall.go +++ b/ct/cmd/lintAndInstall.go @@ -51,11 +51,7 @@ func lintAndInstall(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed loading configuration: %w", err) } - extraSetArgs, err := cmd.Flags().GetString("helm-extra-set-args") - if err != nil { - return err - } - testing, err := chart.NewTesting(*configuration, extraSetArgs) + testing, err := chart.NewTesting(*configuration) if err != nil { return err } diff --git a/ct/cmd/listChanged.go b/ct/cmd/listChanged.go index 177e9df53..0aafc6ebf 100644 --- a/ct/cmd/listChanged.go +++ b/ct/cmd/listChanged.go @@ -50,8 +50,7 @@ func listChanged(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed loading configuration: %w", err) } - emptyExtraSetArgs := "" - testing, err := chart.NewTesting(*configuration, emptyExtraSetArgs) + testing, err := chart.NewTesting(*configuration) if err != nil { return err } diff --git a/ct/cmd/root.go b/ct/cmd/root.go index ea6900412..3afb2621e 100644 --- a/ct/cmd/root.go +++ b/ct/cmd/root.go @@ -65,7 +65,7 @@ func Execute() { func addCommonFlags(flags *pflag.FlagSet) { flags.StringVar(&cfgFile, "config", "", "Config file") flags.String("remote", "origin", "The name of the Git remote used to identify changed charts") - flags.String("target-branch", "master", "The name of the target branch used to identify changed charts") + flags.String("target-branch", "main", "The name of the target branch used to identify changed charts") flags.String("since", "HEAD", "The Git reference used to identify changed charts") flags.StringSlice("chart-dirs", []string{"charts"}, heredoc.Doc(` Directories containing Helm charts. May be specified multiple times @@ -77,6 +77,10 @@ func addCommonFlags(flags *pflag.FlagSet) { Prints the configuration to stderr (caution: setting this may expose sensitive data when helm-repo-extra-args contains passwords)`)) flags.Bool("exclude-deprecated", false, "Skip charts that are marked as deprecated") + flags.Bool("github-groups", false, heredoc.Doc(` + Change the delimiters for github to create collapsible groups + for command output`)) + flags.Bool("use-helmignore", false, "Use .helmignore when identifying changed charts") } func addCommonLintAndInstallFlags(flags *pflag.FlagSet) { @@ -92,6 +96,12 @@ func addCommonLintAndInstallFlags(flags *pflag.FlagSet) { Additional chart repositories for dependency resolutions. Repositories should be formatted as 'name=url' (ex: local=http://127.0.0.1:8879/charts). May be specified multiple times or separate values with commas`)) + flags.String("helm-extra-args", "", heredoc.Doc(` + Additional arguments for Helm. Must be passed as a single quoted string + (e.g. '--timeout 500s')`)) + flags.String("helm-lint-extra-args", "", heredoc.Doc(` + Additional arguments for Helm lint subcommand. Must be passed as a single quoted string + (e.g. '--quiet')`)) flags.StringSlice("helm-repo-extra-args", []string{}, heredoc.Doc(` Additional arguments for the 'helm repo add' command to be specified on a per-repo basis with an equals sign as delimiter diff --git a/doc/ct_install.md b/doc/ct_install.md index b534c47f9..27b5697a7 100644 --- a/doc/ct_install.md +++ b/doc/ct_install.md @@ -48,11 +48,15 @@ ct install [flags] --exclude-deprecated Skip charts that are marked as deprecated --excluded-charts strings Charts that should be skipped. May be specified multiple times or separate values with commas + --github-groups Change the delimiters for github to create collapsible groups + for command output --helm-dependency-extra-args strings Additional arguments for 'helm dependency build' (e.g. ["--skip-refresh"] --helm-extra-args string Additional arguments for Helm. Must be passed as a single quoted string - (e.g. "--timeout 500s" + (e.g. '--timeout 500s') --helm-extra-set-args string Additional arguments for Helm. Must be passed as a single quoted string (e.g. "--set=name=value" + --helm-lint-extra-args string Additional arguments for Helm lint subcommand. Must be passed as a single quoted string + (e.g. '--quiet') --helm-repo-extra-args strings Additional arguments for the 'helm repo add' command to be specified on a per-repo basis with an equals sign as delimiter (e.g. 'myrepo=--username test --password secret'). May be specified @@ -64,15 +68,18 @@ ct install [flags] expose sensitive data when helm-repo-extra-args contains passwords) --release-label string The label to be used as a selector when inspecting resources created by charts. This is only used if namespace is specified (default "app.kubernetes.io/instance") + --release-name string Name for the release. If not specified, is set to the chart name and a random + identifier. --remote string The name of the Git remote used to identify changed charts (default "origin") --since string The Git reference used to identify changed charts (default "HEAD") --skip-clean-up Skip resources clean-up. Used if need to continue other flows or keep it around. --skip-missing-values When --upgrade has been passed, this flag will skip testing CI values files from the previous chart revision if they have been deleted or renamed at the current chart revision - --target-branch string The name of the target branch used to identify changed charts (default "master") + --target-branch string The name of the target branch used to identify changed charts (default "main") --upgrade Whether to test an in-place upgrade of each chart from its previous revision if the current version should not introduce a breaking change according to the SemVer spec + --use-helmignore Use .helmignore when identifying changed charts ``` ### SEE ALSO diff --git a/doc/ct_lint-and-install.md b/doc/ct_lint-and-install.md index ae8808dff..0b341b996 100644 --- a/doc/ct_lint-and-install.md +++ b/doc/ct_lint-and-install.md @@ -40,11 +40,15 @@ ct lint-and-install [flags] --exclude-deprecated Skip charts that are marked as deprecated --excluded-charts strings Charts that should be skipped. May be specified multiple times or separate values with commas + --github-groups Change the delimiters for github to create collapsible groups + for command output --helm-dependency-extra-args strings Additional arguments for 'helm dependency build' (e.g. ["--skip-refresh"] --helm-extra-args string Additional arguments for Helm. Must be passed as a single quoted string - (e.g. "--timeout 500s" + (e.g. '--timeout 500s') --helm-extra-set-args string Additional arguments for Helm. Must be passed as a single quoted string (e.g. "--set=name=value" + --helm-lint-extra-args string Additional arguments for Helm lint subcommand. Must be passed as a single quoted string + (e.g. '--quiet') --helm-repo-extra-args strings Additional arguments for the 'helm repo add' command to be specified on a per-repo basis with an equals sign as delimiter (e.g. 'myrepo=--username test --password secret'). May be specified @@ -59,15 +63,19 @@ ct lint-and-install [flags] expose sensitive data when helm-repo-extra-args contains passwords) --release-label string The label to be used as a selector when inspecting resources created by charts. This is only used if namespace is specified (default "app.kubernetes.io/instance") + --release-name string Name for the release. If not specified, is set to the chart name and a random + identifier. --remote string The name of the Git remote used to identify changed charts (default "origin") --since string The Git reference used to identify changed charts (default "HEAD") --skip-clean-up Skip resources clean-up. Used if need to continue other flows or keep it around. + --skip-helm-dependencies Skip running 'helm dependency build' before linting --skip-missing-values When --upgrade has been passed, this flag will skip testing CI values files from the previous chart revision if they have been deleted or renamed at the current chart revision - --target-branch string The name of the target branch used to identify changed charts (default "master") + --target-branch string The name of the target branch used to identify changed charts (default "main") --upgrade Whether to test an in-place upgrade of each chart from its previous revision if the current version should not introduce a breaking change according to the SemVer spec + --use-helmignore Use .helmignore when identifying changed charts --validate-chart-schema Enable schema validation of 'Chart.yaml' using Yamale (default true) --validate-maintainers Enable validation of maintainer account names in chart.yml. Works for GitHub, GitLab, and Bitbucket (default true) diff --git a/doc/ct_lint.md b/doc/ct_lint.md index c7e5519ff..738d8001f 100644 --- a/doc/ct_lint.md +++ b/doc/ct_lint.md @@ -50,7 +50,13 @@ ct lint [flags] --exclude-deprecated Skip charts that are marked as deprecated --excluded-charts strings Charts that should be skipped. May be specified multiple times or separate values with commas + --github-groups Change the delimiters for github to create collapsible groups + for command output --helm-dependency-extra-args strings Additional arguments for 'helm dependency build' (e.g. ["--skip-refresh"] + --helm-extra-args string Additional arguments for Helm. Must be passed as a single quoted string + (e.g. '--timeout 500s') + --helm-lint-extra-args string Additional arguments for Helm lint subcommand. Must be passed as a single quoted string + (e.g. '--quiet') --helm-repo-extra-args strings Additional arguments for the 'helm repo add' command to be specified on a per-repo basis with an equals sign as delimiter (e.g. 'myrepo=--username test --password secret'). May be specified @@ -63,7 +69,9 @@ ct lint [flags] expose sensitive data when helm-repo-extra-args contains passwords) --remote string The name of the Git remote used to identify changed charts (default "origin") --since string The Git reference used to identify changed charts (default "HEAD") - --target-branch string The name of the target branch used to identify changed charts (default "master") + --skip-helm-dependencies Skip running 'helm dependency build' before linting + --target-branch string The name of the target branch used to identify changed charts (default "main") + --use-helmignore Use .helmignore when identifying changed charts --validate-chart-schema Enable schema validation of 'Chart.yaml' using Yamale (default true) --validate-maintainers Enable validation of maintainer account names in chart.yml. Works for GitHub, GitLab, and Bitbucket (default true) diff --git a/doc/ct_list-changed.md b/doc/ct_list-changed.md index 3fa32c03a..109f6c498 100644 --- a/doc/ct_list-changed.md +++ b/doc/ct_list-changed.md @@ -20,12 +20,15 @@ ct list-changed [flags] --exclude-deprecated Skip charts that are marked as deprecated --excluded-charts strings Charts that should be skipped. May be specified multiple times or separate values with commas + --github-groups Change the delimiters for github to create collapsible groups + for command output -h, --help help for list-changed --print-config Prints the configuration to stderr (caution: setting this may expose sensitive data when helm-repo-extra-args contains passwords) --remote string The name of the Git remote used to identify changed charts (default "origin") --since string The Git reference used to identify changed charts (default "HEAD") - --target-branch string The name of the target branch used to identify changed charts (default "master") + --target-branch string The name of the target branch used to identify changed charts (default "main") + --use-helmignore Use .helmignore when identifying changed charts ``` ### SEE ALSO diff --git a/etc/chart_schema.yaml b/etc/chart_schema.yaml index 2a26d9ba3..e3cd46a81 100644 --- a/etc/chart_schema.yaml +++ b/etc/chart_schema.yaml @@ -29,7 +29,7 @@ dependency: condition: str(required=False) tags: list(str(), required=False) enabled: bool(required=False) - import-values: any(list(str()), list(include('import-value')), required=False) + import-values: list(any(str(), include('import-value')), required=False) alias: str(required=False) --- import-value: diff --git a/examples/docker-for-mac/my_test.sh b/examples/docker-for-mac/my_test.sh index e14feed53..8dd1cd71c 100755 --- a/examples/docker-for-mac/my_test.sh +++ b/examples/docker-for-mac/my_test.sh @@ -18,7 +18,7 @@ set -o errexit set -o nounset set -o pipefail -readonly IMAGE_TAG=v3.7.1 +readonly IMAGE_TAG=v3.14.0 readonly IMAGE_REPOSITORY="quay.io/helmpack/chart-testing" main() { diff --git a/examples/gke/Dockerfile b/examples/gke/Dockerfile index 3939a7472..8b223281d 100644 --- a/examples/gke/Dockerfile +++ b/examples/gke/Dockerfile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM quay.io/helmpack/chart-testing:v3.7.1 +FROM quay.io/helmpack/chart-testing:v3.14.0 ENV PATH /google-cloud-sdk/bin:$PATH ARG CLOUD_SDK_VERSION=221.0.0 diff --git a/examples/kind/.circleci/config.yml b/examples/kind/.circleci/config.yml index 2483989ef..0dd2e25a9 100644 --- a/examples/kind/.circleci/config.yml +++ b/examples/kind/.circleci/config.yml @@ -10,7 +10,7 @@ jobs: lint-charts: docker: - - image: quay.io/helmpack/chart-testing:v3.7.1 + - image: quay.io/helmpack/chart-testing:v3.14.0 steps: - checkout - run: diff --git a/examples/kind/README.md b/examples/kind/README.md index 4f29bb73b..3e5464b72 100644 --- a/examples/kind/README.md +++ b/examples/kind/README.md @@ -3,5 +3,5 @@ `kind` is a tool for running local Kubernetes clusters using Docker container "nodes". This example shows how to lint and test charts using CircleCi and [kind](https://github.com/kubernetes-sigs/kind). -It creates a cluster with a single master node and one worker node. +It creates a cluster with a single control-plane node and one worker node. The cluster configuration can be adjusted in [kind-config.yaml](test/kind-config.yaml). You can check for available configuration options in `kind` [docs](https://kind.sigs.k8s.io/docs/user/quick-start#configuring-your-kind-cluster) diff --git a/examples/kind/test/e2e-kind.sh b/examples/kind/test/e2e-kind.sh index 904752def..3c1d59c7e 100755 --- a/examples/kind/test/e2e-kind.sh +++ b/examples/kind/test/e2e-kind.sh @@ -4,7 +4,7 @@ set -o errexit set -o nounset set -o pipefail -readonly CT_VERSION=v3.7.1 +readonly CT_VERSION=v3.14.0 readonly KIND_VERSION=v0.12.0 readonly CLUSTER_NAME=chart-testing readonly K8S_VERSION=v1.22.7 diff --git a/go.mod b/go.mod index 4dad58bb2..76a91ec44 100644 --- a/go.mod +++ b/go.mod @@ -1,43 +1,43 @@ module github.com/helm/chart-testing/v3 -go 1.20 +go 1.24.0 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/Masterminds/semver v1.5.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/go-retryablehttp v0.7.2 + github.com/hashicorp/go-retryablehttp v0.7.8 github.com/mattn/go-shellwords v1.0.12 github.com/mitchellh/go-homedir v1.1.0 - github.com/spf13/cobra v1.6.1 - github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.2 + github.com/spf13/cobra v1.10.2 + github.com/spf13/pflag v1.0.10 + github.com/spf13/viper v1.21.0 + github.com/stretchr/testify v1.11.1 gopkg.in/yaml.v2 v2.4.0 + helm.sh/helm/v3 v3.19.5 ) require ( - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/hcl v1.0.0 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/magiconair/properties v1.8.7 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.8.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/spf13/afero v1.9.3 // indirect - github.com/spf13/cast v1.5.0 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect - github.com/subosito/gotenv v1.4.2 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect - gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ef563afc2..ddbf78930 100644 --- a/go.sum +++ b/go.sum @@ -1,515 +1,92 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0= -github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48= +github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= -github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= -github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= -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/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= +github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -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= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +helm.sh/helm/v3 v3.19.5 h1:l8zDGBhPaF2z5pTR5ASku/yZwi0qZrWthWMzvf1ZruE= +helm.sh/helm/v3 v3.19.5/go.mod h1:PC1rk7PqacpkV4acUFMLStOOis7QM9Jq3DveHBInu4s= diff --git a/pkg/chart/chart.go b/pkg/chart/chart.go index 7287da850..d409e0a24 100644 --- a/pkg/chart/chart.go +++ b/pkg/chart/chart.go @@ -22,9 +22,11 @@ import ( "strings" "github.com/Masterminds/semver" + helmignore "helm.sh/helm/v3/pkg/ignore" "github.com/helm/chart-testing/v3/pkg/config" "github.com/helm/chart-testing/v3/pkg/exec" + "github.com/helm/chart-testing/v3/pkg/ignore" "github.com/helm/chart-testing/v3/pkg/tool" "github.com/helm/chart-testing/v3/pkg/util" ) @@ -49,6 +51,8 @@ const maxNameLength = 63 // // ValidateRepository checks that the current working directory is a valid git repository, // and returns nil if valid. +// +// BranchExists checks whether a given branch exists in the git repository. type Git interface { FileExistsOnBranch(file string, remote string, branch string) bool Show(file string, remote string, branch string) (string, error) @@ -58,6 +62,7 @@ type Git interface { ListChangedFilesInDirs(commit string, dirs ...string) ([]string, error) GetURLForRemote(remote string) (string, error) ValidateRepository() error + BranchExists(branch string) bool } // Helm is the interface that wraps Helm operations @@ -74,7 +79,8 @@ type Git interface { // InstallWithValues runs `helm install` for the given chart using the specified values file. // Pass a zero value for valuesFile in order to run install without specifying a values file. // -// Upgrade runs `helm upgrade` against an existing release, and re-uses the previously computed values. +// UpgradeWithValues runs `helm upgrade` against an existing release using the specified values file. +// Pass a zero value for valuesFile in order to run install without specifying a values file. // // Test runs `helm test` against an existing release. Set the cleanup argument to true in order // to clean up test pods created by helm after the test command completes. @@ -86,7 +92,7 @@ type Helm interface { BuildDependenciesWithArgs(chart string, extraArgs []string) error LintWithValues(chart string, valuesFile string) error InstallWithValues(chart string, valuesFile string, namespace string, release string) error - Upgrade(chart string, namespace string, release string) error + UpgradeWithValues(chart string, valuesFile string, namespace string, release string) error Test(namespace string, release string) error DeleteRelease(namespace string, release string) Version() (string, error) @@ -200,12 +206,17 @@ func (c *Chart) HasCIValuesFile(path string) bool { } // CreateInstallParams generates a randomized release name and namespace based on the chart path -// and optional buildID. If a buildID is specified, it will be part of the generated namespace. -func (c *Chart) CreateInstallParams(buildID string) (release string, namespace string) { +// and optional buildID. If release_name is specified, the release name is set to that string instead. +// If a buildID is specified, it will be part of the generated namespace. +func (c *Chart) CreateInstallParams(buildID string, releaseName string) (release string, namespace string) { release = filepath.Base(c.Path()) if release == "." || release == "/" { - yaml := c.Yaml() - release = yaml.Name + if releaseName != "" { + release = releaseName + } else { + yaml := c.Yaml() + release = yaml.Name + } } namespace = release if buildID != "" { @@ -239,6 +250,7 @@ type Testing struct { directoryLister DirectoryLister utils Utils previousRevisionWorktree string + loadRules func(string) (*helmignore.Rules, error) } // TestResults holds results and overall status @@ -254,13 +266,15 @@ type TestResult struct { } // NewTesting creates a new Testing struct with the given config. -func NewTesting(config config.Configuration, extraSetArgs string) (Testing, error) { +func NewTesting(config config.Configuration) (Testing, error) { procExec := exec.NewProcessExecutor(config.Debug) - extraArgs := strings.Fields(config.HelmExtraArgs) + helmExtraArgs := strings.Fields(config.HelmExtraArgs) + helmExtraSetArgs := strings.Fields(config.HelmExtraSetArgs) + helmLintExtraArgs := strings.Fields(config.HelmLintExtraArgs) testing := Testing{ config: config, - helm: tool.NewHelm(procExec, extraArgs, strings.Fields(extraSetArgs)), + helm: tool.NewHelm(procExec, helmExtraArgs, helmLintExtraArgs, helmExtraSetArgs), git: tool.NewGit(procExec), kubectl: tool.NewKubectl(procExec, config.KubectlTimeout), linter: tool.NewLinter(procExec), @@ -268,6 +282,7 @@ func NewTesting(config config.Configuration, extraSetArgs string) (Testing, erro accountValidator: tool.AccountValidator{}, directoryLister: util.DirectoryLister{}, utils: util.Utils{}, + loadRules: ignore.LoadRules, } versionString, err := testing.helm.Version() @@ -315,15 +330,23 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes } } - fmt.Println() - util.PrintDelimiterLineToWriter(os.Stdout, "-") - fmt.Println(" Charts to be processed:") - util.PrintDelimiterLineToWriter(os.Stdout, "-") + if !t.config.GithubGroups { + fmt.Println() + util.PrintDelimiterLineToWriter(os.Stdout, "-") + fmt.Println(" Charts to be processed:") + util.PrintDelimiterLineToWriter(os.Stdout, "-") + } else { + util.GithubGroupsBegin(os.Stdout, "Charts to be processed") + } for _, chart := range charts { fmt.Printf(" %s\n", chart) } - util.PrintDelimiterLineToWriter(os.Stdout, "-") - fmt.Println() + if !t.config.GithubGroups { + util.PrintDelimiterLineToWriter(os.Stdout, "-") + fmt.Println() + } else { + util.GithubGroupsEnd(os.Stdout) + } repoArgs := map[string][]string{} @@ -357,7 +380,7 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes return results, fmt.Errorf("failed identifying merge base: %w", err) } // Add worktree for the target revision - worktreePath, err := os.MkdirTemp("./", "ct_previous_revision") + worktreePath, err := os.MkdirTemp("./", "ct-previous-revision") if err != nil { return results, fmt.Errorf("could not create previous revision directory: %w", err) } @@ -368,17 +391,21 @@ func (t *Testing) processCharts(action func(chart *Chart) TestResult) ([]TestRes } defer t.git.RemoveWorktree(worktreePath) // nolint: errcheck - for _, chart := range charts { - if err := t.helm.BuildDependenciesWithArgs(t.computePreviousRevisionPath(chart.Path()), t.config.HelmDependencyExtraArgs); err != nil { - // Only print error (don't exit) if building dependencies for previous revision fails. - fmt.Printf("failed building dependencies for previous revision of chart %q: %v\n", chart, err.Error()) + if !t.config.SkipHelmDependencies { + for _, chart := range charts { + if err := t.helm.BuildDependenciesWithArgs(t.computePreviousRevisionPath(chart.Path()), t.config.HelmDependencyExtraArgs); err != nil { + // Only print error (don't exit) if building dependencies for previous revision fails. + fmt.Printf("failed building dependencies for previous revision of chart %q: %v\n", chart, err.Error()) + } } } } for _, chart := range charts { - if err := t.helm.BuildDependenciesWithArgs(chart.Path(), t.config.HelmDependencyExtraArgs); err != nil { - return nil, fmt.Errorf("failed building dependencies for chart %q: %w", chart, err) + if !t.config.SkipHelmDependencies { + if err := t.helm.BuildDependenciesWithArgs(chart.Path(), t.config.HelmDependencyExtraArgs); err != nil { + return nil, fmt.Errorf("failed building dependencies for chart %q: %w", chart, err) + } } result := action(chart) @@ -411,7 +438,12 @@ func (t *Testing) LintAndInstallCharts() ([]TestResult, error) { // PrintResults writes test results to stdout. func (t *Testing) PrintResults(results []TestResult) { - util.PrintDelimiterLineToWriter(os.Stdout, "-") + if !t.config.GithubGroups { + fmt.Println() + util.PrintDelimiterLineToWriter(os.Stdout, "-") + } else { + util.GithubGroupsBegin(os.Stdout, "Test Results") + } if results != nil { for _, result := range results { err := result.Error @@ -424,7 +456,11 @@ func (t *Testing) PrintResults(results []TestResult) { } else { fmt.Println("No chart changes detected.") } - util.PrintDelimiterLineToWriter(os.Stdout, "-") + if !t.config.GithubGroups { + util.PrintDelimiterLineToWriter(os.Stdout, "-") + } else { + util.GithubGroupsEnd(os.Stdout) + } } // LintChart lints the specified chart. @@ -631,7 +667,7 @@ func (t *Testing) doUpgrade(oldChart, newChart *Chart, oldChartMustPass bool) er return nil } - if err := t.helm.Upgrade(newChart.Path(), namespace, release); err != nil { + if err := t.helm.UpgradeWithValues(newChart.Path(), valuesFile, namespace, release); err != nil { return err } @@ -657,14 +693,14 @@ func (t *Testing) testRelease(namespace, release, releaseSelector string) error func (t *Testing) generateInstallConfig(chart *Chart) (namespace, release, releaseSelector string, cleanup func()) { if t.config.Namespace != "" { namespace = t.config.Namespace - release, _ = chart.CreateInstallParams(t.config.BuildID) + release, _ = chart.CreateInstallParams(t.config.BuildID, t.config.ReleaseName) releaseSelector = fmt.Sprintf("%s=%s", t.config.ReleaseLabel, release) cleanup = func() { t.PrintEventsPodDetailsAndLogs(namespace, releaseSelector) t.helm.DeleteRelease(namespace, release) } } else { - release, namespace = chart.CreateInstallParams(t.config.BuildID) + release, namespace = chart.CreateInstallParams(t.config.BuildID, t.config.ReleaseName) cleanup = func() { t.PrintEventsPodDetailsAndLogs(namespace, releaseSelector) t.helm.DeleteRelease(namespace, release) @@ -701,7 +737,13 @@ func (t *Testing) computeMergeBase() (string, error) { if err != nil { return "", errors.New("must be in a git repository") } - return t.git.MergeBase(fmt.Sprintf("%s/%s", t.config.Remote, t.config.TargetBranch), t.config.Since) + + branch := fmt.Sprintf("%s/%s", t.config.Remote, t.config.TargetBranch) + if !t.git.BranchExists(branch) { + return "", fmt.Errorf("targetBranch '%s' does not exist", branch) + } + + return t.git.MergeBase(branch, t.config.Since) } // ComputeChangedChartDirectories takes the merge base of HEAD and the configured remote and target branch and computes a @@ -719,7 +761,7 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) { return nil, fmt.Errorf("failed creating diff: %w", err) } - var changedChartDirs []string + changedChartFiles := map[string][]string{} for _, file := range allChangedChartFiles { pathElements := strings.SplitN(filepath.ToSlash(file), "/", 3) if len(pathElements) < 2 || util.StringSliceContains(cfg.ExcludedCharts, pathElements[1]) { @@ -736,15 +778,33 @@ func (t *Testing) ComputeChangedChartDirectories() ([]string, error) { continue } } - // Only add it if not already in the list - if !util.StringSliceContains(changedChartDirs, chartDir) { - changedChartDirs = append(changedChartDirs, chartDir) - } + changedChartFiles[chartDir] = append(changedChartFiles[chartDir], strings.TrimPrefix(file, chartDir+"/")) } else { fmt.Fprintf(os.Stderr, "Directory %q is not a valid chart directory. Skipping...\n", dir) } } + changedChartDirs := []string{} + if t.config.UseHelmignore { + for chartDir, changedChartFiles := range changedChartFiles { + rules, err := t.loadRules(chartDir) + if err != nil { + return nil, err + } + filteredChartFiles, err := ignore.FilterFiles(changedChartFiles, rules) + if err != nil { + return nil, err + } + if len(filteredChartFiles) > 0 { + changedChartDirs = append(changedChartDirs, chartDir) + } + } + } else { + for chartDir := range changedChartFiles { + changedChartDirs = append(changedChartDirs, chartDir) + } + } + return changedChartDirs, nil } @@ -874,7 +934,7 @@ func (t *Testing) ValidateMaintainers(chart *Chart) error { func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string) { util.PrintDelimiterLineToWriter(os.Stdout, "=") - printDetails(namespace, "Events of namespace", ".", func(item string) error { + t.printDetails(namespace, "Events of namespace", ".", func(_ string) error { return t.kubectl.GetEvents(namespace) }, namespace) @@ -893,7 +953,7 @@ func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string } for _, pod := range pods { - printDetails(pod, "Description of pod", "~", func(item string) error { + t.printDetails(pod, "Description of pod", "~", func(_ string) error { return t.kubectl.DescribePod(namespace, pod) }, pod) @@ -904,7 +964,7 @@ func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string } if t.config.PrintLogs { - printDetails(pod, "Logs of init container", "-", + t.printDetails(pod, "Logs of init container", "-", func(item string) error { return t.kubectl.Logs(namespace, pod, item) }, initContainers...) @@ -915,7 +975,7 @@ func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string return } - printDetails(pod, "Logs of container", "-", + t.printDetails(pod, "Logs of container", "-", func(item string) error { return t.kubectl.Logs(namespace, pod, item) }, @@ -926,21 +986,29 @@ func (t *Testing) PrintEventsPodDetailsAndLogs(namespace string, selector string util.PrintDelimiterLineToWriter(os.Stdout, "=") } -func printDetails(resource string, text string, delimiterChar string, printFunc func(item string) error, items ...string) { +func (t *Testing) printDetails(resource string, text string, delimiterChar string, printFunc func(item string) error, items ...string) { for _, item := range items { item = strings.Trim(item, "'") - util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) - fmt.Printf("==> %s %s\n", text, resource) - util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) + if !t.config.GithubGroups { + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) + fmt.Printf("==> %s %s\n", text, resource) + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) + } else { + util.GithubGroupsBegin(os.Stdout, fmt.Sprintf("%s %s", text, resource)) + } if err := printFunc(item); err != nil { fmt.Println("Error printing details:", err) return } - util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) - fmt.Printf("<== %s %s\n", text, resource) - util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) + if !t.config.GithubGroups { + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) + fmt.Printf("<== %s %s\n", text, resource) + util.PrintDelimiterLineToWriter(os.Stdout, delimiterChar) + } else { + util.GithubGroupsEnd(os.Stdout) + } } } diff --git a/pkg/chart/chart_test.go b/pkg/chart/chart_test.go index 78cf8d1f6..b95dd9eec 100644 --- a/pkg/chart/chart_test.go +++ b/pkg/chart/chart_test.go @@ -23,23 +23,24 @@ import ( "github.com/helm/chart-testing/v3/pkg/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + helmignore "helm.sh/helm/v3/pkg/ignore" ) type fakeGit struct{} -func (g fakeGit) FileExistsOnBranch(file string, remote string, branch string) bool { +func (g fakeGit) FileExistsOnBranch(_ string, _ string, _ string) bool { return true } -func (g fakeGit) Show(file string, remote string, branch string) (string, error) { +func (g fakeGit) Show(_ string, _ string, _ string) (string, error) { return "", nil } -func (g fakeGit) MergeBase(commit1 string, commit2 string) (string, error) { +func (g fakeGit) MergeBase(_ string, _ string) (string, error) { return "HEAD", nil } -func (g fakeGit) ListChangedFilesInDirs(commit string, dirs ...string) ([]string, error) { +func (g fakeGit) ListChangedFilesInDirs(_ string, _ ...string) ([]string, error) { return []string{ "test_charts/foo/Chart.yaml", "test_charts/bar/Chart.yaml", @@ -54,15 +55,15 @@ func (g fakeGit) ListChangedFilesInDirs(commit string, dirs ...string) ([]string }, nil } -func (g fakeGit) AddWorktree(path string, ref string) error { +func (g fakeGit) AddWorktree(_ string, _ string) error { return nil } -func (g fakeGit) RemoveWorktree(path string) error { +func (g fakeGit) RemoveWorktree(_ string) error { return nil } -func (g fakeGit) GetURLForRemote(remote string) (string, error) { +func (g fakeGit) GetURLForRemote(_ string) (string, error) { return "git@github.com/helm/chart-testing", nil } @@ -70,9 +71,13 @@ func (g fakeGit) ValidateRepository() error { return nil } +func (g fakeGit) BranchExists(_ string) bool { + return true +} + type fakeAccountValidator struct{} -func (v fakeAccountValidator) Validate(repoDomain string, account string) error { +func (v fakeAccountValidator) Validate(_ string, account string) error { if strings.HasPrefix(account, "valid") { return nil } @@ -96,23 +101,23 @@ type fakeHelm struct { mock.Mock } -func (h *fakeHelm) AddRepo(name, url string, extraArgs []string) error { return nil } -func (h *fakeHelm) BuildDependencies(chart string) error { return nil } +func (h *fakeHelm) AddRepo(_, _ string, _ []string) error { return nil } +func (h *fakeHelm) BuildDependencies(_ string) error { return nil } func (h *fakeHelm) BuildDependenciesWithArgs(chart string, extraArgs []string) error { h.Called(chart, extraArgs) return nil } -func (h *fakeHelm) LintWithValues(chart string, valuesFile string) error { return nil } -func (h *fakeHelm) InstallWithValues(chart string, valuesFile string, namespace string, release string) error { +func (h *fakeHelm) LintWithValues(_ string, _ string) error { return nil } +func (h *fakeHelm) InstallWithValues(_ string, _ string, _ string, _ string) error { return nil } -func (h *fakeHelm) Upgrade(chart string, namespace string, release string) error { +func (h *fakeHelm) UpgradeWithValues(_ string, _ string, _ string, _ string) error { return nil } -func (h *fakeHelm) Test(namespace string, release string) error { +func (h *fakeHelm) Test(_ string, _ string) error { return nil } -func (h *fakeHelm) DeleteRelease(namespace string, release string) {} +func (h *fakeHelm) DeleteRelease(_ string, _ string) {} func (h *fakeHelm) Version() (string, error) { return "v3.0.0", nil @@ -148,6 +153,26 @@ func newTestingMock(cfg config.Configuration) Testing { accountValidator: fakeAccountValidator{}, linter: fakeMockLinter, helm: new(fakeHelm), + loadRules: func(dir string) (*helmignore.Rules, error) { + rules := helmignore.Empty() + if dir == "test_charts/foo" { + var err error + rules, err = helmignore.Parse(strings.NewReader("Chart.yaml\n")) + if err != nil { + return nil, err + } + rules.AddDefaults() + } + if dir == "test_chart_at_multi_level/foo/baz" { + var err error + rules, err = helmignore.Parse(strings.NewReader("Chart.yaml\n")) + if err != nil { + return nil, err + } + rules.AddDefaults() + } + return rules, nil + }, } } @@ -161,6 +186,19 @@ func TestComputeChangedChartDirectories(t *testing.T) { assert.Nil(t, err) } +func TestComputeChangedChartDirectoriesWithHelmignore(t *testing.T) { + cfg := config.Configuration{ + ExcludedCharts: []string{"excluded"}, + ChartDirs: []string{"test_charts", "."}, + UseHelmignore: true, + } + ct := newTestingMock(cfg) + actual, err := ct.ComputeChangedChartDirectories() + expected := []string{"test_charts/bar", "test_chart_at_root"} + assert.Nil(t, err) + assert.ElementsMatch(t, expected, actual) +} + func TestComputeChangedChartDirectoriesWithMultiLevelChart(t *testing.T) { cfg := config.Configuration{ ExcludedCharts: []string{"excluded"}, @@ -176,6 +214,19 @@ func TestComputeChangedChartDirectoriesWithMultiLevelChart(t *testing.T) { assert.Nil(t, err) } +func TestComputeChangedChartDirectoriesWithMultiLevelChartWithHelmIgnore(t *testing.T) { + cfg := config.Configuration{ + ExcludedCharts: []string{"excluded"}, + ChartDirs: []string{"test_chart_at_multi_level/foo"}, + UseHelmignore: true, + } + ct := newTestingMock(cfg) + actual, err := ct.ComputeChangedChartDirectories() + expected := []string{"test_chart_at_multi_level/foo/bar"} + assert.Nil(t, err) + assert.ElementsMatch(t, expected, actual) +} + func TestReadAllChartDirectories(t *testing.T) { actual, err := ct.ReadAllChartDirectories() expected := []string{ diff --git a/pkg/chart/integration_test.go b/pkg/chart/integration_test.go index 5322d0f51..c6b5915a1 100644 --- a/pkg/chart/integration_test.go +++ b/pkg/chart/integration_test.go @@ -34,6 +34,8 @@ func newTestingHelmIntegration(cfg config.Configuration, extraSetArgs string) Te fakeMockLinter := new(fakeLinter) procExec := exec.NewProcessExecutor(true) extraArgs := strings.Fields(cfg.HelmExtraArgs) + extraLintArgs := strings.Fields(cfg.HelmLintExtraArgs) + return Testing{ config: cfg, directoryLister: util.DirectoryLister{}, @@ -41,7 +43,7 @@ func newTestingHelmIntegration(cfg config.Configuration, extraSetArgs string) Te utils: util.Utils{}, accountValidator: fakeAccountValidator{}, linter: fakeMockLinter, - helm: tool.NewHelm(procExec, extraArgs, strings.Fields(extraSetArgs)), + helm: tool.NewHelm(procExec, extraArgs, extraLintArgs, strings.Fields(extraSetArgs)), kubectl: tool.NewKubectl(procExec, 30*time.Second), } } diff --git a/pkg/config/config.go b/pkg/config/config.go index a020c7ed7..981b2762b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -52,6 +52,7 @@ type Configuration struct { ValidateMaintainers bool `mapstructure:"validate-maintainers"` ValidateChartSchema bool `mapstructure:"validate-chart-schema"` ValidateYaml bool `mapstructure:"validate-yaml"` + SkipHelmDependencies bool `mapstructure:"skip-helm-dependencies"` AdditionalCommands []string `mapstructure:"additional-commands"` CheckVersionIncrement bool `mapstructure:"check-version-increment"` ProcessAllCharts bool `mapstructure:"all"` @@ -60,6 +61,8 @@ type Configuration struct { ChartDirs []string `mapstructure:"chart-dirs"` ExcludedCharts []string `mapstructure:"excluded-charts"` HelmExtraArgs string `mapstructure:"helm-extra-args"` + HelmExtraSetArgs string `mapstructure:"helm-extra-set-args"` + HelmLintExtraArgs string `mapstructure:"helm-lint-extra-args"` HelmRepoExtraArgs []string `mapstructure:"helm-repo-extra-args"` HelmDependencyExtraArgs []string `mapstructure:"helm-dependency-extra-args"` Debug bool `mapstructure:"debug"` @@ -67,10 +70,13 @@ type Configuration struct { SkipMissingValues bool `mapstructure:"skip-missing-values"` SkipCleanUp bool `mapstructure:"skip-clean-up"` Namespace string `mapstructure:"namespace"` + ReleaseName string `mapstructure:"release-name"` ReleaseLabel string `mapstructure:"release-label"` ExcludeDeprecated bool `mapstructure:"exclude-deprecated"` KubectlTimeout time.Duration `mapstructure:"kubectl-timeout"` PrintLogs bool `mapstructure:"print-logs"` + GithubGroups bool `mapstructure:"github-groups"` + UseHelmignore bool `mapstructure:"use-helmignore"` } func LoadConfiguration(cfgFile string, cmd *cobra.Command, printConfig bool) (*Configuration, error) { @@ -173,9 +179,13 @@ func LoadConfiguration(cfgFile string, cmd *cobra.Command, printConfig bool) (*C } func printCfg(cfg *Configuration) { - util.PrintDelimiterLineToWriter(os.Stderr, "-") - fmt.Fprintln(os.Stderr, " Configuration") - util.PrintDelimiterLineToWriter(os.Stderr, "-") + if !cfg.GithubGroups { + util.PrintDelimiterLineToWriter(os.Stderr, "-") + fmt.Fprintln(os.Stderr, " Configuration") + util.PrintDelimiterLineToWriter(os.Stderr, "-") + } else { + util.GithubGroupsBegin(os.Stderr, "Configuration") + } e := reflect.ValueOf(cfg).Elem() typeOfCfg := e.Type() @@ -191,7 +201,11 @@ func printCfg(cfg *Configuration) { fmt.Fprintf(os.Stderr, pattern, typeOfCfg.Field(i).Name, e.Field(i).Interface()) } - util.PrintDelimiterLineToWriter(os.Stderr, "-") + if !cfg.GithubGroups { + util.PrintDelimiterLineToWriter(os.Stderr, "-") + } else { + util.GithubGroupsEnd(os.Stderr) + } } func findConfigFile(fileName string) (string, error) { diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index bc6413156..f07d912e6 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -52,7 +52,8 @@ func loadAndAssertConfigFromFile(t *testing.T, configFile string) { require.Equal(t, []string{"incubator=--username test"}, cfg.HelmRepoExtraArgs) require.Equal(t, []string{"stable", "incubator"}, cfg.ChartDirs) require.Equal(t, []string{"common"}, cfg.ExcludedCharts) - require.Equal(t, "--timeout 300", cfg.HelmExtraArgs) + require.Equal(t, "--timeout 300s", cfg.HelmExtraArgs) + require.Equal(t, "--quiet", cfg.HelmLintExtraArgs) require.Equal(t, true, cfg.Upgrade) require.Equal(t, true, cfg.SkipMissingValues) require.Equal(t, "default", cfg.Namespace) @@ -60,6 +61,7 @@ func loadAndAssertConfigFromFile(t *testing.T, configFile string) { require.Equal(t, true, cfg.ExcludeDeprecated) require.Equal(t, 120*time.Second, cfg.KubectlTimeout) require.Equal(t, true, cfg.SkipCleanUp) + require.Equal(t, true, cfg.UseHelmignore) } func Test_findConfigFile(t *testing.T) { diff --git a/pkg/config/test_config.json b/pkg/config/test_config.json index df0b1009b..73cd45742 100644 --- a/pkg/config/test_config.json +++ b/pkg/config/test_config.json @@ -24,12 +24,14 @@ "excluded-charts": [ "common" ], - "helm-extra-args": "--timeout 300", + "helm-extra-args": "--timeout 300s", + "helm-lint-extra-args": "--quiet", "upgrade": true, "skip-missing-values": true, "namespace": "default", "release-label": "release", "exclude-deprecated": true, "kubectl-timeout": "120s", - "skip-clean-up": true + "skip-clean-up": true, + "use-helmignore": true } diff --git a/pkg/config/test_config.yaml b/pkg/config/test_config.yaml index 1381b96be..0d1c7c02b 100644 --- a/pkg/config/test_config.yaml +++ b/pkg/config/test_config.yaml @@ -19,7 +19,8 @@ chart-dirs: - incubator excluded-charts: - common -helm-extra-args: --timeout 300 +helm-extra-args: --timeout 300s +helm-lint-extra-args: --quiet upgrade: true skip-missing-values: true namespace: default @@ -27,3 +28,4 @@ release-label: release exclude-deprecated: true kubectl-timeout: 120s skip-clean-up: true +use-helmignore: true diff --git a/pkg/exec/exec.go b/pkg/exec/exec.go index b0869b371..6a946c520 100644 --- a/pkg/exec/exec.go +++ b/pkg/exec/exec.go @@ -91,6 +91,8 @@ func (p ProcessExecutor) RunProcess(executable string, execArgs ...interface{}) scanner := bufio.NewScanner(io.MultiReader(outReader, errReader)) go func() { + defer outReader.Close() + defer errReader.Close() for scanner.Scan() { fmt.Println(scanner.Text()) } diff --git a/pkg/ignore/ignore.go b/pkg/ignore/ignore.go new file mode 100644 index 000000000..99d19c2cd --- /dev/null +++ b/pkg/ignore/ignore.go @@ -0,0 +1,83 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ignore + +import ( + "io/fs" + "os" + "path/filepath" + "testing/fstest" + + helmignore "helm.sh/helm/v3/pkg/ignore" +) + +func LoadRules(dir string) (*helmignore.Rules, error) { + rules, err := helmignore.ParseFile(filepath.Join(dir, helmignore.HelmIgnore)) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + if rules == nil { + rules = helmignore.Empty() + } + rules.AddDefaults() + return rules, nil +} + +func FilterFiles(files []string, rules *helmignore.Rules) ([]string, error) { + fsys := fstest.MapFS{} + for _, file := range files { + fsys[file] = &fstest.MapFile{} + } + + filteredFiles := []string{} + + err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + fi, err := d.Info() + if err != nil { + return err + } + + // Normalize to / since it will also work on Windows + path = filepath.ToSlash(path) + + if fi.IsDir() { + // Directory-based ignore rules should involve skipping the entire + // contents of that directory. + if rules.Ignore(path, fi) { + return filepath.SkipDir + } + return nil + } + + // If a .helmignore file matches, skip this file. + if rules.Ignore(path, fi) { + return nil + } + + filteredFiles = append(filteredFiles, path) + return nil + }) + if err != nil { + return nil, err + } + + return filteredFiles, nil +} diff --git a/pkg/ignore/ignore_test.go b/pkg/ignore/ignore_test.go new file mode 100644 index 000000000..4976b1fa0 --- /dev/null +++ b/pkg/ignore/ignore_test.go @@ -0,0 +1,35 @@ +/* +Copyright The Helm Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ignore + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + helmignore "helm.sh/helm/v3/pkg/ignore" +) + +func TestFilter(t *testing.T) { + rules, err := helmignore.Parse(strings.NewReader("/bar/\nREADME.md\n")) + assert.Nil(t, err) + files := []string{"Chart.yaml", "bar/xxx", "template/svc.yaml", "baz/bar/biz.txt", "README.md"} + actual, err := FilterFiles(files, rules) + assert.Nil(t, err) + expected := []string{"Chart.yaml", "baz/bar/biz.txt", "template/svc.yaml"} + assert.ElementsMatch(t, expected, actual) +} diff --git a/pkg/tool/account.go b/pkg/tool/account.go index 26de6f106..69d3810de 100644 --- a/pkg/tool/account.go +++ b/pkg/tool/account.go @@ -17,12 +17,13 @@ package tool import ( "fmt" "net/http" + "net/url" "regexp" ) type AccountValidator struct{} -var repoDomainPattern = regexp.MustCompile("(?:https://(?:[^@:]+:[^@:]+@)?|git@)([^/:]+)") +var scpStylePattern = regexp.MustCompile("^(?:[^@]+@)?(?[^@/:]+):.+$") func (v AccountValidator) Validate(repoURL string, account string) error { domain, err := parseOutGitRepoDomain(repoURL) @@ -41,10 +42,15 @@ func (v AccountValidator) Validate(repoURL string, account string) error { } func parseOutGitRepoDomain(repoURL string) (string, error) { - // This works for GitHub, Bitbucket, and Gitlab - submatch := repoDomainPattern.FindStringSubmatch(repoURL) - if submatch == nil || len(submatch) < 2 { - return "", fmt.Errorf("could not parse git repository domain for %q", repoURL) + // Git remotes can be either URLs or scp style remotes + parsedURL, err := url.Parse(repoURL) + + if err != nil || len(parsedURL.Hostname()) < 1 { + submatch := scpStylePattern.FindStringSubmatch(repoURL) + if len(submatch) < 2 || len(submatch[1]) < 1 { + return "", fmt.Errorf("could not parse git repository domain for %q", repoURL) + } + return submatch[1], nil } - return submatch[1], nil + return parsedURL.Hostname(), nil } diff --git a/pkg/tool/account_test.go b/pkg/tool/account_test.go index 30a03f5fc..ce2ff2dcc 100644 --- a/pkg/tool/account_test.go +++ b/pkg/tool/account_test.go @@ -15,6 +15,9 @@ func TestParseOutGitDomain(t *testing.T) { err error }{ {"GitHub SSH", "git@github.com:foo/bar", "github.com", nil}, + {"GitHub SSH 2", "ssh://github.com/foo/bar", "github.com", nil}, + {"GitHub SSH 3", "ssh://git@github.com:2222/foo/bar", "github.com", nil}, + {"GitHub SSH 4", "ssh://github.com:2222/foo/bar", "github.com", nil}, {"GitHub HTTPS", "https://github.com/foo/bar", "github.com", nil}, {"GitHub HTTPS with username/password", "https://foo:token@github.com/foo/bar", "github.com", nil}, {"Gitlab SSH", "git@gitlab.com:foo/bar", "gitlab.com", nil}, @@ -23,13 +26,15 @@ func TestParseOutGitDomain(t *testing.T) { {"Bitbucket SSH", "git@bitbucket.com:foo/bar", "bitbucket.com", nil}, {"Bitbucket HTTPS", "https://bitbucket.com/foo/bar", "bitbucket.com", nil}, {"Bitbucket HTTPS with username/password", "https://user:pass@bitbucket.com/foo/bar", "bitbucket.com", nil}, - {"Invalid", "foo/bar", "", fmt.Errorf("could not parse git repository domain for \"foo/bar\"")}, + {"Domain name without dot", "foo/bar", "", fmt.Errorf("could not parse git repository domain for \"foo/bar\"")}, + {"Domain name without dot 2", "foo/some/path/bar.git", "", fmt.Errorf("could not parse git repository domain for \"foo/some/path/bar.git\"")}, + {"Invalid", "user@:2222/bar", "", fmt.Errorf("could not parse git repository domain for \"user@:2222/bar\"")}, } for _, testData := range testDataSlice { t.Run(testData.name, func(t *testing.T) { actual, err := parseOutGitRepoDomain(testData.repoURL) - assert.Equal(t, err, testData.err) + assert.Equal(t, testData.err, err) assert.Equal(t, testData.expected, actual) }) } diff --git a/pkg/tool/git.go b/pkg/tool/git.go index 1fe5551fc..7fcb7ce69 100644 --- a/pkg/tool/git.go +++ b/pkg/tool/git.go @@ -74,3 +74,8 @@ func (g Git) ValidateRepository() error { _, err := g.exec.RunProcessAndCaptureOutput("git", "rev-parse", "--is-inside-work-tree") return err } + +func (g Git) BranchExists(branch string) bool { + _, err := g.exec.RunProcessAndCaptureOutput("git", "rev-parse", "--verify", branch) + return err == nil +} diff --git a/pkg/tool/helm.go b/pkg/tool/helm.go index e257126c8..339a70e5e 100644 --- a/pkg/tool/helm.go +++ b/pkg/tool/helm.go @@ -16,25 +16,35 @@ package tool import ( "fmt" + "strings" "github.com/helm/chart-testing/v3/pkg/exec" ) type Helm struct { - exec exec.ProcessExecutor - extraArgs []string - extraSetArgs []string + exec exec.ProcessExecutor + extraArgs []string + lintExtraArgs []string + extraSetArgs []string } -func NewHelm(exec exec.ProcessExecutor, extraArgs []string, extraSetArgs []string) Helm { +func NewHelm(exec exec.ProcessExecutor, extraArgs, lintExtraArgs, extraSetArgs []string) Helm { return Helm{ - exec: exec, - extraArgs: extraArgs, - extraSetArgs: extraSetArgs, + exec: exec, + extraArgs: extraArgs, + lintExtraArgs: lintExtraArgs, + extraSetArgs: extraSetArgs, } } func (h Helm) AddRepo(name string, url string, extraArgs []string) error { + const ociPrefix string = "oci://" + + if strings.HasPrefix(url, ociPrefix) { + registryDomain := url[len(ociPrefix):] + return h.exec.RunProcess("helm", "registry", "login", registryDomain, extraArgs) + } + return h.exec.RunProcess("helm", "repo", "add", name, url, extraArgs) } @@ -52,7 +62,7 @@ func (h Helm) LintWithValues(chart string, valuesFile string) error { values = []string{"--values", valuesFile} } - return h.exec.RunProcess("helm", "lint", chart, values) + return h.exec.RunProcess("helm", "lint", chart, values, h.lintExtraArgs) } func (h Helm) InstallWithValues(chart string, valuesFile string, namespace string, release string) error { @@ -65,9 +75,14 @@ func (h Helm) InstallWithValues(chart string, valuesFile string, namespace strin "--wait", values, h.extraArgs, h.extraSetArgs) } -func (h Helm) Upgrade(chart string, namespace string, release string) error { +func (h Helm) UpgradeWithValues(chart string, valuesFile string, namespace string, release string) error { + var values []string + if valuesFile != "" { + values = []string{"--values", valuesFile} + } + return h.exec.RunProcess("helm", "upgrade", release, chart, "--namespace", namespace, - "--reuse-values", "--wait", h.extraArgs, h.extraSetArgs) + "--wait", values, h.extraArgs, h.extraSetArgs) } func (h Helm) Test(namespace string, release string) error { @@ -76,7 +91,7 @@ func (h Helm) Test(namespace string, release string) error { func (h Helm) DeleteRelease(namespace string, release string) { fmt.Printf("Deleting release %q...\n", release) - if err := h.exec.RunProcess("helm", "uninstall", release, "--namespace", namespace, h.extraArgs); err != nil { + if err := h.exec.RunProcess("helm", "uninstall", release, "--namespace", namespace, "--wait", h.extraArgs); err != nil { fmt.Println("Error deleting Helm release:", err) } } diff --git a/pkg/tool/kubectl.go b/pkg/tool/kubectl.go index 2a3281737..826572015 100644 --- a/pkg/tool/kubectl.go +++ b/pkg/tool/kubectl.go @@ -222,7 +222,7 @@ func (k Kubectl) GetPods(args ...string) ([]string, error) { func (k Kubectl) GetEvents(namespace string) error { return k.exec.RunProcess("kubectl", fmt.Sprintf("--request-timeout=%s", k.timeout), - "get", "events", "--output", "wide", "--namespace", namespace) + "get", "events", "--output", "wide", "--namespace", namespace, "--sort-by", "lastTimestamp") } func (k Kubectl) DescribePod(namespace string, pod string) error { diff --git a/pkg/util/util.go b/pkg/util/util.go index 495798730..9189ebc7b 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -219,11 +219,15 @@ func BreakingChangeAllowed(left string, right string) (bool, error) { } func PrintDelimiterLineToWriter(w io.Writer, delimiterChar string) { - delim := make([]string, 120) - for i := 0; i < 120; i++ { - delim[i] = delimiterChar - } - fmt.Fprintln(w, strings.Join(delim, "")) + fmt.Fprintln(w, strings.Repeat(delimiterChar, 120)) +} + +func GithubGroupsBegin(w io.Writer, title string) { + fmt.Fprintf(w, "::group::%s\n", title) +} + +func GithubGroupsEnd(w io.Writer) { + fmt.Fprintln(w, "::endgroup::") } func SanitizeName(s string, maxLength int) string { diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 2ff022f39..6cdd9abd1 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package util +package util //nolint: revive import ( "fmt"