From 60a9ff8a0e3675957eabc94af58f58b621b3214f Mon Sep 17 00:00:00 2001 From: Exercism Bot Date: Wed, 23 Nov 2022 13:50:35 +0000 Subject: [PATCH 01/41] =?UTF-8?q?=F0=9F=A4=96=20Sync=20org-wide=20files=20?= =?UTF-8?q?to=20upstream=20repo=20(#1071)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More info: https://github.com/exercism/org-wide-files/commit/ceface8fc48f8f8be135cecafe5ea8355aac9ad6 --- .github/labels.yml | 10 ++++---- CODE_OF_CONDUCT.md | 57 +++++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/.github/labels.yml b/.github/labels.yml index fcb7c3552..cd989c70f 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -157,16 +157,16 @@ description: "Work on Documentation" color: "ffffff" -# This label can be added to accept PRs as part of Hacktoberfest -- name: "hacktoberfest-accepted" - description: "Make this PR count for hacktoberfest" - color: "ff7518" - # This Exercism-wide label is added to all automatically created pull requests that help migrate/prepare a track for Exercism v3 - name: "v3-migration 🤖" description: "Preparing for Exercism v3" color: "e99695" +# This Exercism-wide label can be used to bulk-close issues in preparation for pausing community contributions +- name: "paused" + description: "Work paused until further notice" + color: "e4e669" + # ----------------------------------------------------------------------------------------- # # These are the repository-specific labels that augment the Exercise-wide labels defined in # # https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml. # diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 9bb22baa7..df8e36761 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,17 +2,23 @@ ## Introduction -Exercism is a platform centered around empathetic conversation. We have a low tolerance for communication that makes anyone feel unwelcome, unsupported, insulted or discriminated against. +Exercism is a platform centered around empathetic conversation. +We have a low tolerance for communication that makes anyone feel unwelcome, unsupported, insulted or discriminated against. ## Seen or experienced something uncomfortable? -If you see or experience abuse, harassment, discrimination, or feel unsafe or upset, please email [abuse@exercism.org](mailto:abuse@exercism.org?subject=%5BCoC%5D) and include \[CoC\] in the subject line. We will follow up with you as a priority. +If you see or experience abuse, harassment, discrimination, or feel unsafe or upset, please email [abuse@exercism.org](mailto:abuse@exercism.org?subject=%5BCoC%5D) and include \[CoC\] in the subject line. +We will follow up with you as a priority. ## Enforcement -We actively monitor for Code of Conduct (CoC) violations and take any reports of violations extremely seriously. We have banned contributors, mentors and users due to violations. +We actively monitor for Code of Conduct (CoC) violations and take any reports of violations extremely seriously. +We have banned contributors, mentors and users due to violations. -After we receive a report of a CoC violation, we view that person's conversation history on Exercism and related communication channels and attempt to understand whether someone has deliberately broken the CoC, or accidentally crossed a line. We generally reach out to the person who has been reported to discuss any concerns we have and warn them that repeated violations will result in a ban. Sometimes we decide that no violation has occurred and that no action is required and sometimes we will also ban people on a first offense. We strive to be fair, but will err on the side of protecting the culture of our community. +After we receive a report of a CoC violation, we view that person's conversation history on Exercism and related communication channels and attempt to understand whether someone has deliberately broken the CoC, or accidentally crossed a line. +We generally reach out to the person who has been reported to discuss any concerns we have and warn them that repeated violations will result in a ban. +Sometimes we decide that no violation has occurred and that no action is required and sometimes we will also ban people on a first offense. +We strive to be fair, but will err on the side of protecting the culture of our community. Exercism's leadership reserve the right to take whatever action they feel appropriate with regards to CoC violations. @@ -36,15 +42,16 @@ Exercism should be a safe place for everybody regardless of - Race - Age - Religion -- Anything else you can think of. +- Anything else you can think of As someone who is part of this community, you agree that: -- We are collectively and individually committed to safety and inclusivity. -- We have zero tolerance for abuse, harassment, or discrimination. -- We respect people’s boundaries and identities. -- We refrain from using language that can be considered offensive or oppressive (systemically or otherwise), eg. sexist, racist, homophobic, transphobic, ableist, classist, etc. - this includes (but is not limited to) various slurs. -- We avoid using offensive topics as a form of humor. +- We are collectively and individually committed to safety and inclusivity +- We have zero tolerance for abuse, harassment, or discrimination +- We respect people’s boundaries and identities +- We refrain from using language that can be considered offensive or oppressive (systemically or otherwise), eg. sexist, racist, homophobic, transphobic, ableist, classist, etc. + - this includes (but is not limited to) various slurs. +- We avoid using offensive topics as a form of humor We actively work towards: @@ -57,26 +64,30 @@ We condemn: - Stalking, doxxing, or publishing private information - Violence, threats of violence or violent language - Anything that compromises people’s safety -- Conduct or speech which might be considered sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory or offensive in nature. -- The use of unwelcome, suggestive, derogatory or inappropriate nicknames or terms. -- Disrespect towards others (jokes, innuendo, dismissive attitudes) and towards differences of opinion. -- Intimidation or harassment (online or in-person). Please read the [Citizen Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md) for how we interpret harassment. -- Inappropriate attention or contact. -- Not understanding the differences between constructive criticism and disparagement. +- Conduct or speech which might be considered sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory or offensive in nature +- The use of unwelcome, suggestive, derogatory or inappropriate nicknames or terms +- Disrespect towards others (jokes, innuendo, dismissive attitudes) and towards differences of opinion +- Intimidation or harassment (online or in-person). + Please read the [Citizen Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md) for how we interpret harassment +- Inappropriate attention or contact +- Not understanding the differences between constructive criticism and disparagement These things are NOT OK. -Be aware of how your actions affect others. If it makes someone uncomfortable, stop. +Be aware of how your actions affect others. +If it makes someone uncomfortable, stop. If you say something that is found offensive, and you are called out on it, try to: -- Listen without interruption. -- Believe what the person is saying & do not attempt to disqualify what they have to say. -- Ask for tips / help with avoiding making the offense in the future. -- Apologize and ask forgiveness. +- Listen without interruption +- Believe what the person is saying & do not attempt to disqualify what they have to say +- Ask for tips / help with avoiding making the offense in the future +- Apologize and ask forgiveness ## History -This policy was initially adopted from the Front-end London Slack community and has been modified since. A version history can be seen on [GitHub](https://github.com/exercism/website-copy/edit/main/pages/code_of_conduct.md). +This policy was initially adopted from the Front-end London Slack community and has been modified since. +A version history can be seen on [GitHub](https://github.com/exercism/website-copy/edit/main/pages/code_of_conduct.md). -_This policy is a "living" document, and subject to refinement and expansion in the future. This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Slack, Twitter, email) and any other Exercism entity or event._ +_This policy is a "living" document, and subject to refinement and expansion in the future. +This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Slack, Twitter, email) and any other Exercism entity or event._ From e0dbcd1dbbf95836d6dc9bd634ac0d8c53b27525 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Fri, 2 Dec 2022 09:37:16 +0100 Subject: [PATCH 02/41] Create autoresponder for pausing community contributions (#1072) * Create autoresponder for pausing community contributions We're going to take a step back and redesign the volunteering model for Exercism. Please see [this forum post](https://forum.exercism.org/t/freeing-our-maintainers-exercism-wide-changes-to-track-repositories/1109) for context. This PR adds an autoresponder that runs when an issue or PR is opened. If the person opening the issue is not a member of the Exercism organization, the autoresponder posts a comment and closes the issue. In the comment the author is directed to discuss the issue in the forum. If the discussion in the forum results in the issue/PR being approved, a maintainer or staff member will reopen it. Please feel free to merge this PR. It will be merged on December 1st, 2022. Please do not close it. If you wish to discuss this, please do so in [the forum post](https://forum.exercism.org/t/freeing-our-maintainers-exercism-wide-changes-to-track-repositories/1109) rather than here. * Update workflow for pausing community contributions This removes duplicated logic, relying on a shared workflow. --- .../pause-community-contributions.yml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/pause-community-contributions.yml diff --git a/.github/workflows/pause-community-contributions.yml b/.github/workflows/pause-community-contributions.yml new file mode 100644 index 000000000..055ff8676 --- /dev/null +++ b/.github/workflows/pause-community-contributions.yml @@ -0,0 +1,21 @@ +name: Pause Community Contributions + +on: + issues: + types: + - opened + pull_request_target: + types: + - opened + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + pause: + if: github.repository_owner == 'exercism' # Stops this job from running on forks + uses: exercism/github-actions/.github/workflows/community-contributions.yml@main + with: + forum_category: support From b29b91d4d08051a8008611025c646fe1f9a5f31c Mon Sep 17 00:00:00 2001 From: ee7 <45465154+ee7@users.noreply.github.com> Date: Fri, 9 Dec 2022 09:04:41 +0100 Subject: [PATCH 03/41] goreleaser: add arm64 build for each OS (#1073) * goreleaser: add arm64 build for each OS The latest release of the Exercism CLI (3.1.0, 2022-10-04) includes these assets, via GoReleaser: exercism-3.1.0-darwin-x86_64.tar.gz exercism-3.1.0-freebsd-i386.tar.gz exercism-3.1.0-freebsd-x86_64.tar.gz exercism-3.1.0-linux-armv5.tar.gz exercism-3.1.0-linux-armv6.tar.gz exercism-3.1.0-linux-i386.tar.gz exercism-3.1.0-linux-ppc64.tar.gz exercism-3.1.0-linux-x86_64.tar.gz exercism-3.1.0-openbsd-i386.tar.gz exercism-3.1.0-openbsd-x86_64.tar.gz exercism-3.1.0-windows-armv5.zip exercism-3.1.0-windows-armv6.zip exercism-3.1.0-windows-i386.zip exercism-3.1.0-windows-x86_64.zip exercism_checksums.txt exercism_checksums.txt.sig For future releases, this commit configures GoReleaser to include an arm64 (also known as aarch64) release asset for each of the existing OSes. Note that we will have separate x86_64 and arm64 release assets for macOS; previously macOS users on arm64 had to run the x86_64 binary via Rosetta (or build the CLI themselves). At least for now, let's avoid adding a fat binary. But note that GoReleaser does support it [1]. [1] https://goreleaser.com/customization/universalbinaries/ Closes: #966 * go.mod, go.sum: bump `golang.org/x/sys` from 20170803 to 20201202 This commits the result of running go get golang.org/x/sys@v0.0.0-20201202213521-69691e467435 to fix a build failure for freebsd_arm64. This seems to be the minimum bump to fix that failure without introducing a build failure for darwin_arm64 and openbsd_arm64. We cannot bump to the latest release (0.3.0, 2022-12-03) because that causes the Linux and macOS CI jobs to fail with: Error: ../../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/syscall.go:83:16: undefined: unsafe.Slice Error: ../../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/syscall_darwin.go:95:8: undefined: unsafe.Slice Error: ../../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/syscall_unix.go:118:7: undefined: unsafe.Slice Error: ../../../go/pkg/mod/golang.org/x/sys@v0.3.0/unix/sysvshm_unix.go:33:7: undefined: unsafe.Slice note: module requires Go 1.17 and we need other changes in order to bump the minimum Go version. --- .goreleaser.yml | 1 + go.mod | 2 +- go.sum | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index ca7d2bbcb..cb55b79f4 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -15,6 +15,7 @@ builds: - amd64 - 386 - arm + - arm64 - ppc64 goarm: - 5 diff --git a/go.mod b/go.mod index a3723bfad..91e79ff1a 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/spf13/viper v0.0.0-20180507071007-15738813a09d github.com/stretchr/testify v1.1.4 golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7 - golang.org/x/sys v0.0.0-20170803140359-d8f5ea21b929 + golang.org/x/sys v0.0.0-20201202213521-69691e467435 golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d ) diff --git a/go.sum b/go.sum index 3f5f7852a..7d53fd399 100644 --- a/go.sum +++ b/go.sum @@ -38,6 +38,8 @@ golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7 h1:1Pw+ZX4dmGORIwGkTwnUr7RFu golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sys v0.0.0-20170803140359-d8f5ea21b929 h1:M4VPQYSW/nB4Bcg1XMD4yW2sprnwerD3Kb6apRphtZw= golang.org/x/sys v0.0.0-20170803140359-d8f5ea21b929/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 h1:7aXI3TQ9sZ4JdDoIDGjxL6G2mQxlsPy9dySnJaL6Bdk= golang.org/x/text v0.0.0-20170730040918-3bd178b88a81/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d h1:2DX7x6HUDGZUyuEDAhUsQQNqkb1zvDyKTjVoTdzaEzo= From bfd0789e57da9b70155f23741eb56bd18b44f02f Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Tue, 13 Dec 2022 19:09:41 +0100 Subject: [PATCH 04/41] Add custom token to community contributions workflow (#1076) The pause-community-contributions workflow makes a call to the GitHub API to check if the person contributing is a member of the organization. However, this call currently fails if the contributor has set their membership to 'private'. This is because the default token provided for GitHub Actions only has permissions for the repository, not for the organization. With this token, we're not allowed to see private memberships. We've created a custom, org-wide secret containing a personal token that has permissions to read organization membership. Unfortunately the secret cannot be accessed directly by the shared workflow, it has to be passed in. We updated the shared workflow to use the token, if it is provided, and this PR updates the workflow in this repo to pass the secret. Until this is merged, contributions from people with private membership in the Exercism organization will be automatically closed. Note that this PR also removes the workflow_dispatch which fails if you try to use it. --- .github/workflows/pause-community-contributions.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pause-community-contributions.yml b/.github/workflows/pause-community-contributions.yml index 055ff8676..46f0c60b4 100644 --- a/.github/workflows/pause-community-contributions.yml +++ b/.github/workflows/pause-community-contributions.yml @@ -7,7 +7,6 @@ on: pull_request_target: types: - opened - workflow_dispatch: permissions: issues: write @@ -19,3 +18,5 @@ jobs: uses: exercism/github-actions/.github/workflows/community-contributions.yml@main with: forum_category: support + secrets: + github_membership_token: ${{ secrets.COMMUNITY_CONTRIBUTIONS_WORKFLOW_TOKEN }} From 94755c68f030fac1f8bff3f112c83fe69d7fd8c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 19:59:48 +0100 Subject: [PATCH 05/41] Bump actions/checkout from 3.0.0 to 3.2.0 (#1077) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/a12a3943b4bdde767164f792f33f40b04645d846...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f38a110d..c396f2e2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: actions/setup-go@bfdd3570ce990073878bf10f6b2d79082de49492 with: @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - name: Check formatting run: ./.gha.gofmt.sh From edee2079639ae4e5f2e628eb689bf489ed10b389 Mon Sep 17 00:00:00 2001 From: Nate Eagleson Date: Mon, 13 Feb 2023 11:37:26 -0500 Subject: [PATCH 06/41] Explain auto-close policy in ISSUE_TEMPLATE.md (#1084) * Explain auto-close policy in ISSUE_TEMPLATE.md Per discussion in this forum thread: http://forum.exercism.org/t/update-github-issue-template-to-warn-users-new-issues-are-being-auto-closed/3676/2 * Ask people to use the forum instead in .github/ISSUE_TEMPLATE.md Co-authored-by: Jeremy Walker --------- Co-authored-by: Jeremy Walker --- .github/ISSUE_TEMPLATE.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 04f539626..73ac4bb57 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,7 +1,4 @@ From a8ffc316a462ea07a5e4cfbfb3df24eb0f9342eb Mon Sep 17 00:00:00 2001 From: David Brownman Date: Fri, 28 Jul 2023 00:44:39 -0700 Subject: [PATCH 07/41] Add `test` command to run any unit test (#1092) This commit adds a `test` command that allows the student to run the tests for an exercise without knowing the track-specific test command. This makes it easier for the student to get started. For debugging and education purposes, we print the command that is used to run the tests. --- CHANGELOG.md | 2 + cmd/cmd_test.go | 14 +- cmd/test.go | 84 +++++++++ workspace/exercise_config.go | 57 ++++++ workspace/exercise_config_test.go | 98 ++++++++++ workspace/test_configurations.go | 252 ++++++++++++++++++++++++++ workspace/test_configurations_test.go | 103 +++++++++++ 7 files changed, 604 insertions(+), 6 deletions(-) create mode 100644 cmd/test.go create mode 100644 workspace/exercise_config.go create mode 100644 workspace/exercise_config_test.go create mode 100644 workspace/test_configurations.go create mode 100644 workspace/test_configurations_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 110c6fe80..1c84fa0a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ The exercism CLI follows [semantic versioning](http://semver.org/). ---------------- ## Next Release +* [#1092](https://github.com/exercism/cli/pull/1092) Add `exercism test` command to run the unit tests for nearly any track (inspired by [universal-test-runner](https://github.com/xavdid/universal-test-runner)) - [@xavdid] * **Your contribution here** ## v3.1.0 (2022-10-04) @@ -489,5 +490,6 @@ All changes by [@msgehard] [@sfairchild]: https://github.com/sfairchild [@simonjefford]: https://github.com/simonjefford [@srt32]: https://github.com/srt32 +[@xavdid]: https://github.com/xavdid [@williandrade]: https://github.com/williandrade [@zabawaba99]: https://github.com/zabawaba99 diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 76ed0634e..fee08cd98 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -26,12 +26,14 @@ const cfgHomeKey = "EXERCISM_CONFIG_HOME" // test, call the command by calling Execute on the App. // // Example: -// cmdTest := &CommandTest{ -// Cmd: myCmd, -// InitFn: initMyCmd, -// Args: []string{"fakeapp", "mycommand", "arg1", "--flag", "value"}, -// MockInteractiveResponse: "first-input\nsecond\n", -// } +// +// cmdTest := &CommandTest{ +// Cmd: myCmd, +// InitFn: initMyCmd, +// Args: []string{"fakeapp", "mycommand", "arg1", "--flag", "value"}, +// MockInteractiveResponse: "first-input\nsecond\n", +// } +// // cmdTest.Setup(t) // defer cmdTest.Teardown(t) // ... diff --git a/cmd/test.go b/cmd/test.go new file mode 100644 index 000000000..8f5b54e35 --- /dev/null +++ b/cmd/test.go @@ -0,0 +1,84 @@ +package cmd + +import ( + "fmt" + "log" + "os" + "os/exec" + "strings" + + "github.com/exercism/cli/workspace" + "github.com/spf13/cobra" +) + +var testCmd = &cobra.Command{ + Use: "test", + Aliases: []string{"t"}, + Short: "Run the exercise's tests.", + Long: `Run the exercise's tests. + + Run this command in an exercise's root directory.`, + RunE: func(cmd *cobra.Command, args []string) error { + return runTest(args) + }, +} + +func runTest(args []string) error { + track, err := getTrack() + if err != nil { + return err + } + + testConf, ok := workspace.TestConfigurations[track] + + if !ok { + return fmt.Errorf("the \"%s\" track does not yet support running tests using the Exercism CLI. Please see HELP.md for testing instructions", track) + } + + command, err := testConf.GetTestCommand() + if err != nil { + return err + } + cmdParts := strings.Split(command, " ") + + // pass args/flags to this command down to the test handler + if len(args) > 0 { + cmdParts = append(cmdParts, args...) + } + + fmt.Printf("Running tests via `%s`\n\n", strings.Join(cmdParts, " ")) + exerciseTestCmd := exec.Command(cmdParts[0], cmdParts[1:]...) + + // pipe output directly out, preserving any color + exerciseTestCmd.Stdout = os.Stdout + exerciseTestCmd.Stderr = os.Stderr + + err = exerciseTestCmd.Run() + if err != nil { + // unclear what other errors would pop up here, but it pays to be defensive + if exitErr, ok := err.(*exec.ExitError); ok { + exitCode := exitErr.ExitCode() + // if subcommand returned a non-zero exit code, exit with the same + os.Exit(exitCode) + } else { + log.Fatalf("Failed to get error from failed subcommand: %v", err) + } + } + return nil +} + +func getTrack() (string, error) { + metadata, err := workspace.NewExerciseMetadata(".") + if err != nil { + return "", err + } + if metadata.Track == "" { + return "", fmt.Errorf("no track found in exercise metadata") + } + + return metadata.Track, nil +} + +func init() { + RootCmd.AddCommand(testCmd) +} diff --git a/workspace/exercise_config.go b/workspace/exercise_config.go new file mode 100644 index 000000000..9b0164ebb --- /dev/null +++ b/workspace/exercise_config.go @@ -0,0 +1,57 @@ +package workspace + +import ( + "encoding/json" + "errors" + "io/ioutil" + "path/filepath" +) + +const configFilename = "config.json" + +var configFilepath = filepath.Join(ignoreSubdir, configFilename) + +// ExerciseConfig contains exercise metadata. +// Note: we only use a subset of its fields +type ExerciseConfig struct { + Files struct { + Solution []string `json:"solution"` + Test []string `json:"test"` + } `json:"files"` +} + +// NewExerciseConfig reads exercise metadata from a file in the given directory. +func NewExerciseConfig(dir string) (*ExerciseConfig, error) { + b, err := ioutil.ReadFile(filepath.Join(dir, configFilepath)) + if err != nil { + return nil, err + } + var config ExerciseConfig + if err := json.Unmarshal(b, &config); err != nil { + return nil, err + } + + return &config, nil +} + +// GetTestFiles finds returns the names of the file(s) that hold unit tests for this exercise, if any +func (c *ExerciseConfig) GetSolutionFiles() ([]string, error) { + result := c.Files.Solution + if result == nil { + // solution file(s) key was missing in config json, which is an error when calling this fuction + return []string{}, errors.New("no `files.solution` key in your `config.json`. Was it removed by mistake?") + } + + return result, nil +} + +// GetTestFiles finds returns the names of the file(s) that hold unit tests for this exercise, if any +func (c *ExerciseConfig) GetTestFiles() ([]string, error) { + result := c.Files.Test + if result == nil { + // test file(s) key was missing in config json, which is an error when calling this fuction + return []string{}, errors.New("no `files.test` key in your `config.json`. Was it removed by mistake?") + } + + return result, nil +} diff --git a/workspace/exercise_config_test.go b/workspace/exercise_config_test.go new file mode 100644 index 000000000..d07264c0d --- /dev/null +++ b/workspace/exercise_config_test.go @@ -0,0 +1,98 @@ +package workspace + +import ( + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestExerciseConfig(t *testing.T) { + dir, err := ioutil.TempDir("", "exercise_config") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + err = os.Mkdir(filepath.Join(dir, ".exercism"), os.ModePerm) + assert.NoError(t, err) + + f, err := os.Create(filepath.Join(dir, ".exercism", "config.json")) + assert.NoError(t, err) + defer f.Close() + + _, err = f.WriteString(`{ "blurb": "Learn about the basics of Ruby by following a lasagna recipe.", "authors": ["iHiD", "pvcarrera"], "files": { "solution": ["lasagna.rb"], "test": ["lasagna_test.rb"], "exemplar": [".meta/exemplar.rb"] } } `) + assert.NoError(t, err) + + ec, err := NewExerciseConfig(dir) + assert.NoError(t, err) + + assert.Equal(t, ec.Files.Solution, []string{"lasagna.rb"}) + solutionFiles, err := ec.GetSolutionFiles() + assert.NoError(t, err) + assert.Equal(t, solutionFiles, []string{"lasagna.rb"}) + + assert.Equal(t, ec.Files.Test, []string{"lasagna_test.rb"}) + testFiles, err := ec.GetTestFiles() + assert.NoError(t, err) + assert.Equal(t, testFiles, []string{"lasagna_test.rb"}) +} + +func TestExerciseConfigNoTestKey(t *testing.T) { + dir, err := ioutil.TempDir("", "exercise_config") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + err = os.Mkdir(filepath.Join(dir, ".exercism"), os.ModePerm) + assert.NoError(t, err) + + f, err := os.Create(filepath.Join(dir, ".exercism", "config.json")) + assert.NoError(t, err) + defer f.Close() + + _, err = f.WriteString(`{ "blurb": "Learn about the basics of Ruby by following a lasagna recipe.", "authors": ["iHiD", "pvcarrera"], "files": { "exemplar": [".meta/exemplar.rb"] } } `) + assert.NoError(t, err) + + ec, err := NewExerciseConfig(dir) + assert.NoError(t, err) + + _, err = ec.GetSolutionFiles() + assert.Error(t, err, "no `files.solution` key in your `config.json`") + _, err = ec.GetTestFiles() + assert.Error(t, err, "no `files.test` key in your `config.json`") +} + +func TestMissingExerciseConfig(t *testing.T) { + dir, err := ioutil.TempDir("", "exercise_config") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + _, err = NewExerciseConfig(dir) + assert.Error(t, err) + // any assertions about this error message have to work across all platforms, so be vague + // unix: ".exercism/config.json: no such file or directory" + // windows: "open .exercism\config.json: The system cannot find the path specified." + assert.Contains(t, err.Error(), filepath.Join(".exercism", "config.json:")) +} + +func TestInvalidExerciseConfig(t *testing.T) { + dir, err := ioutil.TempDir("", "exercise_config") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + err = os.Mkdir(filepath.Join(dir, ".exercism"), os.ModePerm) + assert.NoError(t, err) + + f, err := os.Create(filepath.Join(dir, ".exercism", "config.json")) + assert.NoError(t, err) + defer f.Close() + + // invalid JSON + _, err = f.WriteString(`{ "blurb": "Learn about the basics of Ruby by following a lasagna recipe.", "authors": ["iHiD", "pvcarr `) + assert.NoError(t, err) + + _, err = NewExerciseConfig(dir) + assert.Error(t, err) + assert.True(t, strings.Contains(err.Error(), "unexpected end of JSON input")) +} diff --git a/workspace/test_configurations.go b/workspace/test_configurations.go new file mode 100644 index 000000000..32c6fbc3a --- /dev/null +++ b/workspace/test_configurations.go @@ -0,0 +1,252 @@ +package workspace + +import ( + "fmt" + "runtime" + "strings" +) + +type TestConfiguration struct { + // The static portion of the test Command, which will be run for every test on this track. Examples include `cargo test` or `go test`. + // Might be empty if there are platform-specific versions + Command string + + // Windows-specific test command. Mostly relevant for tests wrapped by shell invocations. Falls back to `Command` if we're not running windows or this is empty. + WindowsCommand string +} + +func (c *TestConfiguration) GetTestCommand() (string, error) { + var cmd string + if runtime.GOOS == "windows" && c.WindowsCommand != "" { + cmd = c.WindowsCommand + } else { + cmd = c.Command + } + + // pre-declare these so we can conditionally initialize them + var exerciseConfig *ExerciseConfig + var err error + + if strings.Contains(cmd, "{{") { + // only read exercise's config.json if we need it + exerciseConfig, err = NewExerciseConfig(".") + if err != nil { + return "", err + } + } + + if strings.Contains(cmd, "{{solution_files}}") { + if exerciseConfig == nil { + return "", fmt.Errorf("exerciseConfig not initialize before use") + } + solutionFiles, err := exerciseConfig.GetSolutionFiles() + if err != nil { + return "", err + } + cmd = strings.ReplaceAll(cmd, "{{solution_files}}", strings.Join(solutionFiles, " ")) + } + if strings.Contains(cmd, "{{test_files}}") { + if exerciseConfig == nil { + return "", fmt.Errorf("exerciseConfig not initialize before use") + } + testFiles, err := exerciseConfig.GetTestFiles() + if err != nil { + return "", err + } + cmd = strings.ReplaceAll(cmd, "{{test_files}}", strings.Join(testFiles, " ")) + } + + return cmd, nil +} + +// some tracks aren't (or won't be) implemented; every track is listed either way +var TestConfigurations = map[string]TestConfiguration{ + "8th": { + Command: "bash tester.sh", + WindowsCommand: "tester.bat", + }, + // abap: tests are run via "ABAP Development Tools", not the CLI + "awk": { + Command: "bats {{test_files}}", + }, + "ballerina": { + Command: "bal test", + }, + "bash": { + Command: "bats {{test_files}}", + }, + "c": { + Command: "make", + }, + "cfml": { + Command: "box task run TestRunner", + }, + "clojure": { + // chosen because the docs recommend `clj` by default and `lein` as optional + Command: "clj -X:test", + }, + "cobol": { + Command: "bash test.sh", + WindowsCommand: "pwsh test.ps1", + }, + "coffeescript": { + Command: "jasmine-node --coffee {{test_files}}", + }, + // common-lisp: tests are loaded into a "running Lisp implementation", not the CLI directly + "cpp": { + Command: "make", + }, + "crystal": { + Command: "crystal spec", + }, + "csharp": { + Command: "dotnet test", + }, + "d": { + // this always works even if the user installed DUB + Command: "dmd source/*.d -de -w -main -unittest", + }, + "dart": { + Command: "dart test", + }, + // delphi: tests are run via IDE + "elixir": { + Command: "mix test", + }, + "elm": { + Command: "elm-test", + }, + "emacs-lisp": { + Command: "emacs -batch -l ert -l *-test.el -f ert-run-tests-batch-and-exit", + }, + "erlang": { + Command: "rebar3 eunit", + }, + "fortran": { + Command: "make", + }, + "fsharp": { + Command: "dotnet test", + }, + "gleam": { + Command: "gleam test", + }, + "go": { + Command: "go test", + }, + "groovy": { + Command: "gradle test", + }, + "haskell": { + Command: "stack test", + }, + "java": { + Command: "gradle test", + }, + "javascript": { + Command: "npm run test", + }, + "jq": { + Command: "bats {{test_files}}", + }, + "julia": { + Command: "julia runtests.jl", + }, + "kotlin": { + Command: "./gradlew test", + WindowsCommand: "gradlew.bat test", + }, + "lfe": { + Command: "make test", + }, + "lua": { + Command: "busted", + }, + "mips": { + Command: "java -jar /path/to/mars.jar nc runner.mips impl.mips", + }, + "nim": { + Command: "nim r {{test_files}}", + }, + // objective-c: tests are run via XCode. There's a CLI option (ruby gem `objc`), but the docs note that this is an inferior experience + "ocaml": { + Command: "make", + }, + "perl5": { + Command: "prove .", + }, + // pharo-smalltalk: tests are run via IDE + "php": { + Command: "phpunit {{test_files}}", + }, + // plsql: test are run via a "mounted oracle db" + "powershell": { + Command: "Invoke-Pester", + }, + "prolog": { + Command: "swipl -f {{solution_files}} -s {{test_files}} -g run_tests,halt -t 'halt(1)'", + }, + "purescript": { + Command: "spago test", + }, + "python": { + Command: "python3 -m pytest -o markers=task {{test_files}}", + }, + "r": { + Command: "Rscript {{test_files}}", + }, + "racket": { + Command: "raco test {{test_files}}", + }, + "raku": { + Command: "prove6 {{test_files}}", + }, + "reasonml": { + Command: "npm run test", + }, + "red": { + Command: "red {{test_files}}", + }, + "ruby": { + Command: "ruby {{test_files}}", + }, + "rust": { + Command: "cargo test --", + }, + "scala": { + Command: "sbt test", + }, + // scheme: docs present 2 equally valid test methods (`make chez` and `make guile`). So I wasn't sure which to pick + "sml": { + Command: "poly -q --use {{test_files}}", + }, + "swift": { + Command: "swift test", + }, + "tcl": { + Command: "tclsh {{test_files}}", + }, + "typescript": { + Command: "yarn test", + }, + // unison: tests are run from an active UCM session + "vbnet": { + Command: "dotnet test", + }, + // vimscript: tests are run from inside a vim session + "vlang": { + Command: "v -stats test run_test.v", + }, + "wasm": { + Command: "npm run test", + }, + "wren": { + Command: "wrenc {{test_files}}", + }, + "x86-64-assembly": { + Command: "make", + }, + "zig": { + Command: "zig test {{test_files}}", + }, +} diff --git a/workspace/test_configurations_test.go b/workspace/test_configurations_test.go new file mode 100644 index 000000000..97ff40902 --- /dev/null +++ b/workspace/test_configurations_test.go @@ -0,0 +1,103 @@ +package workspace + +import ( + "os" + "path/filepath" + "runtime" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetCommand(t *testing.T) { + testConfig, ok := TestConfigurations["elixir"] + assert.True(t, ok, "unexpectedly unable to find elixir test config") + + cmd, err := testConfig.GetTestCommand() + assert.NoError(t, err) + + assert.Equal(t, cmd, "mix test") +} + +func TestWindowsCommands(t *testing.T) { + testConfig, ok := TestConfigurations["cobol"] + assert.True(t, ok, "unexpectedly unable to find cobol test config") + + cmd, err := testConfig.GetTestCommand() + assert.NoError(t, err) + + if runtime.GOOS == "windows" { + assert.Contains(t, cmd, ".ps1") + assert.NotContains(t, cmd, ".sh") + } else { + assert.Contains(t, cmd, ".sh") + assert.NotContains(t, cmd, ".ps1") + } +} + +func TestGetCommandMissingConfig(t *testing.T) { + testConfig, ok := TestConfigurations["ruby"] + assert.True(t, ok, "unexpectedly unable to find ruby test config") + + _, err := testConfig.GetTestCommand() + assert.Error(t, err) + // any assertions about this error message have to work across all platforms, so be vague + // unix: ".exercism/config.json: no such file or directory" + // windows: "open .exercism\config.json: The system cannot find the path specified." + assert.Contains(t, err.Error(), filepath.Join(".exercism", "config.json:")) +} + +func TestIncludesSolutionAndTestFilesInCommand(t *testing.T) { + testConfig, ok := TestConfigurations["prolog"] + assert.True(t, ok, "unexpectedly unable to find prolog test config") + + // this creates a config file in the test directory and removes it + dir := filepath.Join(".", ".exercism") + defer os.RemoveAll(dir) + err := os.Mkdir(dir, os.ModePerm) + assert.NoError(t, err) + + f, err := os.Create(filepath.Join(dir, "config.json")) + assert.NoError(t, err) + defer f.Close() + + _, err = f.WriteString(`{ "blurb": "Learn about the basics of Prolog by following a lasagna recipe.", "authors": ["iHiD", "pvcarrera"], "files": { "solution": ["lasagna.pl"], "test": ["lasagna_tests.plt"] } } `) + assert.NoError(t, err) + + cmd, err := testConfig.GetTestCommand() + assert.NoError(t, err) + assert.Equal(t, cmd, "swipl -f lasagna.pl -s lasagna_tests.plt -g run_tests,halt -t 'halt(1)'") +} + +func TestIncludesTestFilesInCommand(t *testing.T) { + testConfig, ok := TestConfigurations["ruby"] + assert.True(t, ok, "unexpectedly unable to find ruby test config") + + // this creates a config file in the test directory and removes it + dir := filepath.Join(".", ".exercism") + defer os.RemoveAll(dir) + err := os.Mkdir(dir, os.ModePerm) + assert.NoError(t, err) + + f, err := os.Create(filepath.Join(dir, "config.json")) + assert.NoError(t, err) + defer f.Close() + + _, err = f.WriteString(`{ "blurb": "Learn about the basics of Ruby by following a lasagna recipe.", "authors": ["iHiD", "pvcarrera"], "files": { "solution": ["lasagna.rb"], "test": ["lasagna_test.rb", "some_other_file.rb"], "exemplar": [".meta/exemplar.rb"] } } `) + assert.NoError(t, err) + + cmd, err := testConfig.GetTestCommand() + assert.NoError(t, err) + assert.Equal(t, cmd, "ruby lasagna_test.rb some_other_file.rb") +} + +func TestRustHasTrailingDashes(t *testing.T) { + testConfig, ok := TestConfigurations["rust"] + assert.True(t, ok, "unexpectedly unable to find rust test config") + + cmd, err := testConfig.GetTestCommand() + assert.NoError(t, err) + + assert.True(t, strings.HasSuffix(cmd, "--"), "rust's test command should have trailing dashes") +} From 3551c62b2cc844255badd0b9926f5362741cf93c Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Fri, 28 Jul 2023 14:02:02 +0200 Subject: [PATCH 08/41] Bump version to 3.2.0 (#1093) --- CHANGELOG.md | 5 ++++- cmd/version.go | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c84fa0a3..a1dcca2ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,12 @@ The exercism CLI follows [semantic versioning](http://semver.org/). ---------------- ## Next Release -* [#1092](https://github.com/exercism/cli/pull/1092) Add `exercism test` command to run the unit tests for nearly any track (inspired by [universal-test-runner](https://github.com/xavdid/universal-test-runner)) - [@xavdid] * **Your contribution here** +## v3.2.0 (2023-07-28) +* [#1092](https://github.com/exercism/cli/pull/1092) Add `exercism test` command to run the unit tests for nearly any track (inspired by [universal-test-runner](https://github.com/xavdid/universal-test-runner)) - [@xavdid] +* [#1073](https://github.com/exercism/cli/pull/1073) Add `arm64` build for each OS + ## v3.1.0 (2022-10-04) * [#979](https://github.com/exercism/cli/pull/979) Protect existing solutions from being overwritten by 'download' - [@harugo] * [#981](https://github.com/exercism/cli/pull/981) Check if authorisation header is set before attempting to extract token - [@harugo] diff --git a/cmd/version.go b/cmd/version.go index 069866b78..d8e287f4a 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -9,7 +9,7 @@ import ( // Version is the version of the current build. // It follows semantic versioning. -const Version = "3.1.0" +const Version = "3.2.0" // checkLatest flag for version command. var checkLatest bool From d0faf4c2fef579ac85012c74cb285b969c274ffa Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Fri, 28 Jul 2023 14:53:22 +0200 Subject: [PATCH 09/41] Fix deprecated argument to goreleaser (#1094) --- RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index bf3e1c8bf..fe41e37ea 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -33,7 +33,7 @@ Commit this change on a branch along with the CHANGELOG updates in a single comm ```bash # Test run -goreleaser --skip-publish --snapshot --rm-dist +goreleaser --skip-publish --snapshot --clean # Create a new tag on the main branch and push it git tag -a v3.0.16 -m "Trying out GoReleaser" From ca046ee7579aacac64b1a4f1390e5dd6084b9415 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:31:17 +0200 Subject: [PATCH 10/41] Bump actions/setup-go from 2.2.0 to 4.0.0 (#1088) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2.2.0 to 4.0.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/bfdd3570ce990073878bf10f6b2d79082de49492...4d34df0c2316fe8122ab82dc22947d607c0c91f9) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Erik Schierboom --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c396f2e2a..493acf702 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: actions/setup-go@bfdd3570ce990073878bf10f6b2d79082de49492 + - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 with: go-version: ${{ matrix.go-version }} From 2ab0439a2cecf71ef418b470471b6dbe6ed238ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 10:31:29 +0200 Subject: [PATCH 11/41] Bump actions/checkout from 3.2.0 to 3.5.0 (#1091) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Erik Schierboom --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 493acf702..f3913210b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 with: @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - name: Check formatting run: ./.gha.gofmt.sh From eaf599b3a89125a9667800f77b8ba07473a07192 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 1 Aug 2023 11:27:35 +0200 Subject: [PATCH 12/41] Fix goreleaser name templates (#1095) --- .goreleaser.yml | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index cb55b79f4..c2f9886af 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -37,10 +37,14 @@ changelog: - '^test:' archives: - - name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - replacements: - amd64: x86_64 - 386: i386 + - name_template: >- + {{- .ProjectName }}- + {{- .Version }}- + {{- .Os }}- + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{- .Arch }}{{ end }} + {{- if .Arm }}v{{- .Arm }}{{ end }} format_overrides: - goos: windows format: zip @@ -92,10 +96,14 @@ snapcrafts: # https://snapcraft.io/docs/reference/channels grade: stable description: Exercism is an online platform designed to help you improve your coding skills through practice and mentorship. Exercism provides you with thousands of exercises spread across numerous language tracks. Each one is a fun and interesting challenge designed to teach you a little more about the features of a language. - name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - replacements: - amd64: x86_64 - 386: i386 + name_template: >- + {{- .ProjectName }}- + {{- .Version }}- + {{- .Os }}- + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{- .Arch }}{{ end }} + {{- if .Arm }}v{{- .Arm }}{{ end }} apps: exercism: plugs: ["home", "network", "removable-media","personal-files"] From 1464c3836b0a7204573f4726b47445309e466e32 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 1 Aug 2023 12:56:50 +0200 Subject: [PATCH 13/41] Fix link in release doc (#1096) --- RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index fe41e37ea..ce89b8503 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -97,6 +97,6 @@ For more information see [How To Open a Homebrew Pull Request](https://docs.brew ## Update the docs site If there are any significant changes, we should describe them on -[exercism.io/cli]([https://exercism.io/cli). +[exercism.io/cli](https://exercism.io/cli). The codebase lives at [exercism/website-copy](https://github.com/exercism/website-copy) in `pages/cli.md`. From cddc1228f3a515b4ee49442eebadc99329b156c2 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 1 Aug 2023 13:02:32 +0200 Subject: [PATCH 14/41] More release doc cleanup (#1097) --- RELEASE.md | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index ce89b8503..47645c282 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,7 +12,7 @@ release process. ## Confirm / Update the Changelog -Make sure all the recent changes are reflected in the "next release" section of the CHANGELOG.md file. All the changes in the "next release" section should be moved to a new section that describes the version number, and gives it a date. +Make sure all the recent changes are reflected in the "next release" section of the CHANGELOG.md file. All the changes in the "next release" section should be moved to a new section that describes the version number, and gives it a date. You can view changes using the /compare/ view: https://github.com/exercism/cli/compare/$PREVIOUS_RELEASE...main @@ -40,7 +40,7 @@ git tag -a v3.0.16 -m "Trying out GoReleaser" git push origin v3.0.16 # Build and release -goreleaser --rm-dist +goreleaser --clean # You must be logged into snapcraft to publish a new snap snapcraft login @@ -53,9 +53,8 @@ for f in `ls dist/*.snap`; do snapcraft push --release=stable $f; done ## Cut Release on GitHub -Run [exercism-cp-archive-hack.sh](https://gist.github.com/ekingery/961650fca4e2233098c8320f32736836) which takes the new archive files and renames them to match the old naming scheme for backward compatibility. Until mid to late 2020, we will need to manually upload the backward-compatible archive files generated in `/tmp/exercism_tmp_upload`. - -The generated archive files should be uploaded to the [draft release page created by GoReleaser](https://github.com/exercism/cli/releases). Describe the release, select a specific commit to target, paste the following release text, and describe the new changes. +At this point, Goreleaser will a created a draft PR at https://github.com/exercism/cli/releases/tag/vX.Y.Z. +On that page, update the release description to: ``` To install, follow the interactive installation instructions at https://exercism.io/cli-walkthrough @@ -64,32 +63,18 @@ To install, follow the interactive installation instructions at https://exercism [describe changes in this release] ``` - Lastly, test and publish the draft - +Lastly, test and publish the draft ## Update Homebrew -This is helpful for the (many) Mac OS X users. - -First, get a copy of the latest tarball of the source code: - -``` -cd ~/tmp && wget https://github.com/exercism/cli/archive/vX.Y.Z.tar.gz -``` - -Get the SHA256 of the tarball: - -``` -shasum -a 256 vX.Y.Z.tar.gz -``` - -Update the homebrew formula: +Next, we'll submit a PR to Homebrew to update the Exercism formula (which is how macOS users usually download the CLI): ``` +cd /tmp && curl -O https://github.com/exercism/cli/archive/vX.Y.Z.tar.gz cd $(brew --repository) git checkout master brew update -brew bump-formula-pr --strict exercism --url=https://github.com/exercism/cli/archive/vX.Y.Z.tar.gz --sha256=$SHA +brew bump-formula-pr --strict exercism --url=https://github.com/exercism/cli/archive/vX.Y.Z.tar.gz --sha256=$(shasum -a 256 /tmp/vX.Y.Z.tar.gz) ``` For more information see [How To Open a Homebrew Pull Request](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request). From ba0ea34a356fe43beed8765f3255a550f8e241d2 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 1 Aug 2023 14:12:12 +0200 Subject: [PATCH 15/41] Remove snapcraft (#1098) --- .goreleaser.yml | 32 -------------------------------- RELEASE.md | 7 ------- 2 files changed, 39 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index c2f9886af..ee029e45c 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -79,35 +79,3 @@ release: # brews: # We do not use the brew config, which is for taps, not core forumulas. - -snapcrafts: - - - name: exercism - license: MIT - # Whether to publish the snap to the snapcraft store. - # Remember you need to `snapcraft login` first. - # Defaults to false. - # publish: true - summary: Command-line client for https://exercism.org - # https://snapcraft.io/docs/reference/confinement - confinement: strict - # A snap of type base to be used as the execution environment for this snap. - base: core18 - # https://snapcraft.io/docs/reference/channels - grade: stable - description: Exercism is an online platform designed to help you improve your coding skills through practice and mentorship. Exercism provides you with thousands of exercises spread across numerous language tracks. Each one is a fun and interesting challenge designed to teach you a little more about the features of a language. - name_template: >- - {{- .ProjectName }}- - {{- .Version }}- - {{- .Os }}- - {{- if eq .Arch "amd64" }}x86_64 - {{- else if eq .Arch "386" }}i386 - {{- else }}{{- .Arch }}{{ end }} - {{- if .Arm }}v{{- .Arm }}{{ end }} - apps: - exercism: - plugs: ["home", "network", "removable-media","personal-files"] - plugs: - personal-files: - write: - - $HOME/ diff --git a/RELEASE.md b/RELEASE.md index 47645c282..1592c7519 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -6,7 +6,6 @@ release process. ## Requirements 1. [Install GoReleaser](https://goreleaser.com/install/) -1. [Install snapcraft](https://snapcraft.io/docs/snapcraft-overview) 1. [Setup GitHub token](https://goreleaser.com/scm/github/) 1. Have a gpg key installed on your machine - it is [used for signing the artifacts](https://goreleaser.com/customization/sign/) @@ -42,12 +41,6 @@ git push origin v3.0.16 # Build and release goreleaser --clean -# You must be logged into snapcraft to publish a new snap -snapcraft login - -# Push to snapcraft -for f in `ls dist/*.snap`; do snapcraft push --release=stable $f; done - # [TODO] Push to homebrew ``` From 8b850d25149a98bfe0cca84afc56160b0b5782e0 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 1 Aug 2023 14:52:18 +0200 Subject: [PATCH 16/41] Simplify release (#1099) * Remove snapcraft * Simply release process --- RELEASE.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 1592c7519..1819773af 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -20,23 +20,27 @@ GoReleaser supports the [auto generation of a changelog](https://goreleaser.com/ ## Bump the version -Edit the `Version` constant in `cmd/version.go` +1. Create a branch for the new version +1. Edit the `Version` constant in `cmd/version.go` +1. Update the `CHANGELOG.md` file +1. Commit the updated version +1. Create a PR _Note: It's useful to add the version to the commit message when you bump it: e.g. `Bump version to v2.3.4`._ -In the future we will probably want to replace the hardcoded `Version` constant with [main.version](https://goreleaser.com/cookbooks/using-main.version). Here is a [stack overflow post on injecting to cmd/version.go](https://stackoverflow.com/a/47510909). - -Commit this change on a branch along with the CHANGELOG updates in a single commit, and create a PR for merge to main. - ## Cut a release +Once the version bump PR has been merged, run the following commands: + ```bash +VERSION=$(sed -n -E 's/^const Version = "([0-9]+\.[0-9]+\.[0-9]+)"$/v\1/p' cmd/version.go) + # Test run goreleaser --skip-publish --snapshot --clean # Create a new tag on the main branch and push it -git tag -a v3.0.16 -m "Trying out GoReleaser" -git push origin v3.0.16 +git tag -a "${VERSION}" -m "Trying out GoReleaser" +git push origin "${VERSION}" # Build and release goreleaser --clean From 16b7d8f6d48309a8b2bb5bb6c32d51c3e1cbdcc8 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Fri, 11 Aug 2023 08:50:53 +0200 Subject: [PATCH 17/41] Update release instructions (#1104) --- RELEASE.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 1819773af..35c26bfba 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -33,24 +33,31 @@ _Note: It's useful to add the version to the commit message when you bump it: e. Once the version bump PR has been merged, run the following commands: ```bash -VERSION=$(sed -n -E 's/^const Version = "([0-9]+\.[0-9]+\.[0-9]+)"$/v\1/p' cmd/version.go) +VERSION=$(sed -n -E 's/^const Version = "([0-9]+\.[0-9]+\.[0-9]+)"$/\1/p' cmd/version.go) +TAG_NAME="v${VERSION}" # Test run goreleaser --skip-publish --snapshot --clean # Create a new tag on the main branch and push it -git tag -a "${VERSION}" -m "Trying out GoReleaser" -git push origin "${VERSION}" +git tag -a "${TAG_NAME}" -m "Trying out GoReleaser" +git push origin "${TAG_NAME}" # Build and release goreleaser --clean +# Upload copies of the Windows files for use by the Exercism Windows installer +cp "dist/exercism-${VERSION}-windows-i386.zip" dist/exercism-windows-32bit.zip +cp "dist/exercism-${VERSION}-windows-x86_64.zip" dist/exercism-windows-64bit.zip +gh release upload "${TAG_NAME}" dist/exercism-windows-32bit.zip +gh release upload "${TAG_NAME}" dist/exercism-windows-64bit.zip + # [TODO] Push to homebrew ``` ## Cut Release on GitHub -At this point, Goreleaser will a created a draft PR at https://github.com/exercism/cli/releases/tag/vX.Y.Z. +At this point, Goreleaser will have created a draft PR at https://github.com/exercism/cli/releases/tag/vX.Y.Z. On that page, update the release description to: ``` From bbd449ee91cb6ea4fa3d05605f38ea4281d8f8df Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 13:49:04 +0200 Subject: [PATCH 18/41] Bump actions/setup-go from 4.0.0 to 4.1.0 (#1105) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/4d34df0c2316fe8122ab82dc22947d607c0c91f9...93397bea11091df50f3d7e59dc26a7711a8bcfbe) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f3913210b..688076d0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 + - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe with: go-version: ${{ matrix.go-version }} From ecd826de4f64cc7a4f3167443701162d4451a09f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 13:49:13 +0200 Subject: [PATCH 19/41] Bump actions/checkout from 3.5.0 to 3.5.3 (#1101) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...c85c95e3d7251135ab7dc9ce3241c5835cc595a9) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 688076d0c..63ee024b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe with: @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - name: Check formatting run: ./.gha.gofmt.sh From 0fcf8c28f821728a0e4bbc533b04e1f4a8e0e495 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Wed, 6 Sep 2023 10:35:27 -0400 Subject: [PATCH 20/41] github/workflow/release.yml: Add automated release pipeline (#1106) --- .github/workflows/release.yml | 41 ++++++++++++++ .goreleaser.yml | 101 ++++++++++++++++++++++++---------- .release/header.md | 3 + RELEASE.md | 21 ++----- 4 files changed, 121 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .release/header.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..c2c9aecad --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: release + +on: + push: + tags: + - 'v*.*.*' # semver release tags + - 'v*.*.*-*' # pre-release tags for testing + +permissions: + contents: write # needed by goreleaser/goreleaser-action for publishing release artifacts + +jobs: + goreleaser: + runs-on: ubuntu-22.04 + steps: + + - name: Checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version: '1.19' + + - name: Import GPG Key + id: import_gpg + uses: crazy-max/ghaction-import-gpg@72b6676b71ab476b77e676928516f6982eef7a41 # v5.3.0 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} + + - name: Cut Release + uses: goreleaser/goreleaser-action@3fa32b8bb5620a2c1afe798654bbad59f9da4906 # v4.4.0 + with: + version: latest + args: release --clean --release-header .release/header.md --timeout 120m # default time is 30m + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} diff --git a/.goreleaser.yml b/.goreleaser.yml index ee029e45c..8a5dccbd2 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,33 +1,48 @@ # You can find the GoReleaser documentation at http://goreleaser.com project_name: exercism +env: + - CGO_ENABLED=0 builds: -- env: - - CGO_ENABLED=0 - main: ./exercism/main.go - goos: - - darwin - - linux - - windows - - freebsd - - openbsd - goarch: - - amd64 - - 386 - - arm - - arm64 - - ppc64 - goarm: - - 5 - - 6 - ignore: - - goos: openbsd - goarch: arm - - goos: freebsd - goarch: arm - -checksum: - name_template: '{{ .ProjectName }}_checksums.txt' + - id: release-build + main: ./exercism/main.go + mod_timestamp: '{{ .CommitTimestamp }}' + flags: + - -trimpath # removes file system paths from compiled executable + ldflags: + - '-s -w' # strip debug symbols and DWARF debugging info + goos: + - darwin + - linux + - windows + - freebsd + - openbsd + goarch: + - amd64 + - 386 + - arm + - arm64 + - ppc64 + goarm: + - 5 + - 6 + ignore: + - goos: openbsd + goarch: arm + - goos: freebsd + goarch: arm + - id: installer-build + main: ./exercism/main.go + mod_timestamp: '{{ .CommitTimestamp }}' + flags: + - -trimpath # removes file system paths from compiled executable + ldflags: + - '-s -w' # strip debug symbols and DWARF debugging info + goos: + - windows + goarch: + - amd64 + - 386 changelog: sort: asc @@ -37,7 +52,10 @@ changelog: - '^test:' archives: - - name_template: >- + - id: release-archives + builds: + - release-build + name_template: >- {{- .ProjectName }}- {{- .Version }}- {{- .Os }}- @@ -49,12 +67,37 @@ archives: - goos: windows format: zip files: - - shell/**/* + - shell/** - LICENSE - README.md + - id: installer-archives + builds: + - installer-build + name_template: >- + {{- .ProjectName }}- + {{- .Version }}- + {{- .Os }}- + {{- if eq .Arch "amd64" }}64bit + {{- else if eq .Arch "386" }}32bit + {{- else }}{{- .Arch }}{{ end }} + {{- if .Arm }}v{{- .Arm }}{{ end }} + format_overrides: + - goos: windows + format: zip + files: + - shell/** + - LICENSE + - README.md + +checksum: + name_template: '{{ .ProjectName }}_checksums.txt' + ids: + - release-archives + - installer-archives signs: -- artifacts: checksum + - artifacts: checksum + args: ["--batch", "-u", "{{ .Env.GPG_FINGERPRINT }}", "--output", "${signature}", "--detach-sign", "${artifact}"] release: # Repo in which the release will be created. diff --git a/.release/header.md b/.release/header.md new file mode 100644 index 000000000..55027b78c --- /dev/null +++ b/.release/header.md @@ -0,0 +1,3 @@ +To install, follow the interactive installation instructions at https://exercism.io/cli-walkthrough + +--- diff --git a/RELEASE.md b/RELEASE.md index 35c26bfba..566db9f83 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,7 +1,6 @@ # Cutting a CLI Release -The Exercism CLI uses [GoReleaser](https://goreleaser.com) to automate the -release process. +The Exercism CLI uses [GoReleaser](https://goreleaser.com) to automate the release process. ## Requirements @@ -11,13 +10,12 @@ release process. ## Confirm / Update the Changelog -Make sure all the recent changes are reflected in the "next release" section of the CHANGELOG.md file. All the changes in the "next release" section should be moved to a new section that describes the version number, and gives it a date. +Make sure all the recent changes are reflected in the "next release" section of the CHANGELOG.md file. +All the changes in the "next release" section should be moved to a new section that describes the version number, and gives it a date. You can view changes using the /compare/ view: https://github.com/exercism/cli/compare/$PREVIOUS_RELEASE...main -GoReleaser supports the [auto generation of a changelog](https://goreleaser.com/customization/#customize-the-changelog) we will want to customize to meet our standards (not including refactors, test updates, etc). We should also consider using [the release notes feature](https://goreleaser.com/customization/#custom-release-notes). - ## Bump the version 1. Create a branch for the new version @@ -43,28 +41,19 @@ goreleaser --skip-publish --snapshot --clean git tag -a "${TAG_NAME}" -m "Trying out GoReleaser" git push origin "${TAG_NAME}" -# Build and release -goreleaser --clean - -# Upload copies of the Windows files for use by the Exercism Windows installer -cp "dist/exercism-${VERSION}-windows-i386.zip" dist/exercism-windows-32bit.zip -cp "dist/exercism-${VERSION}-windows-x86_64.zip" dist/exercism-windows-64bit.zip -gh release upload "${TAG_NAME}" dist/exercism-windows-32bit.zip -gh release upload "${TAG_NAME}" dist/exercism-windows-64bit.zip - # [TODO] Push to homebrew ``` ## Cut Release on GitHub -At this point, Goreleaser will have created a draft PR at https://github.com/exercism/cli/releases/tag/vX.Y.Z. +At this point, Goreleaser will have created a draft release at https://github.com/exercism/cli/releases/tag/vX.Y.Z. On that page, update the release description to: ``` To install, follow the interactive installation instructions at https://exercism.io/cli-walkthrough --- -[describe changes in this release] +[modify the generated release-notes to describe changes in this release] ``` Lastly, test and publish the draft From c763ea58ce341b19407e9e7ac403bf2efc22d25d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 16:58:05 +0200 Subject: [PATCH 21/41] Bump actions/checkout from 3.5.3 to 4.0.0 (#1108) --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63ee024b0..511b27234 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe with: @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac - name: Check formatting run: ./.gha.gofmt.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c2c9aecad..0c827639a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 with: fetch-depth: 0 From 8f2c7caa030d42d6bfbd5c001b036995af10667e Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Fri, 22 Sep 2023 09:38:11 -0400 Subject: [PATCH 22/41] cmd/submit_test.go: Update test server to use unmodified filename (#1115) Following RFC 7578, Go 1.17+ strips the directory information in fileHeader.Filename. This change updates the test server to use Header["Content-Disposition"] for obtaining the unmodified filename for validating the submitted files directory tree in the request. This work builds on the PR opened by @QuLogic https://github.com/exercism/cli/pull/1066 Co-authored-by: Erik Schierboom --- cmd/submit_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/submit_test.go b/cmd/submit_test.go index 7286a19e6..ea16b6543 100644 --- a/cmd/submit_test.go +++ b/cmd/submit_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "mime" "net/http" "net/http/httptest" "os" @@ -561,7 +562,16 @@ func fakeSubmitServer(t *testing.T, submittedFiles map[string]string) *httptest. if err != nil { t.Fatal(err) } - submittedFiles[fileHeader.Filename] = string(body) + // Following RFC 7578, Go 1.17+ strips the directory information in fileHeader.Filename. + // Validating the submitted files directory tree is important so Content-Disposition is used for + // obtaining the unmodified filename. + v := fileHeader.Header.Get("Content-Disposition") + _, dispositionParams, err := mime.ParseMediaType(v) + if err != nil { + t.Fatalf("failed to obtain submitted filename from multipart header: %s", err.Error()) + } + filename := dispositionParams["filename"] + submittedFiles[filename] = string(body) } fmt.Fprint(w, "{}") From 0e017aa3b5f72c8796609557c05f1308ce714d30 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Thu, 5 Oct 2023 02:46:02 -0400 Subject: [PATCH 23/41] Bump target Go version to 1.20 (#1118) * Bump minimum Go version to 1.18 This change bumps the minimum Go version to 1.18 to take advantage of a number of fixes to the language, while matching the minimum version for a number of key dependencies which have been moving away from Go 1.15. This change drops support for Go 1.15 in the Exercism CLI. * Bump minimum go version to 1.19 * fix: update build tags to Go 1.18 syntax ``` ~> go1.18.10 fix ./... ``` * Replace calls to deprecated io/ioutil pkg * fix(deps): update module github.com/spf13/viper to v1.15.0 This change bumps spf13/viper to address reported vulnerabilities in yaml.v2 ``` ~> govulncheck -test ./... Scanning your code and 210 packages across 21 dependent modules for known vulnerabilities... Vulnerability #1: GO-2022-0956 Excessive resource consumption in gopkg.in/yaml.v2 More info: https://pkg.go.dev/vuln/GO-2022-0956 Module: gopkg.in/yaml.v2 Found in: gopkg.in/yaml.v2@v2.0.0-20170721122051-25c4ec802a7d Fixed in: gopkg.in/yaml.v2@v2.2.4 Example traces found: #1: cmd/submit.go:129:23: cmd.getExerciseSolutionFiles calls viper.Viper.ReadInConfig, which eventually calls yaml.Unmarshal Vulnerability #2: GO-2021-0061 Denial of service in gopkg.in/yaml.v2 More info: https://pkg.go.dev/vuln/GO-2021-0061 Module: gopkg.in/yaml.v2 Found in: gopkg.in/yaml.v2@v2.0.0-20170721122051-25c4ec802a7d Fixed in: gopkg.in/yaml.v2@v2.2.3 Example traces found: #1: cmd/submit.go:129:23: cmd.getExerciseSolutionFiles calls viper.Viper.ReadInConfig, which eventually calls yaml.Unmarshal Vulnerability #3: GO-2020-0036 Excessive resource consumption in YAML parsing in gopkg.in/yaml.v2 More info: https://pkg.go.dev/vuln/GO-2020-0036 Module: gopkg.in/yaml.v2 Found in: gopkg.in/yaml.v2@v2.0.0-20170721122051-25c4ec802a7d Fixed in: gopkg.in/yaml.v2@v2.2.8 Example traces found: #1: cmd/submit.go:129:23: cmd.getExerciseSolutionFiles calls viper.Viper.ReadInConfig, which eventually calls yaml.Unmarshal ``` * deps: update module github.com/spf13/cobra to v1.7.0 * deps: update module github.com/stretchr/testify to v1.8.4 * workflows/ci.yml: Add multiple Go versions to testing matrix This change officially removes Go 1.15 from the testing matrix and adds the Go versions used for supporting the Exercism CLI. Namely Go 1.19, 1.20, and 1.21.x. * Bump minimum Go version to 1.20 * Bump Go tooling to use 1.20.x for release and testing. ``` Scanning your code and 207 packages across 19 dependent modules for known vulnerabilities... Vulnerability #1: GO-2023-2043 Improper handling of special tags within script contexts in html/template More info: https://pkg.go.dev/vuln/GO-2023-2043 Standard library Found in: html/template@go1.19.8 Fixed in: html/template@go1.21.1 Example traces found: #1: cmd/troubleshoot.go:127:20: cmd.Status.compile calls template.Template.Execute Vulnerability #2: GO-2023-2041 Improper handling of HTML-like comments in script contexts in html/template More info: https://pkg.go.dev/vuln/GO-2023-2041 Standard library Found in: html/template@go1.19.8 Fixed in: html/template@go1.21.1 Example traces found: #1: cmd/troubleshoot.go:127:20: cmd.Status.compile calls template.Template.Execute Vulnerability #3: GO-2023-1987 Large RSA keys can cause high CPU usage in crypto/tls More info: https://pkg.go.dev/vuln/GO-2023-1987 Standard library Found in: crypto/tls@go1.19.8 Fixed in: crypto/tls@go1.21rc4 Example traces found: #1: api/client.go:68:25: api.Client.Do calls http.Client.Do, which eventually calls tls.Conn.HandshakeContext #2: cli/cli.go:199:23: cli.extractBinary calls io.Copy, which eventually calls tls.Conn.Read #3: debug/debug.go:32:14: debug.Printf calls fmt.Fprintf, which calls tls.Conn.Write #4: api/client.go:68:25: api.Client.Do calls http.Client.Do, which eventually calls tls.Dialer.DialContext Vulnerability #4: GO-2023-1878 Insufficient sanitization of Host header in net/http More info: https://pkg.go.dev/vuln/GO-2023-1878 Standard library Found in: net/http@go1.19.8 Fixed in: net/http@go1.20.6 Example traces found: #1: api/client.go:68:25: api.Client.Do calls http.Client.Do #2: cmd/troubleshoot.go:206:32: cmd.apiPing.Call calls http.Client.Get Vulnerability #5: GO-2023-1840 Unsafe behavior in setuid/setgid binaries in runtime More info: https://pkg.go.dev/vuln/GO-2023-1840 Standard library Found in: runtime@go1.19.8 Fixed in: runtime@go1.20.5 Example traces found: #1: debug/debug.go:80:12: debug.DumpResponse calls log.Fatal, which eventually calls runtime.Caller #2: workspace/exercise_metadata.go:39:26: workspace.NewExerciseMetadata calls json.Unmarshal, which eventually calls runtime.Callers #3: workspace/exercise_metadata.go:39:26: workspace.NewExerciseMetadata calls json.Unmarshal, which eventually calls runtime.CallersFrames #4: workspace/exercise_metadata.go:39:26: workspace.NewExerciseMetadata calls json.Unmarshal, which eventually calls runtime.Frames.Next #5: cmd/root.go:39:27: cmd.Execute calls cobra.Command.Execute, which eventually calls runtime.GC #6: workspace/exercise_metadata.go:66:24: workspace.ExerciseMetadata.Write calls json.Marshal, which eventually calls runtime.GOMAXPROCS #7: config/config.go:57:18: config.Dir calls os.Getenv, which eventually calls runtime.GOROOT #8: cli/cli.go:202:29: cli.extractBinary calls os.File.Seek, which eventually calls runtime.KeepAlive #9: cli/cli.go:135:2: cli.CLI.Upgrade calls os.File.Close, which eventually calls runtime.SetFinalizer #10: debug/debug.go:32:14: debug.Printf calls fmt.Fprintf, which eventually calls runtime.Stack #11: cmd/root.go:39:27: cmd.Execute calls cobra.Command.Execute, which eventually calls runtime.TypeAssertionError.Error #12: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which calls runtime.defaultMemProfileRate #13: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which calls runtime.efaceOf #14: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which eventually calls runtime.findfunc #15: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which calls runtime.float64frombits #16: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which eventually calls runtime.forcegchelper #17: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which eventually calls runtime.funcMaxSPDelta #18: cmd/root.go:39:27: cmd.Execute calls cobra.Command.Execute, which eventually calls runtime.plainError.Error #19: workspace/test_configurations.go:5:2: workspace.init calls runtime.init, which eventually calls runtime.throw Vulnerability #6: GO-2023-1753 Improper handling of empty HTML attributes in html/template More info: https://pkg.go.dev/vuln/GO-2023-1753 Standard library Found in: html/template@go1.19.8 Fixed in: html/template@go1.20.4 Example traces found: #1: cmd/troubleshoot.go:127:20: cmd.Status.compile calls template.Template.Execute Vulnerability #7: GO-2023-1752 Improper handling of JavaScript whitespace in html/template More info: https://pkg.go.dev/vuln/GO-2023-1752 Standard library Found in: html/template@go1.19.8 Fixed in: html/template@go1.20.4 Example traces found: #1: cmd/troubleshoot.go:127:20: cmd.Status.compile calls template.Template.Execute Vulnerability #8: GO-2023-1751 Improper sanitization of CSS values in html/template More info: https://pkg.go.dev/vuln/GO-2023-1751 Standard library Found in: html/template@go1.19.8 Fixed in: html/template@go1.20.4 Example traces found: #1: cmd/troubleshoot.go:127:20: cmd.Status.compile calls template.Template.Execute ``` --- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 2 +- CONTRIBUTING.md | 2 +- api/api.go | 4 +- cli/asset.go | 4 +- cli/cli.go | 8 +- cmd/cmd_test.go | 7 +- cmd/configure_test.go | 8 +- cmd/download.go | 5 +- cmd/download_test.go | 13 +- cmd/submit_symlink_test.go | 8 +- cmd/submit_test.go | 90 ++--- config/config_notwin_test.go | 1 - config/config_windows_test.go | 1 - config/resolve_notwin_test.go | 1 - debug/debug.go | 9 +- go.mod | 47 +-- go.sum | 524 +++++++++++++++++++++++++-- workspace/document_test.go | 5 +- workspace/exercise_config.go | 4 +- workspace/exercise_config_test.go | 9 +- workspace/exercise_metadata.go | 5 +- workspace/exercise_metadata_test.go | 3 +- workspace/exercise_test.go | 23 +- workspace/path_type_symlinks_test.go | 1 - workspace/workspace.go | 7 +- workspace/workspace_darwin_test.go | 3 +- workspace/workspace_test.go | 7 +- 28 files changed, 620 insertions(+), 185 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 511b27234..704eabdf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,9 @@ jobs: strategy: fail-fast: false matrix: - go-version: ["1.15"] + go-version: + - '1.20.x' + - '1.21.x' os: [ubuntu-latest, windows-latest, macOS-latest] steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c827639a..06175aa06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,7 +22,7 @@ jobs: - name: Set up Go uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 with: - go-version: '1.19' + go-version: '1.20.x' - name: Import GPG Key id: import_gpg diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1936a39eb..1515a4fcb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Exercism would be impossible without people like you being willing to spend time ## Dependencies -You'll need Go version 1.11 or higher. Follow the directions on http://golang.org/doc/install +You'll need Go version 1.20 or higher. Follow the directions on http://golang.org/doc/install ## Development diff --git a/api/api.go b/api/api.go index 342ce4230..25b5e9d14 100644 --- a/api/api.go +++ b/api/api.go @@ -2,7 +2,7 @@ package api import ( "bytes" - "io/ioutil" + "os" "golang.org/x/net/html/charset" "golang.org/x/text/transform" @@ -17,7 +17,7 @@ var ( ) func readFileAsUTF8String(filename string) (*string, error) { - b, err := ioutil.ReadFile(filename) + b, err := os.ReadFile(filename) if err != nil { return nil, err } diff --git a/cli/asset.go b/cli/asset.go index 246895faa..10bbab051 100644 --- a/cli/asset.go +++ b/cli/asset.go @@ -3,7 +3,7 @@ package cli import ( "bytes" "fmt" - "io/ioutil" + "io" "net/http" ) @@ -28,7 +28,7 @@ func (a *Asset) download() (*bytes.Reader, error) { } defer res.Body.Close() - bs, err := ioutil.ReadAll(res.Body) + bs, err := io.ReadAll(res.Body) if err != nil { return nil, err } diff --git a/cli/cli.go b/cli/cli.go index 4312eb018..fe113ec5b 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -8,8 +8,8 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" + "os" "runtime" "strings" "time" @@ -161,8 +161,8 @@ func (c *CLI) fetchLatestRelease() error { return nil } -func extractBinary(source *bytes.Reader, os string) (binary io.ReadCloser, err error) { - if os == "windows" { +func extractBinary(source *bytes.Reader, platform string) (binary io.ReadCloser, err error) { + if platform == "windows" { zr, err := zip.NewReader(source, int64(source.Len())) if err != nil { return nil, err @@ -191,7 +191,7 @@ func extractBinary(source *bytes.Reader, os string) (binary io.ReadCloser, err e if err != nil { return nil, err } - tmpfile, err := ioutil.TempFile("", "temp-exercism") + tmpfile, err := os.CreateTemp("", "temp-exercism") if err != nil { return nil, err } diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index fee08cd98..782be18d2 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -2,7 +2,6 @@ package cmd import ( "io" - "io/ioutil" "os" "testing" @@ -63,7 +62,7 @@ type CommandTest struct { // The method takes a *testing.T as an argument, that way the method can // fail the test if the creation of the temporary directory fails. func (test *CommandTest) Setup(t *testing.T) { - dir, err := ioutil.TempDir("", "command-test") + dir, err := os.MkdirTemp("", "command-test") defer os.RemoveAll(dir) assert.NoError(t, err) @@ -104,8 +103,8 @@ func newCapturedOutput() capturedOutput { return capturedOutput{ oldOut: Out, oldErr: Err, - newOut: ioutil.Discard, - newErr: ioutil.Discard, + newOut: io.Discard, + newErr: io.Discard, } } diff --git a/cmd/configure_test.go b/cmd/configure_test.go index 7a0f28eac..df3542328 100644 --- a/cmd/configure_test.go +++ b/cmd/configure_test.go @@ -1,11 +1,9 @@ //go:build !windows -// +build !windows package cmd import ( "bytes" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -344,7 +342,7 @@ func TestConfigureDefaultWorkspaceWithoutClobbering(t *testing.T) { ts := httptest.NewServer(endpoint) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "no-clobber") + tmpDir, err := os.MkdirTemp("", "no-clobber") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -379,7 +377,7 @@ func TestConfigureExplicitWorkspaceWithoutClobberingNonDirectory(t *testing.T) { co.override() defer co.reset() - tmpDir, err := ioutil.TempDir("", "no-clobber") + tmpDir, err := os.MkdirTemp("", "no-clobber") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -396,7 +394,7 @@ func TestConfigureExplicitWorkspaceWithoutClobberingNonDirectory(t *testing.T) { } // Create a file at the workspace directory's location - err = ioutil.WriteFile(filepath.Join(tmpDir, "workspace"), []byte("This is not a directory"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(tmpDir, "workspace"), []byte("This is not a directory"), os.FileMode(0755)) assert.NoError(t, err) flags := pflag.NewFlagSet("fake", pflag.PanicOnError) diff --git a/cmd/download.go b/cmd/download.go index 7bf278bff..f376e959b 100644 --- a/cmd/download.go +++ b/cmd/download.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net/http" netURL "net/url" "os" @@ -202,8 +201,8 @@ func newDownload(flags *pflag.FlagSet, usrCfg *viper.Viper) (*download, error) { return nil, decodedAPIError(res) } - body, _ := ioutil.ReadAll(res.Body) - res.Body = ioutil.NopCloser(bytes.NewReader(body)) + body, _ := io.ReadAll(res.Body) + res.Body = io.NopCloser(bytes.NewReader(body)) if err := json.Unmarshal(body, &d.payload); err != nil { return nil, decodedAPIError(res) diff --git a/cmd/download_test.go b/cmd/download_test.go index 676d90518..d95729719 100644 --- a/cmd/download_test.go +++ b/cmd/download_test.go @@ -3,7 +3,6 @@ package cmd import ( "encoding/json" "fmt" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -169,7 +168,7 @@ func TestDownload(t *testing.T) { } for _, tc := range testCases { - tmpDir, err := ioutil.TempDir("", "download-cmd") + tmpDir, err := os.MkdirTemp("", "download-cmd") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -197,7 +196,7 @@ func TestDownload(t *testing.T) { assertDownloadedCorrectFiles(t, targetDir) dir := filepath.Join(targetDir, "bogus-track", "bogus-exercise") - b, err := ioutil.ReadFile(workspace.NewExerciseFromDir(dir).MetadataFilepath()) + b, err := os.ReadFile(workspace.NewExerciseFromDir(dir).MetadataFilepath()) assert.NoError(t, err) var metadata workspace.ExerciseMetadata err = json.Unmarshal(b, &metadata) @@ -229,7 +228,7 @@ func TestDownloadToExistingDirectory(t *testing.T) { } for _, tc := range testCases { - tmpDir, err := ioutil.TempDir("", "download-cmd") + tmpDir, err := os.MkdirTemp("", "download-cmd") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -281,7 +280,7 @@ func TestDownloadToExistingDirectoryWithForce(t *testing.T) { } for _, tc := range testCases { - tmpDir, err := ioutil.TempDir("", "download-cmd") + tmpDir, err := os.MkdirTemp("", "download-cmd") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -363,7 +362,7 @@ func assertDownloadedCorrectFiles(t *testing.T, targetDir string) { for _, file := range expectedFiles { t.Run(file.desc, func(t *testing.T) { - b, err := ioutil.ReadFile(file.path) + b, err := os.ReadFile(file.path) assert.NoError(t, err) assert.Equal(t, file.contents, string(b)) }) @@ -383,7 +382,7 @@ func TestDownloadError(t *testing.T) { ts := httptest.NewServer(handler) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-err-tmp-dir") + tmpDir, err := os.MkdirTemp("", "submit-err-tmp-dir") defer os.RemoveAll(tmpDir) assert.NoError(t, err) diff --git a/cmd/submit_symlink_test.go b/cmd/submit_symlink_test.go index e10fb4890..093895fb3 100644 --- a/cmd/submit_symlink_test.go +++ b/cmd/submit_symlink_test.go @@ -1,10 +1,8 @@ //go:build !windows -// +build !windows package cmd import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -25,12 +23,12 @@ func TestSubmitFilesInSymlinkedPath(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "symlink-destination") + tmpDir, err := os.MkdirTemp("", "symlink-destination") defer os.RemoveAll(tmpDir) assert.NoError(t, err) dstDir := filepath.Join(tmpDir, "workspace") - srcDir, err := ioutil.TempDir("", "symlink-source") + srcDir, err := os.MkdirTemp("", "symlink-source") defer os.RemoveAll(srcDir) assert.NoError(t, err) @@ -53,7 +51,7 @@ func TestSubmitFilesInSymlinkedPath(t *testing.T) { } file := filepath.Join(dir, "file.txt") - err = ioutil.WriteFile(filepath.Join(dir, "file.txt"), []byte("This is a file."), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(dir, "file.txt"), []byte("This is a file."), os.FileMode(0755)) assert.NoError(t, err) err = runSubmit(cfg, pflag.NewFlagSet("symlinks", pflag.PanicOnError), []string{file}) diff --git a/cmd/submit_test.go b/cmd/submit_test.go index ea16b6543..2a12d0bca 100644 --- a/cmd/submit_test.go +++ b/cmd/submit_test.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" + "io" "mime" "net/http" "net/http/httptest" @@ -49,7 +49,7 @@ func TestSubmitWithoutWorkspace(t *testing.T) { } func TestSubmitNonExistentFile(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "submit-no-such-file") + tmpDir, err := os.MkdirTemp("", "submit-no-such-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -64,10 +64,10 @@ func TestSubmitNonExistentFile(t *testing.T) { DefaultBaseURL: "http://example.com", } - err = ioutil.WriteFile(filepath.Join(tmpDir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(tmpDir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(filepath.Join(tmpDir, "file-2.txt"), []byte("This is file 2"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(tmpDir, "file-2.txt"), []byte("This is file 2"), os.FileMode(0755)) assert.NoError(t, err) files := []string{ filepath.Join(tmpDir, "file-1.txt"), @@ -81,7 +81,7 @@ func TestSubmitNonExistentFile(t *testing.T) { } func TestSubmitExerciseWithoutMetadataFile(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "no-metadata-file") + tmpDir, err := os.MkdirTemp("", "no-metadata-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -89,7 +89,7 @@ func TestSubmitExerciseWithoutMetadataFile(t *testing.T) { os.MkdirAll(dir, os.FileMode(0755)) file := filepath.Join(dir, "file.txt") - err = ioutil.WriteFile(file, []byte("This is a file."), os.FileMode(0755)) + err = os.WriteFile(file, []byte("This is a file."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() @@ -111,7 +111,7 @@ func TestSubmitExerciseWithoutMetadataFile(t *testing.T) { func TestGetExerciseSolutionFiles(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "dir-with-no-metadata") + tmpDir, err := os.MkdirTemp("", "dir-with-no-metadata") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -120,7 +120,7 @@ func TestGetExerciseSolutionFiles(t *testing.T) { assert.Regexp(t, "no files to submit", err.Error()) } - validTmpDir, err := ioutil.TempDir("", "dir-with-valid-metadata") + validTmpDir, err := os.MkdirTemp("", "dir-with-valid-metadata") defer os.RemoveAll(validTmpDir) assert.NoError(t, err) @@ -128,7 +128,7 @@ func TestGetExerciseSolutionFiles(t *testing.T) { err = os.MkdirAll(metadataDir, os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile( + err = os.WriteFile( filepath.Join(metadataDir, "config.json"), []byte(` { @@ -149,7 +149,7 @@ func TestGetExerciseSolutionFiles(t *testing.T) { } func TestSubmitFilesAndDir(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "submit-no-such-file") + tmpDir, err := os.MkdirTemp("", "submit-no-such-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -164,10 +164,10 @@ func TestSubmitFilesAndDir(t *testing.T) { DefaultBaseURL: "http://example.com", } - err = ioutil.WriteFile(filepath.Join(tmpDir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(tmpDir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(filepath.Join(tmpDir, "file-2.txt"), []byte("This is file 2"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(tmpDir, "file-2.txt"), []byte("This is file 2"), os.FileMode(0755)) assert.NoError(t, err) files := []string{ filepath.Join(tmpDir, "file-1.txt"), @@ -192,7 +192,7 @@ func TestDuplicateFiles(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "duplicate-files") + tmpDir, err := os.MkdirTemp("", "duplicate-files") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -212,7 +212,7 @@ func TestDuplicateFiles(t *testing.T) { } file1 := filepath.Join(dir, "file-1.txt") - err = ioutil.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) + err = os.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) err = runSubmit(cfg, pflag.NewFlagSet("fake", pflag.PanicOnError), []string{file1, file1}) assert.NoError(t, err) @@ -232,7 +232,7 @@ func TestSubmitFiles(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-files") + tmpDir, err := os.MkdirTemp("", "submit-files") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -241,16 +241,16 @@ func TestSubmitFiles(t *testing.T) { writeFakeMetadata(t, dir, "bogus-track", "bogus-exercise") file1 := filepath.Join(dir, "file-1.txt") - err = ioutil.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) + err = os.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) assert.NoError(t, err) file2 := filepath.Join(dir, "subdir", "file-2.txt") - err = ioutil.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) + err = os.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) assert.NoError(t, err) // We don't filter *.md files if you explicitly pass the file path. readme := filepath.Join(dir, "README.md") - err = ioutil.WriteFile(readme, []byte("This is the readme."), os.FileMode(0755)) + err = os.WriteFile(readme, []byte("This is the readme."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() @@ -289,7 +289,7 @@ func TestLegacyMetadataMigration(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "legacy-metadata-file") + tmpDir, err := os.MkdirTemp("", "legacy-metadata-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -306,11 +306,11 @@ func TestLegacyMetadataMigration(t *testing.T) { b, err := json.Marshal(metadata) assert.NoError(t, err) exercise := workspace.NewExerciseFromDir(dir) - err = ioutil.WriteFile(exercise.LegacyMetadataFilepath(), b, os.FileMode(0600)) + err = os.WriteFile(exercise.LegacyMetadataFilepath(), b, os.FileMode(0600)) assert.NoError(t, err) file := filepath.Join(dir, "file.txt") - err = ioutil.WriteFile(file, []byte("This is a file."), os.FileMode(0755)) + err = os.WriteFile(file, []byte("This is a file."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() @@ -352,7 +352,7 @@ func TestSubmitWithEmptyFile(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "empty-file") + tmpDir, err := os.MkdirTemp("", "empty-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -372,9 +372,9 @@ func TestSubmitWithEmptyFile(t *testing.T) { } file1 := filepath.Join(dir, "file-1.txt") - err = ioutil.WriteFile(file1, []byte(""), os.FileMode(0755)) + err = os.WriteFile(file1, []byte(""), os.FileMode(0755)) file2 := filepath.Join(dir, "file-2.txt") - err = ioutil.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) + err = os.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) err = runSubmit(cfg, pflag.NewFlagSet("fake", pflag.PanicOnError), []string{file1, file2}) assert.NoError(t, err) @@ -393,7 +393,7 @@ func TestSubmitWithEnormousFile(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "enormous-file") + tmpDir, err := os.MkdirTemp("", "enormous-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -413,7 +413,7 @@ func TestSubmitWithEnormousFile(t *testing.T) { } file := filepath.Join(dir, "file.txt") - err = ioutil.WriteFile(file, make([]byte, 65535), os.FileMode(0755)) + err = os.WriteFile(file, make([]byte, 65535), os.FileMode(0755)) if err != nil { t.Fatal(err) } @@ -435,7 +435,7 @@ func TestSubmitFilesForTeamExercise(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-files") + tmpDir, err := os.MkdirTemp("", "submit-files") assert.NoError(t, err) dir := filepath.Join(tmpDir, "teams", "bogus-team", "bogus-track", "bogus-exercise") @@ -443,11 +443,11 @@ func TestSubmitFilesForTeamExercise(t *testing.T) { writeFakeMetadata(t, dir, "bogus-track", "bogus-exercise") file1 := filepath.Join(dir, "file-1.txt") - err = ioutil.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) + err = os.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) assert.NoError(t, err) file2 := filepath.Join(dir, "subdir", "file-2.txt") - err = ioutil.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) + err = os.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() @@ -477,7 +477,7 @@ func TestSubmitOnlyEmptyFile(t *testing.T) { co.override() defer co.reset() - tmpDir, err := ioutil.TempDir("", "just-an-empty-file") + tmpDir, err := os.MkdirTemp("", "just-an-empty-file") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -497,7 +497,7 @@ func TestSubmitOnlyEmptyFile(t *testing.T) { } file := filepath.Join(dir, "file.txt") - err = ioutil.WriteFile(file, []byte(""), os.FileMode(0755)) + err = os.WriteFile(file, []byte(""), os.FileMode(0755)) err = runSubmit(cfg, pflag.NewFlagSet("fake", pflag.PanicOnError), []string{file}) if assert.Error(t, err) { @@ -506,7 +506,7 @@ func TestSubmitOnlyEmptyFile(t *testing.T) { } func TestSubmitFilesFromDifferentSolutions(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "dir-1-submit") + tmpDir, err := os.MkdirTemp("", "dir-1-submit") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -519,11 +519,11 @@ func TestSubmitFilesFromDifferentSolutions(t *testing.T) { writeFakeMetadata(t, dir2, "bogus-track", "bogus-exercise-2") file1 := filepath.Join(dir1, "file-1.txt") - err = ioutil.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) + err = os.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) assert.NoError(t, err) file2 := filepath.Join(dir2, "file-2.txt") - err = ioutil.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) + err = os.WriteFile(file2, []byte("This is file 2."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() @@ -558,7 +558,7 @@ func fakeSubmitServer(t *testing.T, submittedFiles map[string]string) *httptest. t.Fatal(err) } defer file.Close() - body, err := ioutil.ReadAll(file) + body, err := io.ReadAll(file) if err != nil { t.Fatal(err) } @@ -589,7 +589,7 @@ func TestSubmitRelativePath(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "relative-path") + tmpDir, err := os.MkdirTemp("", "relative-path") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -608,7 +608,7 @@ func TestSubmitRelativePath(t *testing.T) { UserViperConfig: v, } - err = ioutil.WriteFile(filepath.Join(dir, "file.txt"), []byte("This is a file."), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(dir, "file.txt"), []byte("This is a file."), os.FileMode(0755)) err = os.Chdir(dir) assert.NoError(t, err) @@ -629,7 +629,7 @@ func TestSubmitServerErr(t *testing.T) { ts := httptest.NewServer(handler) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-err-tmp-dir") + tmpDir, err := os.MkdirTemp("", "submit-err-tmp-dir") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -648,7 +648,7 @@ func TestSubmitServerErr(t *testing.T) { os.MkdirAll(filepath.Join(dir, "subdir"), os.FileMode(0755)) writeFakeMetadata(t, dir, "bogus-track", "bogus-exercise") - err = ioutil.WriteFile(filepath.Join(dir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(dir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) assert.NoError(t, err) files := []string{ @@ -668,7 +668,7 @@ func TestHandleErrorResponse(t *testing.T) { ts := httptest.NewServer(handler) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-nonsuccess") + tmpDir, err := os.MkdirTemp("", "submit-nonsuccess") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -687,7 +687,7 @@ func TestHandleErrorResponse(t *testing.T) { os.MkdirAll(filepath.Join(dir, "subdir"), os.FileMode(0755)) writeFakeMetadata(t, dir, "bogus-track", "bogus-exercise") - err = ioutil.WriteFile(filepath.Join(dir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) + err = os.WriteFile(filepath.Join(dir, "file-1.txt"), []byte("This is file 1"), os.FileMode(0755)) assert.NoError(t, err) files := []string{ @@ -703,7 +703,7 @@ func TestSubmissionNotConnectedToRequesterAccount(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-files") + tmpDir, err := os.MkdirTemp("", "submit-files") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -721,7 +721,7 @@ func TestSubmissionNotConnectedToRequesterAccount(t *testing.T) { assert.NoError(t, err) file1 := filepath.Join(dir, "file-1.txt") - err = ioutil.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) + err = os.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() @@ -746,7 +746,7 @@ func TestExerciseDirnameMatchesMetadataSlug(t *testing.T) { ts := fakeSubmitServer(t, submittedFiles) defer ts.Close() - tmpDir, err := ioutil.TempDir("", "submit-files") + tmpDir, err := os.MkdirTemp("", "submit-files") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -755,7 +755,7 @@ func TestExerciseDirnameMatchesMetadataSlug(t *testing.T) { writeFakeMetadata(t, dir, "bogus-track", "bogus-exercise") file1 := filepath.Join(dir, "file-1.txt") - err = ioutil.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) + err = os.WriteFile(file1, []byte("This is file 1."), os.FileMode(0755)) assert.NoError(t, err) v := viper.New() diff --git a/config/config_notwin_test.go b/config/config_notwin_test.go index 31ddf77f0..33912cc9b 100644 --- a/config/config_notwin_test.go +++ b/config/config_notwin_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package config diff --git a/config/config_windows_test.go b/config/config_windows_test.go index da676739f..5757b783f 100644 --- a/config/config_windows_test.go +++ b/config/config_windows_test.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package config diff --git a/config/resolve_notwin_test.go b/config/resolve_notwin_test.go index eea7ae440..fb70d5f69 100644 --- a/config/resolve_notwin_test.go +++ b/config/resolve_notwin_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package config diff --git a/debug/debug.go b/debug/debug.go index 133681439..a96d1f3bd 100644 --- a/debug/debug.go +++ b/debug/debug.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "log" "net/http" "net/http/httputil" @@ -42,7 +41,7 @@ func DumpRequest(req *http.Request) { var bodyCopy bytes.Buffer body := io.TeeReader(req.Body, &bodyCopy) - req.Body = ioutil.NopCloser(body) + req.Body = io.NopCloser(body) authHeader := req.Header.Get("Authorization") @@ -63,7 +62,7 @@ func DumpRequest(req *http.Request) { Println("") req.Header.Set("Authorization", authHeader) - req.Body = ioutil.NopCloser(&bodyCopy) + req.Body = io.NopCloser(&bodyCopy) } // DumpResponse dumps out the provided http.Response @@ -74,7 +73,7 @@ func DumpResponse(res *http.Response) { var bodyCopy bytes.Buffer body := io.TeeReader(res.Body, &bodyCopy) - res.Body = ioutil.NopCloser(body) + res.Body = io.NopCloser(body) dump, err := httputil.DumpResponse(res, res.ContentLength > 0) if err != nil { @@ -86,7 +85,7 @@ func DumpResponse(res *http.Response) { Println("========================= END DumpResponse =========================") Println("") - res.Body = ioutil.NopCloser(body) + res.Body = io.NopCloser(body) } // Redact masks the given token by replacing part of the string with * diff --git a/go.mod b/go.mod index 91e79ff1a..c6a4a02a2 100644 --- a/go.mod +++ b/go.mod @@ -1,28 +1,33 @@ module github.com/exercism/cli -go 1.15 +go 1.20 require ( github.com/blang/semver v3.5.1+incompatible - github.com/davecgh/go-spew v1.1.0 - github.com/fsnotify/fsnotify v1.4.2 - github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf - github.com/inconshreveable/mousetrap v1.0.0 - github.com/magiconair/properties v1.7.3 - github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 - github.com/pelletier/go-buffruneio v0.2.0 - github.com/pelletier/go-toml v1.0.0 - github.com/pmezard/go-difflib v1.0.0 - github.com/spf13/afero v0.0.0-20170217164146-9be650865eab - github.com/spf13/cast v1.1.0 - github.com/spf13/cobra v0.0.0-20170731170427-b26b538f6930 - github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 - github.com/spf13/pflag v1.0.0 - github.com/spf13/viper v0.0.0-20180507071007-15738813a09d - github.com/stretchr/testify v1.1.4 - golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7 - golang.org/x/sys v0.0.0-20201202213521-69691e467435 - golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 - gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d + github.com/spf13/cobra v1.7.0 + github.com/spf13/pflag v1.0.5 + github.com/spf13/viper v1.15.0 + github.com/stretchr/testify v1.8.4 + golang.org/x/net v0.4.0 + golang.org/x/text v0.5.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // 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/spf13/afero v1.9.3 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/subosito/gotenv v1.4.2 // indirect + golang.org/x/sys v0.3.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 7d53fd399..bc3b4c47c 100644 --- a/go.sum +++ b/go.sum @@ -1,46 +1,492 @@ +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/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +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/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fsnotify/fsnotify v1.4.2 h1:v5tKwtf2hNhBV24eNYfQ5UmvFOGlOCmRqk7/P1olxtk= -github.com/fsnotify/fsnotify v1.4.2/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e h1:KJWs1uTCkN3E/J5ofCH9Pf8KKsibTFc3fv0CA9+WsVo= -github.com/hashicorp/hcl v0.0.0-20170509225359-392dba7d905e/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +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/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/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/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/magiconair/properties v1.7.3 h1:6AOjgCKyZFMG/1yfReDPDz3CJZPxnYk7DGmj2HtyF24= -github.com/magiconair/properties v1.7.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992 h1:W7VHAEVflA5/eTyRvQ53Lz5j8bhRd1myHZlI/IZFvbU= -github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= -github.com/pelletier/go-toml v1.0.0 h1:QFDlmAXZrfPXEF6c9+15fMqhQIS3O0pxszhnk936vg4= -github.com/pelletier/go-toml v1.0.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/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/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +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/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/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/spf13/afero v0.0.0-20170217164146-9be650865eab h1:IVAbBHQR8rXL2Fc8Zba/lMF7KOnTi70lqdx91UTuAwQ= -github.com/spf13/afero v0.0.0-20170217164146-9be650865eab/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.1.0 h1:0Rhw4d6C8J9VPu6cjZLIhZ8+aAOHcDvGeKn+cq5Aq3k= -github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/cobra v0.0.0-20170731170427-b26b538f6930 h1:uJND9FKkf5s8kdTQX1jDygtp/zV4BJQpYvOmXPCYWgc= -github.com/spf13/cobra v0.0.0-20170731170427-b26b538f6930/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046 h1:RpxSq53NruItMGgp6q5MsDYoZynisJgEpisQdWJ7PyM= -github.com/spf13/jwalterweatherman v0.0.0-20170523133247-0efa5202c046/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.0 h1:oaPbdDe/x0UncahuwiPxW1GYJyilRAdsPnq3e1yaPcI= -github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v0.0.0-20180507071007-15738813a09d h1:pIz+bbPLk78K39d3u77IlNpJvpS/f0ao8n3sdy82eCs= -github.com/spf13/viper v0.0.0-20180507071007-15738813a09d/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= -github.com/stretchr/testify v1.1.4 h1:ToftOQTytwshuOSj6bDSolVUa3GINfJP/fg3OkkOzQQ= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7 h1:1Pw+ZX4dmGORIwGkTwnUr7RFuMhfpCYHXRZNF04XPYs= -golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sys v0.0.0-20170803140359-d8f5ea21b929 h1:M4VPQYSW/nB4Bcg1XMD4yW2sprnwerD3Kb6apRphtZw= -golang.org/x/sys v0.0.0-20170803140359-d8f5ea21b929/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20170730040918-3bd178b88a81 h1:7aXI3TQ9sZ4JdDoIDGjxL6G2mQxlsPy9dySnJaL6Bdk= -golang.org/x/text v0.0.0-20170730040918-3bd178b88a81/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d h1:2DX7x6HUDGZUyuEDAhUsQQNqkb1zvDyKTjVoTdzaEzo= -gopkg.in/yaml.v2 v2.0.0-20170721122051-25c4ec802a7d/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +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.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +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.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +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/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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +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/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +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= +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.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= diff --git a/workspace/document_test.go b/workspace/document_test.go index 4e055df2f..50013ee73 100644 --- a/workspace/document_test.go +++ b/workspace/document_test.go @@ -1,7 +1,6 @@ package workspace import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -10,7 +9,7 @@ import ( ) func TestNormalizedDocumentPath(t *testing.T) { - root, err := ioutil.TempDir("", "docpath") + root, err := os.MkdirTemp("", "docpath") assert.NoError(t, err) defer os.RemoveAll(root) @@ -32,7 +31,7 @@ func TestNormalizedDocumentPath(t *testing.T) { } for _, tc := range testCases { - err = ioutil.WriteFile(tc.filepath, []byte("a file"), os.FileMode(0600)) + err = os.WriteFile(tc.filepath, []byte("a file"), os.FileMode(0600)) assert.NoError(t, err) doc, err := NewDocument(root, tc.filepath) diff --git a/workspace/exercise_config.go b/workspace/exercise_config.go index 9b0164ebb..35ae7545c 100644 --- a/workspace/exercise_config.go +++ b/workspace/exercise_config.go @@ -3,7 +3,7 @@ package workspace import ( "encoding/json" "errors" - "io/ioutil" + "os" "path/filepath" ) @@ -22,7 +22,7 @@ type ExerciseConfig struct { // NewExerciseConfig reads exercise metadata from a file in the given directory. func NewExerciseConfig(dir string) (*ExerciseConfig, error) { - b, err := ioutil.ReadFile(filepath.Join(dir, configFilepath)) + b, err := os.ReadFile(filepath.Join(dir, configFilepath)) if err != nil { return nil, err } diff --git a/workspace/exercise_config_test.go b/workspace/exercise_config_test.go index d07264c0d..5d9847453 100644 --- a/workspace/exercise_config_test.go +++ b/workspace/exercise_config_test.go @@ -1,7 +1,6 @@ package workspace import ( - "io/ioutil" "os" "path/filepath" "strings" @@ -11,7 +10,7 @@ import ( ) func TestExerciseConfig(t *testing.T) { - dir, err := ioutil.TempDir("", "exercise_config") + dir, err := os.MkdirTemp("", "exercise_config") assert.NoError(t, err) defer os.RemoveAll(dir) @@ -40,7 +39,7 @@ func TestExerciseConfig(t *testing.T) { } func TestExerciseConfigNoTestKey(t *testing.T) { - dir, err := ioutil.TempDir("", "exercise_config") + dir, err := os.MkdirTemp("", "exercise_config") assert.NoError(t, err) defer os.RemoveAll(dir) @@ -64,7 +63,7 @@ func TestExerciseConfigNoTestKey(t *testing.T) { } func TestMissingExerciseConfig(t *testing.T) { - dir, err := ioutil.TempDir("", "exercise_config") + dir, err := os.MkdirTemp("", "exercise_config") assert.NoError(t, err) defer os.RemoveAll(dir) @@ -77,7 +76,7 @@ func TestMissingExerciseConfig(t *testing.T) { } func TestInvalidExerciseConfig(t *testing.T) { - dir, err := ioutil.TempDir("", "exercise_config") + dir, err := os.MkdirTemp("", "exercise_config") assert.NoError(t, err) defer os.RemoveAll(dir) diff --git a/workspace/exercise_metadata.go b/workspace/exercise_metadata.go index 0a0305576..729174258 100644 --- a/workspace/exercise_metadata.go +++ b/workspace/exercise_metadata.go @@ -3,7 +3,6 @@ package workspace import ( "encoding/json" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -32,7 +31,7 @@ type ExerciseMetadata struct { // NewExerciseMetadata reads exercise metadata from a file in the given directory. func NewExerciseMetadata(dir string) (*ExerciseMetadata, error) { - b, err := ioutil.ReadFile(filepath.Join(dir, metadataFilepath)) + b, err := os.ReadFile(filepath.Join(dir, metadataFilepath)) if err != nil { return nil, err } @@ -72,7 +71,7 @@ func (em *ExerciseMetadata) Write(dir string) error { if err = os.MkdirAll(filepath.Dir(metadataAbsoluteFilepath), os.FileMode(0755)); err != nil { return err } - if err = ioutil.WriteFile(metadataAbsoluteFilepath, b, os.FileMode(0600)); err != nil { + if err = os.WriteFile(metadataAbsoluteFilepath, b, os.FileMode(0600)); err != nil { return err } em.Dir = dir diff --git a/workspace/exercise_metadata_test.go b/workspace/exercise_metadata_test.go index e05ffeac3..0c3c7afa7 100644 --- a/workspace/exercise_metadata_test.go +++ b/workspace/exercise_metadata_test.go @@ -1,7 +1,6 @@ package workspace import ( - "io/ioutil" "os" "testing" "time" @@ -10,7 +9,7 @@ import ( ) func TestExerciseMetadata(t *testing.T) { - dir, err := ioutil.TempDir("", "solution") + dir, err := os.MkdirTemp("", "solution") assert.NoError(t, err) defer os.RemoveAll(dir) diff --git a/workspace/exercise_test.go b/workspace/exercise_test.go index 0a6d1d8fa..7dd15c583 100644 --- a/workspace/exercise_test.go +++ b/workspace/exercise_test.go @@ -1,7 +1,6 @@ package workspace import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -10,7 +9,7 @@ import ( ) func TestHasMetadata(t *testing.T) { - ws, err := ioutil.TempDir("", "fake-workspace") + ws, err := os.MkdirTemp("", "fake-workspace") defer os.RemoveAll(ws) assert.NoError(t, err) @@ -22,7 +21,7 @@ func TestHasMetadata(t *testing.T) { err = os.MkdirAll(filepath.Dir(exerciseB.MetadataFilepath()), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(exerciseA.MetadataFilepath(), []byte{}, os.FileMode(0600)) + err = os.WriteFile(exerciseA.MetadataFilepath(), []byte{}, os.FileMode(0600)) assert.NoError(t, err) ok, err := exerciseA.HasMetadata() @@ -35,7 +34,7 @@ func TestHasMetadata(t *testing.T) { } func TestHasLegacyMetadata(t *testing.T) { - ws, err := ioutil.TempDir("", "fake-workspace") + ws, err := os.MkdirTemp("", "fake-workspace") defer os.RemoveAll(ws) assert.NoError(t, err) @@ -47,7 +46,7 @@ func TestHasLegacyMetadata(t *testing.T) { err = os.MkdirAll(filepath.Dir(exerciseB.LegacyMetadataFilepath()), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(exerciseA.LegacyMetadataFilepath(), []byte{}, os.FileMode(0600)) + err = os.WriteFile(exerciseA.LegacyMetadataFilepath(), []byte{}, os.FileMode(0600)) assert.NoError(t, err) ok, err := exerciseA.HasLegacyMetadata() @@ -76,7 +75,7 @@ func TestMigrationStatusString(t *testing.T) { } func TestMigrateLegacyMetadataFileWithoutLegacy(t *testing.T) { - ws, err := ioutil.TempDir("", "fake-workspace") + ws, err := os.MkdirTemp("", "fake-workspace") defer os.RemoveAll(ws) assert.NoError(t, err) @@ -85,7 +84,7 @@ func TestMigrateLegacyMetadataFileWithoutLegacy(t *testing.T) { err = os.MkdirAll(filepath.Dir(metadataFilepath), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(metadataFilepath, []byte{}, os.FileMode(0600)) + err = os.WriteFile(metadataFilepath, []byte{}, os.FileMode(0600)) assert.NoError(t, err) ok, _ := exercise.HasLegacyMetadata() @@ -104,7 +103,7 @@ func TestMigrateLegacyMetadataFileWithoutLegacy(t *testing.T) { } func TestMigrateLegacyMetadataFileWithLegacy(t *testing.T) { - ws, err := ioutil.TempDir("", "fake-workspace") + ws, err := os.MkdirTemp("", "fake-workspace") defer os.RemoveAll(ws) assert.NoError(t, err) @@ -113,7 +112,7 @@ func TestMigrateLegacyMetadataFileWithLegacy(t *testing.T) { err = os.MkdirAll(filepath.Dir(legacyMetadataFilepath), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(legacyMetadataFilepath, []byte{}, os.FileMode(0600)) + err = os.WriteFile(legacyMetadataFilepath, []byte{}, os.FileMode(0600)) assert.NoError(t, err) ok, _ := exercise.HasLegacyMetadata() @@ -132,7 +131,7 @@ func TestMigrateLegacyMetadataFileWithLegacy(t *testing.T) { } func TestMigrateLegacyMetadataFileWithLegacyAndModern(t *testing.T) { - ws, err := ioutil.TempDir("", "fake-workspace") + ws, err := os.MkdirTemp("", "fake-workspace") defer os.RemoveAll(ws) assert.NoError(t, err) @@ -144,9 +143,9 @@ func TestMigrateLegacyMetadataFileWithLegacyAndModern(t *testing.T) { err = os.MkdirAll(filepath.Dir(metadataFilepath), os.FileMode(0755)) assert.NoError(t, err) - err = ioutil.WriteFile(legacyMetadataFilepath, []byte{}, os.FileMode(0600)) + err = os.WriteFile(legacyMetadataFilepath, []byte{}, os.FileMode(0600)) assert.NoError(t, err) - err = ioutil.WriteFile(metadataFilepath, []byte{}, os.FileMode(0600)) + err = os.WriteFile(metadataFilepath, []byte{}, os.FileMode(0600)) assert.NoError(t, err) ok, _ := exercise.HasLegacyMetadata() diff --git a/workspace/path_type_symlinks_test.go b/workspace/path_type_symlinks_test.go index ace7b741d..a80b6171a 100644 --- a/workspace/path_type_symlinks_test.go +++ b/workspace/path_type_symlinks_test.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package workspace diff --git a/workspace/workspace.go b/workspace/workspace.go index eb9875e8a..0011d4be2 100644 --- a/workspace/workspace.go +++ b/workspace/workspace.go @@ -3,7 +3,6 @@ package workspace import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" @@ -46,7 +45,7 @@ func New(dir string) (Workspace, error) { func (ws Workspace) PotentialExercises() ([]Exercise, error) { exercises := []Exercise{} - topInfos, err := ioutil.ReadDir(ws.Dir) + topInfos, err := os.ReadDir(ws.Dir) if err != nil { return nil, err } @@ -60,7 +59,7 @@ func (ws Workspace) PotentialExercises() ([]Exercise, error) { } if topInfo.Name() == "teams" { - subInfos, err := ioutil.ReadDir(filepath.Join(ws.Dir, "teams")) + subInfos, err := os.ReadDir(filepath.Join(ws.Dir, "teams")) if err != nil { return nil, err } @@ -81,7 +80,7 @@ func (ws Workspace) PotentialExercises() ([]Exercise, error) { continue } - subInfos, err := ioutil.ReadDir(filepath.Join(ws.Dir, topInfo.Name())) + subInfos, err := os.ReadDir(filepath.Join(ws.Dir, topInfo.Name())) if err != nil { return nil, err } diff --git a/workspace/workspace_darwin_test.go b/workspace/workspace_darwin_test.go index 03794a795..47bcab7ec 100644 --- a/workspace/workspace_darwin_test.go +++ b/workspace/workspace_darwin_test.go @@ -2,11 +2,12 @@ package workspace import ( "fmt" - "github.com/stretchr/testify/assert" "path/filepath" "runtime" "strings" "testing" + + "github.com/stretchr/testify/assert" ) func TestExerciseDir_case_insensitive(t *testing.T) { diff --git a/workspace/workspace_test.go b/workspace/workspace_test.go index 160c7cd0e..63053a5cd 100644 --- a/workspace/workspace_test.go +++ b/workspace/workspace_test.go @@ -1,7 +1,6 @@ package workspace import ( - "io/ioutil" "os" "path/filepath" "runtime" @@ -12,7 +11,7 @@ import ( ) func TestWorkspacePotentialExercises(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "walk") + tmpDir, err := os.MkdirTemp("", "walk") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -54,7 +53,7 @@ func TestWorkspacePotentialExercises(t *testing.T) { } func TestWorkspaceExercises(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "walk-with-metadata") + tmpDir, err := os.MkdirTemp("", "walk-with-metadata") defer os.RemoveAll(tmpDir) assert.NoError(t, err) @@ -69,7 +68,7 @@ func TestWorkspaceExercises(t *testing.T) { assert.NoError(t, err) if path != a2 { - err = ioutil.WriteFile(metadataAbsoluteFilepath, []byte{}, os.FileMode(0600)) + err = os.WriteFile(metadataAbsoluteFilepath, []byte{}, os.FileMode(0600)) assert.NoError(t, err) } } From 6e178aa57dc37967e950fefae72c9d4120fb5213 Mon Sep 17 00:00:00 2001 From: baduker Date: Thu, 23 Nov 2023 14:12:40 +0100 Subject: [PATCH 24/41] Setup goreleaser to update homebrew (#1121) --- .goreleaser.yml | 16 ++++++++++++++-- RELEASE.md | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 8a5dccbd2..1fa59b225 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -120,5 +120,17 @@ release: # Default is `{{.Tag}}` name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}" -# brews: -# We do not use the brew config, which is for taps, not core forumulas. +brews: + - + name: exercism + repository: + owner: exercism + name: homebrew-exercism + commit_author: + name: Exercism Bot + email: 66069679+exercism-bot@users.noreply.github.com + folder: Formula + homepage: "https://exercism.org/" + description: "Command-line tool to interact with exercism.io" + test: | + system "exercism version" diff --git a/RELEASE.md b/RELEASE.md index 566db9f83..87155f4e8 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -40,9 +40,11 @@ goreleaser --skip-publish --snapshot --clean # Create a new tag on the main branch and push it git tag -a "${TAG_NAME}" -m "Trying out GoReleaser" git push origin "${TAG_NAME}" - -# [TODO] Push to homebrew ``` +Brew tap is now managed by `.goreleaser.yml` so no need to update it manually. +GoReleaser can generate and publish a homebrew-tap recipe into a repository +automatically. See [GoReleaser docs](https://goreleaser.com/customization/homebrew/) +for more details. ## Cut Release on GitHub From 90b4b86e8009a992bd1fa34d374418b07383e840 Mon Sep 17 00:00:00 2001 From: Tomas Norre Mikkelsen Date: Fri, 5 Jan 2024 10:44:59 +0100 Subject: [PATCH 25/41] Update FAQ link in Upgrade output (#1124) * Update FAQ link in Upgrade output * Update FAQ link in Upgrade output - update after feedback --- cmd/upgrade.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 4b78d4b6f..e4ec04508 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -32,7 +32,7 @@ We were not able to upgrade the cli because we encountered an error: Please check the FAQ for solutions to common upgrading issues. -https://exercism.io/faqs`, err) +https://exercism.org/faqs`, err) } return nil }, From 331bc718ba974f5f5aafedbc789c26b7533e0ae8 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 9 Jan 2024 14:45:14 +0100 Subject: [PATCH 26/41] Simplify the root command description (#1125) --- cmd/root.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/root.go b/cmd/root.go index 734c8d4b7..35d266356 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,7 +16,7 @@ import ( var RootCmd = &cobra.Command{ Use: BinaryName, Short: "A friendly command-line interface to Exercism.", - Long: `A command-line interface for the v3 redesign of Exercism. + Long: `A command-line interface for Exercism. Download exercises and submit your solutions.`, SilenceUsage: true, From 4950e3cc4a7a85f3cb8da3f005602e3f6c39824f Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Wed, 14 Feb 2024 09:10:34 -0500 Subject: [PATCH 27/41] test: update 8th and emacs-lisp test commands (#1128) --- workspace/test_configurations.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/workspace/test_configurations.go b/workspace/test_configurations.go index 32c6fbc3a..176729e1b 100644 --- a/workspace/test_configurations.go +++ b/workspace/test_configurations.go @@ -62,8 +62,7 @@ func (c *TestConfiguration) GetTestCommand() (string, error) { // some tracks aren't (or won't be) implemented; every track is listed either way var TestConfigurations = map[string]TestConfiguration{ "8th": { - Command: "bash tester.sh", - WindowsCommand: "tester.bat", + Command: "8th -f test.8th", }, // abap: tests are run via "ABAP Development Tools", not the CLI "awk": { @@ -117,7 +116,7 @@ var TestConfigurations = map[string]TestConfiguration{ Command: "elm-test", }, "emacs-lisp": { - Command: "emacs -batch -l ert -l *-test.el -f ert-run-tests-batch-and-exit", + Command: "emacs -batch -l ert -l {{test_files}} -f ert-run-tests-batch-and-exit", }, "erlang": { Command: "rebar3 eunit", From 32aeac6c28d426a5149145813d14a3085f84ad1f Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 15 Feb 2024 09:14:35 +0100 Subject: [PATCH 28/41] Bump version to v3.3.0 (#1129) --- CHANGELOG.md | 5 +++++ cmd/version.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1dcca2ff..9063d3e46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ The exercism CLI follows [semantic versioning](http://semver.org/). ## Next Release * **Your contribution here** +## v3.3.0 (2024-02-15) +* [#1128](https://github.com/exercism/cli/pull/1128) Fix `exercism test` command not working for the `8th` and `emacs-lisp` tracks - [@glennj] +* [#1125](https://github.com/exercism/cli/pull/1125) Simplify root command description +* [#1124](https://github.com/exercism/cli/pull/1124) Use correct domain for FAQ link [@tomasnorre] + ## v3.2.0 (2023-07-28) * [#1092](https://github.com/exercism/cli/pull/1092) Add `exercism test` command to run the unit tests for nearly any track (inspired by [universal-test-runner](https://github.com/xavdid/universal-test-runner)) - [@xavdid] * [#1073](https://github.com/exercism/cli/pull/1073) Add `arm64` build for each OS diff --git a/cmd/version.go b/cmd/version.go index d8e287f4a..c143cc403 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -9,7 +9,7 @@ import ( // Version is the version of the current build. // It follows semantic versioning. -const Version = "3.2.0" +const Version = "3.3.0" // checkLatest flag for version command. var checkLatest bool From 0a8f77b21f57905722cf182909a71ab6ab0b05f4 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 15 Feb 2024 09:52:50 +0100 Subject: [PATCH 29/41] Add fingerprint export --- RELEASE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASE.md b/RELEASE.md index 87155f4e8..bded12a2c 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -10,7 +10,7 @@ The Exercism CLI uses [GoReleaser](https://goreleaser.com) to automate the relea ## Confirm / Update the Changelog -Make sure all the recent changes are reflected in the "next release" section of the CHANGELOG.md file. +Make sure all the recent changes are reflected in the "next release" section of the CHANGELOG.md file. All the changes in the "next release" section should be moved to a new section that describes the version number, and gives it a date. You can view changes using the /compare/ view: @@ -33,6 +33,7 @@ Once the version bump PR has been merged, run the following commands: ```bash VERSION=$(sed -n -E 's/^const Version = "([0-9]+\.[0-9]+\.[0-9]+)"$/\1/p' cmd/version.go) TAG_NAME="v${VERSION}" +GPG_FINGERPRINT="" # Test run goreleaser --skip-publish --snapshot --clean @@ -41,6 +42,7 @@ goreleaser --skip-publish --snapshot --clean git tag -a "${TAG_NAME}" -m "Trying out GoReleaser" git push origin "${TAG_NAME}" ``` + Brew tap is now managed by `.goreleaser.yml` so no need to update it manually. GoReleaser can generate and publish a homebrew-tap recipe into a repository automatically. See [GoReleaser docs](https://goreleaser.com/customization/homebrew/) From d461855c5bb9a7d7dcce00e8abed53e4513d8288 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 15 Feb 2024 10:26:13 +0100 Subject: [PATCH 30/41] Format goreleaser.yml --- .goreleaser.yml | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 1fa59b225..16e221e4a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -6,11 +6,11 @@ env: builds: - id: release-build main: ./exercism/main.go - mod_timestamp: '{{ .CommitTimestamp }}' + mod_timestamp: "{{ .CommitTimestamp }}" flags: - -trimpath # removes file system paths from compiled executable ldflags: - - '-s -w' # strip debug symbols and DWARF debugging info + - "-s -w" # strip debug symbols and DWARF debugging info goos: - darwin - linux @@ -33,11 +33,11 @@ builds: goarch: arm - id: installer-build main: ./exercism/main.go - mod_timestamp: '{{ .CommitTimestamp }}' + mod_timestamp: "{{ .CommitTimestamp }}" flags: - -trimpath # removes file system paths from compiled executable ldflags: - - '-s -w' # strip debug symbols and DWARF debugging info + - "-s -w" # strip debug symbols and DWARF debugging info goos: - windows goarch: @@ -48,8 +48,8 @@ changelog: sort: asc filters: exclude: - - '^docs:' - - '^test:' + - "^docs:" + - "^test:" archives: - id: release-archives @@ -64,8 +64,8 @@ archives: {{- else }}{{- .Arch }}{{ end }} {{- if .Arm }}v{{- .Arm }}{{ end }} format_overrides: - - goos: windows - format: zip + - goos: windows + format: zip files: - shell/** - LICENSE @@ -82,22 +82,31 @@ archives: {{- else }}{{- .Arch }}{{ end }} {{- if .Arm }}v{{- .Arm }}{{ end }} format_overrides: - - goos: windows - format: zip + - goos: windows + format: zip files: - shell/** - LICENSE - README.md checksum: - name_template: '{{ .ProjectName }}_checksums.txt' + name_template: "{{ .ProjectName }}_checksums.txt" ids: - release-archives - installer-archives signs: - artifacts: checksum - args: ["--batch", "-u", "{{ .Env.GPG_FINGERPRINT }}", "--output", "${signature}", "--detach-sign", "${artifact}"] + args: + [ + "--batch", + "-u", + "{{ .Env.GPG_FINGERPRINT }}", + "--output", + "${signature}", + "--detach-sign", + "${artifact}", + ] release: # Repo in which the release will be created. @@ -121,8 +130,7 @@ release: name_template: "{{.ProjectName}}-v{{.Version}} {{.Env.USER}}" brews: - - - name: exercism + - name: exercism repository: owner: exercism name: homebrew-exercism From 8f1e8f296f7a08158a2f8138c810ddc95e39f279 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 15 Feb 2024 10:33:14 +0100 Subject: [PATCH 31/41] Fix homebrew repo name (#1130) --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 16e221e4a..f3f965002 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -133,7 +133,7 @@ brews: - name: exercism repository: owner: exercism - name: homebrew-exercism + name: homebrew-core commit_author: name: Exercism Bot email: 66069679+exercism-bot@users.noreply.github.com From 7677e4b17c910ce22d47b39d7eac66052e3dd89d Mon Sep 17 00:00:00 2001 From: Exercism Bot Date: Fri, 1 Mar 2024 14:05:57 +0000 Subject: [PATCH 32/41] =?UTF-8?q?=F0=9F=A4=96=20Sync=20org-wide=20files=20?= =?UTF-8?q?to=20upstream=20repo=20(#1134)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More info: https://github.com/exercism/org-wide-files/commit/0c0972d1df4cd18d98c7df316348315b06ef49b4 --- CODE_OF_CONDUCT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index df8e36761..3f7813de1 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -90,4 +90,4 @@ This policy was initially adopted from the Front-end London Slack community and A version history can be seen on [GitHub](https://github.com/exercism/website-copy/edit/main/pages/code_of_conduct.md). _This policy is a "living" document, and subject to refinement and expansion in the future. -This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Slack, Twitter, email) and any other Exercism entity or event._ +This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Discord, Forum, Twitter, email) and any other Exercism entity or event._ From c0825fd32b4beba5956b004761d8386635d06942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:12:37 +0100 Subject: [PATCH 33/41] Bump actions/checkout from 4.0.0 to 4.1.0 (#1116) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/3df4ab11eba7bda6032a0b82a6bb43b11571feac...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 704eabdf9..b4510d825 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe with: @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - name: Check formatting run: ./.gha.gofmt.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06175aa06..b7b3c3a47 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0 + uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0 with: fetch-depth: 0 From 38961a652c31b2213fbef766d4c74e58d6cf19e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 09:01:57 +0200 Subject: [PATCH 34/41] Bump golang.org/x/net from 0.4.0 to 0.23.0 (#1135) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.4.0 to 0.23.0. - [Commits](https://github.com/golang/net/compare/v0.4.0...v0.23.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index c6a4a02a2..e56c3f97a 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.8.4 - golang.org/x/net v0.4.0 - golang.org/x/text v0.5.0 + golang.org/x/net v0.23.0 + golang.org/x/text v0.14.0 ) require ( @@ -26,7 +26,7 @@ require ( github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect - golang.org/x/sys v0.3.0 // indirect + golang.org/x/sys v0.18.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 bc3b4c47c..c042354a7 100644 --- a/go.sum +++ b/go.sum @@ -260,8 +260,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY 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/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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= @@ -316,8 +316,8 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w 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/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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= @@ -325,8 +325,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 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/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 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= From 0b4ebdca31931e2198fa6ae7a25fad76db7a1af7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 09:09:24 +0200 Subject: [PATCH 35/41] Bump goreleaser/goreleaser-action from 4.4.0 to 5.0.0 (#1112) Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4.4.0 to 5.0.0. - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/3fa32b8bb5620a2c1afe798654bbad59f9da4906...7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8) --- updated-dependencies: - dependency-name: goreleaser/goreleaser-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b7b3c3a47..ef69cb37d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,7 @@ jobs: passphrase: ${{ secrets.PASSPHRASE }} - name: Cut Release - uses: goreleaser/goreleaser-action@3fa32b8bb5620a2c1afe798654bbad59f9da4906 # v4.4.0 + uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0 with: version: latest args: release --clean --release-header .release/header.md --timeout 120m # default time is 30m From e6aeb01305d4717feb98ecb74097862a3054499a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 09:09:31 +0200 Subject: [PATCH 36/41] Bump crazy-max/ghaction-import-gpg from 5.3.0 to 6.0.0 (#1111) Bumps [crazy-max/ghaction-import-gpg](https://github.com/crazy-max/ghaction-import-gpg) from 5.3.0 to 6.0.0. - [Release notes](https://github.com/crazy-max/ghaction-import-gpg/releases) - [Commits](https://github.com/crazy-max/ghaction-import-gpg/compare/72b6676b71ab476b77e676928516f6982eef7a41...82a020f1f7f605c65dd2449b392a52c3fcfef7ef) --- updated-dependencies: - dependency-name: crazy-max/ghaction-import-gpg dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef69cb37d..b74d61e58 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: - name: Import GPG Key id: import_gpg - uses: crazy-max/ghaction-import-gpg@72b6676b71ab476b77e676928516f6982eef7a41 # v5.3.0 + uses: crazy-max/ghaction-import-gpg@82a020f1f7f605c65dd2449b392a52c3fcfef7ef # v6.0.0 with: gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} passphrase: ${{ secrets.PASSPHRASE }} From d08e50e28f898c6b7a9a82e0c28206fcc5d4a074 Mon Sep 17 00:00:00 2001 From: Erivelton de Andrade Nascimento <85421753+eNascimento178@users.noreply.github.com> Date: Thu, 2 May 2024 03:25:37 -0300 Subject: [PATCH 37/41] Add support for j in test_configurations.go (#1136) * Add support for j in test_configurations.go * Exchange double quotes to backtick * Update test_configurations.go --- workspace/test_configurations.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/workspace/test_configurations.go b/workspace/test_configurations.go index 176729e1b..c6ac6fef8 100644 --- a/workspace/test_configurations.go +++ b/workspace/test_configurations.go @@ -139,6 +139,9 @@ var TestConfigurations = map[string]TestConfiguration{ "haskell": { Command: "stack test", }, + "j": { + Command: `jconsole -js "exit echo unittest {{test_files}} [ load {{solution_files}}"`, + }, "java": { Command: "gradle test", }, From 31bf0dc8a2f91516e201b363be2def059eb2477c Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Thu, 2 May 2024 02:35:18 -0400 Subject: [PATCH 38/41] Update homebrew formula description to use "exercism.org" (#1131) Co-authored-by: Erik Schierboom --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index f3f965002..149fbd8e5 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -139,6 +139,6 @@ brews: email: 66069679+exercism-bot@users.noreply.github.com folder: Formula homepage: "https://exercism.org/" - description: "Command-line tool to interact with exercism.io" + description: "Command-line tool to interact with exercism.org" test: | system "exercism version" From 6bbd4146a822cf2931b2087cc9cbcb2e8858ecc1 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 2 May 2024 09:22:39 +0200 Subject: [PATCH 39/41] Add scripts (#1138) * Add test build script * Add test script * Ignore test binary --- .gitignore | 1 + bin/build.sh | 3 +++ bin/format.sh | 3 +++ bin/test.sh | 3 +++ 4 files changed, 10 insertions(+) create mode 100755 bin/build.sh create mode 100755 bin/format.sh create mode 100755 bin/test.sh diff --git a/.gitignore b/.gitignore index 1f3baf919..c7963cd6f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ _testmain.go out/ release/ go-exercism +testercism # Intellij /.idea diff --git a/bin/build.sh b/bin/build.sh new file mode 100755 index 000000000..f2ed29c5d --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +go build -o testercism ./exercism/main.go diff --git a/bin/format.sh b/bin/format.sh new file mode 100755 index 000000000..25c19b2e3 --- /dev/null +++ b/bin/format.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +go fmt ./... diff --git a/bin/test.sh b/bin/test.sh new file mode 100755 index 000000000..062c46972 --- /dev/null +++ b/bin/test.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +go test ./... From 664afb7aa437c85ac9f927551d0718ef87d7bd6e Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Thu, 2 May 2024 09:25:09 +0200 Subject: [PATCH 40/41] Add pyret support to `exercism test` (#1139) --- workspace/test_configurations.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/workspace/test_configurations.go b/workspace/test_configurations.go index c6ac6fef8..ebf9cb4b7 100644 --- a/workspace/test_configurations.go +++ b/workspace/test_configurations.go @@ -191,6 +191,9 @@ var TestConfigurations = map[string]TestConfiguration{ "purescript": { Command: "spago test", }, + "pyret": { + Command: "pyret {{test_files}}", + }, "python": { Command: "python3 -m pytest -o markers=task {{test_files}}", }, From f2ee85a948667cf7bf7275e2211ee48bab963cdd Mon Sep 17 00:00:00 2001 From: Glenn Jackman Date: Thu, 2 May 2024 03:28:44 -0400 Subject: [PATCH 41/41] troubleshoot command should not recommend creating a github issue (#1122) Co-authored-by: Erik Schierboom --- cmd/troubleshoot.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/troubleshoot.go b/cmd/troubleshoot.go index 5fd134d3c..8e5572794 100644 --- a/cmd/troubleshoot.go +++ b/cmd/troubleshoot.go @@ -26,7 +26,7 @@ var troubleshootCmd = &cobra.Command{ Long: `Provides output to help with troubleshooting. If you're running into trouble, copy and paste the output from the troubleshoot -command into a GitHub issue so we can help figure out what's going on. +command into a topic on the Exercism forum so we can help figure out what's going on. `, RunE: func(cmd *cobra.Command, args []string) error { cli.TimeoutInSeconds = cli.TimeoutInSeconds * 2 @@ -255,8 +255,8 @@ API Reachability * {{ .Latency }} {{ end }} -If you are having trouble please file a GitHub issue at -https://github.com/exercism/exercism.io/issues and include +If you are having trouble, please create a new topic in the Exercism forum +at https://forum.exercism.org/c/support/cli/10 and include this information. {{ if not .Censor }} Don't share your API key. Keep that private.