From 5d267f48de6b5892c8a4b949267ed5b773b8ed9a Mon Sep 17 00:00:00 2001 From: tony Date: Sat, 8 Jun 2024 01:25:06 +0200 Subject: [PATCH] feat(breaking): drop Jsonnet support (#39) --- README.md | 31 ++---- README.tpl.md | 108 ++++++++++++++++++++ cmd/zit/main.go | 2 +- examples/example.yaml | 20 ++++ go.mod | 3 +- go.sum | 15 --- internal/config/config.go | 14 +-- internal/config/config_test.go | 29 ------ internal/config/load.go | 27 +---- internal/config/test_data/config_01.jsonnet | 11 -- tools/update-readme/main.go | 35 +++++++ 11 files changed, 182 insertions(+), 113 deletions(-) create mode 100644 README.tpl.md create mode 100644 examples/example.yaml delete mode 100644 internal/config/test_data/config_01.jsonnet create mode 100644 tools/update-readme/main.go diff --git a/README.md b/README.md index 65c9cd8..effba26 100644 --- a/README.md +++ b/README.md @@ -15,21 +15,21 @@ _zit_ chooses a git identity based on: ```yaml users: work: &work_user - name: John Doe - email: john.doe@corp.com + name: "John Doe" + email: "john.doe@corp.com" personal: github_user: &personal_github_user - name: JD42 - email: JD42@users.noreply.github.com + name: "JD42" + email: "JD42@users.noreply.github.com" gitlab_user: &personal_gitlab_user - name: JD42 - email: 786972-JD42@users.noreply.gitlab.com + name: "JD42" + email: "786972-JD42@users.noreply.gitlab.com" hosts: github.com: default: *personal_github_user overrides: - - owner: corp + - owner: "corp" user: *work_user gitlab.com: default: *personal_gitlab_user @@ -125,20 +125,3 @@ $ zit doctor - [x] git config --unset-all --system user.name - [x] git config --unset-all --system user.email ``` - -## Development - -Run all tests: - -``` -./scripts/test.sh -``` - -Release: - -- [ ] Bump version -- [ ] Commit changes - -``` -./scripts/release.sh -``` diff --git a/README.tpl.md b/README.tpl.md new file mode 100644 index 0000000..92c36d1 --- /dev/null +++ b/README.tpl.md @@ -0,0 +1,108 @@ +# zit + +_git identity manager_ + +## How it works + +_zit_ chooses a git identity based on: + +1. git remote host +2. repository owner +3. repository name + +… as defined in the configuration file: + +```yaml +{{.ExampleYaml}} +``` + +## Setup + +There are 2 ways to set up a configuration file: + +1. Place it at the default location: `$HOME/.zit/config.yaml` +2. Specify an environment variable that points to the config file: + +```bash +export ZIT_CONFIG=/custom-location/.zit-config.yaml +``` + +If the environment variable is set up, it will be chosen over the config at the +default location. + +## Usage + +To set up an identity, run `zit set` inside a repo directory: + +```bash +$ zit set # personal repo +set user: jdoe + +$ git remote get-url origin +https://github.com/jdoe/repo.git +``` + +```bash +$ zit set # work repo +set user: John Doe + +$ git remote get-url origin +git@github.corp.com:team/repo.git +``` + +**Note**: Use `--dry-run` flag to test which identity will be used without +applying it. + +## Installation + +**On Mac/Linux with Homebrew** + +```bash +brew tap ayakovlenko/tools +brew install ayakovlenko/tools/zit +``` + +**From sources** + +```bash +git clone https://github.com/ayakovlenko/zit.git +cd zit +go install +``` + +**From binaries** + +Download binaries from the +[releases](https://github.com/ayakovlenko/zit/releases) page. + +## Setup + +**Remove any existing global identity** + +```bash +git config --unset-all --global user.name +git config --unset-all --global user.email +git config --unset-all --system user.name +git config --unset-all --system user.email +``` + +**Require config to exist in order to make commits** + +```bash +git config --global user.useConfigOnly true +``` + +Without the global user name and user email, git would use the system's hostname +and username to make commits. Tell git to throw an error instead, requiring you +to specify an identity for every new project. + +Run `zit doctor` to make sure the system is configured correctly: + +```bash +$ zit doctor +- [x] git config --global user.useConfigOnly true +- [x] git config --unset-all --global user.name +- [x] git config --unset-all --global user.email +- [x] git config --unset-all --system user.name +- [x] git config --unset-all --system user.email +``` diff --git a/cmd/zit/main.go b/cmd/zit/main.go index 302424e..5753866 100644 --- a/cmd/zit/main.go +++ b/cmd/zit/main.go @@ -10,7 +10,7 @@ import ( "github.com/urfave/cli/v2" ) -const AppVersion = "v2.6.1+1" +const AppVersion = "v3.0.0" func main() { app := &cli.App{ diff --git a/examples/example.yaml b/examples/example.yaml new file mode 100644 index 0000000..6127904 --- /dev/null +++ b/examples/example.yaml @@ -0,0 +1,20 @@ +users: + work: &work_user + name: "John Doe" + email: "john.doe@corp.com" + personal: + github_user: &personal_github_user + name: "JD42" + email: "JD42@users.noreply.github.com" + gitlab_user: &personal_gitlab_user + name: "JD42" + email: "786972-JD42@users.noreply.gitlab.com" + +hosts: + github.com: + default: *personal_github_user + overrides: + - owner: "corp" + user: *work_user + gitlab.com: + default: *personal_gitlab_user diff --git a/go.mod b/go.mod index 916bc2d..0028fe9 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module zit go 1.22 require ( - github.com/google/go-jsonnet v0.17.0 github.com/mojotx/git-urls v1.0.4 github.com/spf13/afero v1.11.0 github.com/stretchr/testify v1.8.4 @@ -14,9 +13,11 @@ require ( require ( github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/pretty v0.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect golang.org/x/text v0.14.0 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 43b288c..ad7f3eb 100644 --- a/go.sum +++ b/go.sum @@ -1,46 +1,31 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/google/go-jsonnet v0.17.0 h1:/9NIEfhK1NQRKl3sP2536b2+x5HnZMdql7x3yK/l8JY= -github.com/google/go-jsonnet v0.17.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mojotx/git-urls v1.0.4 h1:SuaKu7PABynwXFpQ4Sdo4xRqZnPlLTfiH02MZnwPhsU= github.com/mojotx/git-urls v1.0.4/go.mod h1:3r/CupaM0w80YWMgD/chjQLJWS6cSVHf5fxGwoxyC3g= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/config/config.go b/internal/config/config.go index 2fedc17..4bda5f9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -26,21 +26,21 @@ type HostMap map[string]HostConfig // HostConfig TODO type HostConfig struct { - Default *User `json:"default" yaml:"default"` - Overrides []Override `json:"overrides" yaml:"overrides"` + Default *User `yaml:"default"` + Overrides []Override `yaml:"overrides"` } // User TODO type User struct { - Name string `json:"name" yaml:"name"` - Email string `json:"email" yaml:"email"` + Name string `yaml:"name"` + Email string `yaml:"email"` } // Override TODO type Override struct { - Owner string `json:"owner" yaml:"owner"` - Repo string `json:"repo,omitempty" yaml:"repo"` - User User `json:"user" yaml:"user"` + Owner string `yaml:"owner"` + Repo string `yaml:"repo"` + User User `yaml:"user"` } type ConfigRoot struct { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 1ee4d5f..4c2b616 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -7,18 +7,6 @@ import ( ) func TestLocateConfig(t *testing.T) { - t.Run("get default Jsonnet config if it exists", func(t *testing.T) { - fs := afero.NewMemMapFs() - _, _ = fs.Create("/home/.zit/config.jsonnet") - - have, _ := LocateConfFile(fs, "/home", "") - want := "/home/.zit/config.jsonnet" - - if have != want { - t.Errorf("want: %s, have: %s", want, have) - } - }) - t.Run("get default YAML config if it exists", func(t *testing.T) { fs := afero.NewMemMapFs() _, _ = fs.Create("/home/.zit/config.yaml") @@ -53,23 +41,6 @@ func TestLoad(t *testing.T) { } }) - t.Run("simple Jsonnet config", func(t *testing.T) { - config, _ := Load("test_data/config_01.jsonnet") - - host, _ := config.Get("github.corp.com") - - name := host.Default.Name - email := host.Default.Email - - if name != "John Doe" { - t.Errorf("want: John Doe; have: %s", name) - } - - if email != "john.doe@corp.com" { - t.Errorf("want: john.doe@corp.com; have: %s", email) - } - }) - t.Run("simple YAML config", func(t *testing.T) { config, _ := Load("test_data/config_01.yaml") diff --git a/internal/config/load.go b/internal/config/load.go index 58bd19c..a1f8472 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -1,13 +1,11 @@ package config import ( - "encoding/json" "fmt" "os" "path" "strings" - "github.com/google/go-jsonnet" "github.com/spf13/afero" "gopkg.in/yaml.v2" ) @@ -35,8 +33,7 @@ func Load(filename string) (*ConfigRoot, error) { } return parseYaml(contents) case jsonnetFormat: - fmt.Println("WARN: Jsonnet configs are deprecated and going to be unsupported in future versions. Migrate to YAML format.") - return parseJsonnet(filename) + return nil, fmt.Errorf("zit no longer supports Jsonnet configs since v3") default: return nil, fmt.Errorf("something went horribly wrong") } @@ -55,18 +52,13 @@ func formatFromFilename(filename string) string { func LocateConfFile(fs afero.Fs, userHomeDir, confPathFromEnv string) (string, error) { var confPath string - jsonnetDefault := path.Join(userHomeDir, ".zit", "config.jsonnet") yamlDefault := path.Join(userHomeDir, ".zit", "config.yaml") // if ZIT_CONFIG is not set, try default location envVarDefined := confPathFromEnv != "" if !envVarDefined { - if fileExists(fs, jsonnetDefault) { - return jsonnetDefault, nil - } else { - return yamlDefault, nil - } + return yamlDefault, nil } if !fileExists(fs, confPathFromEnv) { @@ -90,21 +82,6 @@ func fileExists(fs afero.Fs, filename string) bool { return true } -func parseJsonnet(filename string) (*ConfigRoot, error) { - vm := jsonnet.MakeVM() - confJSON, err := vm.EvaluateFile(filename) - if err != nil { - return nil, err - } - - var Hosts HostMap - if err := json.Unmarshal([]byte(confJSON), &Hosts); err != nil { - return nil, err - } - - return &ConfigRoot{Hosts}, nil -} - func parseYaml(contents []byte) (*ConfigRoot, error) { var config ConfigRoot if err := yaml.Unmarshal(contents, &config); err != nil { diff --git a/internal/config/test_data/config_01.jsonnet b/internal/config/test_data/config_01.jsonnet deleted file mode 100644 index 510cf4c..0000000 --- a/internal/config/test_data/config_01.jsonnet +++ /dev/null @@ -1,11 +0,0 @@ -local User(name, email) = { name: name, email: email }; - -local user = { - "work": User("John Doe", "john.doe@corp.com") -}; - -{ - "github.corp.com": { - "default": user.work - } -} diff --git a/tools/update-readme/main.go b/tools/update-readme/main.go new file mode 100644 index 0000000..9f66294 --- /dev/null +++ b/tools/update-readme/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "fmt" + "os" + "strings" + "text/template" +) + +type ReadmeData struct { + ExampleYaml string +} + +func main() { + tpl := template.Must(template.ParseFiles("./README.tpl.md")) + + example, err := os.ReadFile("./examples/example.yaml") + if err != nil { + panic(fmt.Errorf("load example: %v", err)) + } + + rd := ReadmeData{ + ExampleYaml: strings.TrimSpace(string(example)), + } + + readme, err := os.Create("./README.md") + if err != nil { + panic(fmt.Errorf("create readme: %v", err)) + } + defer readme.Close() + + if err := tpl.Execute(readme, rd); err != nil { + panic(fmt.Errorf("write readme: %v", err)) + } +}