From 6b8ad93e626a34b08fd3bacc06c2681aa9dad495 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 21:52:22 +0200 Subject: [PATCH 01/10] test: fix flaky test --- serve/config/filewatcher_test.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index 513b93b..7e4b41b 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -17,6 +17,10 @@ func (env *testEnvState) handleChange(variables map[string]*string) { } func TestShouldUpdateDotEnvOnChange(t *testing.T) { + if os.Getenv("CI") != "" { + t.Skip("Skipping flaky test in CI environment") + } + context := test.NewTestDir(t) envFilePath := filepath.Join(context.Path, "../config/.env") os.WriteFile(envFilePath, []byte("ENV =production\nPORT =8080 \nDELAY = 200"), 0666) @@ -33,17 +37,11 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 3) - f, err := os.OpenFile(envFilePath, os.O_WRONLY, 0666) + err = os.WriteFile(envFilePath, []byte("TEST = example"), 0666) if err != nil { t.Fatalf("failed to write to file: %s", err) } - f.Sync() - time.Sleep(time.Millisecond) - f.WriteString("TEST = example") - f.Sync() - f.Close() - // This test is flaky on GitHub Actions, so we do this workaround counter := 0 for counter < 200 && len(testEnv.env) != 1 { From ea2d620c7e3ee4f769bcedebae65544ce83a5d96 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 21:58:46 +0200 Subject: [PATCH 02/10] test: re-enable test --- serve/config/filewatcher_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index 7e4b41b..ca62983 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -17,10 +17,6 @@ func (env *testEnvState) handleChange(variables map[string]*string) { } func TestShouldUpdateDotEnvOnChange(t *testing.T) { - if os.Getenv("CI") != "" { - t.Skip("Skipping flaky test in CI environment") - } - context := test.NewTestDir(t) envFilePath := filepath.Join(context.Path, "../config/.env") os.WriteFile(envFilePath, []byte("ENV =production\nPORT =8080 \nDELAY = 200"), 0666) From eb3f32851126babbde2adc1c53f7360e7b2a236c Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 22:00:47 +0200 Subject: [PATCH 03/10] test: wip --- serve/config/filewatcher_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index ca62983..94bc2ca 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "ngstaticserver/test" "os" "path/filepath" @@ -33,14 +34,17 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 3) + fmt.Println(env.env) err = os.WriteFile(envFilePath, []byte("TEST = example"), 0666) if err != nil { t.Fatalf("failed to write to file: %s", err) } + fmt.Println(env.env) // This test is flaky on GitHub Actions, so we do this workaround counter := 0 for counter < 200 && len(testEnv.env) != 1 { + fmt.Println(env.env) time.Sleep(time.Millisecond * 50) counter++ } From a7681af7796a305237e265c3bf758e7fef6eadab Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 22:30:00 +0200 Subject: [PATCH 04/10] test: wip2 --- serve/config/filewatcher_test.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index 94bc2ca..8108750 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -34,17 +34,17 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 3) - fmt.Println(env.env) + printState(env, envFilePath) err = os.WriteFile(envFilePath, []byte("TEST = example"), 0666) if err != nil { t.Fatalf("failed to write to file: %s", err) } - fmt.Println(env.env) + printState(env, envFilePath) // This test is flaky on GitHub Actions, so we do this workaround counter := 0 for counter < 200 && len(testEnv.env) != 1 { - fmt.Println(env.env) + printState(env, envFilePath) time.Sleep(time.Millisecond * 50) counter++ } @@ -52,3 +52,9 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 1) test.AssertEqual(t, readValue(t, testEnv.env, "TEST"), "example") } + +func printState(env *DotEnv, file string) { + fmt.Println(env.env) + content, _ := os.ReadFile(file) + fmt.Println(string(content)) +} From 060ec24111497146c9a19faa575f9fa055898638 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 22:41:22 +0200 Subject: [PATCH 05/10] test: wip3 --- serve/config/filewatcher_test.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index 8108750..3c2bea4 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "ngstaticserver/test" "os" "path/filepath" @@ -34,17 +33,16 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 3) - printState(env, envFilePath) err = os.WriteFile(envFilePath, []byte("TEST = example"), 0666) if err != nil { t.Fatalf("failed to write to file: %s", err) } - printState(env, envFilePath) // This test is flaky on GitHub Actions, so we do this workaround counter := 0 for counter < 200 && len(testEnv.env) != 1 { - printState(env, envFilePath) + // Reading the file seems to fix the issue + os.ReadFile(envFilePath) time.Sleep(time.Millisecond * 50) counter++ } @@ -52,9 +50,3 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 1) test.AssertEqual(t, readValue(t, testEnv.env, "TEST"), "example") } - -func printState(env *DotEnv, file string) { - fmt.Println(env.env) - content, _ := os.ReadFile(file) - fmt.Println(string(content)) -} From d6a8a4a772e9d880c6c2ec5d9c5597cb2c2b4cb0 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 22:44:28 +0200 Subject: [PATCH 06/10] test: wip4 --- serve/config/filewatcher_test.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index 3c2bea4..49da076 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "ngstaticserver/test" "os" "path/filepath" @@ -41,8 +42,7 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { // This test is flaky on GitHub Actions, so we do this workaround counter := 0 for counter < 200 && len(testEnv.env) != 1 { - // Reading the file seems to fix the issue - os.ReadFile(envFilePath) + printState(env, envFilePath) time.Sleep(time.Millisecond * 50) counter++ } @@ -50,3 +50,9 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { test.AssertEqual(t, len(testEnv.env), 1) test.AssertEqual(t, readValue(t, testEnv.env, "TEST"), "example") } + +func printState(env *DotEnv, file string) { + fmt.Println(env.env) + content, _ := os.ReadFile(file) + fmt.Println(string(content)) +} From 01ac285f1f01ce95d2730de84e73edb4733741d2 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 22:46:51 +0200 Subject: [PATCH 07/10] test: wip5 --- serve/config/dotenv.go | 1 + 1 file changed, 1 insertion(+) diff --git a/serve/config/dotenv.go b/serve/config/dotenv.go index 178c6f8..e2c097e 100644 --- a/serve/config/dotenv.go +++ b/serve/config/dotenv.go @@ -56,6 +56,7 @@ func (dotEnv *DotEnv) HandleChange() { func parseDotEnv(filePath string) map[string]*string { content, err := os.ReadFile(filePath) + fmt.Printf("parse: %v", string(content)) if err != nil { return make(map[string]*string, 0) } From bcb6b48aeac2f31d9981103a9c5b7b71aad781a9 Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 22:51:05 +0200 Subject: [PATCH 08/10] test: wip6 --- serve/config/dotenv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serve/config/dotenv.go b/serve/config/dotenv.go index e2c097e..b725b97 100644 --- a/serve/config/dotenv.go +++ b/serve/config/dotenv.go @@ -56,7 +56,7 @@ func (dotEnv *DotEnv) HandleChange() { func parseDotEnv(filePath string) map[string]*string { content, err := os.ReadFile(filePath) - fmt.Printf("parse: %v", string(content)) + fmt.Printf("parse %v: %v", filePath, string(content)) if err != nil { return make(map[string]*string, 0) } From 4acab60e59bb45784742a780905cb6eeb2345e2c Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 23:04:23 +0200 Subject: [PATCH 09/10] test: wip7 --- serve/config/filewatcher.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/serve/config/filewatcher.go b/serve/config/filewatcher.go index c3bb8f7..18c1fff 100644 --- a/serve/config/filewatcher.go +++ b/serve/config/filewatcher.go @@ -3,6 +3,7 @@ package config import ( "log/slog" "path" + "time" "github.com/fsnotify/fsnotify" ) @@ -44,6 +45,12 @@ func CreateFileWatcher() *FileWatcher { if ok { for _, watchable := range watchables { if watchable.Name() == name { + // When e.g. using os.WriteFile, the truncation already triggers + // a change event, which results in the file being empty when + // calling HandleChange. + // Due to this, we wait for a millisecond, which should be enough for + // the write operation to finish. + time.Sleep(time.Millisecond) watchable.HandleChange() } return From 35274629dddeb6d657c8b972f1fa26d4a7bb3bba Mon Sep 17 00:00:00 2001 From: Lukas Spirig Date: Sun, 20 Aug 2023 23:14:10 +0200 Subject: [PATCH 10/10] test: wip8 --- serve/config/dotenv.go | 6 +++--- serve/config/filewatcher_test.go | 15 +-------------- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/serve/config/dotenv.go b/serve/config/dotenv.go index b725b97..125bff3 100644 --- a/serve/config/dotenv.go +++ b/serve/config/dotenv.go @@ -25,8 +25,9 @@ func CreateDotEnv(workingDirectory string, onChange func(variables map[string]*s slog.Info(fmt.Sprintf("Detected .env file at %v. Reading variables and adding watch.", configEnvPath)) env = parseDotEnv(configEnvPath) } else { - slog.Info(fmt.Sprintf("Detected .env file at %v. Reading variables.", configEnvPath)) - env = parseDotEnv(filepath.Join(workingDirectory, ".env")) + localEnv := filepath.Join(workingDirectory, ".env") + slog.Info(fmt.Sprintf("Detected .env file at %v. Reading variables.", localEnv)) + env = parseDotEnv(localEnv) } instance := DotEnv{ @@ -56,7 +57,6 @@ func (dotEnv *DotEnv) HandleChange() { func parseDotEnv(filePath string) map[string]*string { content, err := os.ReadFile(filePath) - fmt.Printf("parse %v: %v", filePath, string(content)) if err != nil { return make(map[string]*string, 0) } diff --git a/serve/config/filewatcher_test.go b/serve/config/filewatcher_test.go index 49da076..a8247d6 100644 --- a/serve/config/filewatcher_test.go +++ b/serve/config/filewatcher_test.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "ngstaticserver/test" "os" "path/filepath" @@ -39,20 +38,8 @@ func TestShouldUpdateDotEnvOnChange(t *testing.T) { t.Fatalf("failed to write to file: %s", err) } - // This test is flaky on GitHub Actions, so we do this workaround - counter := 0 - for counter < 200 && len(testEnv.env) != 1 { - printState(env, envFilePath) - time.Sleep(time.Millisecond * 50) - counter++ - } + time.Sleep(time.Millisecond * 50) test.AssertEqual(t, len(testEnv.env), 1) test.AssertEqual(t, readValue(t, testEnv.env, "TEST"), "example") } - -func printState(env *DotEnv, file string) { - fmt.Println(env.env) - content, _ := os.ReadFile(file) - fmt.Println(string(content)) -}