-
Notifications
You must be signed in to change notification settings - Fork 28
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
feat: add github app #1070
Changes from 32 commits
74626c9
974c8e6
2f2c425
528291a
b53c687
4734dcb
1fb52df
e996aa6
c299ee4
c8da9e3
1ee254f
8dd6033
0eb92b1
d5dcb6d
be8dd9a
73893b5
355017b
3e17278
d3c1e06
d63abfe
a353552
f1a8ab6
c23c599
f0a145d
00e13f2
ccab2bf
f4456e5
8c14e0f
6de5bcc
7b89f5b
b011b7c
d4efd6b
8dec758
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
"fmt" | ||
"time" | ||
|
||
"github.com/go-vela/server/scm" | ||
|
||
"github.com/go-vela/server/database" | ||
"github.com/go-vela/types/constants" | ||
"github.com/go-vela/types/library" | ||
|
@@ -16,7 +18,7 @@ | |
// PlanSteps is a helper function to plan all steps | ||
// in the build for execution. This creates the steps | ||
// for the build in the configured backend. | ||
func PlanSteps(ctx context.Context, database database.Interface, p *pipeline.Build, b *library.Build) ([]*library.Step, error) { | ||
func PlanSteps(ctx context.Context, database database.Interface, scm scm.Service, p *pipeline.Build, b *library.Build, r *library.Repo) ([]*library.Step, error) { | ||
// variable to store planned steps | ||
steps := []*library.Step{} | ||
|
||
|
@@ -25,7 +27,7 @@ | |
// iterate through all steps for each pipeline stage | ||
for _, step := range stage.Steps { | ||
// create the step object | ||
s, err := planStep(ctx, database, b, step, stage.Name) | ||
s, err := planStep(ctx, database, scm, b, r, step, stage.Name) | ||
if err != nil { | ||
return steps, err | ||
} | ||
|
@@ -36,7 +38,7 @@ | |
|
||
// iterate through all pipeline steps | ||
for _, step := range p.Steps { | ||
s, err := planStep(ctx, database, b, step, "") | ||
Check failure on line 41 in api/step/plan.go GitHub Actions / golangci[golangci] api/step/plan.go#L41
Raw output
|
||
if err != nil { | ||
return steps, err | ||
} | ||
|
@@ -47,7 +49,7 @@ | |
return steps, nil | ||
} | ||
|
||
func planStep(ctx context.Context, database database.Interface, b *library.Build, c *pipeline.Container, stage string) (*library.Step, error) { | ||
func planStep(ctx context.Context, database database.Interface, scm scm.Service, b *library.Build, r *library.Repo, c *pipeline.Container, stage string) (*library.Step, error) { | ||
// create the step object | ||
s := new(library.Step) | ||
s.SetBuildID(b.GetID()) | ||
|
@@ -59,8 +61,17 @@ | |
s.SetStatus(constants.StatusPending) | ||
s.SetCreated(time.Now().UTC().Unix()) | ||
|
||
id, err := scm.CreateChecks(ctx, r, b.GetCommit(), s.GetName()) | ||
if err != nil { | ||
// TODO: make this error more meaningful | ||
return nil, err | ||
} | ||
|
||
// TODO: have to store the check ID somewhere | ||
s.SetCheckID(id) | ||
Check failure on line 71 in api/step/plan.go GitHub Actions / golangci[golangci] api/step/plan.go#L71
Raw output
|
||
|
||
// send API call to create the step | ||
s, err := database.CreateStep(ctx, s) | ||
Check failure on line 74 in api/step/plan.go GitHub Actions / golangci[golangci] api/step/plan.go#L74
Raw output
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
if err != nil { | ||
return nil, fmt.Errorf("unable to create step %s: %w", s.GetName(), err) | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
||
|
@@ -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 | ||
} | ||
|
@@ -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 | ||
} | ||
|
||
|
@@ -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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
// 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()) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -585,3 +585,75 @@ | |
|
||
return data.GetName(), data.GetCommit().GetSHA(), nil | ||
} | ||
|
||
// CreateChecks defines a function that does stuff... | ||
func (c *client) CreateChecks(ctx context.Context, r *library.Repo, commit, step string) (int64, error) { | ||
// create client from GitHub App | ||
client := c.newGithubAppToken(r) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
|
||
opts := github.CreateCheckRunOptions{ | ||
Name: fmt.Sprintf("vela-%s-%s", commit, step), | ||
HeadSHA: commit, | ||
} | ||
|
||
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, commit string) error { | ||
// create client from GitHub App | ||
client := c.newGithubAppToken(r) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
|
||
var ( | ||
conclusion string | ||
status string | ||
) | ||
// set the conclusion and status for the step check depending on what the status of the step is | ||
switch s.GetStatus() { | ||
case constants.StatusPending: | ||
conclusion = "neutral" | ||
status = "queued" | ||
case constants.StatusPendingApproval: | ||
conclusion = "action_required" | ||
status = "queued" | ||
case constants.StatusRunning: | ||
conclusion = "neutral" | ||
status = "in_progress" | ||
case constants.StatusSuccess: | ||
conclusion = "success" | ||
status = "completed" | ||
case constants.StatusFailure: | ||
conclusion = "failure" | ||
status = "completed" | ||
case constants.StatusCanceled: | ||
conclusion = "cancelled" | ||
status = "completed" | ||
case constants.StatusKilled: | ||
conclusion = "cancelled" | ||
status = "completed" | ||
case constants.StatusSkipped: | ||
conclusion = "skipped" | ||
status = "completed" | ||
default: | ||
conclusion = "neutral" | ||
status = "completed" | ||
} | ||
|
||
opts := github.UpdateCheckRunOptions{ | ||
Name: fmt.Sprintf("vela-%s-%s", commit, s.GetName()), | ||
Conclusion: github.String(conclusion), | ||
Status: github.String(status), | ||
} | ||
|
||
_, _, err := client.Checks.UpdateCheckRun(ctx, r.GetOrg(), r.GetName(), s.GetCheckID(), opts) | ||
Check failure on line 653 in scm/github/repo.go GitHub Actions / golangci[golangci] scm/github/repo.go#L653
Raw output
Check failure on line 653 in scm/github/repo.go GitHub Actions / golangci[golangci] scm/github/repo.go#L653
Raw output
Check failure on line 653 in scm/github/repo.go GitHub Actions / golangci[golangci] scm/github/repo.go#L653
Raw output
Check failure on line 653 in scm/github/repo.go GitHub Actions / golangci[golangci] scm/github/repo.go#L653
Raw output
Check failure on line 653 in scm/github/repo.go GitHub Actions / build
Check failure on line 653 in scm/github/repo.go GitHub Actions / build
Check failure on line 653 in scm/github/repo.go GitHub Actions / validate
Check failure on line 653 in scm/github/repo.go GitHub Actions / validate
Check failure on line 653 in scm/github/repo.go GitHub Actions / test
Check failure on line 653 in scm/github/repo.go GitHub Actions / test
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [golangci] reported by reviewdog 🐶 |
||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫 [golangci] reported by reviewdog 🐶
s.SetCheckID undefined (type *library.Step has no field or method SetCheckID) (typecheck)