mirror of
https://github.com/Luzifer/repo-template.git
synced 2024-12-22 20:21:19 +00:00
Initial version
This commit is contained in:
commit
28b0084631
2 changed files with 231 additions and 0 deletions
34
filters.go
Normal file
34
filters.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type filterFunc func(*github.Repository) bool
|
||||
|
||||
var filters = map[string]filterFunc{
|
||||
"fork": filterFork,
|
||||
"dockerfile": filterDockerfile,
|
||||
"public": filterPublic,
|
||||
}
|
||||
|
||||
func filterDockerfile(repo *github.Repository) bool {
|
||||
ctx := context.Background()
|
||||
_, _, resp, err := client.Repositories.GetContents(ctx, *repo.Owner.Login, *repo.Name, "Dockerfile", nil)
|
||||
if err != nil {
|
||||
if resp.StatusCode == 404 {
|
||||
return false
|
||||
}
|
||||
|
||||
log.WithError(err).Error("Error while looking for Dockerfile")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func filterFork(repo *github.Repository) bool { return repo.Fork != nil && *repo.Fork }
|
||||
func filterPublic(repo *github.Repository) bool { return repo.Private != nil && !*repo.Private }
|
197
main.go
Normal file
197
main.go
Normal file
|
@ -0,0 +1,197 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/Luzifer/rconfig"
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/gosimple/slug"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg = struct {
|
||||
Filters []string `flag:"filter,f" default:"" description:"Filters to match the repos against"`
|
||||
GithubToken string `flag:"token" default:"" env:"GITHUB_TOKEN" description:"Token to access Github API"`
|
||||
LogLevel string `flag:"log-level" default:"info" description:"Log level for output (debug, info, warn, error, fatal)"`
|
||||
NameRegex string `flag:"name-regex" default:".*" description:"Regex to match the name against"`
|
||||
Output string `flag:"out,o" default:"-" description:"File to write to (- = stdout)"`
|
||||
Template string `flag:"template" default:"" description:"Template file to use for rendering" validate:"nonzero"`
|
||||
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
|
||||
}{}
|
||||
|
||||
client *github.Client
|
||||
|
||||
version = "dev"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := rconfig.ParseAndValidate(&cfg); err != nil {
|
||||
log.Fatalf("Unable to parse commandline options: %s", err)
|
||||
}
|
||||
|
||||
if l, err := log.ParseLevel(cfg.LogLevel); err != nil {
|
||||
log.WithError(err).Fatalf("Could not parse log level")
|
||||
} else {
|
||||
log.SetLevel(l)
|
||||
}
|
||||
|
||||
if cfg.VersionAndExit {
|
||||
fmt.Printf("repo-template %s\n", version)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: cfg.GithubToken},
|
||||
)
|
||||
tc := oauth2.NewClient(ctx, ts)
|
||||
|
||||
client = github.NewClient(tc)
|
||||
|
||||
repos, err := fetchRepos()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("Error while fetching repos")
|
||||
}
|
||||
|
||||
for _, repo := range repos {
|
||||
if !regexp.MustCompile(cfg.NameRegex).MatchString(*repo.FullName) {
|
||||
continue
|
||||
}
|
||||
|
||||
skip := false
|
||||
|
||||
for _, f := range cfg.Filters {
|
||||
if f == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
var (
|
||||
inverse = false
|
||||
filter = f
|
||||
)
|
||||
|
||||
if strings.HasPrefix(filter, "no-") {
|
||||
inverse = true
|
||||
filter = filter[3:]
|
||||
}
|
||||
|
||||
if filters[filter](repo) == inverse {
|
||||
log.WithFields(log.Fields{
|
||||
"filter": filter,
|
||||
"repo": *repo.FullName,
|
||||
}).Debug("Repo was filtered")
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
|
||||
if skip {
|
||||
continue
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"repo": *repo.FullName,
|
||||
"private": *repo.Private,
|
||||
"fork": *repo.Fork,
|
||||
}).Print("Found repo")
|
||||
|
||||
if err := render(repo); err != nil {
|
||||
log.WithError(err).Error("Unable to render output")
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fetchRepos() ([]*github.Repository, error) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
repos = []*github.Repository{}
|
||||
)
|
||||
|
||||
opt := &github.RepositoryListOptions{
|
||||
ListOptions: github.ListOptions{PerPage: 100},
|
||||
}
|
||||
|
||||
for {
|
||||
rs, res, err := client.Repositories.List(ctx, "", opt)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repos = append(repos, rs...)
|
||||
|
||||
if res.NextPage == 0 {
|
||||
break
|
||||
}
|
||||
opt.Page = res.NextPage
|
||||
}
|
||||
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
func render(repo *github.Repository) error {
|
||||
var outFile io.Writer
|
||||
if cfg.Output == "-" {
|
||||
outFile = os.Stdout
|
||||
} else {
|
||||
outName, err := getOutfile(repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.WithFields(log.Fields{
|
||||
"repo": *repo.FullName,
|
||||
"outName": outName,
|
||||
}).Debug("")
|
||||
|
||||
f, err := os.Create(outName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
outFile = f
|
||||
}
|
||||
|
||||
tplRaw, err := ioutil.ReadFile(cfg.Template)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tpl, err := template.New("output").Funcs(tplFuncs()).Parse(string(tplRaw))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tpl.Execute(outFile, repo)
|
||||
}
|
||||
|
||||
func getOutfile(repo *github.Repository) (string, error) {
|
||||
tpl, err := template.New("outfile").Funcs(tplFuncs()).Parse(cfg.Output)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
err = tpl.Execute(buf, repo)
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
func tplFuncs() template.FuncMap {
|
||||
return template.FuncMap{
|
||||
"chkPtrBool": func(i *bool) bool { return i != nil && *i },
|
||||
"slugify": slug.Make,
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue