Skip to content

Commit

Permalink
Merge pull request #17 from k-kinzal/support-label-command
Browse files Browse the repository at this point in the history
support label manipuration
  • Loading branch information
k-kinzal authored Jan 20, 2020
2 parents c05532e + 03ea217 commit d164116
Show file tree
Hide file tree
Showing 6 changed files with 603 additions and 3 deletions.
23 changes: 20 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,24 @@ $ pr merge [owner]/[repo] --with-statuses -l 'state == `"open"`' -l 'length(stat
[...]
```
## Check
### Label
Append/Remove/Replace labels to PRs that match the rule.
```bash
$ pr label [owner]/[repo] -l 'state == `"open"`' --action "append" --label "foo"
...
$ pr label [owner]/[repo] -l 'state == `"open"`' --action "remove" --label "foo"
...
$ pr label [owner]/[repo] -l 'state == `"open"`' --action "replace" --label "foo"
...
```
`--action "append"` appends the specified label to the PR that matches the rule.
`--action "remove"` removes the label specified for the PR that matched the rule.
`--action "replace"` replaces all labels on PR that match the rule with the specified label.
### Check
When the PR CLI is run on the CI, the rule status is displayed separately from the CI.
This is a solution to the problem where multiple CI statuses are displayed in GitHub Action.
Expand All @@ -67,7 +84,7 @@ $ pr check [owner]/[repo] --merge -l 'number == `1`' -l 'state == `"open"`' -l '
For PR with `number == 1`, merge if the condition is met, or change status to pending if the condition is not met.
## Show
### Show
Check the PR that matches the rule.
Expand All @@ -83,7 +100,7 @@ $ pr show [owner]/[repo] --exit-code -l 'number == `1`' -l 'state == `"open"`'
[...]
```
## Validate
### Validate
Validate the rules.
Expand Down
61 changes: 61 additions & 0 deletions cmd/label.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"encoding/json"
"fmt"
"os"

"github.com/k-kinzal/pr/pkg/pr"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
)

func LabelRun(cmd *cobra.Command, args []string) error {
labelOption.Action = pr.LabelAction(labelAction)

pulls, err := pr.Label(owner, repo, labelOption)
if err != nil {
if _, ok := err.(*pr.NoMatchError); ok {
fmt.Fprintln(os.Stderr, err.Error())
fmt.Fprintln(os.Stdout, "[]")
if exitCode {
os.Exit(127)
}
return nil
}
return err
}

out, err := json.Marshal(pulls)
if err != nil {
return xerrors.Errorf("merge: %s", err)
}
fmt.Fprintln(os.Stdout, string(out))

return nil
}

var (
labelOption *pr.LabelOption
labelCmd = &cobra.Command{
Use: "label owner/repo",
Short: "Manipulate labels that match a rule",
RunE: LabelRun,
SilenceErrors: true,
SilenceUsage: true,
}
labelAction string
)

func setLabelFrags(cmd *cobra.Command) *pr.LabelOption {
opt := &pr.LabelOption{}
cmd.Flags().StringArrayVarP(&opt.Labels, "label", "", nil, "Manipulate labels")
cmd.Flags().StringVar(&labelAction, "action", "append", "Manipulation of `append`, `remove`, `replace` for labels")
return opt
}

func init() {
labelOption = setLabelFrags(labelCmd)
labelOption.ListOption = setListFrags(labelCmd)
rootCmd.AddCommand(labelCmd)
}
100 changes: 100 additions & 0 deletions pkg/api/label.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package api

import (
"context"
"time"

"golang.org/x/sync/errgroup"
)

type LabelOption struct {
Labels []string
}

func (c *Client) AppendLabel(ctx context.Context, pulls []*PullRequest, opt *LabelOption) ([]*PullRequest, error) {
eg, ctx := errgroup.WithContext(ctx)

for _, pull := range pulls {
eg.Go(func(pull *PullRequest) func() error {
return func() error {
now := Timestamp(time.Now().UTC().Unix())
labels, _, err := c.github.Issues.AddLabelsToIssue(ctx, pull.Owner, pull.Repo, int(pull.Number), opt.Labels)
if err != nil {
return err
}

for _, label := range labels {
pull.Labels = append(pull.Labels, newLabel(label))
}
pull.UpdatedAt = now

return nil
}
}(pull))
}
if err := eg.Wait(); err != nil {
return nil, err
}

return pulls, nil
}

func (c *Client) RemoveLabel(ctx context.Context, pulls []*PullRequest, opt *LabelOption) ([]*PullRequest, error) {
eg, ctx := errgroup.WithContext(ctx)

for _, pull := range pulls {
for _, label := range opt.Labels {
eg.Go(func(pull *PullRequest, label string) func() error {
return func() error {
now := Timestamp(time.Now().UTC().Unix())
_, err := c.github.Issues.RemoveLabelForIssue(ctx, pull.Owner, pull.Repo, int(pull.Number), label)
if err != nil {
return err
}
for i, lbl := range pull.Labels {
if lbl.Name == label {
pull.Labels[i] = pull.Labels[len(pull.Labels)-1]
pull.Labels = pull.Labels[:len(pull.Labels)-1]
break
}
}
pull.UpdatedAt = now
return nil
}
}(pull, label))
}
}
if err := eg.Wait(); err != nil {
return nil, err
}

return pulls, nil
}

func (c *Client) ReplaceLabel(ctx context.Context, pulls []*PullRequest, opt *LabelOption) ([]*PullRequest, error) {
eg, ctx := errgroup.WithContext(ctx)

for _, pull := range pulls {
eg.Go(func(pull *PullRequest) func() error {
return func() error {
now := Timestamp(time.Now().UTC().Unix())
labels, _, err := c.github.Issues.ReplaceLabelsForIssue(ctx, pull.Owner, pull.Repo, int(pull.Number), opt.Labels)
if err != nil {
return err
}
pull.Labels = make([]*Label, len(labels))
for i, label := range labels {
pull.Labels[i] = newLabel(label)
}
pull.UpdatedAt = now

return nil
}
}(pull))
}
if err := eg.Wait(); err != nil {
return nil, err
}

return pulls, nil
}
Loading

0 comments on commit d164116

Please sign in to comment.