Skip to content

Commit

Permalink
enhance: added repo sync to create and repair
Browse files Browse the repository at this point in the history
  • Loading branch information
plyr4 committed Oct 25, 2024
1 parent 9654dbc commit b60da20
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 4 deletions.
16 changes: 16 additions & 0 deletions api/repo/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,20 @@ func CreateRepo(c *gin.Context) {
}
}

// map this repo to an installation if possible
if r.GetInstallID() == 0 {
r, err = scm.FromContext(c).SyncRepoWithInstallation(ctx, r)
if err != nil {
retErr := fmt.Errorf("unable to sync repo %s with installation: %w", r.GetFullName(), err)

util.HandleError(c, http.StatusInternalServerError, retErr)

return
}
}

logrus.Warnf("repo %s has been synced with installation %d", r.GetFullName(), r.GetInstallID())

// if the repo exists but is inactive
if len(dbRepo.GetOrg()) > 0 && !dbRepo.GetActive() {
// update the repo owner
Expand All @@ -281,6 +295,8 @@ func CreateRepo(c *gin.Context) {
dbRepo.SetBranch(r.GetBranch())
// activate the repo
dbRepo.SetActive(true)
// update the install_id
dbRepo.SetInstallID(r.GetInstallID())

// send API call to update the repo
// NOTE: not logging modification out separately
Expand Down
33 changes: 30 additions & 3 deletions api/repo/repair.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,21 +163,48 @@ func RepairRepo(c *gin.Context) {
}
}

dirty := false

// if the repo was previously inactive, mark it as active
if !r.GetActive() {
r.SetActive(true)

// send API call to update the repo
dirty = true

l.Tracef("repo %s repaired - set to active", r.GetFullName())
}

// map this repo to an installation, if possible
if r.GetInstallID() == 0 {
r, err = scm.FromContext(c).SyncRepoWithInstallation(ctx, r)
if err != nil {
retErr := fmt.Errorf("unable to sync repo %s with installation: %w", r.GetFullName(), err)

util.HandleError(c, http.StatusInternalServerError, retErr)

return
}

// install_id was synced
if r.GetInstallID() != 0 {
dirty = true

l.Tracef("repo %s repaired - set install_id to %d", r.GetFullName(), r.GetInstallID())
}
}

// update the repo in the database, if necessary
if dirty {
_, err := database.FromContext(c).UpdateRepo(ctx, r)
if err != nil {
retErr := fmt.Errorf("unable to set repo %s to active: %w", r.GetFullName(), err)
retErr := fmt.Errorf("unable to update repo %s during repair: %w", r.GetFullName(), err)

util.HandleError(c, http.StatusInternalServerError, retErr)

return
}

l.Infof("repo %s updated - set to active", r.GetFullName())
l.Infof("repo %s repaired - database updated", r.GetFullName())
}

c.JSON(http.StatusOK, fmt.Sprintf("repo %s repaired", r.GetFullName()))
Expand Down
2 changes: 1 addition & 1 deletion scm/github/app_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (c *client) newGithubAppClient() (*github.Client, error) {
return client, nil
}

// newGithubAppInstallationRepoToken returns the GitHub App installation token.
// newGithubAppInstallationRepoToken returns the GitHub App installation token for a particular repo with granular permissions.
func (c *client) newGithubAppInstallationRepoToken(ctx context.Context, r *api.Repo, repos []string, permissions *github.InstallationPermissions) (string, error) {
// create a github client based off the existing GitHub App configuration
client, err := c.newGithubAppClient()
Expand Down
62 changes: 62 additions & 0 deletions scm/github/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,68 @@ func (c *client) UpdateChecks(ctx context.Context, r *api.Repo, s *api.Step, com
return nil
}

// SyncRepoWithInstallation ensures the repo is synchronized with the scm installation, if it exists.
func (c *client) SyncRepoWithInstallation(ctx context.Context, r *api.Repo) (*api.Repo, error) {
c.Logger.WithFields(logrus.Fields{
"org": r.GetOrg(),
"repo": r.GetName(),
}).Tracef("syncing app installation for repo %s/%s", r.GetOrg(), r.GetName())

client, err := c.newGithubAppClient()
if err != nil {
return r, err
}

installations, _, err := client.Apps.ListInstallations(ctx, &github.ListOptions{})
if err != nil {
return r, err
}

var installation *github.Installation
for _, install := range installations {

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

View workflow job for this annotation

GitHub Actions / golangci

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

ranges should only be cuddled with assignments used in the iteration (wsl)
Raw output
scm/github/repo.go:913:2: ranges should only be cuddled with assignments used in the iteration (wsl)
	for _, install := range installations {
	^
if strings.EqualFold(install.GetAccount().GetLogin(), r.GetOrg()) {
installation = install
}
}

if installation == nil {
return nil, nil
}

installationCanReadRepo := false
if installation.GetRepositorySelection() != "all" {

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

View workflow job for this annotation

GitHub Actions / golangci

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

if statements should only be cuddled with assignments used in the if statement itself (wsl)
Raw output
scm/github/repo.go:924:2: if statements should only be cuddled with assignments used in the if statement itself (wsl)
	if installation.GetRepositorySelection() != "all" {
	^
client, err := c.newGithubAppClient()
if err != nil {
return r, err
}

t, _, err := client.Apps.CreateInstallationToken(ctx, installation.GetID(), &github.InstallationTokenOptions{})
if err != nil {
return r, err
}

client = c.newClientToken(ctx, t.GetToken())

repos, _, err := client.Apps.ListRepos(ctx, &github.ListOptions{})
if err != nil {
return r, err
}

for _, repo := range repos.Repositories {
if strings.EqualFold(repo.GetFullName(), r.GetFullName()) {
installationCanReadRepo = true
break
}
}
}

if installationCanReadRepo {
r.SetInstallID(installation.GetID())
}

return r, nil
}

// WithGitHubInstallationPermission takes permissions and applies a new permission if valid.
func WithGitHubInstallationPermission(perms *github.InstallationPermissions, resource, perm string) (*github.InstallationPermissions, error) {
// convert permissions from yaml string
Expand Down
3 changes: 3 additions & 0 deletions scm/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ type Service interface {
// GetNetrc defines a function that returns the netrc
// password injected into build steps.
GetNetrcPassword(context.Context, *api.Repo, *api.User, []string, map[string]string) (string, error)
// SyncRepoWithInstallation defines a function that syncs
// a repo with the installation, if it exists.
SyncRepoWithInstallation(context.Context, *api.Repo) (*api.Repo, error)
// CreateChecks defines a function that creates
// a check for a given repo and check id.
CreateChecks(context.Context, *api.Repo, string, string, string) (int64, error)
Expand Down

0 comments on commit b60da20

Please sign in to comment.