Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add github app #1070

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
74626c9
Merge branch 'main' of github.com:go-vela/server
jbrockopp Feb 14, 2023
974c8e6
Merge branch 'main' of github.com:go-vela/server
jbrockopp Mar 3, 2023
2f2c425
Merge branch 'main' of github.com:go-vela/server
jbrockopp Mar 20, 2023
528291a
Merge branch 'main' of github.com:go-vela/server
jbrockopp Apr 8, 2023
b53c687
Merge branch 'main' of github.com:go-vela/server
jbrockopp Apr 8, 2023
4734dcb
Merge branch 'main' of github.com:go-vela/server
jbrockopp Apr 16, 2023
1fb52df
Merge branch 'main' of github.com:go-vela/server
jbrockopp Apr 21, 2023
e996aa6
Merge branch 'main' of github.com:go-vela/server
jbrockopp Apr 27, 2023
c299ee4
Merge branch 'main' of github.com:go-vela/server
jbrockopp May 11, 2023
c8da9e3
Merge branch 'main' of github.com:go-vela/server
jbrockopp May 16, 2023
1ee254f
Merge branch 'main' of github.com:go-vela/server
jbrockopp May 22, 2023
8dd6033
Merge branch 'main' of github.com:go-vela/server
jbrockopp May 22, 2023
0eb92b1
Merge branch 'main' of github.com:go-vela/server
jbrockopp May 26, 2023
d5dcb6d
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 1, 2023
be8dd9a
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 5, 2023
73893b5
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 7, 2023
355017b
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 8, 2023
3e17278
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 8, 2023
d3c1e06
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 12, 2023
d63abfe
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 17, 2023
a353552
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 21, 2023
f1a8ab6
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 26, 2023
c23c599
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jun 28, 2023
f0a145d
Merge branch 'main' of github.com:go-vela/server
jbrockopp Jul 12, 2023
00e13f2
Merge branches 'main' and 'main' of github.com:go-vela/server
jbrockopp Jul 26, 2023
ccab2bf
Merge branch 'main' of github.com:go-vela/server
jbrockopp Aug 18, 2023
f4456e5
Merge branch 'main' of github.com:go-vela/server
jbrockopp Oct 15, 2023
8c14e0f
Merge branch 'main' of github.com:go-vela/server
jbrockopp Feb 27, 2024
6de5bcc
feat: initial start of github app
jbrockopp Feb 27, 2024
7b89f5b
feat: create token from github app
jbrockopp Feb 27, 2024
b011b7c
feat(scm): initial checks code
jbrockopp Feb 27, 2024
d4efd6b
chore: push up updates
jbrockopp Feb 27, 2024
8dec758
Merge branch 'main' into hackathon/github_app
ecrupper Jun 21, 2024
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
2 changes: 2 additions & 0 deletions cmd/vela-server/scm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ func setupSCM(c *cli.Context) (scm.Service, error) {
StatusContext: c.String("scm.context"),
WebUIAddress: c.String("webui-addr"),
Scopes: c.StringSlice("scm.scopes"),
GithubAppID: c.Int64("scm.app.id"),
GithubAppPrivateKey: c.String("scm.app.private_key"),
}

// setup the scm
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/adhocore/gronx v1.6.7
github.com/alicebob/miniredis/v2 v2.31.1
github.com/aws/aws-sdk-go v1.50.24
github.com/bradleyfalzon/ghinstallation/v2 v2.9.0
github.com/buildkite/yaml v0.0.0-20181016232759-0caa5f0796e3
github.com/drone/envsubst v1.0.3
github.com/gin-gonic/gin v1.9.1
Expand Down Expand Up @@ -66,8 +67,10 @@ require (
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/google/go-github/v57 v57.0.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/gorilla/css v1.0.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd3
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bradleyfalzon/ghinstallation/v2 v2.9.0 h1:HmxIYqnxubRYcYGRc5v3wUekmo5Wv2uX3gukmWJ0AFk=
github.com/bradleyfalzon/ghinstallation/v2 v2.9.0/go.mod h1:wmkTDJf8CmVypxE8ijIStFnKoTa6solK5QfdmJrP9KI=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
Expand Down Expand Up @@ -92,6 +94,8 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand All @@ -108,6 +112,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
github.com/google/go-github/v59 v59.0.0 h1:7h6bgpF5as0YQLLkEiVqpgtJqjimMYhBkD4jT5aN3VA=
github.com/google/go-github/v59 v59.0.0/go.mod h1:rJU4R0rQHFVFDOkqGWxfLNo6vEk4dv40oDjhV/gH6wM=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
Expand Down
12 changes: 12 additions & 0 deletions scm/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,16 @@ var Flags = []cli.Flag{
"is behind a Firewall or NAT, or when using something like ngrok to forward webhooks. " +
"(defaults to VELA_ADDR).",
},
&cli.Int64Flag{
EnvVars: []string{"VELA_SCM_APP_ID", "SCM_APP_ID"},
FilePath: "/vela/scm/app_id",
Name: "scm.app.id",
Usage: "(optional & experimental) ID for the GitHub App",
},
&cli.StringFlag{
EnvVars: []string{"VELA_SCM_APP_PRIVATE_KEY", "SCM_APP_PRIVATE_KEY"},
FilePath: "/vela/scm/app_private_key",
Name: "scm.app.private_key",
Usage: "(optional & experimental) path to private key for the GitHub App",
},
}
63 changes: 60 additions & 3 deletions scm/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ package github
import (
"context"
"fmt"
"net/http"
"net/url"
"strings"

"github.com/go-vela/types/library"

"github.com/bradleyfalzon/ghinstallation/v2"
"github.com/google/go-github/v59/github"
"github.com/sirupsen/logrus"

Expand Down Expand Up @@ -45,12 +50,16 @@ type config struct {
WebUIAddress string
// specifies the OAuth scopes to use for the GitHub client
Scopes []string
// optional and experimental
GithubAppID int64
GithubAppPrivateKey string
}

type client struct {
config *config
OAuth *oauth2.Config
AuthReq *github.AuthorizationRequest
config *config
OAuth *oauth2.Config
AuthReq *github.AuthorizationRequest
AppsTransport *ghinstallation.AppsTransport
// https://pkg.go.dev/github.com/sirupsen/logrus#Entry
Logger *logrus.Entry
}
Expand Down Expand Up @@ -109,6 +118,17 @@ func New(opts ...ClientOpt) (*client, error) {
Scopes: githubScopes,
}

if c.config.GithubAppID != 0 && len(c.config.GithubAppPrivateKey) > 0 {
c.Logger.Infof("sourcing private key from path: %s", c.config.GithubAppPrivateKey)
transport, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, c.config.GithubAppID, c.config.GithubAppPrivateKey)
if err != nil {
return nil, err
}

transport.BaseURL = c.config.API
c.AppsTransport = transport
}

return c, nil
}

Expand Down Expand Up @@ -164,3 +184,40 @@ func (c *client) newClientToken(token string) *github.Client {

return github
}

// helper function to return the GitHub App token.
func (c *client) newGithubAppToken(r *library.Repo) *github.Client {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
func (*client).newGithubAppToken is unused (unused)

// create a github client based off the existing GitHub App configuration
client, err := github.NewClient(&http.Client{Transport: c.AppsTransport}).WithEnterpriseURLs(c.config.API, c.config.API)
if err != nil {
panic(err)
}

// list all installations (a.k.a. orgs) where the GitHub App is installed
installations, _, err := client.Apps.ListInstallations(context.Background(), &github.ListOptions{})
if err != nil {
panic(err)
}

var id int64
// iterate through the list of installations
for _, install := range installations {
// find the installation that matches the org for the repo
if strings.EqualFold(install.GetAccount().GetLogin(), r.GetOrg()) {
id = install.GetID()
}
}

// failsafe in case the repo does not belong to an org where the GitHub App is installed
if id == 0 {
panic(err)
}

// create installation token for the repo
t, _, err := client.Apps.CreateInstallationToken(context.Background(), id, &github.InstallationTokenOptions{})
if err != nil {
panic(err)
}

return c.newClientToken(t.GetToken())
}
24 changes: 24 additions & 0 deletions scm/github/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,27 @@ func WithScopes(scopes []string) ClientOpt {
return nil
}
}

// WithGithubAppID sets the ID for the GitHub App in the scm client.
func WithGithubAppID(id int64) ClientOpt {
return func(c *client) error {
c.Logger.Trace("configuring ID for GitHub App in github scm client")

// set the ID for the GitHub App in the github client
c.config.GithubAppID = id

return nil
}
}

// WithGithubPrivateKey sets the private key for the GitHub App in the scm client.
func WithGithubPrivateKey(key string) ClientOpt {
return func(c *client) error {
c.Logger.Trace("configuring private key for GitHub App in github scm client")

// set the private key for the GitHub App in the github client
c.config.GithubAppPrivateKey = key

return nil
}
}
39 changes: 39 additions & 0 deletions scm/github/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@
// loop to capture *ALL* the repos
for {
// send API call to capture the user's repos
repos, resp, err := client.Repositories.List(ctx, "", opts)

Check failure on line 450 in scm/github/repo.go

View workflow job for this annotation

GitHub Actions / golangci

[golangci] scm/github/repo.go#L450

SA1019: client.Repositories.List is deprecated: Use RepositoriesService.ListByUser or RepositoriesService.ListByAuthenticatedUser instead. (staticcheck)
Raw output
scm/github/repo.go:450:23: SA1019: client.Repositories.List is deprecated: Use RepositoriesService.ListByUser or RepositoriesService.ListByAuthenticatedUser instead. (staticcheck)
		repos, resp, err := client.Repositories.List(ctx, "", opts)
		                    ^
if err != nil {
return nil, fmt.Errorf("unable to list user repos: %w", err)
}
Expand Down Expand Up @@ -585,3 +585,42 @@

return data.GetName(), data.GetCommit().GetSHA(), nil
}

// CreateChecks defines a function that does stuff...
func (c *client) CreateChecks(ctx context.Context, r *library.Repo, s *library.Step, branch string) (int64, error) {
// create client from GitHub App
client := c.newGithubAppToken(r)

Check failure on line 592 in scm/github/repo.go

View workflow job for this annotation

GitHub Actions / golangci

[golangci] scm/github/repo.go#L592

Function `newGithubAppToken->newClientToken` should pass the context parameter (contextcheck)
Raw output
scm/github/repo.go:592:31: Function `newGithubAppToken->newClientToken` should pass the context parameter (contextcheck)
	client := c.newGithubAppToken(r)
	                             ^

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
Function newGithubAppToken->newClientToken should pass the context parameter (contextcheck)


opts := github.CreateCheckRunOptions{
// TODO: add step name?
Name: fmt.Sprintf("vela-%s-%s", branch, s.GetName()),
HeadSHA: branch,
}

check, _, err := client.Checks.CreateCheckRun(ctx, r.GetOrg(), r.GetName(), opts)
if err != nil {
return 0, err
}

return check.GetID(), nil
}

// UpdateChecks defines a function that does stuff...
func (c *client) UpdateChecks(ctx context.Context, r *library.Repo, s *library.Step, id int64, branch string) error {
// create client from GitHub App
client := c.newGithubAppToken(r)

Check failure on line 611 in scm/github/repo.go

View workflow job for this annotation

GitHub Actions / golangci

[golangci] scm/github/repo.go#L611

Function `newGithubAppToken->newClientToken` should pass the context parameter (contextcheck)
Raw output
scm/github/repo.go:611:31: Function `newGithubAppToken->newClientToken` should pass the context parameter (contextcheck)
	client := c.newGithubAppToken(r)
	                             ^

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [golangci] reported by reviewdog 🐶
Function newGithubAppToken->newClientToken should pass the context parameter (contextcheck)


opts := github.UpdateCheckRunOptions{
// TODO: add step name?
Name: fmt.Sprintf("vela-%s-%s", branch, s.GetName()),
Status: github.String("completed"),
Conclusion: github.String("success"),
}

_, _, err := client.Checks.UpdateCheckRun(ctx, r.GetOrg(), r.GetName(), id, opts)
if err != nil {
return err
}

return nil
}
4 changes: 4 additions & 0 deletions scm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ type Service interface {
// a repository file's html_url.
GetHTMLURL(context.Context, *library.User, string, string, string, string) (string, error)

// TODO: add comments
CreateChecks(context.Context, *library.Repo, *library.Step, string) (int64, error)
UpdateChecks(context.Context, *library.Repo, *library.Step, int64, string) error

// Webhook SCM Interface Functions

// ProcessWebhook defines a function that
Expand Down
5 changes: 5 additions & 0 deletions scm/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ type Setup struct {
WebUIAddress string
// specifies the OAuth scopes to use for the scm client
Scopes []string
// optional and experimental
GithubAppID int64
GithubAppPrivateKey string
}

// Github creates and returns a Vela service capable of
Expand All @@ -55,6 +58,8 @@ func (s *Setup) Github() (Service, error) {
github.WithStatusContext(s.StatusContext),
github.WithWebUIAddress(s.WebUIAddress),
github.WithScopes(s.Scopes),
github.WithGithubAppID(s.GithubAppID),
github.WithGithubPrivateKey(s.GithubAppPrivateKey),
)
}

Expand Down
Loading