diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d0333d..d15178f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,9 +3,9 @@ name: build on: push: branches: - - 'main' + - "main" tags: - - 'v*' + - "v*" pull_request: jobs: @@ -18,8 +18,8 @@ jobs: build: strategy: matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] - go-version: [ oldstable, stable] + os: [ubuntu-latest, macos-latest, windows-latest] + go-version: [1.18, oldstable, stable] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 diff --git a/env_generic.go b/env_generic.go new file mode 100644 index 0000000..d14003e --- /dev/null +++ b/env_generic.go @@ -0,0 +1,26 @@ +//go:build go1.18 +// +build go1.18 + +package env + +// ParseAs parses the given struct type containing `env` tags and loads its +// values from environment variables. +func ParseAs[T any]() (T, error) { + var t T + return t, Parse(&t) +} + +// ParseWithOptions parses the given struct type containing `env` tags and +// loads its values from environment variables. +func ParseAsWithOptions[T any](opts Options) (T, error) { + var t T + return t, ParseWithOptions(&t, opts) +} + +// Must panic is if err is not nil, and returns t otherwise. +func Must[T any](t T, err error) T { + if err != nil { + panic(err) + } + return t +} diff --git a/env_generic_test.go b/env_generic_test.go new file mode 100644 index 0000000..bed4896 --- /dev/null +++ b/env_generic_test.go @@ -0,0 +1,46 @@ +//go:build go1.18 +// +build go1.18 + +package env + +import "testing" + +type Conf struct { + Foo string `env:"FOO" envDefault:"bar"` +} + +func TestParseAs(t *testing.T) { + config, err := ParseAs[Conf]() + isNoErr(t, err) + isEqual(t, "bar", config.Foo) +} + +func TestParseAsWithOptions(t *testing.T) { + config, err := ParseAsWithOptions[Conf](Options{ + Environment: map[string]string{ + "FOO": "not bar", + }, + }) + isNoErr(t, err) + isEqual(t, "not bar", config.Foo) +} + +type ConfRequired struct { + Foo string `env:"FOO,required"` +} + +func TestMust(t *testing.T) { + t.Run("error", func(t *testing.T) { + defer func() { + err := recover() + isErrorWithMessage(t, err.(error), `env: required environment variable "FOO" is not set`) + }() + conf := Must(ParseAs[ConfRequired]()) + isEqual(t, "", conf.Foo) + }) + t.Run("success", func(t *testing.T) { + t.Setenv("FOO", "bar") + conf := Must(ParseAs[ConfRequired]()) + isEqual(t, "bar", conf.Foo) + }) +}