Skip to content

Commit

Permalink
Merge pull request #4 from b4b4r07/import-flag
Browse files Browse the repository at this point in the history
Import flag
  • Loading branch information
b4b4r07 authored Feb 7, 2020
2 parents 7beef07 + f61649d commit 4362d33
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 42 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.12
require (
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.0.0 // indirect
github.com/jessevdk/go-flags v1.4.0
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
gopkg.in/yaml.v2 v2.2.8
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4r
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
145 changes: 103 additions & 42 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package main
import (
"context"
"errors"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
Expand All @@ -16,6 +16,7 @@ import (
"golang.org/x/sync/errgroup"

"github.com/google/go-github/github"
"github.com/jessevdk/go-flags"
)

// These variables are set in Goreleaser
Expand All @@ -35,7 +36,7 @@ type Label struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Color string `yaml:"color"`
PreviousName string `yaml:"previous_name"`
PreviousName string `yaml:"previous_name,omitempty"`
}

// Labels represents a collection of Label
Expand All @@ -50,6 +51,22 @@ type Repo struct {
// Repos represents a collection of Repo
type Repos []Repo

type CLI struct {
Stdout io.Writer
Stderr io.Writer
Option Option

Client *githubClient
Config Manifest
}

type Option struct {
DryRun bool `long:"dry-run" description:"Just dry run"`
Config string `short:"c" long:"config" description:"Path to YAML file that labels are defined" default:"labels.yaml"`
Import bool `long:"import" description:"Path to import labels existing on GitHub"`
Version bool `long:"version" description:"Show version"`
}

func loadManifest(path string) (Manifest, error) {
var m Manifest
buf, err := ioutil.ReadFile(path)
Expand Down Expand Up @@ -201,32 +218,32 @@ func (g *LabelService) Delete(owner, repo string, label Label) error {
}

// applyLabels creates/edits labels described in YAML
func (l Labeler) applyLabels(owner, repo string, label Label) error {
ghLabel, err := l.github.Label.Get(owner, repo, label)
func (c *CLI) applyLabels(owner, repo string, label Label) error {
ghLabel, err := c.Client.Label.Get(owner, repo, label)
if err != nil {
return l.github.Label.Create(owner, repo, label)
return c.Client.Label.Create(owner, repo, label)
}

if ghLabel.Description != label.Description || ghLabel.Color != label.Color {
return l.github.Label.Edit(owner, repo, label)
return c.Client.Label.Edit(owner, repo, label)
}

return nil
}

// deleteLabels deletes the label not described in YAML but exists on GitHub
func (l Labeler) deleteLabels(owner, repo string) error {
labels, err := l.github.Label.List(owner, repo)
func (c *CLI) deleteLabels(owner, repo string) error {
labels, err := c.Client.Label.List(owner, repo)
if err != nil {
return err
}

for _, label := range labels {
if l.manifest.checkIfRepoHasLabel(owner+"/"+repo, label.Name) {
if c.Config.checkIfRepoHasLabel(owner+"/"+repo, label.Name) {
// no need to delete
continue
}
err := l.github.Label.Delete(owner, repo, label)
err := c.Client.Label.Delete(owner, repo, label)
if err != nil {
return err
}
Expand All @@ -236,28 +253,62 @@ func (l Labeler) deleteLabels(owner, repo string) error {
}

// Sync syncs labels based on YAML
func (l Labeler) Sync(repo Repo) error {
func (c *CLI) Sync(repo Repo) error {
slugs := strings.Split(repo.Name, "/")
if len(slugs) != 2 {
return fmt.Errorf("repository name %q is invalid", repo.Name)
}
for _, labelName := range repo.Labels {
label, err := l.manifest.getDefinedLabel(labelName)
label, err := c.Config.getDefinedLabel(labelName)
if err != nil {
return err
}
err = l.applyLabels(slugs[0], slugs[1], label)
err = c.applyLabels(slugs[0], slugs[1], label)
if err != nil {
return err
}
}
return l.deleteLabels(slugs[0], slugs[1])
return c.deleteLabels(slugs[0], slugs[1])
}

func main() {
os.Exit(run(os.Args[1:]))
}

func run(args []string) int {
// clilog.Env = "GOMI_LOG"
// clilog.SetOutput()
// defer log.Printf("[INFO] finish main function")
//
// log.Printf("[INFO] Version: %s (%s)", Version, Revision)
// log.Printf("[INFO] gomiPath: %s", gomiPath)
// log.Printf("[INFO] inventoryPath: %s", inventoryPath)
// log.Printf("[INFO] Args: %#v", args)

var opt Option
args, err := flags.ParseArgs(&opt, args)
if err != nil {
return 2
}

cli := CLI{
Stdout: os.Stdout,
Stderr: os.Stderr,
Option: opt,
}

if err := cli.Run(args); err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
return 1
}

return 0
}

func newLabeler(configPath string, dryRun bool) (Labeler, error) {
func (c *CLI) Run(args []string) error {
token := os.Getenv("GITHUB_TOKEN")
if token == "" {
return Labeler{}, errors.New("GITHUB_TOKEN is missing")
return errors.New("GITHUB_TOKEN is missing")
}

ts := oauth2.StaticTokenSource(&oauth2.Token{
Expand All @@ -266,51 +317,61 @@ func newLabeler(configPath string, dryRun bool) (Labeler, error) {
tc := oauth2.NewClient(oauth2.NoContext, ts)
client := github.NewClient(tc)

m, err := loadManifest(configPath)
m, err := loadManifest(c.Option.Config)
if err != nil {
return Labeler{}, err
return err
}

gc := &githubClient{
Client: client,
dryRun: dryRun,
dryRun: c.Option.DryRun,
logger: log.New(os.Stdout, "labeler: ", log.Ldate|log.Ltime),
}
if dryRun {

if c.Option.DryRun {
gc.logger.SetPrefix("labeler (dry-run): ")
// gc.logger = log.New(os.Stdout, "labeler (dry-run): ", 0)
}

gc.common.client = gc
gc.Label = (*LabelService)(&gc.common)
return Labeler{
github: gc,
manifest: m,
}, nil
}

func main() {
var (
manifest = flag.String("manifest", "labels.yaml", "YAML file to be described about labels and repos")
dryRun = flag.Bool("dry-run", false, "dry run flag")
)
flag.Parse()
c.Client = gc
c.Config = m

labeler, err := newLabeler(*manifest, *dryRun)
if err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] %v\n", err.Error())
os.Exit(1)
if c.Option.Import {
if len(c.Config.Repos) == 0 {
return fmt.Errorf("no repos found in %s", c.Option.Config)
}
var m Manifest
for _, repo := range c.Config.Repos {
e := strings.Split(repo.Name, "/")
if len(e) != 2 {
// TODO: handle error
continue
}
labels, err := c.Client.Label.List(e[0], e[1])
if err != nil {
// TODO: handle error
continue
}
m.Repos = append(m.Repos, repo)
m.Labels = append(m.Labels, labels...)
}
f, err := os.Create(c.Option.Config)
if err != nil {
return err
}
defer f.Close()
return yaml.NewEncoder(f).Encode(&m)
}

eg := errgroup.Group{}
for _, repo := range labeler.manifest.Repos {
for _, repo := range c.Config.Repos {
repo := repo
eg.Go(func() error {
return labeler.Sync(repo)
return c.Sync(repo)
})
}

if err := eg.Wait(); err != nil {
fmt.Fprintf(os.Stderr, "[ERROR] %v\n", err.Error())
os.Exit(1)
}
return eg.Wait()
}

0 comments on commit 4362d33

Please sign in to comment.