diff --git a/cmd/tk/bootstrap_github.go b/cmd/tk/bootstrap_github.go index 968c2b0d13..0b1452031c 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= --repository= + # Run bootstrap for a private repo and assign organization teams to it + bootstrap github --owner= --repository= --team= --team= + # Run bootstrap for a repository path bootstrap github --owner= --repository= --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 3d8b011167..d08b4ed0fc 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) }