From 4f43b504f4ffde1abe5c98c41cc2e246b4d4e999 Mon Sep 17 00:00:00 2001
From: stefanprodan <stefan.prodan@gmail.com>
Date: Tue, 16 Jun 2020 14:29:47 +0300
Subject: [PATCH] Assign GitHub teams during bootstrap

---
 cmd/tk/bootstrap_github.go  | 56 ++++++++++++++++++++++++++++++++++++-
 cmd/tk/get_kustomization.go |  6 +++-
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/cmd/tk/bootstrap_github.go b/cmd/tk/bootstrap_github.go
index 968c2b0d..0b145203 100644
--- a/cmd/tk/bootstrap_github.go
+++ b/cmd/tk/bootstrap_github.go
@@ -43,6 +43,9 @@ the bootstrap command will perform an upgrade if needed.`,
   # Run bootstrap for a private repo owned by a GitHub organization
   bootstrap github --owner=<organization> --repository=<repo name>
 
+  # Run bootstrap for a private repo and assign organization teams to it
+  bootstrap github --owner=<organization> --repository=<repo name> --team=<team1 slug> --team=<team2 slug>
+
   # Run bootstrap for a repository path
   bootstrap github --owner=<organization> --repository=<repo name> --path=dev-cluster
 
@@ -63,6 +66,7 @@ var (
 	ghPrivate    bool
 	ghHostname   string
 	ghPath       string
+	ghTeams      []string
 )
 
 const (
@@ -72,11 +76,13 @@ const (
 	ghSourceManifest        = "toolkit-source.yaml"
 	ghKustomizationManifest = "toolkit-kustomization.yaml"
 	ghDefaultHostname       = "github.com"
+	ghDefaultPermission     = "maintain"
 )
 
 func init() {
 	bootstrapGitHubCmd.Flags().StringVar(&ghOwner, "owner", "", "GitHub user or organization name")
 	bootstrapGitHubCmd.Flags().StringVar(&ghRepository, "repository", "", "GitHub repository name")
+	bootstrapGitHubCmd.Flags().StringArrayVar(&ghTeams, "team", []string{}, "GitHub team to be given maintainer access")
 	bootstrapGitHubCmd.Flags().BoolVar(&ghPersonal, "personal", false, "is personal repository")
 	bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "is private repository")
 	bootstrapGitHubCmd.Flags().DurationVar(&ghInterval, "interval", time.Minute, "sync interval")
@@ -118,6 +124,19 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
+	withErrors := false
+	// add teams to org repository
+	if !ghPersonal {
+		for _, team := range ghTeams {
+			if err := addGitHubTeam(ctx, ghHostname, ghOwner, ghRepository, ghToken, team, ghDefaultPermission); err != nil {
+				logFailure(err.Error())
+				withErrors = true
+			} else {
+				logSuccess("%s team access granted", team)
+			}
+		}
+	}
+
 	// clone repository and checkout the master branch
 	repo, err := checkoutGitHubRepository(ctx, ghURL, ghBranch, ghToken, tmpDir)
 	if err != nil {
@@ -221,6 +240,10 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
 		}
 	}
 
+	if withErrors {
+		return fmt.Errorf("bootstrap completed with errors")
+	}
+
 	logSuccess("bootstrap finished")
 	return nil
 }
@@ -275,6 +298,37 @@ func createGitHubRepository(ctx context.Context, hostname, owner, name, token st
 	return nil
 }
 
+func addGitHubTeam(ctx context.Context, hostname, owner, repository, token string, teamSlug, permission string) error {
+	gh, err := makeGitHubClient(hostname, token)
+	if err != nil {
+		return err
+	}
+
+	// check team exists
+	_, _, err = gh.Teams.GetTeamBySlug(ctx, owner, teamSlug)
+	if err != nil {
+		return fmt.Errorf("github get team %s error: %w", teamSlug, err)
+	}
+
+	// check if team is assigned to the repo
+	_, resp, err := gh.Teams.IsTeamRepoBySlug(ctx, owner, teamSlug, owner, repository)
+	if resp == nil && err != nil {
+		return fmt.Errorf("github is team %s error: %w", teamSlug, err)
+	}
+
+	// add team to the repo
+	if resp.StatusCode == 404 {
+		_, err = gh.Teams.AddTeamRepoBySlug(ctx, owner, teamSlug, owner, repository, &github.TeamAddTeamRepoOptions{
+			Permission: permission,
+		})
+		if err != nil {
+			return fmt.Errorf("github add team %s error: %w", teamSlug, err)
+		}
+	}
+
+	return nil
+}
+
 func checkoutGitHubRepository(ctx context.Context, url, branch, token, path string) (*git.Repository, error) {
 	auth := &http.BasicAuth{
 		Username: "git",
@@ -423,7 +477,7 @@ func generateGitHubKustomization(url, name, namespace, targetPath, tmpDir string
 			Interval: metav1.Duration{
 				Duration: 10 * time.Minute,
 			},
-			Path:  "./" + strings.TrimPrefix("./", targetPath),
+			Path:  fmt.Sprintf("./%s", strings.TrimPrefix(targetPath, "./")),
 			Prune: true,
 			SourceRef: corev1.TypedLocalObjectReference{
 				APIGroup: &emptyAPIGroup,
diff --git a/cmd/tk/get_kustomization.go b/cmd/tk/get_kustomization.go
index 3d8b0111..d08b4ed0 100644
--- a/cmd/tk/get_kustomization.go
+++ b/cmd/tk/get_kustomization.go
@@ -51,7 +51,11 @@ func getKsCmdRun(cmd *cobra.Command, args []string) error {
 		for _, condition := range kustomization.Status.Conditions {
 			if condition.Type == kustomizev1.ReadyCondition {
 				if condition.Status != corev1.ConditionFalse {
-					logSuccess("%s last applied revision %s", kustomization.GetName(), kustomization.Status.LastAppliedRevision)
+					if kustomization.Status.LastAppliedRevision != "" {
+						logSuccess("%s last applied revision %s", kustomization.GetName(), kustomization.Status.LastAppliedRevision)
+					} else {
+						logSuccess("%s reconciling", kustomization.GetName())
+					}
 				} else {
 					logFailure("%s %s", kustomization.GetName(), condition.Message)
 				}
-- 
GitLab