Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: add support forcoder_git_auth data source#6334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
kylecarbs merged 21 commits intomainfromgitauth
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
21 commits
Select commitHold shift + click to select a range
c64636b
Add git auth providers schema
kylecarbsFeb 22, 2023
6a61712
Pipe git auth providers to the schema
kylecarbsFeb 22, 2023
3d67a0d
Add git auth providers to the API
kylecarbsFeb 22, 2023
604cf5b
Add gitauth endpoint to query authenticated state
kylecarbsFeb 23, 2023
85db3c2
Add endpoint to query git state
kylecarbsFeb 23, 2023
e418892
Use BroadcastChannel to automatically authenticate with Git
kylecarbsFeb 23, 2023
6b75f3e
Add error validation for submitting the create workspace form
kylecarbsFeb 24, 2023
1ad5db1
Fix panic on template dry-run
kylecarbsFeb 25, 2023
320c10d
Add tests for the template version Git auth endpoint
kylecarbsFeb 25, 2023
ff2b822
Merge branch 'main' into gitauth
kylecarbsFeb 25, 2023
18488f8
Show error if no gitauth is configured
kylecarbsFeb 26, 2023
18523d5
Add gitauth to cliui
kylecarbsFeb 26, 2023
2c9fb64
Fix unused method receiver
kylecarbsFeb 26, 2023
7cbf190
Fix linting errors
kylecarbsFeb 26, 2023
1335c93
Fix dbauthz querier test
kylecarbsFeb 27, 2023
671be8c
Fix make gen
kylecarbsFeb 27, 2023
177625a
Add JavaScript test for git auth
kylecarbsFeb 27, 2023
2be97bb
Fix bad error message
kylecarbsFeb 27, 2023
69dea35
Fix provisionerd test race
kylecarbsFeb 27, 2023
5fdf8ce
Fix requested changes
kylecarbsFeb 27, 2023
993ede8
Add comment to CreateWorkspacePageView
kylecarbsFeb 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletionscli/cliui/gitauth.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
package cliui

import (
"context"
"fmt"
"io"
"time"

"github.com/briandowns/spinner"

"github.com/coder/coder/codersdk"
)

type GitAuthOptions struct {
Fetch func(context.Context) ([]codersdk.TemplateVersionGitAuth, error)
FetchInterval time.Duration
}

func GitAuth(ctx context.Context, writer io.Writer, opts GitAuthOptions) error {
if opts.FetchInterval == 0 {
opts.FetchInterval = 500 * time.Millisecond
}
gitAuth, err := opts.Fetch(ctx)
if err != nil {
return err
}

spin := spinner.New(spinner.CharSets[78], 100*time.Millisecond, spinner.WithColor("fgHiGreen"))
spin.Writer = writer
spin.ForceOutput = true
spin.Suffix = " Waiting for Git authentication..."
defer spin.Stop()

ticker := time.NewTicker(opts.FetchInterval)
defer ticker.Stop()
for _, auth := range gitAuth {
if auth.Authenticated {
return nil
}

_, _ = fmt.Fprintf(writer, "You must authenticate with %s to create a workspace with this template. Visit:\n\n\t%s\n\n", auth.Type.Pretty(), auth.AuthenticateURL)

ticker.Reset(opts.FetchInterval)
spin.Start()
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
}
gitAuth, err := opts.Fetch(ctx)
if err != nil {
return err
}
var authed bool
for _, a := range gitAuth {
if !a.Authenticated || a.ID != auth.ID {
continue
}
authed = true
break
}
// The user authenticated with the provider!
if authed {
break
}
}
spin.Stop()
_, _ = fmt.Fprintf(writer, "Successfully authenticated with %s!\n\n", auth.Type.Pretty())
}
return nil
}
55 changes: 55 additions & 0 deletionscli/cliui/gitauth_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
package cliui_test

import (
"context"
"net/url"
"sync/atomic"
"testing"
"time"

"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"

"github.com/coder/coder/cli/cliui"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/pty/ptytest"
"github.com/coder/coder/testutil"
)

func TestGitAuth(t *testing.T) {
t.Parallel()

ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitShort)
defer cancel()

ptty := ptytest.New(t)
cmd := &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error {
var fetched atomic.Bool
return cliui.GitAuth(cmd.Context(), cmd.OutOrStdout(), cliui.GitAuthOptions{
Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
defer fetched.Store(true)
return []codersdk.TemplateVersionGitAuth{{
ID: "github",
Type: codersdk.GitProviderGitHub,
Authenticated: fetched.Load(),
AuthenticateURL: "https://example.com/gitauth/github?redirect=" + url.QueryEscape("/gitauth?notify"),
}}, nil
},
FetchInterval: time.Millisecond,
})
},
}
cmd.SetOutput(ptty.Output())
cmd.SetIn(ptty.Input())
done := make(chan struct{})
go func() {
defer close(done)
err := cmd.Execute()
assert.NoError(t, err)
}()
ptty.ExpectMatchContext(ctx, "You must authenticate with")
ptty.ExpectMatchContext(ctx, "https://example.com/gitauth/github")
ptty.ExpectMatchContext(ctx, "Successfully authenticated with GitHub")
<-done
}
10 changes: 10 additions & 0 deletionscli/create.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
package cli

import (
"context"
"fmt"
"io"
"time"
Expand DownExpand Up@@ -324,6 +325,15 @@ PromptRichParamLoop:
_, _ = fmt.Fprintln(cmd.OutOrStdout())
}

