Skip to content

Commit

Permalink
Add tests for override and document
Browse files Browse the repository at this point in the history
  • Loading branch information
m-mizutani committed Jun 22, 2024
1 parent 9972f8c commit 4cdaaa1
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 7 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,31 @@ You can specify arguments to specify loading environment in same manner with exe

## Advanced Usage

### Overriding environment variable

`zenv` can override environment variable by multiple `-e` option.

```sh
$ cat .env
POSTGRES_DB=your_local_db
POSTGRES_USER=test_user
$ cat .env.local
POSTGRES_DB=your_local_dev_db
$ zenv -e .env -e .env.local psql
# Access to your_local_dev_db with test_user
```

The priority for loading environment variables is as follows: first, the `-e` option, followed by additional `-e` options, and finally, the arguments of the `zenv` command.

```sh
$ cat .env1
COLOR=blue
$ cat .env2
COLOR=orange
$ zenv -e .env1 -e .env2 COLOR=red echo %COLOR
red
```

### Generate random secure value

`secret generate` subcommand can generate random value like token and save to KeyChain.
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ require (
github.com/google/uuid v1.3.0
github.com/keybase/go-keychain v0.0.0-20221221221913-9be78f6c498b
github.com/m-mizutani/goerr v0.1.8
github.com/m-mizutani/gt v0.0.4-0.20230223020823-2e7042cd92a6
github.com/m-mizutani/gt v0.0.10
github.com/mattn/go-shellwords v1.0.12
github.com/rs/zerolog v1.29.0
github.com/urfave/cli/v2 v2.24.4
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/keybase/go-keychain v0.0.0-20221221221913-9be78f6c498b h1:k2ZvAPXrDB1Q7fGRdUane+T08K+UaL96qH47Setr/7k=
github.com/keybase/go-keychain v0.0.0-20221221221913-9be78f6c498b/go.mod h1:TXh6wFVZNh4iuqbymzy4r3obmj8hTPDlLNnoKNIbvJE=
github.com/m-mizutani/goerr v0.1.8 h1:6UtsMmOkJsaYNtAsMNLvWIteZPl1NOxpKFYK5m65vpQ=
github.com/m-mizutani/goerr v0.1.8/go.mod h1:fQkXuu06q+oLlp4FkbiTFzI/N/+WAK/Mz1W5kPZ6yzs=
github.com/m-mizutani/gt v0.0.4-0.20230223020823-2e7042cd92a6 h1:aB3qT7U3VGuzOyoz/6QbwE7DxbrFWQBLlbOYwjSSBss=
github.com/m-mizutani/gt v0.0.4-0.20230223020823-2e7042cd92a6/go.mod h1:0MPYSfGBLmYjTduzADVmIqD58ELQ5IfBFiK/f0FmB3k=
github.com/m-mizutani/gt v0.0.10 h1:gJsRcZ0R0kcVAGeahwDAVBCDCwOA/tFw3N1/kh3DnAY=
github.com/m-mizutani/gt v0.0.10/go.mod h1:0MPYSfGBLmYjTduzADVmIqD58ELQ5IfBFiK/f0FmB3k=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
Expand Down
10 changes: 10 additions & 0 deletions pkg/usecase/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ func (x *Usecase) parseArgs(args types.Arguments) (types.Arguments, []*model.Env
}
}

// Remove duplicated env vars. The last one is used.
unique := make(map[types.EnvKey]*model.EnvVar)
for _, v := range envVars {
unique[v.Key] = v
}
envVars = make([]*model.EnvVar, 0, len(unique))
for _, v := range unique {
envVars = append(envVars, v)
}

assigned := make([]*model.EnvVar, len(envVars))
for i, v := range envVars {
newVar := *v
Expand Down
90 changes: 90 additions & 0 deletions pkg/usecase/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package usecase_test

import (
"fmt"
"os"
"sort"
"testing"

"github.com/m-mizutani/gt"
Expand Down Expand Up @@ -82,6 +84,9 @@ func TestDotEnv(t *testing.T) {
gt.Array(t, args).
Equal([]types.Argument{"this", "test"})

sort.Slice(vars, func(i, j int) bool {
return vars[i].Key < vars[j].Key
})
gt.Array(t, vars).Equal([]*model.EnvVar{
{
Key: "COLOR",
Expand Down Expand Up @@ -163,3 +168,88 @@ func TestReplacement(t *testing.T) {
}))
})
}

func TestOverride(t *testing.T) {
type testCase struct {
inputFiles []types.FilePath
envVars []*model.EnvVar
}

runTest := func(tc testCase) func(t *testing.T) {
return func(t *testing.T) {
var called int
uc, mock := usecase.NewWithMock(usecase.WithConfig(&model.Config{
DotEnvFiles: tc.inputFiles,
}))
mock.ReadFileMock = func(filename types.FilePath) ([]byte, error) {
return os.ReadFile(string(filename))
}

mock.ExecMock = func(vars []*model.EnvVar, args types.Arguments) error {
called++

sort.Slice(vars, func(i, j int) bool {
return vars[i].Key < vars[j].Key
})

gt.Array(t, vars).Equal(tc.envVars)
return nil
}

gt.NoError(t, uc.Exec(&model.ExecInput{
Args: types.Arguments{"this", "test"},
}))
gt.Equal(t, called, 1)
}
}

t.Run("no override env vars", runTest(testCase{
inputFiles: []types.FilePath{"testdata/basic.env"},
envVars: []*model.EnvVar{
{Key: "COLOR", Value: "blue"},
},
}))

t.Run("override env vars by one file", runTest(testCase{
inputFiles: []types.FilePath{
"testdata/basic.env",
"testdata/override1.env",
},
envVars: []*model.EnvVar{
{Key: "COLOR", Value: "orange"},
},
}))

t.Run("override env vars by two files", runTest(testCase{
inputFiles: []types.FilePath{
"testdata/basic.env",
"testdata/override1.env",
"testdata/override2.env",
},
envVars: []*model.EnvVar{
{Key: "COLOR", Value: "red"},
},
}))

t.Run("override env vars prioritize by order", runTest(testCase{
inputFiles: []types.FilePath{
"testdata/basic.env",
"testdata/override2.env",
"testdata/override1.env",
},
envVars: []*model.EnvVar{
{Key: "COLOR", Value: "orange"},
},
}))

t.Run("override env vars prioritize by order (2)", runTest(testCase{
inputFiles: []types.FilePath{
"testdata/override2.env",
"testdata/override1.env",
"testdata/basic.env",
},
envVars: []*model.EnvVar{
{Key: "COLOR", Value: "blue"},
},
}))
}
1 change: 1 addition & 0 deletions pkg/usecase/testdata/basic.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
COLOR=blue
1 change: 1 addition & 0 deletions pkg/usecase/testdata/override1.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
COLOR=orange
1 change: 1 addition & 0 deletions pkg/usecase/testdata/override2.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
COLOR=red
2 changes: 1 addition & 1 deletion pkg/usecase/usecase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestGenerate(t *testing.T) {
mock.PutKeyChainValuesMock = func(envVars []*model.EnvVar, namespace types.Namespace) error {
gt.V(t, namespace).Equal("zenv.bridge")
gt.A(t, envVars).Length(1).
Elem(0, func(t testing.TB, v *model.EnvVar) {
At(0, func(t testing.TB, v *model.EnvVar) {
gt.Value(t, v.Key).Equal("SECRET")
gt.N(t, len(v.Value)).Equal(24)
})
Expand Down

0 comments on commit 4cdaaa1

Please sign in to comment.