A .env file in the working directory is now optional

This commit is contained in:
bwilliams committed 2026-10-21 15:28:52 +01:00
1 parent 0b1952bd69
commit 1e3acaeff3
5 files changed
+30 -9

No files matched your search

+2 -2
View File
@@ -46,8 +46,8 @@ Configuration is read from, in increasing priority:
given with `--config` given with `--config`
3. `JOBSEARCH_*` environment variables, e.g. `JOBSEARCH_LOGGING_LEVEL=debug` 3. `JOBSEARCH_*` environment variables, e.g. `JOBSEARCH_LOGGING_LEVEL=debug`
A `.env` file in the working directory is loaded into the environment first, A `.env` file in the working directory, if there is one, is loaded into the
and must exist. environment first.
Example `config.yaml`: Example `config.yaml`:
```yaml ```yaml
+7 -1
View File
@@ -73,11 +73,17 @@ func TestConfigFlag(t *testing.T) {
} }
} }
func TestMissingEnvFile(t *testing.T) { // A .env file is optional, but one that can't be parsed is an error.
func TestEnvFile(t *testing.T) {
cmdtest.Setup(t, appConfig) cmdtest.Setup(t, appConfig)
if err := os.Remove(".env"); err != nil { if err := os.Remove(".env"); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if _, err := cmdtest.Run(t, newRoot, "", "level"); err != nil {
t.Errorf("without a .env file: %v; want no error", err)
}
cmdtest.WriteFile(t, ".env", "NOT VALID\n")
_, err := cmdtest.Run(t, newRoot, "", "level") _, err := cmdtest.Run(t, newRoot, "", "level")
cmdtest.ErrContains(t, err, ".env") cmdtest.ErrContains(t, err, ".env")
} }
+2 -2
View File
@@ -8,8 +8,8 @@ environment variables, merged through [Viper](https://github.com/spf13/viper).
## Loading order ## Loading order
`Init(cfgFile, &conf)` builds the configuration in this order: `Init(cfgFile, &conf)` builds the configuration in this order:
1. Loads `.env` from the working directory into the environment. A missing 1. Loads `.env` from the working directory into the environment, if there
`.env` file is an error. is one. A `.env` file that can't be read or parsed is an error.
2. Sets the defaults from the `default` struct tags as Viper defaults. 2. Sets the defaults from the `default` struct tags as Viper defaults.
3. Reads the config file: `cfgFile` if given, otherwise the first 3. Reads the config file: `cfgFile` if given, otherwise the first
`config.yaml` found in `/etc/job-search` then the working directory. If no `config.yaml` found in `/etc/job-search` then the working directory. If no
+7 -2
View File
@@ -3,6 +3,7 @@ package config
import ( import (
"errors" "errors"
"fmt" "fmt"
"io/fs"
"log/slog" "log/slog"
"os" "os"
"strings" "strings"
@@ -34,9 +35,13 @@ func isExplicitlySet(key string) bool {
} }
// loadEnv loads environment variables from a .env file in the working // loadEnv loads environment variables from a .env file in the working
// directory. // directory, if there is one. One that can't be read or parsed is an error.
func loadEnv() error { func loadEnv() error {
if err := godotenv.Load(); err != nil { err := godotenv.Load()
if errors.Is(err, fs.ErrNotExist) {
return nil
}
if err != nil {
return fmt.Errorf("invalid .env file: %w", err) return fmt.Errorf("invalid .env file: %w", err)
} }
return nil return nil
+12 -2
View File
@@ -141,10 +141,20 @@ func TestInitKeepsCommandLineLevel(t *testing.T) {
} }
} }
func TestInitErrors(t *testing.T) { // A .env file is optional.
t.Run("no .env file", func(t *testing.T) { func TestInitWithoutEnvFile(t *testing.T) {
initDir(t, nil, testConfigYAML) initDir(t, nil, testConfigYAML)
var conf JobSearchConfig var conf JobSearchConfig
if err := Init("", &conf); err != nil {
t.Fatalf("err = %v; want nil without a .env file", err)
}
}
func TestInitErrors(t *testing.T) {
t.Run("invalid .env file", func(t *testing.T) {
dir := initDir(t, nil, testConfigYAML)
writeFile(t, filepath.Join(dir, ".env"), "NOT VALID\n")
var conf JobSearchConfig
if err := Init("", &conf); err == nil || if err := Init("", &conf); err == nil ||
!strings.Contains(err.Error(), ".env") { !strings.Contains(err.Error(), ".env") {
t.Fatalf("err = %v; want an invalid .env file error", err) t.Fatalf("err = %v; want an invalid .env file error", err)