Skip to content

Commit

Permalink
feat: repo install endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
plyr4 committed Oct 8, 2024
1 parent e8b493d commit 146131e
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 8 deletions.
11 changes: 11 additions & 0 deletions action/repo/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@ func (c *Config) Add(client *vela.Client) error {
return err
}

err = c.Install(client, repo)
if err != nil {
return err
}

// client.Install

// todo: this just redirects to the auth callback
// we need this to redirect to the server
// the server then sees whether or not it was a cli auth flow and it

// handle the output based off the provided configuration
switch c.Output {
case output.DriverDump:
Expand Down
91 changes: 91 additions & 0 deletions action/repo/install.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: Apache-2.0

package repo

import (
"fmt"
"strconv"

"github.com/cli/browser"
"github.com/sirupsen/logrus"

"github.com/go-vela/sdk-go/vela"
api "github.com/go-vela/server/api/types"
)

// Install executes the repo app installation process, which should redirect to the SCM web flow.
func (c *Config) Install(client *vela.Client, repo *api.Repo) error {
logrus.Debug("executing app install for repo configuration")

// start the local server
err := c.StartServer()
if err != nil {
return err
}

// request the install URL from the server
installHTMLURL, _, err := client.Repo.InstallHTMLURL(repo.GetOrg(), repo.GetName())
if err != nil {
return err
}

// attach contextual information like cli type and local server port
*installHTMLURL = fmt.Sprintf(
"%s&type=%s&port=%s",
*installHTMLURL,
"cli", strconv.Itoa(c.server.Port()),
)

// launch the login process in the browser
err = browser.OpenURL(*installHTMLURL)
if err != nil {
return err
}

// capture result from local server
err = c.WaitForResult(client)
if err != nil {
return err
}

return nil
}

// WaitForResult will wait for the callback and handle the response.
func (c *Config) WaitForResult(client *vela.Client) error {
logrus.Debug("waiting for app installation server callback")

// waiting for local server to receive the redirect
_, err := c.server.WaitForResult()
if err != nil {
return err
}

return nil
}

// StartServer starts a local server as part of the
// auth flow. It will handle the callback.
func (c *Config) StartServer() error {
logrus.Debug("starting local server")

// set up the local server to capture the redirect from auth
server, err := bindLocalServer()
if err != nil {
return err
}

logrus.Debug("local server is bound")

// store on struct
c.server = server

// start the server up
go func() {
_ = c.server.Serve()
}()

logrus.Debug("local server started")

return nil
}
85 changes: 85 additions & 0 deletions action/repo/local_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: Apache-2.0

// mostly taken from https://github.com/cli/oauth/tree/v0.8.0/webapp

package repo

import (
"fmt"
"io"
"net"
"net/http"
)

type CodeResponse struct {
Code string
State string
}

type localServer struct {
CallbackPath string
WriteSuccessHTML func(w io.Writer)

resultChan chan (CodeResponse)
listener net.Listener
}

// bindLocalServer initializes a LocalServer that will listen on a randomly available TCP port.
func bindLocalServer() (*localServer, error) {
listener, err := net.Listen("tcp4", "127.0.0.1:0")
if err != nil {
return nil, err
}

return &localServer{
listener: listener,
resultChan: make(chan CodeResponse, 1),
}, nil
}

func (s *localServer) Port() int {
return s.listener.Addr().(*net.TCPAddr).Port
}

func (s *localServer) Close() error {
return s.listener.Close()
}

func (s *localServer) Serve() error {
//nolint:gosec // TODO: add a way to timeout the local server
return http.Serve(s.listener, s)
}

func (s *localServer) WaitForResult() (CodeResponse, error) {
return <-s.resultChan, nil
}

// ServeHTTP implements http.Handler.
func (s *localServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if s.CallbackPath != "" && r.URL.Path != s.CallbackPath {
w.WriteHeader(http.StatusNotFound)
return
}

defer func() {
_ = s.Close()
}()

params := r.URL.Query()
s.resultChan <- CodeResponse{
Code: params.Get("code"),
State: params.Get("state"),
}

w.Header().Add("content-type", "text/html")

if s.WriteSuccessHTML != nil {
s.WriteSuccessHTML(w)
} else {
defaultSuccessHTML(w)
}
}

func defaultSuccessHTML(w io.Writer) {
fmt.Fprint(w, authSuccess)
}
2 changes: 2 additions & 0 deletions action/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ type Config struct {
PerPage int
Output string
Color output.ColorOptions

server *localServer
}
76 changes: 76 additions & 0 deletions action/repo/success_page.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: Apache-2.0

package repo

// authSuccess provides the HTML for rendering
// a message in the browser after successfully
// completing the oauth workflow.
const authSuccess = `
<!doctype html>
<meta charset="utf-8">
<title>Success: Vela CLI</title>
<style type="text/css">
body {
color: hsl(0, 0%, 98%);
background-color: hsl(0, 0%, 16%);
font-size: 14px;
font-family: -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
line-height: 1.5;
max-width: 620px;
margin: 28px auto;
text-align: center;
}
.vela-logo-star {
fill: hsl(289, 54.8%, 57.5%);
}
.vela-logo-lines {
fill: hsl(194, 89.7%, 58%);
}
.box {
background-color: hsl(0, 0%, 16%);
}
h1 {
font-size: 24px;
margin-bottom: 0;
}
p {
margin-top: 0;
}
.box {
border: 1px solid hsl(286, 29%, 51%);
padding: 24px;
margin: 28px;
}
@media (prefers-color-scheme: light) {
body {
color: hsl(0, 0%, 16%);
background-color: hsl(0, 0%, 98%);
}
.box {
background-color: hsl(0, 0%, 98%);
}
</style>
<body>
<svg width="72" height="72" viewBox="0 0 1920 1920" class="vela-logo">
<path class="vela-logo-lines"
d="M618.73 431.74h-162.1a56.87 56.87 0 0 0-50.86 82.3l501.05 1002.1a56.86 56.86 0 0 0 101.72 0l332.85-665.72 63.63 127.07-294.74 589.5a170.64 170.64 0 0 1-152.6 94.33 170.64 170.64 0 0 1-152.6-94.33L304.03 564.9A170.61 170.61 0 0 1 456.63 318h105.14l56.96 113.75Z" />
<path class="vela-logo-lines"
d="M625.05 318h126.9l56.94 113.74h-126.9L625.05 318Zm253.65 0h63.45l56.94 113.74h-63.44L878.7 318ZM675.82 545.47l281.86 563.74 147.3-294.62 137.58-20.82-284.88 569.76-409.03-818.06h127.17Z" />
<path class="vela-logo-star"
d="m1372.75 659.05-234.4 35.44 168.8-166.43L1201.96 318l209.51 107.16 168.8-166.45-38.7 233.88 210.46 109.1-234.4 35.43-38.7 233.89-106.17-211.97Z" />
</svg>
<div class="box">
<h1>Successfully authenticated with Vela!</h1>
<p>You may now close this tab and return to the terminal.</p>
</div>
</body>
`
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,11 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

replace github.com/go-vela/types => ../types

replace github.com/go-vela/server => ../server

replace github.com/go-vela/worker => ../worker

replace github.com/go-vela/sdk-go => ../sdk-go
8 changes: 0 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,6 @@ github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-vela/sdk-go v0.25.1 h1:aEWH88BjLmV5s3mWPbi7OeGY5u8IQ9xQNF8CWH3e5HU=
github.com/go-vela/sdk-go v0.25.1/go.mod h1:98yxwcqGQidNke/QsbG8WeYJG56AImc9o9dcKiXBQ5k=
github.com/go-vela/server v0.25.1 h1:KM3g5ZD3N6SnttnkfOyJjS2utbL6baKx0mGSJLCEf0c=
github.com/go-vela/server v0.25.1/go.mod h1:QZ9troVMUpDCAdUxxAquHqahkeSwp9Lmx6a47ao0gGs=
github.com/go-vela/types v0.25.1 h1:DCPHv1+ouqldjfsjfcVTcm/Yyd0OwazIfxYyR+GwpMo=
github.com/go-vela/types v0.25.1/go.mod h1:5+MHUI9ZSY2Uz1cTJa64FWUv8jKzzUUq96UQTokGJzs=
github.com/go-vela/worker v0.25.1 h1:vpD82MEZUBgloNiXUa0KtZzxz9+V5+vOusiFdQbE6lM=
github.com/go-vela/worker v0.25.1/go.mod h1:tZ4AEUc4kf5umXFZ3/9piQhqe4E8QkmxjrhoJ2/9rt8=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
Expand Down

0 comments on commit 146131e

Please sign in to comment.