Skip to content
This repository was archived by the owner on Sep 6, 2025. It is now read-only.

Commit 3cb82ec

Browse files
authored
Merge pull request #6 from hellofresh/improved-repo-creation
Improved repo creation
2 parents ce5bc52 + 6f81c20 commit 3cb82ec

File tree

9 files changed

+144
-39
lines changed

9 files changed

+144
-39
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ script:
1111
- make test
1212

1313
before_deploy:
14+
- export VERSION = ${TRAVIS_BRANCH}
1415
- make
1516

1617
deploy:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ github-cli [command] [--flags]
3434
| `github-cli repo create [--flags]` | Creates a new github repository |
3535
| `github-cli test create [--flags]` | Creates a new hellofresh hiring test |
3636
| `github-cli unseat [--flags]` | Removes external collaborators from repositories |
37+
| `github-cli version` | Prints the version information |
3738

3839
## Contributing
3940

cmd/create_repo.go

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"github.com/fatih/color"
5+
"github.com/google/go-github/github"
56
"github.com/hellofresh/github-cli/pkg/pullapprove"
67
"github.com/hellofresh/github-cli/pkg/repo"
78
"github.com/pkg/errors"
@@ -22,6 +23,9 @@ type (
2223
HasDefaultLabels bool
2324
HasWebhooks bool
2425
HasBranchProtections bool
26+
HasIssues bool
27+
HasWiki bool
28+
HasPages bool
2529
}
2630
)
2731

@@ -34,28 +38,32 @@ func init() {
3438
createRepoCmd.Flags().StringVarP(&createRepoFlags.Description, "description", "d", "", "The repository's description")
3539
createRepoCmd.Flags().StringVarP(&createRepoFlags.Org, "organization", "o", "", "Github's organization")
3640
createRepoCmd.Flags().BoolVar(&createRepoFlags.Private, "private", true, "Is the repository private?")
37-
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasPullApprove, "add-pullapprove", true, "Enables pull approve")
38-
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasTeams, "add-teams", true, "Enable teams")
39-
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasLabels, "add-labels", true, "Enable labels")
40-
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasDefaultLabels, "add-default-labels", true, "Removes the default github labels")
41-
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasWebhooks, "add-webhooks", true, "Enables webhooks configurations")
42-
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasBranchProtections, "add-branch-protections", true, "Enables branch protections")
41+
42+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasIssues, "has-issues", true, "Enables issue pages")
43+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasWiki, "has-wiki", false, "Enables wiki pages?")
44+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasPages, "has-pages", false, "Enables github pages?")
45+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasPullApprove, "has-pullapprove", true, "Enables pull approve")
46+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasTeams, "has-teams", true, "Enable teams")
47+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasLabels, "has-labels", true, "Enable labels")
48+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasDefaultLabels, "rm-default-labels", true, "Removes the default github labels")
49+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasWebhooks, "has-webhooks", false, "Enables webhooks configurations")
50+
createRepoCmd.Flags().BoolVar(&createRepoFlags.HasBranchProtections, "has-branch-protections", true, "Enables branch protections")
4351
}
4452

