mirror of
https://github.com/Luzifer/repo-template.git
synced 2024-12-23 04:31:20 +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