From 8e8fc696f13ce3396eabb92471bc4ae71a86274e Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Thu, 12 Sep 2024 09:20:02 -0700 Subject: [PATCH 01/11] disable auth check for att trusted-root cmd Signed-off-by: Brian DeHamer --- pkg/cmd/attestation/trustedroot/trustedroot.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/cmd/attestation/trustedroot/trustedroot.go b/pkg/cmd/attestation/trustedroot/trustedroot.go index c9c3fdb04..a79c32ddb 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot.go @@ -94,6 +94,7 @@ func NewTrustedRootCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Com }, } + cmdutil.DisableAuthCheck(&trustedRootCmd) trustedRootCmd.Flags().StringVarP(&opts.TufUrl, "tuf-url", "", "", "URL to the TUF repository mirror") trustedRootCmd.Flags().StringVarP(&opts.TufRootPath, "tuf-root", "", "", "Path to the TUF root.json file on disk") trustedRootCmd.MarkFlagsRequiredTogether("tuf-url", "tuf-root") From cbe85253214d1ff3ce3c4fe707d55e99fe2adfaf Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Fri, 13 Sep 2024 15:26:14 -0700 Subject: [PATCH 02/11] enforce auth for tenancy Signed-off-by: Brian DeHamer --- .../attestation/trustedroot/trustedroot.go | 9 ++ .../trustedroot/trustedroot_test.go | 97 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/pkg/cmd/attestation/trustedroot/trustedroot.go b/pkg/cmd/attestation/trustedroot/trustedroot.go index a79c32ddb..7dba916eb 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot.go @@ -69,6 +69,15 @@ func NewTrustedRootCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Com } if ghinstance.IsTenancy(opts.Hostname) { + c, err := f.Config() + if err != nil { + return err + } + + if token, _ := c.Authentication().ActiveToken(opts.Hostname); token == "" { + return fmt.Errorf("not authenticated with %s", opts.Hostname) + } + hc, err := f.HttpClient() if err != nil { return err diff --git a/pkg/cmd/attestation/trustedroot/trustedroot_test.go b/pkg/cmd/attestation/trustedroot/trustedroot_test.go index 70b5ae2a1..b7d5f6c2f 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot_test.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot_test.go @@ -3,6 +3,7 @@ package trustedroot import ( "bytes" "fmt" + "net/http" "strings" "testing" @@ -10,8 +11,13 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/gh" + ghmock "github.com/cli/cli/v2/internal/gh/mock" + "github.com/cli/cli/v2/pkg/cmd/attestation/api" "github.com/cli/cli/v2/pkg/cmd/attestation/test" "github.com/cli/cli/v2/pkg/cmdutil" + "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" ) @@ -19,6 +25,9 @@ func TestNewTrustedRootCmd(t *testing.T) { testIO, _, _, _ := iostreams.Test() f := &cmdutil.Factory{ IOStreams: testIO, + Config: func() (gh.Config, error) { + return &ghmock.ConfigMock{}, nil + }, } testcases := []struct { @@ -72,6 +81,83 @@ func TestNewTrustedRootCmd(t *testing.T) { } } +func TestNewTrustedRootWithTenancy(t *testing.T) { + testIO, _, _, _ := iostreams.Test() + var testReg httpmock.Registry + var metaResp = api.MetaResponse{ + Domains: api.Domain{ + ArtifactAttestations: api.ArtifactAttestations{ + TrustDomain: "foo", + }, + }, + } + testReg.Register(httpmock.REST(http.MethodGet, "meta"), + httpmock.StatusJSONResponse(200, &metaResp)) + + httpClientFunc := func() (*http.Client, error) { + reg := &testReg + client := &http.Client{} + httpmock.ReplaceTripper(client, reg) + return client, nil + } + + cli := "--hostname foo-bar.ghe.com" + + t.Run("Host with NO auth configured", func(t *testing.T) { + f := &cmdutil.Factory{ + IOStreams: testIO, + Config: func() (gh.Config, error) { + return &ghmock.ConfigMock{ + AuthenticationFunc: func() gh.AuthConfig { + return &MockAuthConfig{Token: ""} + }, + }, nil + }, + } + + cmd := NewTrustedRootCmd(f, func(_ *Options) error { + return nil + }) + + argv := strings.Split(cli, " ") + cmd.SetArgs(argv) + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(&bytes.Buffer{}) + cmd.SetErr(&bytes.Buffer{}) + _, err := cmd.ExecuteC() + + assert.Error(t, err) + assert.ErrorContains(t, err, "not authenticated") + }) + + t.Run("Host wth auth configured", func(t *testing.T) { + f := &cmdutil.Factory{ + IOStreams: testIO, + Config: func() (gh.Config, error) { + return &ghmock.ConfigMock{ + AuthenticationFunc: func() gh.AuthConfig { + return &MockAuthConfig{Token: "TOKEN"} + }, + }, nil + }, + HttpClient: httpClientFunc, + } + + cmd := NewTrustedRootCmd(f, func(_ *Options) error { + return nil + }) + + argv := strings.Split(cli, " ") + cmd.SetArgs(argv) + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(&bytes.Buffer{}) + cmd.SetErr(&bytes.Buffer{}) + + _, err := cmd.ExecuteC() + assert.NoError(t, err) + }) +} + var newTUFErrClient tufClientInstantiator = func(o *tuf.Options) (*tuf.Client, error) { return nil, fmt.Errorf("failed to create TUF client") } @@ -99,3 +185,14 @@ func TestGetTrustedRoot(t *testing.T) { }) } + +type MockAuthConfig struct { + config.AuthConfig + Token string +} + +var _ gh.AuthConfig = (*MockAuthConfig)(nil) + +func (c *MockAuthConfig) ActiveToken(host string) (string, string) { + return c.Token, "" +} From 3bcedfe7f071904af24b0d9096980e53844ca42a Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Tue, 17 Sep 2024 14:18:00 -0700 Subject: [PATCH 03/11] Update pkg/cmd/attestation/trustedroot/trustedroot_test.go Co-authored-by: Fredrik Skogman --- pkg/cmd/attestation/trustedroot/trustedroot_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/attestation/trustedroot/trustedroot_test.go b/pkg/cmd/attestation/trustedroot/trustedroot_test.go index b7d5f6c2f..c3c1818dd 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot_test.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot_test.go @@ -130,7 +130,7 @@ func TestNewTrustedRootWithTenancy(t *testing.T) { assert.ErrorContains(t, err, "not authenticated") }) - t.Run("Host wth auth configured", func(t *testing.T) { + t.Run("Host with auth configured", func(t *testing.T) { f := &cmdutil.Factory{ IOStreams: testIO, Config: func() (gh.Config, error) { From dded0391254781d1222b1050885a5c658b4461b0 Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Thu, 12 Sep 2024 10:48:12 +0100 Subject: [PATCH 04/11] Improve the suggested command for creating an issue when an extension doesn't have a binary for your platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When installing an extension, the CLI must to select the correct binary to download for the machine (see the [`installBin` function](https://github.com/cli/cli/blob/78c1d00eccac1b2ae82ac0bfeea3e2292c98056a/pkg/cmd/extension/manager.go#L240)). By default, the CLI will download a binary matching the current machine's architecture. If a suitable binary isn't available, the CLI [outputs an error](https://github.com/cli/cli/blob/78c1d00eccac1b2ae82ac0bfeea3e2292c98056a/pkg/cmd/extension/manager.go#L278), directing the user to create an issue on the extension's repository: ```go if asset == nil { return fmt.Errorf( "%[1]s unsupported for %[2]s. Open an issue: `gh issue create -R %[3]s/%[1]s -t'Support %[2]s'`", repo.RepoName(), platform, repo.RepoOwner()) } ``` The issue this creates isn't very clear or helpful. It isn't obvious where it is coming from, or what you need to do. This improves the suggested command, adding a better title to the issue and an explanatory body. To test this, try installing my `timrogers/gh-extension-without-binary` extension, which only has an esoteric `linux-ppc64` binary 😸: ```bash gh extension install timrogers/gh-extension-without-binary ``` You'll get a nice output like this: ``` gh-extension-without-binary unsupported for darwin-arm64. Open an issue: `gh issue create -R timrogers/gh-extension-without-binary --title "Add support for the darwin-arm64 architecture" --body "This extension does not support the darwin-arm64 architecture. I tried to install it on a darwin-arm64 machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see ."` ``` ...which produces an issue like https://github.com/timrogers/gh-extension-without-binary/issues/4. I have tested the resulting command on macOS and Windows, so I am confident that it has *at least reasonable* cross-platform support. Fixes https://github.com/cli/cli/issues/9600. --- pkg/cmd/extension/manager.go | 15 +++++++++++++-- pkg/cmd/extension/manager_test.go | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index 45186d689..37140ee0f 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -280,9 +280,11 @@ func (m *Manager) installBin(repo ghrepo.Interface, target string) error { } if asset == nil { + issueCreateCommand := generateMissingBinaryIssueCreateCommand(repo.RepoOwner(), repo.RepoName(), platform) + return fmt.Errorf( - "%[1]s unsupported for %[2]s. Open an issue: `gh issue create -R %[3]s/%[1]s -t'Support %[2]s'`", - repo.RepoName(), platform, repo.RepoOwner()) + "%[1]s unsupported for %[2]s. Open an issue: `%[3]s`", + repo.RepoName(), platform, issueCreateCommand) } name := repo.RepoName() @@ -334,6 +336,15 @@ func (m *Manager) installBin(repo ghrepo.Interface, target string) error { return nil } +func generateMissingBinaryIssueCreateCommand(repoOwner string, repoName string, currentPlatform string) string { + issueBody := generateMissingBinaryIssueBody(currentPlatform) + return fmt.Sprintf("gh issue create -R %[1]s/%[2]s --title \"Add support for the %[3]s architecture\" --body \"%[4]s\"", repoOwner, repoName, currentPlatform, issueBody) +} + +func generateMissingBinaryIssueBody(currentPlatform string) string { + return fmt.Sprintf("This extension does not support the %[1]s architecture. I tried to install it on a %[1]s machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see .", currentPlatform) +} + func writeManifest(dir, name string, data []byte) (writeErr error) { path := filepath.Join(dir, name) var f *os.File diff --git a/pkg/cmd/extension/manager_test.go b/pkg/cmd/extension/manager_test.go index 5de4e15cb..78fd40978 100644 --- a/pkg/cmd/extension/manager_test.go +++ b/pkg/cmd/extension/manager_test.go @@ -906,7 +906,7 @@ func TestManager_Install_binary_unsupported(t *testing.T) { m := newTestManager(tempDir, &client, nil, ios) err := m.Install(repo, "") - assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64. Open an issue: `gh issue create -R owner/gh-bin-ext -t'Support windows-amd64'`") + assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64. Open an issue: `gh issue create -R owner/gh-bin-ext --title \"Add support for the windows-amd64 architecture\" --body \"This extension does not support the windows-amd64 architecture. I tried to install it on a windows-amd64 machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see .\"`") assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) From 81d57a0643ff5856a96c0c5735184a571985f3df Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Thu, 12 Sep 2024 23:18:37 +0100 Subject: [PATCH 05/11] Improve error presentation --- pkg/cmd/extension/manager.go | 6 ++++-- pkg/cmd/extension/manager_test.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index 37140ee0f..6bed532d3 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -280,11 +280,13 @@ func (m *Manager) installBin(repo ghrepo.Interface, target string) error { } if asset == nil { + cs := m.io.ColorScheme() + errorMessageInRed := fmt.Sprintf(cs.Red("%[1]s unsupported for %[2]s."), repo.RepoName(), platform) issueCreateCommand := generateMissingBinaryIssueCreateCommand(repo.RepoOwner(), repo.RepoName(), platform) return fmt.Errorf( - "%[1]s unsupported for %[2]s. Open an issue: `%[3]s`", - repo.RepoName(), platform, issueCreateCommand) + "%[1]s\n\nOpen an issue on the extension's repo by running the following command:\n\n `%[2]s`", + errorMessageInRed, issueCreateCommand) } name := repo.RepoName() diff --git a/pkg/cmd/extension/manager_test.go b/pkg/cmd/extension/manager_test.go index 78fd40978..ae3a9a469 100644 --- a/pkg/cmd/extension/manager_test.go +++ b/pkg/cmd/extension/manager_test.go @@ -906,7 +906,7 @@ func TestManager_Install_binary_unsupported(t *testing.T) { m := newTestManager(tempDir, &client, nil, ios) err := m.Install(repo, "") - assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64. Open an issue: `gh issue create -R owner/gh-bin-ext --title \"Add support for the windows-amd64 architecture\" --body \"This extension does not support the windows-amd64 architecture. I tried to install it on a windows-amd64 machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see .\"`") + assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64.\n\nOpen an issue on the extension's repo by running the following command:\n\n\t`gh issue create -R owner/gh-bin-ext --title \"Add support for the windows-amd64 architecture\" --body \"This extension does not support the windows-amd64 architecture. I tried to install it on a windows-amd64 machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see .\"") assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) From e7403b89d0c0be36dacae29f61cb040525ba7246 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Wed, 18 Sep 2024 08:42:19 -0600 Subject: [PATCH 06/11] Add HasActiveToken to AuthConfig. Co-authored-by: William Martin --- internal/config/auth_config_test.go | 26 +++++++++++++++++++++++++- internal/config/config.go | 7 +++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/internal/config/auth_config_test.go b/internal/config/auth_config_test.go index ed000ff18..61245c650 100644 --- a/internal/config/auth_config_test.go +++ b/internal/config/auth_config_test.go @@ -52,8 +52,32 @@ func TestTokenFromKeyringForUserErrorsIfUsernameIsBlank(t *testing.T) { require.ErrorContains(t, err, "username cannot be blank") } +func TestHasActiveToken(t *testing.T) { + // Given the user has logged in for a host + authCfg := newTestAuthConfig(t) + _, err := authCfg.Login("github.com", "test-user", "test-token", "", false) + require.NoError(t, err) + + // When we check if that host has an active token + hasActiveToken := authCfg.HasActiveToken("github.com") + + // Then there is an active token + require.True(t, hasActiveToken, "expected there to be an active token") +} + +func TestHasNoActiveToken(t *testing.T) { + // Given there are no users logged in for a host + authCfg := newTestAuthConfig(t) + + // When we check if any host has an active token + hasActiveToken := authCfg.HasActiveToken("github.com") + + // Then there is no active token + require.False(t, hasActiveToken, "expected there to be no active token") +} + func TestTokenStoredInConfig(t *testing.T) { - // When the user has logged in insecurely + // Given the user has logged in insecurely authCfg := newTestAuthConfig(t) _, err := authCfg.Login("github.com", "test-user", "test-token", "", false) require.NoError(t, err) diff --git a/internal/config/config.go b/internal/config/config.go index 29b66b73b..f7c949a46 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -217,6 +217,13 @@ func (c *AuthConfig) ActiveToken(hostname string) (string, string) { return token, source } +// HasActiveToken returns true when a token for the hostname is +// present. +func (c *AuthConfig) HasActiveToken(hostname string) bool { + token, _ := c.ActiveToken(hostname) + return token != "" +} + // HasEnvToken returns true when a token has been specified in an // environment variable, else returns false. func (c *AuthConfig) HasEnvToken() bool { From 88d48f23654838ea7428ed47ed28f64f65405f6a Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:32:58 -0600 Subject: [PATCH 07/11] Add HasActiveToken method to AuthConfig interface --- internal/gh/gh.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/gh/gh.go b/internal/gh/gh.go index c39734075..e4431fdab 100644 --- a/internal/gh/gh.go +++ b/internal/gh/gh.go @@ -93,6 +93,9 @@ type Migration interface { // with knowledge on how to access encrypted storage when neccesarry. // Behavior is scoped to authentication specific tasks. type AuthConfig interface { + // HasActiveToken returns true when a token for the hostname is present. + HasActiveToken(hostname string) bool + // ActiveToken will retrieve the active auth token for the given hostname, searching environment variables, // general configuration, and finally encrypted storage. ActiveToken(hostname string) (token string, source string) From d8e77d256fe83791cf675e0ff539e1390ffd98d5 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:35:11 -0600 Subject: [PATCH 08/11] Use new HasActiveToken method in trustedroot.go --- pkg/cmd/attestation/trustedroot/trustedroot.go | 2 +- .../attestation/trustedroot/trustedroot_test.go | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/attestation/trustedroot/trustedroot.go b/pkg/cmd/attestation/trustedroot/trustedroot.go index 7dba916eb..6f741dcd4 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot.go @@ -74,7 +74,7 @@ func NewTrustedRootCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Com return err } - if token, _ := c.Authentication().ActiveToken(opts.Hostname); token == "" { + if !c.Authentication().HasActiveToken(opts.Hostname) { return fmt.Errorf("not authenticated with %s", opts.Hostname) } diff --git a/pkg/cmd/attestation/trustedroot/trustedroot_test.go b/pkg/cmd/attestation/trustedroot/trustedroot_test.go index c3c1818dd..c4a259436 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot_test.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot_test.go @@ -109,7 +109,7 @@ func TestNewTrustedRootWithTenancy(t *testing.T) { Config: func() (gh.Config, error) { return &ghmock.ConfigMock{ AuthenticationFunc: func() gh.AuthConfig { - return &MockAuthConfig{Token: ""} + return &stubAuthConfig{hasActiveToken: false} }, }, nil }, @@ -136,7 +136,7 @@ func TestNewTrustedRootWithTenancy(t *testing.T) { Config: func() (gh.Config, error) { return &ghmock.ConfigMock{ AuthenticationFunc: func() gh.AuthConfig { - return &MockAuthConfig{Token: "TOKEN"} + return &stubAuthConfig{hasActiveToken: true} }, }, nil }, @@ -186,13 +186,13 @@ func TestGetTrustedRoot(t *testing.T) { } -type MockAuthConfig struct { +type stubAuthConfig struct { config.AuthConfig - Token string + hasActiveToken bool } -var _ gh.AuthConfig = (*MockAuthConfig)(nil) +var _ gh.AuthConfig = (*stubAuthConfig)(nil) -func (c *MockAuthConfig) ActiveToken(host string) (string, string) { - return c.Token, "" +func (c *stubAuthConfig) HasActiveToken(host string) bool { + return c.hasActiveToken } From d24dfbeacfdc87ea108835ee79e9f766fd75f639 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:35:35 -0600 Subject: [PATCH 09/11] Update comment formatting --- internal/config/config.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index f7c949a46..1b56d30b2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -217,8 +217,7 @@ func (c *AuthConfig) ActiveToken(hostname string) (string, string) { return token, source } -// HasActiveToken returns true when a token for the hostname is -// present. +// HasActiveToken returns true when a token for the hostname is present. func (c *AuthConfig) HasActiveToken(hostname string) bool { token, _ := c.ActiveToken(hostname) return token != "" From 195188cee8751247d94c0196ac5ab20371210591 Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Wed, 18 Sep 2024 18:55:20 +0100 Subject: [PATCH 10/11] Update pkg/cmd/extension/manager.go Co-authored-by: Tyler McGoffin --- pkg/cmd/extension/manager.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index 6bed532d3..410d4c224 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -285,8 +285,8 @@ func (m *Manager) installBin(repo ghrepo.Interface, target string) error { issueCreateCommand := generateMissingBinaryIssueCreateCommand(repo.RepoOwner(), repo.RepoName(), platform) return fmt.Errorf( - "%[1]s\n\nOpen an issue on the extension's repo by running the following command:\n\n `%[2]s`", - errorMessageInRed, issueCreateCommand) + "%[1]s\n\nTo request support for %[2]s, open an issue on the extension's repo by running the following command:\n\n `%[3]s`", + errorMessageInRed, platform, issueCreateCommand) } name := repo.RepoName() From 665e41566fe0856fd8d4c2991f81535b50b7da61 Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Wed, 18 Sep 2024 19:07:32 +0100 Subject: [PATCH 11/11] Fix test --- pkg/cmd/extension/manager_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/extension/manager_test.go b/pkg/cmd/extension/manager_test.go index ae3a9a469..0ad8e991e 100644 --- a/pkg/cmd/extension/manager_test.go +++ b/pkg/cmd/extension/manager_test.go @@ -906,7 +906,7 @@ func TestManager_Install_binary_unsupported(t *testing.T) { m := newTestManager(tempDir, &client, nil, ios) err := m.Install(repo, "") - assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64.\n\nOpen an issue on the extension's repo by running the following command:\n\n\t`gh issue create -R owner/gh-bin-ext --title \"Add support for the windows-amd64 architecture\" --body \"This extension does not support the windows-amd64 architecture. I tried to install it on a windows-amd64 machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see .\"") + assert.EqualError(t, err, "gh-bin-ext unsupported for windows-amd64.\n\nTo request support for windows-amd64, open an issue on the extension's repo by running the following command:\n\n\t`gh issue create -R owner/gh-bin-ext --title \"Add support for the windows-amd64 architecture\" --body \"This extension does not support the windows-amd64 architecture. I tried to install it on a windows-amd64 machine, and it failed due to the lack of an available binary. Would you be able to update the extension's build and release process to include the relevant binary? For more details, see .\"`") assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String())