Skip to content

Commit

Permalink
Change to expecting a local dir of templates, vs embedded fs (#2)
Browse files Browse the repository at this point in the history
* Change to expecting a local dir of templates, vs embedded fs

* Add readme
  • Loading branch information
cmmarslender authored Mar 21, 2024
1 parent f29ec09 commit 01ef892
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 52 deletions.
6 changes: 4 additions & 2 deletions cmd/debugTemplate.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package cmd

import (
"fmt"
"log"
"os"
"path"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/chia-network/repo-content-updater/internal/repo"
)
Expand All @@ -14,7 +16,7 @@ var debugTemplateCmd = &cobra.Command{
Use: "debug-template",
Short: "Renders the given template for debugging",
Run: func(cmd *cobra.Command, args []string) {
tmplContent, err := fs.ReadFile(fmt.Sprintf("templates/%s", args[0]))
tmplContent, err := os.ReadFile(path.Join(viper.GetString("templates"), args[0]))
if err != nil {
log.Fatalln(err.Error())
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var licenseCmd = &cobra.Command{
Use: "license",
Short: "Updates licenses in repos with license flag",
Run: func(cmd *cobra.Command, args []string) {
content, err := repo.NewContent(&fs, viper.GetString("github-token"))
content, err := repo.NewContent(viper.GetString("templates"), viper.GetString("github-token"))
if err != nil {
log.Fatalf("Error creating content manager: %s", err.Error())
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/managedFiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ var managedFilesCmd = &cobra.Command{
Use: "managed-files",
Short: "Updates all managed files across the org",
Run: func(cmd *cobra.Command, args []string) {
content, err := repo.NewContent(&fs, viper.GetString("github-token"))
content, err := repo.NewContent(viper.GetString("templates"), viper.GetString("github-token"))
if err != nil {
log.Fatalf("Error creating content manager: %s", err.Error())
}

cfg, err := config.LoadConfig("config.yaml")
cfg, err := config.LoadConfig(viper.GetString("config"))
if err != nil {
log.Fatalf("error loading config: %s\n", err.Error())
}
Expand Down
35 changes: 14 additions & 21 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmd

import (
"embed"
"fmt"
"os"
"strings"
Expand All @@ -10,9 +9,6 @@ import (
"github.com/spf13/viper"
)

var fs embed.FS
var cfgFile string

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "repo-content-updater",
Expand All @@ -21,8 +17,7 @@ var rootCmd = &cobra.Command{

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute(_fs embed.FS) {
fs = _fs
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
Expand All @@ -31,39 +26,37 @@ func Execute(_fs embed.FS) {

func init() {
var (
cfgFile string
templateDir string
githubToken string
signCommits bool
push bool
)

cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.repo-content-updater.yaml)")

rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "config.yaml", "template config file (default is config.yaml)")
rootCmd.PersistentFlags().StringVar(&templateDir, "templates", "templates", "Path to templates defined in the config. Defaults to ./templates")
rootCmd.PersistentFlags().StringVar(&githubToken, "github-token", "", "The token to use to auth to GitHub API and Push to Repos")
rootCmd.PersistentFlags().BoolVar(&signCommits, "sign-commits", true, "Whether or not to sign commits")
rootCmd.PersistentFlags().BoolVar(&push, "push", true, "Whether or not to push and create the pull request")

cobra.CheckErr(viper.BindPFlag("config", rootCmd.PersistentFlags().Lookup("config")))
cobra.CheckErr(viper.BindPFlag("templates", rootCmd.PersistentFlags().Lookup("templates")))
cobra.CheckErr(viper.BindPFlag("github-token", rootCmd.PersistentFlags().Lookup("github-token")))
cobra.CheckErr(viper.BindPFlag("sign-commits", rootCmd.PersistentFlags().Lookup("sign-commits")))
cobra.CheckErr(viper.BindPFlag("push", rootCmd.PersistentFlags().Lookup("push")))
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

// Search config in home directory with name ".repo-content-updater" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".repo-content-updater")
}
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

// Search config in home directory with name ".repo-content-updater" (without extension).
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".repo-content-updater")
viper.SetEnvPrefix("REPO_CONTENT_UPDATER")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.AutomaticEnv() // read in environment variables that match
Expand Down
7 changes: 3 additions & 4 deletions internal/repo/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package repo

import (
"context"
"embed"
"errors"
"fmt"
"log"
Expand Down Expand Up @@ -31,16 +30,16 @@ const (

// Content the content manager object
type Content struct {
fs *embed.FS
templates string
githubToken string
githubClient *github.Client
}

// NewContent returns new repo content manager
func NewContent(fs *embed.FS, githubToken string) (*Content, error) {
func NewContent(templates, githubToken string) (*Content, error) {
client := github.NewClient(nil).WithAuthToken(githubToken)
return &Content{
fs: fs,
templates: templates,
githubToken: githubToken,
githubClient: client,
}, nil
Expand Down
3 changes: 2 additions & 1 deletion internal/repo/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
"path"
"path/filepath"
"strings"

Expand Down Expand Up @@ -117,7 +118,7 @@ func (c *Content) CheckFiles(repoName string, files []string, cfg *config.Config
_ = os.Remove(fmt.Sprintf("%s/%s", repoDir(repoName), form))
}

tmplContent, err := c.fs.ReadFile(fmt.Sprintf("templates/%s", fileinfo.TemplateName))
tmplContent, err := os.ReadFile(path.Join(c.templates, fileinfo.TemplateName))
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion internal/repo/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
"path"

"github.com/google/go-github/v59/github"
)
Expand Down Expand Up @@ -71,7 +72,7 @@ func (c *Content) UpdateLicense(repoName string) error {
}
}

file, err := c.fs.ReadFile("templates/LICENSE")
file, err := os.ReadFile(path.Join(c.templates, "LICENSE"))
if err != nil {
return err
}
Expand Down
28 changes: 14 additions & 14 deletions internal/repo/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ func ProcessTemplate(templateContent []byte, overrides map[string]string) ([]byt
notOverridable := map[string]bool{"CURRENT_YEAR": true}
defaultPullRequestLimit := "10"
data := map[string]string{
"CURRENT_YEAR": strconv.Itoa(time.Now().Year()),
"COMPANY_NAME": "Chia Network Inc.",
"CGO_ENABLED": "0",
"DEPENDABOT_GOMOD_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_GOMOD_DIRECTORY": "/",
"DEPENDABOT_GOMOD_REVIEWERS": "[\"cmmarslender\", \"starttoaster\"]",
"DEPENDABOT_PIP_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_PIP_DIRECTORY": "/",
"DEPENDABOT_PIP_REVIEWERS": "[\"emlowe\", \"altendky\"]",
"CURRENT_YEAR": strconv.Itoa(time.Now().Year()),
"COMPANY_NAME": "Chia Network Inc.",
"CGO_ENABLED": "0",
"DEPENDABOT_GOMOD_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_GOMOD_DIRECTORY": "/",
"DEPENDABOT_GOMOD_REVIEWERS": "[\"cmmarslender\", \"starttoaster\"]",
"DEPENDABOT_PIP_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_PIP_DIRECTORY": "/",
"DEPENDABOT_PIP_REVIEWERS": "[\"emlowe\", \"altendky\"]",
"DEPENDABOT_ACTIONS_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_ACTIONS_DIRECTORY": "/",
"DEPENDABOT_ACTIONS_REVIEWERS": "[\"cmmarslender\", \"altendky\"]",
"DEPENDABOT_NPM_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_NPM_DIRECTORY": "/",
"DEPENDABOT_NPM_REVIEWERS": "[\"cmmarslender\", \"emlowe\"]",
"DEPENDABOT_ACTIONS_DIRECTORY": "/",
"DEPENDABOT_ACTIONS_REVIEWERS": "[\"cmmarslender\", \"altendky\"]",
"DEPENDABOT_NPM_PULL_REQUEST_LIMIT": defaultPullRequestLimit,
"DEPENDABOT_NPM_DIRECTORY": "/",
"DEPENDABOT_NPM_REVIEWERS": "[\"cmmarslender\", \"emlowe\"]",
}

// Merge `overrides` into `data`, with `overrides` taking precedence
Expand Down
7 changes: 1 addition & 6 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package main

import (
"embed"

"github.com/chia-network/repo-content-updater/cmd"
)

//go:embed templates/*
var fs embed.FS

func main() {
cmd.Execute(fs)
cmd.Execute()
}
52 changes: 52 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Repo Content Updater

Manages files across repos in a GitHub org based on [custom properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization).

## Manage Licenses

Applies a `LICENSE` template to all repos with the custom property `manage-license` set to `yes`. This is split out from the generic managed files so that the property can be set to required org wide and specific "yes" and "no" options (only) provided in a drop down, ensuring a repo either opts in or out of the license specifically.

## Manage Files

Looks for the `managed-files` custom property on a repo, and parses out a comma separated list of files/groups to include. Files must be referenced by their name in the config file, and groups should be referenced by their group name, prefixed with `group:`.

For example, the value could be: `group:base,go-test`. This would pull in the base group of files and the go-test file.

### Config Format

```yaml
groups:
- name: base
templates:
- dep-review

- name: go
templates:
- go-makefile
- go-dependabot

files:
- name: go-makefile
template_name: go-makefile
repo_path: Makefile

- name: go-dependabot
template_name: go-dependabot.yml
repo_path: .github/dependabot.yml
alternate_paths:
- .github/dependabot.yaml

- name: dep-review
template_name: dependency-review.yml
repo_path: .github/workflows/dependency-review.yml
alternate_paths:
- .github/workflows/dependency-review.yaml
```
`groups` allows combining multiple items from `files` into a single group, making it easier to reference in the custom property

`files` is where every supported template must be listed.
* `name` is the name to reference the file by in groups or in the custom property.
* `template_name` is the name of the template to use from the supplied templates directory
* `repo_path` is the path within the repo to place the file
* `alternate_paths` is a list of alternate/equivalent paths this template might have been named before being managed. These files will be renamed and updated to the latest version of the template, if present

0 comments on commit 01ef892

Please sign in to comment.