err = cliui.GitAuth(ctx, cmd.OutOrStdout(), cliui.GitAuthOptions{
Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
return client.TemplateVersionGitAuth(ctx, templateVersion.ID)
},
})
if err != nil {
return nil, xerrors.Errorf("template version git auth: %w", err)
}

// Run a dry-run with the given parameters to check correctness
dryRun, err := client.CreateTemplateVersionDryRun(cmd.Context(), templateVersion.ID, codersdk.CreateTemplateVersionDryRunRequest{
WorkspaceName: args.NewWorkspaceName,
Expand Down
89 changes: 89 additions & 0 deletionscli/create_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,15 +3,21 @@ package cli_test
import (
"context"
"fmt"
"net/http"
"net/url"
"os"
"regexp"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"

"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/gitauth"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto"
Expand DownExpand Up@@ -603,6 +609,61 @@ func TestCreateValidateRichParameters(t *testing.T) {
})
}

func TestCreateWithGitAuth(t *testing.T) {
t.Parallel()
echoResponses := &echo.Responses{
Parse: echo.ParseComplete,
ProvisionPlan: []*proto.Provision_Response{
{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{
GitAuthProviders: []string{"github"},
},
},
},
},
ProvisionApply: []*proto.Provision_Response{{
Type: &proto.Provision_Response_Complete{
Complete: &proto.Provision_Complete{},
},
}},
}

client := coderdtest.New(t, &coderdtest.Options{
GitAuthConfigs: []*gitauth.Config{{
OAuth2Config: &oauth2Config{},
ID: "github",
Regex: regexp.MustCompile(`github\.com`),
Type: codersdk.GitProviderGitHub,
}},
IncludeProvisionerDaemon: true,
})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, echoResponses)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)

cmd, root := clitest.New(t, "create", "my-workspace", "--template", template.Name)
clitest.SetupConfig(t, client, root)
doneChan := make(chan struct{})
pty := ptytest.New(t)
cmd.SetIn(pty.Input())
cmd.SetOut(pty.Output())
go func() {
defer close(doneChan)
err := cmd.Execute()
assert.NoError(t, err)
}()

pty.ExpectMatch("You must authenticate with GitHub to create a workspace")
resp := coderdtest.RequestGitAuthCallback(t, "github", client)
_ = resp.Body.Close()
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
pty.ExpectMatch("Confirm create?")
pty.WriteLine("yes")
<-doneChan
}

func createTestParseResponseWithDefault(defaultValue string) []*proto.Parse_Response {
return []*proto.Parse_Response{{
Type: &proto.Parse_Response_Complete{
Expand DownExpand Up@@ -638,3 +699,31 @@ func createTestParseResponseWithDefault(defaultValue string) []*proto.Parse_Resp
},
}}
}

type oauth2Config struct{}

func (*oauth2Config) AuthCodeURL(state string, _ ...oauth2.AuthCodeOption) string {
return "/?state=" + url.QueryEscape(state)
}

func (*oauth2Config) Exchange(context.Context, string, ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
return &oauth2.Token{
AccessToken: "token",
RefreshToken: "refresh",
Expiry: database.Now().Add(time.Hour),
}, nil
}

func (*oauth2Config) TokenSource(context.Context, *oauth2.Token) oauth2.TokenSource {
return &oauth2TokenSource{}
}

type oauth2TokenSource struct{}

func (*oauth2TokenSource) Token() (*oauth2.Token, error) {
return &oauth2.Token{
AccessToken: "token",
RefreshToken: "refresh",
Expiry: database.Now().Add(time.Hour),
}, nil
}
37 changes: 37 additions & 0 deletionscmd/cliui/main.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,10 @@ import (
"errors"
"fmt"
"io"
"net/url"
"os"
"strings"
"sync/atomic"
"time"

"github.com/spf13/cobra"
Expand DownExpand Up@@ -235,6 +237,41 @@ func main() {
},
})

root.AddCommand(&cobra.Command{
Use: "git-auth",
RunE: func(cmd *cobra.Command, args []string) error {
var count atomic.Int32
var githubAuthed atomic.Bool
var gitlabAuthed atomic.Bool
go func() {
// Sleep to display the loading indicator.
time.Sleep(time.Second)
// Swap to true to display success and move onto GitLab.
githubAuthed.Store(true)
// Show the loading indicator again...
time.Sleep(time.Second * 2)
// Complete the auth!
gitlabAuthed.Store(true)
}()
return cliui.GitAuth(cmd.Context(), cmd.OutOrStdout(), cliui.GitAuthOptions{
Fetch: func(ctx context.Context) ([]codersdk.TemplateVersionGitAuth, error) {
count.Add(1)
return []codersdk.TemplateVersionGitAuth{{
ID: "github",
Type: codersdk.GitProviderGitHub,
Authenticated: githubAuthed.Load(),
AuthenticateURL: "https://example.com/gitauth/github?redirect=" + url.QueryEscape("/gitauth?notify"),
}, {
ID: "gitlab",
Type: codersdk.GitProviderGitLab,
Authenticated: gitlabAuthed.Load(),
AuthenticateURL: "https://example.com/gitauth/gitlab?redirect=" + url.QueryEscape("/gitauth?notify"),
}}, nil
},
})
},
})

err := root.Execute()
if err != nil {
_, _ = fmt.Println(err.Error())
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp