Skip to content

Commit

Permalink
feat: refactor cli (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Sep 13, 2018
1 parent ac380bb commit 0ad995f
Show file tree
Hide file tree
Showing 8 changed files with 632 additions and 453 deletions.
File renamed without changes.
56 changes: 40 additions & 16 deletions fetch.go → cmd_pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/ioutil"
"log"
"os"
"strings"
"sync"

"github.com/google/go-github/github"
Expand All @@ -19,53 +20,76 @@ import (
"golang.org/x/oauth2"
)

type fetchOptions struct {
type pullOptions struct {
// db
DBOpts dbOptions

// fetch
// pull
Repos []string
GithubToken string `mapstructure:"github-token"`
GitlabToken string `mapstructure:"gitlab-token"`
// includeExternalDeps bool

Targets []string
}

func (opts fetchOptions) String() string {
func (opts pullOptions) String() string {
out, _ := json.Marshal(opts)
return string(out)
}

func fetchSetupFlags(flags *pflag.FlagSet, opts *fetchOptions) {
flags.StringSliceVarP(&opts.Repos, "repos", "r", []string{}, "list of repositories to aggregate issues from") // FIXME: get the default value dynamically from .git, if present
func pullSetupFlags(flags *pflag.FlagSet, opts *pullOptions) {
flags.StringVarP(&opts.GithubToken, "github-token", "", "", "GitHub Token with 'issues' access")
flags.StringVarP(&opts.GitlabToken, "gitlab-token", "", "", "GitLab Token with 'issues' access")
viper.BindPFlags(flags)
}

func newFetchCommand() *cobra.Command {
opts := &fetchOptions{}
func newPullCommand() *cobra.Command {
opts := &pullOptions{}
cmd := &cobra.Command{
Use: "fetch",
Use: "pull",
RunE: func(cmd *cobra.Command, args []string) error {
if err := viper.Unmarshal(opts); err != nil {
return err
}
return fetch(opts)
return pull(opts)
},
}
fetchSetupFlags(cmd.Flags(), opts)
pullSetupFlags(cmd.Flags(), opts)
dbSetupFlags(cmd.Flags(), &opts.DBOpts)
return cmd
}

func fetch(opts *fetchOptions) error {
logger().Debug("fetch", zap.Stringer("opts", *opts))
func getReposFromTargets(targets []string) []string {
reposMap := map[string]bool{}

for _, target := range targets {
if _, err := os.Stat(target); err == nil {
logger().Fatal("filesystem target are not yet supported")
}
repo := strings.Split(target, "/issues")[0]
reposMap[repo] = true
}
repos := []string{}
for repo := range reposMap {
repos = append(repos, repo)
}
return repos
}

func pull(opts *pullOptions) error {
logger().Debug("pull", zap.Stringer("opts", *opts))

var (
wg sync.WaitGroup
allIssues []*Issue
out = make(chan []*Issue, 100)
)
wg.Add(len(opts.Repos))
for _, repoURL := range opts.Repos {

repos := getReposFromTargets(opts.Targets)

wg.Add(len(repos))
for _, repoURL := range repos {
repo := NewRepo(repoURL)
switch repo.Provider() {
case GitHubProvider:
Expand Down Expand Up @@ -107,7 +131,7 @@ func fetch(opts *fetchOptions) error {
}(repo)
case GitLabProvider:
go func(repo Repo) {
client := gitlab.NewClient(nil, os.Getenv("GITLAB_TOKEN"))
client := gitlab.NewClient(nil, opts.GitlabToken)
client.SetBaseURL(fmt.Sprintf("%s/api/v4", repo.SiteURL()))

//projectID := url.QueryEscape(repo.RepoPath())
Expand All @@ -123,7 +147,7 @@ func fetch(opts *fetchOptions) error {
for {
issues, resp, err := client.Issues.ListProjectIssues(projectID, opts)
if err != nil {
logger().Error("failed to fetch issues", zap.Error(err))
logger().Error("failed to pull issues", zap.Error(err))
return
}
total += len(issues)
Expand Down
54 changes: 29 additions & 25 deletions render.go → cmd_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,33 @@ import (
"go.uber.org/zap"
)

type renderOptions struct {
// fetch
FetchOpts fetchOptions
NoFetch bool
type runOptions struct {
// pull
PullOpts pullOptions
NoPull bool

// db
DBOpts dbOptions

// render
RenderType string
// run
RunType string
ShowClosed bool `mapstructure:"show-closed"`
ShowOrphans bool
EpicLabel string
Destination string

Targets []string
//Preview bool
}

func (opts renderOptions) String() string {
func (opts runOptions) String() string {
out, _ := json.Marshal(opts)
return string(out)
}

func renderSetupFlags(flags *pflag.FlagSet, opts *renderOptions) {
flags.BoolVarP(&opts.NoFetch, "no-fetch", "f", false, "do not fetch new issues before rendering")
flags.StringVarP(&opts.RenderType, "type", "t", "roadmap", "graph type ('roadmap', 'orphans')")
func runSetupFlags(flags *pflag.FlagSet, opts *runOptions) {
flags.BoolVarP(&opts.NoPull, "no-pull", "f", false, "do not pull new issues before runing")
flags.StringVarP(&opts.RunType, "type", "t", "roadmap", "graph type ('roadmap', 'orphans')")
flags.BoolVarP(&opts.ShowClosed, "show-closed", "", false, "show closed issues")
flags.BoolVarP(&opts.ShowOrphans, "show-orphans", "", false, "show issues not linked to an epic")
flags.StringVarP(&opts.EpicLabel, "epic-label", "", "", "label used for epics (empty means issues with dependencies but without dependants)")
Expand All @@ -46,34 +48,36 @@ func renderSetupFlags(flags *pflag.FlagSet, opts *renderOptions) {
viper.BindPFlags(flags)
}

func newRenderCommand() *cobra.Command {
opts := &renderOptions{}
func newRunCommand() *cobra.Command {
opts := &runOptions{}
cmd := &cobra.Command{
Use: "render",
Use: "run",
RunE: func(cmd *cobra.Command, args []string) error {
if err := viper.Unmarshal(opts); err != nil {
return err
}
if err := viper.Unmarshal(&opts.FetchOpts); err != nil {
if err := viper.Unmarshal(&opts.PullOpts); err != nil {
return err
}
if err := viper.Unmarshal(&opts.DBOpts); err != nil {
return err
}
opts.FetchOpts.DBOpts = opts.DBOpts
return render(opts)
opts.PullOpts.DBOpts = opts.DBOpts
opts.PullOpts.Targets = args
opts.Targets = args
return run(opts)
},
}
renderSetupFlags(cmd.Flags(), opts)
fetchSetupFlags(cmd.Flags(), &opts.FetchOpts)
runSetupFlags(cmd.Flags(), opts)
pullSetupFlags(cmd.Flags(), &opts.PullOpts)
dbSetupFlags(cmd.Flags(), &opts.DBOpts)
return cmd
}

func render(opts *renderOptions) error {
logger().Debug("render", zap.Stringer("opts", *opts))
if !opts.NoFetch || !dbExists(&opts.DBOpts) {
if err := fetch(&opts.FetchOpts); err != nil {
func run(opts *runOptions) error {
logger().Debug("run", zap.Stringer("opts", *opts))
if !opts.NoPull || !dbExists(&opts.DBOpts) {
if err := pull(&opts.PullOpts); err != nil {
return err
}
}
Expand All @@ -88,16 +92,16 @@ func render(opts *renderOptions) error {
}

var out string
switch opts.RenderType {
switch opts.RunType {
case "roadmap":
out, err = roadmapGraph(issues, opts)
case "orphans":
out, err = orphansGraph(issues, opts)
default:
err = fmt.Errorf("unknown graph type: %q", opts.RenderType)
err = fmt.Errorf("unknown graph type: %q", opts.RunType)
}
if err != nil {
return errors.Wrap(err, "failed to render graph")
return errors.Wrap(err, "failed to run graph")
}

var dest io.WriteCloser
Expand Down
8 changes: 4 additions & 4 deletions examples/depviz/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
.PHONY: run
run:
depviz render -f | dot -Tsvg > depviz.svg
depviz render -t orphans -f | dot -Tsvg > orphans.svg
cat orphans.svg | grep -s text || rm orphans.svg
depviz run | dot -Tsvg > depviz.svg
depviz run -t orphans | dot -Tsvg > orphans.svg
cat orphans.svg | grep -q text || rm orphans.svg

.PHONY: preview
preview:
depviz render -f | dot -Tpng | imgcat
depviz run | dot -Tpng | imgcat
Loading

0 comments on commit 0ad995f

Please sign in to comment.