4553
// RunCreateRepo runs the command to create a new repository
4654
func RunCreateRepo(cmd *cobra.Command, args []string) {
4755
var err error
56+
var org string
4857

4958
name := createRepoFlags.Name
5059
checkEmpty(name, "Please provide a repository name")
5160

5261
description := createRepoFlags.Description
5362

54-
org := createRepoFlags.Org
63+
org = createRepoFlags.Org
5564
if org == "" {
5665
org = globalConfig.Github.Organization
5766
}
58-
checkEmpty(org, "Please provide an organization")
5967

6068
opts := &repo.GithubRepoOpts{
6169
PullApprove: &repo.PullApproveOpts{
@@ -75,7 +83,15 @@ func RunCreateRepo(cmd *cobra.Command, args []string) {
7583
creator := repo.NewGithub(githubClient)
7684

7785
color.White("Creating repository...")
78-
err = creator.CreateRepo(name, description, org, createRepoFlags.Private)
86+
ghRepo, err := creator.CreateRepo(org, &github.Repository{
87+
Name: github.String(name),
88+
Description: github.String(description),
89+
Private: github.Bool(createRepoFlags.Private),
90+
HasIssues: github.Bool(createRepoFlags.HasIssues),
91+
HasWiki: github.Bool(createRepoFlags.HasWiki),
92+
HasPages: github.Bool(createRepoFlags.HasPages),
93+
AutoInit: github.Bool(true),
94+
})
7995
if errors.Cause(err) == repo.ErrRepositoryAlreadyExists {
8096
color.Cyan("Repository already exists. Trying to normalize it...")
8197
} else {
@@ -120,16 +136,19 @@ func RunCreateRepo(cmd *cobra.Command, args []string) {
120136
if errors.Cause(err) == repo.ErrWebhookAlreadyExist {
121137
color.Cyan("Webhook already exists, moving on...")
122138
} else {
123-
checkEmpty(errors.Wrap(err, "could add webhooks to repository"), "")
139+
checkEmpty(errors.Wrap(err, "could not add webhooks to repository"), "")
124140
}
125141
}
126142

127143
if createRepoFlags.HasBranchProtections {
128144
color.White("Adding branch protections to repository...")
129145
err = creator.AddBranchProtections(name, org, opts.BranchProtections)
130-
checkEmpty(errors.Wrap(err, "could add branch protections to repository"), "")
146+
checkEmpty(errors.Wrap(err, "could not add branch protections to repository"), "")
131147
}
132148

133-
color.Green("Repository created!")
134-
checkEmpty(err, "Could not create github repo")
149+
if ghRepo != nil {
150+
color.Green("Repository created! \n Here is how to access it %s", *ghRepo.URL)
151+
} else {
152+
color.Green("Repository normalized!")
153+
}
135154
}

cmd/create_test_repo.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os/user"
88

99
"github.com/fatih/color"
10+
"github.com/google/go-github/github"
1011
"github.com/hellofresh/github-cli/pkg/config"
1112
"github.com/hellofresh/github-cli/pkg/repo"
1213
"github.com/pkg/errors"
@@ -56,7 +57,13 @@ func RunCreateTestRepo(cmd *cobra.Command, args []string) {
5657
creator := repo.NewGithub(githubClient)
5758

5859
color.White("Creating repository...")
59-
err = creator.CreateRepo(target, "", org, true)
60+
_, err = creator.CreateRepo(org, &github.Repository{
61+
Name: github.String(target),
62+
Private: github.Bool(true),
63+
HasIssues: github.Bool(false),
64+
HasPages: github.Bool(false),
65+
HasWiki: github.Bool(false),
66+
})
6067
checkEmpty(err, "Could not create github repo for candidate")
6168

6269
color.White("Adding collaborators to repository...")

cmd/delete_repo.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
6+
"github.com/fatih/color"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
type (
11+
// DeleteRepoFlags are the flags for the delete repo command
12+
DeleteRepoFlags struct {
13+
Org string
14+
Name string
15+
}
16+
)
17+
18+
var (
19+
deleteRepoFlags DeleteRepoFlags
20+
21+
// Delete repo command
22+
deleteRepoCmd = &cobra.Command{
23+
Use: "delete",
24+
Aliases: []string{"del"},
25+
Short: "Deletes a github repository",
26+
Run: RunDeleteRepo,
27+
}
28+
)
29+
30+
func init() {
31+
repoCmd.AddCommand(deleteRepoCmd)
32+
33+
deleteRepoCmd.Flags().StringVarP(&deleteRepoFlags.Name, "name", "n", "", "The name of the repository")
34+
deleteRepoCmd.Flags().StringVarP(&deleteRepoFlags.Org, "organization", "o", "", "Github's organization")
35+
}
36+
37+
// RunDeleteRepo runs the command to delete a repository
38+
func RunDeleteRepo(cmd *cobra.Command, args []string) {
39+
org := deleteRepoFlags.Org
40+
if org == "" {
41+
org = globalConfig.Github.Organization
42+
}
43+
checkEmpty(org, "Please provide an organization")
44+
45+
_, err := githubClient.Repositories.Delete(context.Background(), org, deleteRepoFlags.Name)
46+
checkEmpty(err, "Could not delete repository")
47+
48+
color.Green("Repository %s deleted!", deleteRepoFlags.Name)
49+
}

cmd/root.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ var (
1616
cfgFile string
1717
globalConfig *config.Spec
1818
githubClient *github.Client
19-
version string
2019
token string
2120

2221
// RootCmd is our main command
@@ -54,15 +53,6 @@ var (
5453
Long: `Creates a new hellofresh hiring test based on the rules defined on your .github.toml`,
5554
Run: RunCreateTestRepo,
5655
}
57-
58-
// Unseat commands
59-
unseatCmd = &cobra.Command{
60-
Use: "unseat",
61-
Aliases: []string{"un"},
62-
Short: "Removes external collaborators from repositories",
63-
Long: `Removes external (people not in the organization) collaborators from repositories`,
64-
Run: RunUnseat,
65-
}
6656
)
6757

6858
func init() {
@@ -100,6 +90,7 @@ func init() {
10090
RootCmd.PersistentFlags().StringVarP(&token, "token", "t", "", "config file (default is /etc/github/.github.toml)")
10191

10292
// Aggregates Root commands
93+
RootCmd.AddCommand(versionCmd)
10394
RootCmd.AddCommand(repoCmd)
10495
RootCmd.AddCommand(testsCmd)
10596
RootCmd.AddCommand(unseatCmd)

cmd/unseat.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,18 @@ type (
1717
}
1818
)
1919

20-
var unseatFlags UnseatFlags
20+
var (
21+
unseatFlags UnseatFlags
22+
23+
// Unseat commands
24+
unseatCmd = &cobra.Command{
25+
Use: "unseat",
26+
Aliases: []string{"un"},
27+
Short: "Removes external collaborators from repositories",
28+
Long: `Removes external (people not in the organization) collaborators from repositories`,
29+
Run: RunUnseat,
30+
}
31+
)
2132

2233
func init() {
2334
unseatCmd.Flags().StringVarP(&unseatFlags.Org, "organization", "o", "", "Github's organization")

cmd/version.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package cmd
2+
3+
import (
4+
"github.com/fatih/color"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
var (
9+
version = "0.0.0-dev"
10+
11+
versionCmd = &cobra.Command{
12+
Use: "version",
13+
Short: "Print the version information",
14+
Aliases: []string{"v"},
15+
Run: RunVersion,
16+
}
17+
)
18+
19+
// RunVersion runs the command to print the current version
20+
func RunVersion(cmd *cobra.Command, args []string) {
21+
color.Green("github-cli %s", version)
22+
}

pkg/repo/github.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package repo
33
import (
44
"context"
55
"net/http"
6+
"strings"
67

78
"github.com/google/go-github/github"
89
"github.com/hellofresh/github-cli/pkg/config"
@@ -11,7 +12,7 @@ import (
1112
)
1213

1314
type (
14-
// GithubRepo contains all the hellofresh repository creation Optss for github
15+
// GithubRepo contains all the hellofresh repository creation Opts for github
1516
GithubRepo struct {
1617
GithubClient *github.Client
1718
}
@@ -44,12 +45,16 @@ var (
4445
ctx = context.Background()
4546
// ErrRepositoryAlreadyExists is used when the repository already exists
4647
ErrRepositoryAlreadyExists = errors.New("github repository already exists")
48+
// ErrRepositoryLimitExceeded is used when the repository limit is exceeded
49+
ErrRepositoryLimitExceeded = errors.New("limit for private repos on this account is exceeded")
4750
// ErrPullApproveFileAlreadyExists is used when the pull approve file already exists
4851
ErrPullApproveFileAlreadyExists = errors.New("github pull approve file already exists")
4952
// ErrLabelNotFound is used when a label is not found
5053
ErrLabelNotFound = errors.New("github label does not exist")
5154
// ErrWebhookAlreadyExist is used when a webhook already exists
5255
ErrWebhookAlreadyExist = errors.New("github webhook already exists")
56+
// ErrOrganizationNotFound is used when a webhook already exists
57+
ErrOrganizationNotFound = errors.New("you must specify an organization to use this functionality")
5358
)
5459

5560
// NewGithub creates a new instance of Client
@@ -60,22 +65,17 @@ func NewGithub(githubClient *github.Client) *GithubRepo {
6065
}
6166

6267
// CreateRepo creates a github repository
63-
func (c *GithubRepo) CreateRepo(name string, description string, org string, private bool) error {
64-
repo := &github.Repository{
65-
Name: github.String(name),
66-
Description: github.String(description),
67-
Private: github.Bool(private),
68-
HasIssues: github.Bool(true),
69-
}
70-
71-
_, _, err := c.GithubClient.Repositories.Create(ctx, org, repo)
68+
func (c *GithubRepo) CreateRepo(org string, repoOpts *github.Repository) (*github.Repository, error) {
69+
ghRepo, _, err := c.GithubClient.Repositories.Create(ctx, org, repoOpts)
7270
if githubError, ok := err.(*github.ErrorResponse); ok {
73-
if githubError.Response.StatusCode == http.StatusUnprocessableEntity {
74-
err = errors.Wrap(ErrRepositoryAlreadyExists, "repository already exists")
71+
if strings.Contains(githubError.Message, "Visibility can't be private") {
72+
err = ErrRepositoryLimitExceeded
73+
} else if githubError.Response.StatusCode == http.StatusUnprocessableEntity {
74+
err = ErrRepositoryAlreadyExists
7575
}
7676
}
7777

78-
return err
78+
return ghRepo, err
7979
}
8080

8181
// AddPullApprove adds a file to the github repository and calls pull approve API to register the new repo
@@ -93,7 +93,7 @@ func (c *GithubRepo) AddPullApprove(repo string, org string, opts *PullApproveOp
9393
_, _, err = c.GithubClient.Repositories.CreateFile(ctx, org, repo, opts.Filename, fileOpt)
9494
if githubError, ok := err.(*github.ErrorResponse); ok {
9595
if githubError.Response.StatusCode == http.StatusUnprocessableEntity {
96-
return errors.Wrap(ErrPullApproveFileAlreadyExists, "pull approve file already exists")
96+
return ErrPullApproveFileAlreadyExists
9797
}
9898
} else {
9999
return err
@@ -111,6 +111,10 @@ func (c *GithubRepo) AddPullApprove(repo string, org string, opts *PullApproveOp
111111
func (c *GithubRepo) AddTeamsToRepo(repo string, org string, teams []*config.Team) error {
112112
var err error
113113

114+
if org == "" {
115+
return ErrOrganizationNotFound
116+
}
117+
114118
for _, team := range teams {
115119
opt := &github.OrganizationAddTeamRepoOptions{
116120
Permission: team.Permission,

0 commit comments

Comments
 (0)