This commit is contained in:
Benson Wong 2018-02-05 13:16:30 -08:00
Родитель a8deb58009 1cc0d7ee63
Коммит e7c26d89b8
5 изменённых файлов: 145 добавлений и 106 удалений

6
Gopkg.lock сгенерированный
Просмотреть файл

@ -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",