Skip to content

Commit

Permalink
chore: moving more code to isolated file for future reference
Browse files Browse the repository at this point in the history
  • Loading branch information
plyr4 committed Oct 14, 2024
1 parent 38e8db6 commit cbe94e6
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 102 deletions.
86 changes: 81 additions & 5 deletions api/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import (
"github.com/go-vela/server/internal"
"github.com/go-vela/server/router/middleware/repo"
"github.com/go-vela/server/router/middleware/user"
"github.com/go-vela/server/scm"
"github.com/go-vela/server/util"
"github.com/google/go-github/v62/github"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -79,7 +79,7 @@ func HandleInstallCallback(c *gin.Context) {
func Install(c *gin.Context) {
// capture middleware values
l := c.MustGet("logger").(*logrus.Entry)
scm := scm.FromContext(c)
// scm := scm.FromContext(c)

l.Debug("redirecting to SCM to complete app flow installation")

Expand Down Expand Up @@ -130,7 +130,8 @@ func Install(c *gin.Context) {
}

// construct the repo installation url
redirectURL, err := scm.GetRepoInstallURL(c.Request.Context(), ri)
// todo: this would need a github client
redirectURL, err := GetRepoInstallURL(c.Request.Context(), nil, ri)
if err != nil {
l.Errorf("unable to get repo install url: %v", err)

Expand Down Expand Up @@ -228,11 +229,12 @@ func GetInstallInfo(c *gin.Context) {
l := c.MustGet("logger").(*logrus.Entry)
u := user.Retrieve(c)
r := repo.Retrieve(c)
scm := scm.FromContext(c)
// scm := scm.FromContext(c)

l.Debug("retrieving repo install information")

ri, err := scm.GetRepoInstallInfo(c.Request.Context(), u, r)
// todo: this would need github clients
ri, err := GetRepoInstallInfo(c.Request.Context(), nil, nil, u, r)
if err != nil {
retErr := fmt.Errorf("unable to get repo scm install info %s: %w", u.GetName(), err)

Expand All @@ -250,3 +252,77 @@ func GetInstallInfo(c *gin.Context) {

c.JSON(http.StatusOK, ri)
}

// GetRepoInstallInfo retrieves the repo information required for installation, such as org and repo ID for the given org and repo name.
func GetRepoInstallInfo(ctx context.Context, userClient *github.Client, appClient *github.Client, u *types.User, r *types.Repo) (*types.RepoInstall, error) {
// client := c.newClientToken(ctx, u.GetToken())

// send an API call to get the org info
repoInfo, resp, err := userClient.Repositories.Get(ctx, r.GetOrg(), r.GetName())

orgID := repoInfo.GetOwner().GetID()

// if org is not found, return the personal org
if resp.StatusCode == http.StatusNotFound {
user, _, err := userClient.Users.Get(ctx, "")
if err != nil {
return nil, err
}
orgID = user.GetID()
} else if err != nil {
return nil, err
}

ri := &types.RepoInstall{
OrgSCMID: orgID,
RepoSCMID: repoInfo.GetID(),
}

// todo: pagination...
installations, resp, err := appClient.Apps.ListInstallations(ctx, &github.ListOptions{})
if err != nil && (resp == nil || resp.StatusCode != http.StatusNotFound) {
return nil, err
}

// check if the app is installed on the org
var id int64
for _, installation := range installations {
// app is installed to the org
if installation.GetAccount().GetID() == orgID {
ri.AppInstalled = true
ri.InstallID = installation.GetID()
}
}

// todo: remove all this, it doesnt work without a PAT, lol
_, _, err = appClient.Apps.AddRepository(ctx, id, repoInfo.GetID())
if err != nil {
return nil, err
}

return ri, nil
}

// GetRepoInstallURL takes RepoInstall configurations and returns the SCM URL for installing the application.
func GetRepoInstallURL(ctx context.Context, appClient *github.Client, ri *types.RepoInstall) (string, error) {
// retrieve the authenticated app information
// required for slug and HTML URL
app, _, err := appClient.Apps.Get(ctx, "")
if err != nil {
return "", err
}

path := fmt.Sprintf(
"%s/installations/new/permissions",
app.GetHTMLURL())

// stored as state to retrieve from the post-install callback
state := fmt.Sprintf("type=%s,port=%s", ri.Type, ri.Port)

v := &url.Values{}
v.Set("state", state)
v.Set("suggested_target_id", strconv.FormatInt(ri.OrgSCMID, 10))
v.Set("repository_ids", strconv.FormatInt(ri.RepoSCMID, 10))

return fmt.Sprintf("%s?%s", path, v.Encode()), nil
}
1 change: 1 addition & 0 deletions api/types/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type RepoInstall struct {
OrgSCMID int64
RepoSCMID int64
AppInstalled bool
InstallID int64
RepoAdded bool
InstallURL string
InstallCallback
Expand Down
96 changes: 2 additions & 94 deletions scm/github/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -809,7 +808,8 @@ func (c *client) UpdateChecks(ctx context.Context, r *api.Repo, s *library.Step,
// GetNetrcPassword returns a clone token using the repo's github app installation if it exists.
// If not, it defaults to the user OAuth token.
func (c *client) GetNetrcPassword(ctx context.Context, u *api.User, r *api.Repo, repositories []string) (string, error) {
logrus.Infof("getting clone token")
logrus.Infof("getting netrc password")

// the app might not be installed
// todo: pass in THIS repo to only get access to that repo
// https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation
Expand All @@ -826,95 +826,3 @@ func (c *client) GetNetrcPassword(ctx context.Context, u *api.User, r *api.Repo,

return u.GetToken(), nil
}

// GetRepoInstallInfo retrieves the repo information required for installation, such as org and repo ID for the given org and repo name.
func (c *client) GetRepoInstallInfo(ctx context.Context, u *api.User, r *api.Repo) (*api.RepoInstall, error) {
c.Logger.WithFields(logrus.Fields{
"org": r.GetOrg(),
"user": u.GetName(),
}).Tracef("retrieving repo install information for %s", r.GetFullName())

client := c.newClientToken(ctx, u.GetToken())

// send an API call to get the org info
repoInfo, resp, err := client.Repositories.Get(ctx, r.GetOrg(), r.GetName())

// orgName := repoInfo.GetOwner().GetLogin()
orgID := repoInfo.GetOwner().GetID()

// if org is not found, return the personal org
if resp.StatusCode == http.StatusNotFound {
user, _, err := client.Users.Get(ctx, "")
if err != nil {
return nil, err
}

// orgName = user.GetLogin()
orgID = user.GetID()
} else if err != nil {
return nil, err
}

ri := &api.RepoInstall{
OrgSCMID: orgID,
RepoSCMID: repoInfo.GetID(),
}

ghAppClient, err := c.newGithubAppClient(ctx)
if err != nil {
return nil, err
}

// todo: pagination...
installations, resp, err := ghAppClient.Apps.ListInstallations(ctx, &github.ListOptions{})
if err != nil && (resp == nil || resp.StatusCode != http.StatusNotFound) {
return nil, err
}

// check if the app is installed on the org
var id int64
for _, installation := range installations {
// app is installed to the org
if installation.GetAccount().GetID() == orgID {
ri.AppInstalled = true
id = installation.GetID()
}
}

// todo: remove all this, it doesnt work without a PAT, lol
_, _, err = client.Apps.AddRepository(ctx, id, repoInfo.GetID())
if err != nil {
return nil, err
}

return ri, nil
}

// GetRepoInstallURL takes RepoInstall configurations and returns the SCM URL for installing the application.
func (c *client) GetRepoInstallURL(ctx context.Context, ri *api.RepoInstall) (string, error) {
client, err := c.newGithubAppClient(ctx)
if err != nil {
return "", err
}

// retrieve the authenticated app information
// required for slug and HTML URL
app, _, err := client.Apps.Get(ctx, "")
if err != nil {
return "", err
}

path := fmt.Sprintf(
"%s/installations/new/permissions",
app.GetHTMLURL())

// stored as state to retrieve from the post-install callback
state := fmt.Sprintf("type=%s,port=%s", ri.Type, ri.Port)

v := &url.Values{}
v.Set("state", state)
v.Set("suggested_target_id", strconv.FormatInt(ri.OrgSCMID, 10))
v.Set("repository_ids", strconv.FormatInt(ri.RepoSCMID, 10))

return fmt.Sprintf("%s?%s", path, v.Encode()), nil
}
3 changes: 0 additions & 3 deletions scm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,6 @@ type Service interface {
// a repository file's html_url.
GetHTMLURL(context.Context, *api.User, string, string, string, string) (string, error)

GetRepoInstallInfo(context.Context, *api.User, *api.Repo) (*api.RepoInstall, error)
GetRepoInstallURL(context.Context, *api.RepoInstall) (string, error)

GetNetrcPassword(context.Context, *api.User, *api.Repo, []string) (string, error)
CreateChecks(context.Context, *api.Repo, string, string, string) (int64, error)
UpdateChecks(context.Context, *api.Repo, *library.Step, string, string) error
Expand Down

0 comments on commit cbe94e6

Please sign in to comment.