зеркало из https://github.com/mozilla/pd-cli.git
Merge branch 'master' of https://github.com/mozilla/pd-cli
This commit is contained in:
Коммит
e7c26d89b8
|
@ -2,16 +2,16 @@
|
|||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/protobuf"
|
||||
packages = ["proto"]
|
||||
revision = "925541529c1fa6821df4e44ce2723319eb2be768"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/google/go-github"
|
||||
packages = ["github"]
|
||||
revision = "e48060a28fac52d0f1cb758bc8b87c07bac4a87d"
|
||||
version = "v15.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
@ -23,7 +23,7 @@
|
|||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context","context/ctxhttp"]
|
||||
revision = "0ed95abb35c445290478a5348a7b38bb154135fd"
|
||||
revision = "2fb46b16b8dda405028c50f7c7f0f9dd1fa6bfb1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
|
|
@ -4,11 +4,8 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
|
@ -39,7 +36,7 @@ func checkAll(c *cli.Context) error {
|
|||
checkLabels,
|
||||
checkUnassigned,
|
||||
checkUnlabled,
|
||||
checkMilestones,
|
||||
checkProjects,
|
||||
}
|
||||
|
||||
for _, f := range funcs {
|
||||
|
@ -98,6 +95,7 @@ func checkLabels(c *cli.Context) error {
|
|||
standardLabels := map[string]string{
|
||||
"bug": "b60205",
|
||||
"security": "b60205",
|
||||
"improvement": "0e8a16",
|
||||
"documentation": "0e8a16",
|
||||
"fix": "0e8a16",
|
||||
"new-feature": "0e8a16",
|
||||
|
@ -115,8 +113,8 @@ func checkLabels(c *cli.Context) error {
|
|||
continue
|
||||
}
|
||||
|
||||
name := *label.Name
|
||||
color := *label.Color
|
||||
name := label.GetName()
|
||||
color := label.GetColor()
|
||||
|
||||
if expectedColor, ok := standardLabels[name]; !ok {
|
||||
// not a standard label
|
||||
|
@ -162,11 +160,11 @@ func checkUnassigned(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
count := *results.Total
|
||||
count := results.GetTotal()
|
||||
if count > 0 {
|
||||
fmt.Fprintf(outError, " - Error: %d unassigned P1 issues\n", count)
|
||||
for _, issue := range results.Issues {
|
||||
fmt.Fprintf(outError, " #%-4d %s", *issue.Number, *issue.Title)
|
||||
fmt.Fprintf(outError, " #%-4d %s", issue.GetNumber(), issue.GetTitle())
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(outInfo, " - OK. All P1 issues assigned\n")
|
||||
|
@ -188,11 +186,11 @@ func checkUnlabled(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
unassigned := *results.Total
|
||||
unassigned := results.GetTotal()
|
||||
if unassigned > 0 {
|
||||
fmt.Fprintf(outError, " - Error: %d issues unlabeled\n", unassigned)
|
||||
for _, issue := range results.Issues {
|
||||
fmt.Fprintf(outError, " #%-4d %s\n", *issue.Number, *issue.Title)
|
||||
fmt.Fprintf(outError, " #%-4d %s\n", issue.GetNumber(), issue.GetTitle())
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(outInfo, " - OK. All issues are labeled\n")
|
||||
|
@ -201,93 +199,75 @@ func checkUnlabled(c *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func checkMilestones(c *cli.Context) error {
|
||||
func checkProjects(c *cli.Context) error {
|
||||
owner, repo, err := extractOwnerRepo(c.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outInfo, outError := getWriters(c)
|
||||
fmt.Fprintf(outInfo, "Checking Milestones\n")
|
||||
fmt.Fprintf(outInfo, "Checking Projects\n")
|
||||
ctx := context.Background()
|
||||
|
||||
milestones, _, err := ghClient.Issues.ListMilestones(ctx, owner, repo, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(outError, " - Error: Feteching milestones, %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
projects, _, err := ghClient.Repositories.ListProjects(ctx, owner, repo, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(outError, " - Error: Fetching projects, %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
pMap := make(map[string]*github.Project)
|
||||
for _, p := range projects {
|
||||
pMap[*p.Name] = p
|
||||
}
|
||||
projError := false
|
||||
for _, project := range projects {
|
||||
|
||||
errHappend := false
|
||||
for _, milestone := range milestones {
|
||||
if project, found := pMap[*milestone.Title]; !found {
|
||||
fmt.Fprintf(outError, " - Error: %s does not have a matching project", *milestone.Title)
|
||||
} else {
|
||||
// check the project's columns
|
||||
pCols, _, err := ghClient.Projects.ListProjectColumns(ctx, *project.ID, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(outError, " - Error: Fetching project columns, %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
if project.GetBody() == "" {
|
||||
fmt.Fprintf(outError, " - WARNING: Project [%s] *SHOULD* have a description\n", project.GetName())
|
||||
}
|
||||
|
||||
flags := 0
|
||||
for _, col := range pCols {
|
||||
switch *col.Name {
|
||||
case "Backlog":
|
||||
flags |= 0x01
|
||||
case "In Progress":
|
||||
flags |= 0x02
|
||||
case "Blocked":
|
||||
flags |= 0x04
|
||||
case "Completed":
|
||||
flags |= 0x08
|
||||
default:
|
||||
fmt.Fprintf(outError, ` - Error: Project "%s" has unexpected column %s\n`,
|
||||
*project.Name, *col.Name)
|
||||
errHappend = true
|
||||
}
|
||||
}
|
||||
// check the project's columns
|
||||
pCols, _, err := ghClient.Projects.ListProjectColumns(ctx, project.GetID(), nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(outError, " - Error: Fetching project columns, %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
if flags&0x01 == 0 {
|
||||
fmt.Fprintf(outError, ` - Error: Project "%s" missing "Backlog" column\n`, *project.Name)
|
||||
errHappend = true
|
||||
}
|
||||
if flags&0x02 == 0 {
|
||||
fmt.Fprintf(outError, ` - Error: Project "%s" missing "In Progress" column\n`, *project.Name)
|
||||
errHappend = true
|
||||
}
|
||||
if flags&0x04 == 0 {
|
||||
fmt.Fprintf(outError, ` - Error: Project "%s" missing "Blocked" column\n`, *project.Name)
|
||||
errHappend = true
|
||||
}
|
||||
if flags&0x08 == 0 {
|
||||
fmt.Fprintf(outError, ` - Error: Project "%s" missing "Completed" column\n`, *project.Name)
|
||||
errHappend = true
|
||||
flags := 0
|
||||
for _, col := range pCols {
|
||||
switch col.GetName() {
|
||||
case "Backlog":
|
||||
flags |= 0x01
|
||||
case "In Progress":
|
||||
flags |= 0x02
|
||||
case "Blocked":
|
||||
flags |= 0x04
|
||||
case "Completed":
|
||||
flags |= 0x08
|
||||
default:
|
||||
fmt.Fprintf(outError, " - Error: Project [%s] has unexpected column %s\n",
|
||||
project.GetName(), col.GetName())
|
||||
projError = true
|
||||
}
|
||||
}
|
||||
|
||||
if flags&0x01 == 0 {
|
||||
fmt.Fprintf(outError, " - Error: Project [%s] missing [Backlog] column\n", project.GetName())
|
||||
projError = true
|
||||
}
|
||||
if flags&0x02 == 0 {
|
||||
fmt.Fprintf(outError, " - Error: Project [%s] missing [In Progress] column\n", project.GetName())
|
||||
projError = true
|
||||
}
|
||||
if flags&0x04 == 0 {
|
||||
fmt.Fprintf(outError, " - Error: Project [%s] missing [Blocked] column\n", project.GetName())
|
||||
projError = true
|
||||
}
|
||||
if flags&0x08 == 0 {
|
||||
fmt.Fprintf(outError, " - Error: Project [%s] missing [Completed] column\n", project.GetName())
|
||||
projError = true
|
||||
}
|
||||
}
|
||||
|
||||
if !errHappend {
|
||||
fmt.Fprintf(outInfo, " - OK. Milestones verified\n")
|
||||
if !projError {
|
||||
fmt.Fprintf(outInfo, " - OK. Projects verified\n")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getWriters(c *cli.Context) (info, err io.Writer) {
|
||||
if c.Bool("quiet") {
|
||||
return ioutil.Discard, c.App.Writer
|
||||
} else {
|
||||
return c.App.Writer, c.App.Writer
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
|
@ -24,11 +26,13 @@ var (
|
|||
|
||||
// preflight ensures necessary flags and sets the package vars: ghClient, owner and repo
|
||||
func preflight(c *cli.Context) (err error) {
|
||||
_, outError := getWriters(c)
|
||||
|
||||
// set package vars
|
||||
ghtoken = c.String("ghtoken")
|
||||
|
||||
if ghtoken == "" {
|
||||
fmt.Fprintf(c.App.Writer, "Error: github access token required\n")
|
||||
fmt.Fprintf(outError, "Error: github access token required\n")
|
||||
err = errMissingFlag
|
||||
}
|
||||
|
||||
|
@ -46,6 +50,17 @@ func preflight(c *cli.Context) (err error) {
|
|||
tc := oauth2.NewClient(ctx, ts)
|
||||
ghClient = github.NewClient(tc)
|
||||
}
|
||||
|
||||
// check that we got the repo value, which should be the last thing in
|
||||
// the arg list
|
||||
args := c.Args()
|
||||
if len(args) > 0 {
|
||||
_, _, err = extractOwnerRepo(args[len(args)-1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(outError, "ERROR: %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -55,8 +70,16 @@ func extractOwnerRepo(arg string) (string, string, error) {
|
|||
parts := strings.Split(arg, "/")
|
||||
l := len(parts)
|
||||
if l < 2 {
|
||||
return "", "", errors.New("Invalid repo path, expect: owner/reponame")
|
||||
return "", "", errors.New("Invalid or missing repo path, expect: owner/reponame")
|
||||
}
|
||||
|
||||
return parts[l-2], parts[l-1], nil
|
||||
}
|
||||
|
||||
func getWriters(c *cli.Context) (info, err io.Writer) {
|
||||
if c.Bool("quiet") {
|
||||
return ioutil.Discard, c.App.Writer
|
||||
} else {
|
||||
return c.App.Writer, c.App.Writer
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package repo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
|
@ -15,7 +16,7 @@ func initRepo(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := createMilestone(c); err != nil {
|
||||
if err := createProject(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -29,7 +30,9 @@ func initLabels(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(c.App.Writer, "Initializing labels on %s/%s\n", owner, repo)
|
||||
outInfo, outError := getWriters(c)
|
||||
|
||||
fmt.Fprintf(outInfo, "Initializing labels on %s/%s\n", owner, repo)
|
||||
|
||||
// make Issue labels
|
||||
labels := map[string]string{
|
||||
|
@ -39,6 +42,7 @@ func initLabels(c *cli.Context) error {
|
|||
"P5": "ffa32c",
|
||||
"bug": "b60205",
|
||||
"security": "b60205",
|
||||
"improvement": "0e8a16",
|
||||
"documentation": "0e8a16",
|
||||
"fix": "0e8a16",
|
||||
"new-feature": "0e8a16",
|
||||
|
@ -56,17 +60,17 @@ func initLabels(c *cli.Context) error {
|
|||
label := &github.Label{Name: &name, Color: &color}
|
||||
_, _, err := ghClient.Issues.CreateLabel(ctx, owner, repo, label)
|
||||
if err != nil {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: Creating label %s\n", name)
|
||||
fmt.Fprintf(outError, " - Error: Creating label %s\n", name)
|
||||
continue
|
||||
} else {
|
||||
fmt.Fprintf(c.App.Writer, " - Created label %s\n", name)
|
||||
fmt.Fprintf(outError, " - Created label %s\n", name)
|
||||
}
|
||||
} else if *label.Color != color {
|
||||
_, _, err := ghClient.Issues.EditLabel(ctx, owner, repo, name, &github.Label{Color: &color})
|
||||
if err != nil {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: changing color for %s\n", name)
|
||||
fmt.Fprintf(outError, " - Error: changing color for %s\n", name)
|
||||
} else {
|
||||
fmt.Fprintf(c.App.Writer, " - Changed color for label %s to %s\n", name, color)
|
||||
fmt.Fprintf(outInfo, " - Changed color for label %s to %s\n", name, color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,43 +84,68 @@ func createMilestone(c *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
outInfo, outError := getWriters(c)
|
||||
|
||||
milestoneTitle := c.String("milestone")
|
||||
fmt.Fprintf(c.App.Writer, "Creating Milestone/Project: %s\n", milestoneTitle)
|
||||
fmt.Fprintf(outInfo, "Creating Milestone: %s\n", milestoneTitle)
|
||||
ctx := context.Background()
|
||||
milestones, _, err := ghClient.Issues.ListMilestones(ctx, owner, repo, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: Could not list milestones\n")
|
||||
fmt.Fprintf(outError, " - Error: Could not list milestones\n")
|
||||
return err
|
||||
}
|
||||
|
||||
// short circuit if milestone already exists
|
||||
for _, m := range milestones {
|
||||
if *m.Title == milestoneTitle {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: Milestone %s already exists\n", milestoneTitle)
|
||||
return nil
|
||||
fmt.Fprintf(outError, " - Error: Milestone [%s] already exists\n", milestoneTitle)
|
||||
return errors.New("Duplicate Milestone Name")
|
||||
}
|
||||
}
|
||||
|
||||
milestone := &github.Milestone{Title: &milestoneTitle}
|
||||
if _, _, err := ghClient.Issues.CreateMilestone(ctx, owner, repo, milestone); err != nil {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: Creating milestone %s: %s\n", milestoneTitle, err.Error())
|
||||
fmt.Fprintf(outError, " - Error: Creating milestone %s: %s\n", milestoneTitle, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// Make Project w/ Backlog, In Progress, Blocked and Completed
|
||||
// ... note: it will always create a new Project 1.0. Your repo will just have
|
||||
// multiple ones if you run this several times..
|
||||
fmt.Fprintf(c.App.Writer, " - Creating milestone %s\n", milestoneTitle)
|
||||
project := &github.ProjectOptions{Name: milestoneTitle}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createProject(c *cli.Context) error {
|
||||
owner, repo, err := extractOwnerRepo(c.Args().Get(0))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
projectTitle := c.String("project")
|
||||
outInfo, outError := getWriters(c)
|
||||
ctx := context.Background()
|
||||
|
||||
projects, _, err := ghClient.Repositories.ListProjects(ctx, owner, repo, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(outError, " - Error: Fetching projects, %s\n", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
for _, project := range projects {
|
||||
if project.GetName() == projectTitle {
|
||||
fmt.Fprintf(outError, " - Error: Project [%s] already exists\n", projectTitle)
|
||||
return errors.New("Duplicate Project Name")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(outInfo, "Creating Project %s\n", projectTitle)
|
||||
project := &github.ProjectOptions{Name: projectTitle}
|
||||
if proj, _, err := ghClient.Repositories.CreateProject(ctx, owner, repo, project); err != nil {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: Creating Project %s: %s\n", milestoneTitle, err.Error())
|
||||
fmt.Fprintf(outError, " - Error: Creating Project %s: %s\n", projectTitle, err.Error())
|
||||
return err
|
||||
} else {
|
||||
fmt.Fprintf(c.App.Writer, " - Created project %s\n", milestoneTitle)
|
||||
fmt.Fprintf(outInfo, " - Created project %s\n", projectTitle)
|
||||
for _, colName := range []string{"Backlog", "In Progress", "Blocked", "Completed"} {
|
||||
ops := &github.ProjectColumnOptions{Name: colName}
|
||||
if _, _, err := ghClient.Projects.CreateProjectColumn(ctx, *proj.ID, ops); err != nil {
|
||||
fmt.Fprintf(c.App.Writer, " - Error: creating Project Column [%s]: %s\n", colName, err.Error())
|
||||
fmt.Fprintf(outError, " - Error: Creating Project Column [%s]: %s\n", colName, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ func NewCommand() cli.Command {
|
|||
Subcommands: cli.Commands{
|
||||
cli.Command{
|
||||
Name: "init",
|
||||
Usage: "initializes labels and a milestone for a repo",
|
||||
Usage: "initializes labels and a project for a repo",
|
||||
Flags: []cli.Flag{cli.StringFlag{
|
||||
Name: "milestone, m",
|
||||
Name: "project, p",
|
||||
Value: "Version 1.0",
|
||||
Usage: "initial milestone",
|
||||
Usage: "initial project to create",
|
||||
}},
|
||||
Action: initRepo,
|
||||
},
|
||||
|
@ -39,7 +39,14 @@ func NewCommand() cli.Command {
|
|||
}},
|
||||
Action: createMilestone,
|
||||
},
|
||||
|
||||
cli.Command{
|
||||
Name: "create-project",
|
||||
Usage: "creates a project with standard columns",
|
||||
Flags: []cli.Flag{cli.StringFlag{
|
||||
Name: "p, project",
|
||||
}},
|
||||
Action: createProject,
|
||||
},
|
||||
cli.Command{
|
||||
Name: "check",
|
||||
Usage: "checks to verify standards conformity",
|
||||
|
@ -100,9 +107,9 @@ func NewCommand() cli.Command {
|
|||
},
|
||||
},
|
||||
cli.Command{
|
||||
Name: "milestones",
|
||||
Usage: "verify milestones have a project to track them",
|
||||
Action: checkMilestones,
|
||||
Name: "projects",
|
||||
Usage: "verify projects fit standards",
|
||||
Action: checkProjects,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
|
|
Загрузка…
Ссылка в новой задаче