diff --git a/cmd/community/main.go b/cmd/community/main.go index f54ba51..6c6ad46 100644 --- a/cmd/community/main.go +++ b/cmd/community/main.go @@ -13,6 +13,7 @@ var app = &cli.App{ Commands: []*cli.Command{ teamCmd, reportCmd, + trackCmd, }, } diff --git a/cmd/community/track.go b/cmd/community/track.go new file mode 100644 index 0000000..80d1d3c --- /dev/null +++ b/cmd/community/track.go @@ -0,0 +1,89 @@ +package main + +import ( + "context" + "fmt" + "io/ioutil" + + "github.com/gobwas/glob" + "github.com/urfave/cli/v2" + + "github.com/beyondstorage/go-community/env" + "github.com/beyondstorage/go-community/services" +) + +var trackCmd = &cli.Command{ + Name: "track", + Usage: "maintain community tracking issues", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "title", + Usage: "the tracking issue title", + }, + &cli.StringFlag{ + Name: "path", + Usage: "the tracking issue content path", + }, + &cli.StringFlag{ + Name: "repo", + Usage: "the tracking repos, support glob style like go-service-*", + }, + &cli.StringFlag{ + Name: "owner", + Usage: "github organization name", + Required: true, + EnvVars: []string{ + env.GithubOwner, + }, + }, + &cli.StringFlag{ + Name: "token", + Usage: "github access token", + Required: true, + EnvVars: []string{ + env.GithubAccessToken, + }, + }, + }, + Action: func(c *cli.Context) (err error) { + owner := c.String("owner") + + g, err := services.NewGithub( + owner, + c.String("token")) + if err != nil { + return + } + + ctx := context.Background() + + repoGlob, err := glob.Compile(c.String("repo")) + if err != nil { + return fmt.Errorf("invalid glob pattern: %s", c.String("repo")) + } + + content, err := ioutil.ReadFile(c.String("path")) + if err != nil { + return err + } + + repos, err := g.ListRepos(ctx, owner) + if err != nil { + return err + } + + for _, v := range repos { + // Ignore all non-matched repos. + if !repoGlob.Match(v) { + continue + } + + url, err := g.CreateIssue(ctx, v, c.String("title"), string(content)) + if err != nil { + return err + } + fmt.Printf("Created issue %s\n", url) + } + return nil + }, +} diff --git a/go.mod b/go.mod index 8f22203..5d0461d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.15 require ( github.com/BurntSushi/toml v0.3.1 + github.com/gobwas/glob v0.2.3 github.com/google/go-github/v35 v35.3.0 github.com/pkg/errors v0.9.1 // indirect github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 0af7693..05df703 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/services/github.go b/services/github.go index 755b9e0..5477c21 100644 --- a/services/github.go +++ b/services/github.go @@ -220,6 +220,17 @@ func (g *Github) CreateWeeklyReportIssue(ctx context.Context, repo, content stri return issue.GetHTMLURL(), nil } +func (g *Github) CreateIssue(ctx context.Context, repo, title, content string) (issueURL string, err error) { + issue, _, err := g.client.Issues.Create(ctx, g.owner, repo, &github.IssueRequest{ + Title: github.String(title), + Body: github.String(content), + }) + if err != nil { + return + } + return issue.GetHTMLURL(), nil +} + func (g *Github) listTeams(ctx context.Context) (teams map[string]*github.Team, err error) { opt := &github.ListOptions{ PerPage: 100,