diff --git a/app/app.go b/app/app.go new file mode 100644 index 0000000..bfe7c3f --- /dev/null +++ b/app/app.go @@ -0,0 +1,75 @@ +package app + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + + "github.com/google/go-github/v29/github" + jira "gopkg.in/andygrunwald/go-jira.v1" + + "git.ctrlz.es/mgdelacroix/campaigner/model" +) + +type App struct { + Path string + + jiraClient *jira.Client + githubClient *github.Client + Campaign *model.Campaign +} + +func SaveCampaign(campaign *model.Campaign, path string) error { + marshaledCampaign, err := json.MarshalIndent(campaign, "", " ") + if err != nil { + return err + } + + if err := ioutil.WriteFile(path, marshaledCampaign, 0600); err != nil { + return fmt.Errorf("cannot save campaign: %w", err) + } + return nil +} + +func (a *App) Save() error { + return SaveCampaign(a.Campaign, a.Path) +} + +func (a *App) Load() error { + if _, err := os.Stat("."); err != nil { + return fmt.Errorf("cannot read campaign: %w", err) + } + + fileContents, err := ioutil.ReadFile(a.Path) + if err != nil { + return fmt.Errorf("there was a problem reading the campaign file: %w", err) + } + + var campaign model.Campaign + if err := json.Unmarshal(fileContents, &campaign); err != nil { + return fmt.Errorf("there was a problem parsing the campaign file: %w", err) + } + + a.Campaign = &campaign + return nil +} + +func (a *App) InitClients() error { + if err := a.InitGithubClient(); err != nil { + return err + } + if err := a.InitJiraClient(); err != nil { + return err + } + return nil +} + +func NewApp(path string) (*App, error) { + app := &App{Path: path} + + if err := app.Load(); err != nil { + return nil, err + } + return app, nil +} diff --git a/github/github.go b/app/github.go similarity index 58% rename from github/github.go rename to app/github.go index 7dceedd..61f6e43 100644 --- a/github/github.go +++ b/app/github.go @@ -1,4 +1,4 @@ -package github +package app import ( "bytes" @@ -7,7 +7,6 @@ import ( "fmt" "text/template" - "git.ctrlz.es/mgdelacroix/campaigner/campaign" "git.ctrlz.es/mgdelacroix/campaigner/model" "github.com/StevenACoffman/j2m" @@ -15,21 +14,13 @@ import ( "golang.org/x/oauth2" ) -type GithubClient struct { - *github.Client - Repo string -} - -func NewClient(repo, token string) *GithubClient { +func (a *App) InitGithubClient() error { ctx := context.Background() - ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) + ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: a.Campaign.Github.Token}) tc := oauth2.NewClient(ctx, ts) - client := github.NewClient(tc) - return &GithubClient{ - Client: client, - Repo: repo, - } + a.githubClient = github.NewClient(tc) + return nil } func getFooterTemplate(ticket *model.Ticket, templatePath string) (string, error) { @@ -45,10 +36,10 @@ func getFooterTemplate(ticket *model.Ticket, templatePath string) (string, error return footerBytes.String(), nil } -func (c *GithubClient) PublishTicket(ticket *model.Ticket, cmp *model.Campaign, dryRun bool) (*github.Issue, error) { +func (a *App) PublishInGithub(ticket *model.Ticket, dryRun bool) (*github.Issue, error) { mdDescription := j2m.JiraToMD(ticket.Description) - if cmp.FooterTemplate != "" { - footer, err := getFooterTemplate(ticket, cmp.FooterTemplate) + if a.Campaign.FooterTemplate != "" { + footer, err := getFooterTemplate(ticket, a.Campaign.FooterTemplate) if err != nil { return nil, err } @@ -59,7 +50,7 @@ func (c *GithubClient) PublishTicket(ticket *model.Ticket, cmp *model.Campaign, issueRequest := &github.IssueRequest{ Title: &ticket.Summary, Body: &mdDescription, - Labels: &cmp.Github.Labels, + Labels: &a.Campaign.Github.Labels, } if dryRun { @@ -71,21 +62,21 @@ func (c *GithubClient) PublishTicket(ticket *model.Ticket, cmp *model.Campaign, }, nil } - owner, repo := cmp.RepoComponents() - newIssue, _, err := c.Issues.Create(context.Background(), owner, repo, issueRequest) + owner, repo := a.Campaign.RepoComponents() + newIssue, _, err := a.githubClient.Issues.Create(context.Background(), owner, repo, issueRequest) if err != nil { return nil, err } return newIssue, nil } -func (c *GithubClient) PublishNextTicket(cmp *model.Campaign, dryRun bool) (bool, error) { - ticket := cmp.NextGithubUnpublishedTicket() +func (a *App) PublishNextInGithub(dryRun bool) (bool, error) { + ticket := a.Campaign.NextGithubUnpublishedTicket() if ticket == nil { return false, nil } - issue, err := c.PublishTicket(ticket, cmp, dryRun) + issue, err := a.PublishInGithub(ticket, dryRun) if err != nil { return false, err } @@ -99,16 +90,16 @@ func (c *GithubClient) PublishNextTicket(cmp *model.Campaign, dryRun bool) (bool ticket.GithubAssignee = user.GetLogin() } ticket.GithubStatus = issue.GetState() - if err := campaign.Save(cmp); err != nil { + if err := a.Save(); err != nil { return false, err } return true, nil } -func (c *GithubClient) PublishAll(cmp *model.Campaign, dryRun bool) (int, error) { +func (a *App) PublishAllInGithub(dryRun bool) (int, error) { count := 0 for { - next, err := c.PublishNextTicket(cmp, dryRun) + next, err := a.PublishNextInGithub(dryRun) if err != nil { return count, err } @@ -120,9 +111,9 @@ func (c *GithubClient) PublishAll(cmp *model.Campaign, dryRun bool) (int, error) return count, nil } -func (c *GithubClient) PublishBatch(cmp *model.Campaign, batch int, dryRun bool) error { +func (a *App) PublishBatchInGithub(batch int, dryRun bool) error { for i := 1; i <= batch; i++ { - next, err := c.PublishNextTicket(cmp, dryRun) + next, err := a.PublishNextInGithub(dryRun) if err != nil { return err } diff --git a/jira/jira.go b/app/jira.go similarity index 51% rename from jira/jira.go rename to app/jira.go index 4f8bc42..860251f 100644 --- a/jira/jira.go +++ b/app/jira.go @@ -1,4 +1,4 @@ -package jira +package app import ( "bytes" @@ -6,32 +6,28 @@ import ( "fmt" "text/template" - "git.ctrlz.es/mgdelacroix/campaigner/campaign" "git.ctrlz.es/mgdelacroix/campaigner/model" jira "gopkg.in/andygrunwald/go-jira.v1" ) -type JiraClient struct { - *jira.Client -} - -func NewClient(url, username, token string) (*JiraClient, error) { +func (a *App) InitJiraClient() error { tp := jira.BasicAuthTransport{ - Username: username, - Password: token, + Username: a.Campaign.Jira.Username, + Password: a.Campaign.Jira.Token, } - client, err := jira.NewClient(tp.Client(), url) + client, err := jira.NewClient(tp.Client(), a.Campaign.Jira.Url) if err != nil { - return nil, err + return err } - return &JiraClient{client}, nil + a.jiraClient = client + return nil } -func (c *JiraClient) GetIssueFromTicket(ticket *model.Ticket, cmp *model.Campaign) (*jira.Issue, error) { - summaryTmpl, err := template.New("").Parse(cmp.Summary) +func (a *App) GetJiraIssueFromTicket(ticket *model.Ticket) (*jira.Issue, error) { + summaryTmpl, err := template.New("").Parse(a.Campaign.Summary) if err != nil { return nil, err } @@ -42,7 +38,7 @@ func (c *JiraClient) GetIssueFromTicket(ticket *model.Ticket, cmp *model.Campaig } summary := summaryBytes.String() - descriptionTemplate, err := template.ParseFiles(cmp.IssueTemplate) + descriptionTemplate, err := template.ParseFiles(a.Campaign.IssueTemplate) if err != nil { return nil, err } @@ -56,22 +52,22 @@ func (c *JiraClient) GetIssueFromTicket(ticket *model.Ticket, cmp *model.Campaig data := map[string]string{ "Description": description, "Summary": summary, - "Project": cmp.Jira.Project, - "Issue Type": cmp.Jira.IssueType, - "Epic Link": cmp.Jira.Epic, + "Project": a.Campaign.Jira.Project, + "Issue Type": a.Campaign.Jira.IssueType, + "Epic Link": a.Campaign.Jira.Epic, } - createMetaInfo, _, err := c.Issue.GetCreateMeta(cmp.Jira.Project) + createMetaInfo, _, err := a.jiraClient.Issue.GetCreateMeta(a.Campaign.Jira.Project) if err != nil { return nil, err } - project := createMetaInfo.GetProjectWithKey(cmp.Jira.Project) + project := createMetaInfo.GetProjectWithKey(a.Campaign.Jira.Project) if project == nil { - return nil, fmt.Errorf("Error retrieving project with key %s", cmp.Jira.Project) + return nil, fmt.Errorf("Error retrieving project with key %s", a.Campaign.Jira.Project) } - issueType := project.GetIssueTypeWithName(cmp.Jira.IssueType) + issueType := project.GetIssueTypeWithName(a.Campaign.Jira.IssueType) if issueType == nil { return nil, fmt.Errorf("Error retrieving issue type with name Story") } @@ -84,8 +80,8 @@ func (c *JiraClient) GetIssueFromTicket(ticket *model.Ticket, cmp *model.Campaig return issue, nil } -func (c *JiraClient) PublishTicket(ticket *model.Ticket, cmp *model.Campaign, dryRun bool) (*jira.Issue, error) { - issue, err := c.GetIssueFromTicket(ticket, cmp) +func (a *App) PublishInJira(ticket *model.Ticket, dryRun bool) (*jira.Issue, error) { + issue, err := a.GetJiraIssueFromTicket(ticket) if err != nil { return nil, err } @@ -96,7 +92,7 @@ func (c *JiraClient) PublishTicket(ticket *model.Ticket, cmp *model.Campaign, dr return issue, nil } - newIssue, _, err := c.Issue.Create(issue) + newIssue, _, err := a.jiraClient.Issue.Create(issue) if err != nil { return nil, err } @@ -104,21 +100,21 @@ func (c *JiraClient) PublishTicket(ticket *model.Ticket, cmp *model.Campaign, dr return newIssue, nil } -func (c *JiraClient) GetIssue(issueNo string) (*jira.Issue, error) { - issue, _, err := c.Issue.Get(issueNo, nil) +func (a *App) GetIssue(issueNo string) (*jira.Issue, error) { + issue, _, err := a.jiraClient.Issue.Get(issueNo, nil) if err != nil { return nil, err } return issue, nil } -func (c *JiraClient) PublishNextTicket(cmp *model.Campaign, dryRun bool) (bool, error) { - ticket := cmp.NextJiraUnpublishedTicket() +func (a *App) PublishNextInJira(dryRun bool) (bool, error) { + ticket := a.Campaign.NextJiraUnpublishedTicket() if ticket == nil { return false, nil } - issue, err := c.PublishTicket(ticket, cmp, dryRun) + issue, err := a.PublishInJira(ticket, dryRun) if err != nil { return false, err } @@ -127,25 +123,25 @@ func (c *JiraClient) PublishNextTicket(cmp *model.Campaign, dryRun bool) (bool, return true, nil } - issue, _, err = c.Issue.Get(issue.Key, nil) + issue, _, err = a.jiraClient.Issue.Get(issue.Key, nil) if err != nil { return false, err } - ticket.JiraLink = fmt.Sprintf("%s/browse/%s", cmp.Jira.Url, issue.Key) + ticket.JiraLink = fmt.Sprintf("%s/browse/%s", a.Campaign.Jira.Url, issue.Key) ticket.Summary = issue.Fields.Summary ticket.Description = issue.Fields.Description ticket.JiraStatus = issue.Fields.Status.Name - if err := campaign.Save(cmp); err != nil { + if err := a.Save(); err != nil { return false, err } return true, nil } -func (c *JiraClient) PublishAll(cmp *model.Campaign, dryRun bool) (int, error) { +func (a *App) PublishAllInJira(dryRun bool) (int, error) { count := 0 for { - next, err := c.PublishNextTicket(cmp, dryRun) + next, err := a.PublishNextInJira(dryRun) if err != nil { return count, err } @@ -157,9 +153,9 @@ func (c *JiraClient) PublishAll(cmp *model.Campaign, dryRun bool) (int, error) { return count, nil } -func (c *JiraClient) PublishBatch(cmp *model.Campaign, batch int, dryRun bool) error { +func (a *App) PublishBatchInJira(batch int, dryRun bool) error { for i := 1; i <= batch; i++ { - next, err := c.PublishNextTicket(cmp, dryRun) + next, err := a.PublishNextInJira(dryRun) if err != nil { return err } diff --git a/campaign/campaign.go b/campaign/campaign.go deleted file mode 100644 index 3447825..0000000 --- a/campaign/campaign.go +++ /dev/null @@ -1,40 +0,0 @@ -package campaign - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - - "git.ctrlz.es/mgdelacroix/campaigner/model" -) - -func Save(campaign *model.Campaign) error { - marshaledCampaign, err := json.MarshalIndent(campaign, "", " ") - if err != nil { - return err - } - - if err := ioutil.WriteFile("./campaign.json", marshaledCampaign, 0600); err != nil { - return fmt.Errorf("cannot save campaign: %w", err) - } - return nil -} - -func Read() (*model.Campaign, error) { - if _, err := os.Stat("."); err != nil { - return nil, fmt.Errorf("cannot read campaign: %w", err) - } - - fileContents, err := ioutil.ReadFile("./campaign.json") - if err != nil { - return nil, fmt.Errorf("there was a problem reading the campaign file: %w", err) - } - - var campaign model.Campaign - if err := json.Unmarshal(fileContents, &campaign); err != nil { - return nil, fmt.Errorf("there was a problem parsing the campaign file: %w", err) - } - - return &campaign, nil -} diff --git a/cmd/add.go b/cmd/add.go index 292ae7a..20512db 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/cobra" - "git.ctrlz.es/mgdelacroix/campaigner/campaign" + "git.ctrlz.es/mgdelacroix/campaigner/app" "git.ctrlz.es/mgdelacroix/campaigner/model" "git.ctrlz.es/mgdelacroix/campaigner/parsers" ) @@ -25,7 +25,7 @@ func GrepAddCmd() *cobra.Command { `, Example: ` grep -nriIF --include \*.go cobra.Command | campaigner add grep`, Args: cobra.NoArgs, - Run: grepAddCmdF, + Run: withApp(grepAddCmdF), } cmd.Flags().BoolP("file-only", "f", false, "Generates one ticket per file instead of per match") @@ -60,7 +60,7 @@ func GovetAddCmd() *cobra.Command { `, Example: ` govet ./... 2>&1 | campaigner add govet`, Args: cobra.NoArgs, - Run: govetAddCmdF, + Run: withApp(govetAddCmdF), } cmd.Flags().BoolP("file-only", "f", false, "Generates one ticket per file instead of per match") @@ -74,7 +74,7 @@ func CsvAddCmd() *cobra.Command { Short: "Generates the tickets reading a csv file", Example: ` campaigner add csv tickets.csv`, Args: cobra.ExactArgs(1), - Run: csvAddCmdF, + Run: withApp(csvAddCmdF), } } @@ -95,20 +95,13 @@ func AddCmd() *cobra.Command { return cmd } -func grepAddCmdF(cmd *cobra.Command, _ []string) { +func grepAddCmdF(a *app.App, cmd *cobra.Command, _ []string) { fileOnly, _ := cmd.Flags().GetBool("file-only") tickets := parsers.ParseWith(parsers.GREP) + a.Campaign.AddTickets(tickets, fileOnly) - cmp, err := campaign.Read() - if err != nil { - ErrorAndExit(cmd, err) - } - - cmp.Tickets = append(cmp.Tickets, tickets...) - cmp.Tickets = model.RemoveDuplicateTickets(cmp.Tickets, fileOnly) - - if err := campaign.Save(cmp); err != nil { + if err := a.Save(); err != nil { ErrorAndExit(cmd, err) } cmd.Printf("%d tickets have been added\n", len(tickets)) @@ -118,36 +111,24 @@ func agAddCmdF(_ *cobra.Command, _ []string) error { return fmt.Errorf("not implemented yet") } -func govetAddCmdF(cmd *cobra.Command, _ []string) { +func govetAddCmdF(a *app.App, cmd *cobra.Command, _ []string) { fileOnly, _ := cmd.Flags().GetBool("file-only") tickets := parsers.ParseWith(parsers.GOVET) + a.Campaign.AddTickets(tickets, fileOnly) - cmp, err := campaign.Read() - if err != nil { - ErrorAndExit(cmd, err) - } - - cmp.Tickets = append(cmp.Tickets, tickets...) - cmp.Tickets = model.RemoveDuplicateTickets(cmp.Tickets, fileOnly) - - if err := campaign.Save(cmp); err != nil { + if err := a.Save(); err != nil { ErrorAndExit(cmd, err) } cmd.Printf("%d tickets have been added\n", len(tickets)) } -func csvAddCmdF(cmd *cobra.Command, args []string) { +func csvAddCmdF(a *app.App, cmd *cobra.Command, args []string) { file, err := os.Open(args[0]) if err != nil { ErrorAndExit(cmd, err) } - cmp, err := campaign.Read() - if err != nil { - ErrorAndExit(cmd, err) - } - csvReader := csv.NewReader(bufio.NewReader(file)) records, err := csvReader.ReadAll() if err != nil { @@ -160,10 +141,10 @@ func csvAddCmdF(cmd *cobra.Command, args []string) { for i, header := range headers { data[header] = line[i] } - cmp.Tickets = append(cmp.Tickets, &model.Ticket{Data: data}) + a.Campaign.Tickets = append(a.Campaign.Tickets, &model.Ticket{Data: data}) } - if err := campaign.Save(cmp); err != nil { + if err := a.Save(); err != nil { ErrorAndExit(cmd, err) } cmd.Printf("%d tickets have been added\n", len(records[1:])) diff --git a/cmd/init.go b/cmd/init.go index 02e9121..ee86c64 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -6,7 +6,7 @@ import ( "os" "strings" - "git.ctrlz.es/mgdelacroix/campaigner/campaign" + "git.ctrlz.es/mgdelacroix/campaigner/app" "git.ctrlz.es/mgdelacroix/campaigner/model" "github.com/spf13/cobra" @@ -78,7 +78,7 @@ func initCmdF(cmd *cobra.Command, _ []string) { project := strings.Split(epic, "-")[0] - cmp := &model.Campaign{ + campaign := &model.Campaign{ Jira: model.ConfigJira{ Url: url, Username: jiraUsername, @@ -96,7 +96,7 @@ func initCmdF(cmd *cobra.Command, _ []string) { IssueTemplate: issueTemplate, FooterTemplate: footerTemplate, } - if err := campaign.Save(cmp); err != nil { + if err := app.SaveCampaign(campaign, "./campaign.json"); err != nil { ErrorAndExit(cmd, err) } } diff --git a/cmd/publish.go b/cmd/publish.go index b502a0d..4796ad8 100644 --- a/cmd/publish.go +++ b/cmd/publish.go @@ -3,9 +3,7 @@ package cmd import ( "fmt" - "git.ctrlz.es/mgdelacroix/campaigner/campaign" - "git.ctrlz.es/mgdelacroix/campaigner/github" - "git.ctrlz.es/mgdelacroix/campaigner/jira" + "git.ctrlz.es/mgdelacroix/campaigner/app" "github.com/spf13/cobra" ) @@ -15,7 +13,7 @@ func JiraPublishCmd() *cobra.Command { Use: "jira", Short: "Publishes the campaign tickets in jira", Args: cobra.NoArgs, - RunE: jiraPublishCmdF, + RunE: withAppE(jiraPublishCmdF), } cmd.Flags().BoolP("all", "a", false, "Publish all the tickets of the campaign") @@ -30,7 +28,7 @@ func GithubPublishCmd() *cobra.Command { Use: "github", Short: "Publishes the campaign tickets in github", Args: cobra.NoArgs, - RunE: githubPublishCmdF, + RunE: withAppE(githubPublishCmdF), } cmd.Flags().BoolP("all", "a", false, "Publish all the tickets of the campaign") @@ -55,7 +53,7 @@ func PublishCmd() *cobra.Command { return cmd } -func jiraPublishCmdF(cmd *cobra.Command, _ []string) error { +func jiraPublishCmdF(a *app.App, cmd *cobra.Command, _ []string) error { all, _ := cmd.Flags().GetBool("all") batch, _ := cmd.Flags().GetInt("batch") dryRun, _ := cmd.Flags().GetBool("dry-run") @@ -64,24 +62,14 @@ func jiraPublishCmdF(cmd *cobra.Command, _ []string) error { return fmt.Errorf("One of --all or --batch flags is required") } - cmp, err := campaign.Read() - if err != nil { - ErrorAndExit(cmd, err) - } - - jiraClient, err := jira.NewClient(cmp.Jira.Url, cmp.Jira.Username, cmp.Jira.Token) - if err != nil { - ErrorAndExit(cmd, err) - } - if all { - count, err := jiraClient.PublishAll(cmp, dryRun) + count, err := a.PublishAllInJira(dryRun) if err != nil { ErrorAndExit(cmd, err) } cmd.Printf("All %d tickets successfully published in jira\n", count) } else { - if err := jiraClient.PublishBatch(cmp, batch, dryRun); err != nil { + if err := a.PublishBatchInJira(batch, dryRun); err != nil { ErrorAndExit(cmd, err) } cmd.Printf("Batch of %d tickets successfully published in jira\n", batch) @@ -90,7 +78,7 @@ func jiraPublishCmdF(cmd *cobra.Command, _ []string) error { return nil } -func githubPublishCmdF(cmd *cobra.Command, _ []string) error { +func githubPublishCmdF(a *app.App, cmd *cobra.Command, _ []string) error { all, _ := cmd.Flags().GetBool("all") batch, _ := cmd.Flags().GetInt("batch") dryRun, _ := cmd.Flags().GetBool("dry-run") @@ -99,21 +87,14 @@ func githubPublishCmdF(cmd *cobra.Command, _ []string) error { return fmt.Errorf("One of --all or --batch flags is required") } - cmp, err := campaign.Read() - if err != nil { - ErrorAndExit(cmd, err) - } - - githubClient := github.NewClient(cmp.Github.Repo, cmp.Github.Token) - if all { - count, err := githubClient.PublishAll(cmp, dryRun) + count, err := a.PublishAllInGithub(dryRun) if err != nil { ErrorAndExit(cmd, err) } cmd.Printf("All %d tickets successfully published in github\n", count) } else { - if err := githubClient.PublishBatch(cmp, batch, dryRun); err != nil { + if err := a.PublishBatchInGithub(batch, dryRun); err != nil { ErrorAndExit(cmd, err) } cmd.Printf("Batch of %d tickets successfully published in github\n", batch) diff --git a/cmd/root.go b/cmd/root.go index 7708d45..2f266c1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,8 +5,34 @@ import ( "os" "github.com/spf13/cobra" + + "git.ctrlz.es/mgdelacroix/campaigner/app" ) +func withApp(f func(*app.App, *cobra.Command, []string)) func(*cobra.Command, []string) { + a, err := app.NewApp("./campaign.json") + if err != nil { + fmt.Fprintln(os.Stderr, "ERROR: "+err.Error()) + os.Exit(1) + } + + return func(cmd *cobra.Command, args []string) { + f(a, cmd, args) + } +} + +func withAppE(f func(*app.App, *cobra.Command, []string) error) func(*cobra.Command, []string) error { + a, err := app.NewApp("./campaign.json") + if err != nil { + fmt.Fprintln(os.Stderr, "ERROR: "+err.Error()) + os.Exit(1) + } + + return func(cmd *cobra.Command, args []string) error { + return f(a, cmd, args) + } +} + func RootCmd() *cobra.Command { cmd := &cobra.Command{ Use: "campaigner", diff --git a/cmd/status.go b/cmd/status.go index 63b96a9..0a351ae 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -1,9 +1,9 @@ package cmd import ( - "git.ctrlz.es/mgdelacroix/campaigner/campaign" - "github.com/spf13/cobra" + + "git.ctrlz.es/mgdelacroix/campaigner/app" ) func StatusCmd() *cobra.Command { @@ -12,15 +12,10 @@ func StatusCmd() *cobra.Command { Short: "Prints the campaign status", Long: "Prints the current status of the campaign and its tickets", Args: cobra.NoArgs, - Run: statusCmdF, + Run: withApp(statusCmdF), } } -func statusCmdF(cmd *cobra.Command, _ []string) { - cmp, err := campaign.Read() - if err != nil { - ErrorAndExit(cmd, err) - } - - cmp.PrintStatus() +func statusCmdF(a *app.App, cmd *cobra.Command, _ []string) { + a.Campaign.PrintStatus() } diff --git a/model/campaign.go b/model/campaign.go index 571620a..9849bff 100644 --- a/model/campaign.go +++ b/model/campaign.go @@ -70,6 +70,31 @@ func (c *Campaign) PrintStatus() { fmt.Printf("\t%d/%d\tpublished in Github\n\n", totalPublishedGithub, totalPublishedJira) } +func (c *Campaign) AddTickets(tickets []*Ticket, fileOnly bool) { + c.Tickets = append(c.Tickets, tickets...) + c.RemoveDuplicateTickets(fileOnly) +} + +func (c *Campaign) RemoveDuplicateTickets(fileOnly bool) { + ticketMap := map[string]*Ticket{} + for _, t := range c.Tickets { + filename, _ := t.Data["filename"].(string) + lineNo, _ := t.Data["lineNo"].(int) + if fileOnly { + ticketMap[filename] = t + } else { + ticketMap[fmt.Sprintf("%s:%d", filename, lineNo)] = t + } + } + + cleanTickets := []*Ticket{} + for _, t := range ticketMap { + cleanTickets = append(cleanTickets, t) + } + + c.Tickets = cleanTickets +} + func (c *Campaign) FillTicket(t *Ticket) error { summaryTmpl, err := template.New("").Parse(c.Summary) if err != nil { diff --git a/model/ticket.go b/model/ticket.go index 94de336..5738605 100644 --- a/model/ticket.go +++ b/model/ticket.go @@ -15,26 +15,6 @@ type Ticket struct { Data map[string]interface{} `json:"data,omitempty"` } -func RemoveDuplicateTickets(tickets []*Ticket, fileOnly bool) []*Ticket { - ticketMap := map[string]*Ticket{} - for _, t := range tickets { - filename, _ := t.Data["filename"].(string) - lineNo, _ := t.Data["lineNo"].(int) - if fileOnly { - ticketMap[filename] = t - } else { - ticketMap[fmt.Sprintf("%s:%d", filename, lineNo)] = t - } - } - - cleanTickets := []*Ticket{} - for _, t := range ticketMap { - cleanTickets = append(cleanTickets, t) - } - - return cleanTickets -} - func (t *Ticket) IsPublishedJira() bool { return t.JiraLink != "" }