Repository: GreenmaskIO/greenmask
Pull request #318 (2025-07-21 17:36:50)

Fix: set global salt from context
Changes:
* Fixed global salt usage from context - now it correctly gets salt for generator. Covered by unit tests.
* Fixed github actions and docker compose for integration testings
* Added `make integration` target to run integration tests locally

Closes #317 


Patch:
diff --git a/Makefile b/Makefile
index 4e9897f..c6faa01 100644
--- a/Makefile
+++ b/Makefile
@@ -29,3 +29,11 @@ lint:
 
 up:
 	docker-compose up playground-dbs-filler
+
+integration:
+	docker buildx build --load -t greenmask-test-dbs-filler:latest -f docker/integration/filldb/Dockerfile docker/integration/filldb
+	docker buildx build --load -t greenmask-integration:latest -f docker/integration/tests/Dockerfile .
+	docker compose -f docker-compose-integration.yml -p greenmask up \
+                --renew-anon-volumes --force-recreate \
+                --exit-code-from greenmask --abort-on-container-exit greenmask
+
diff --git a/docker-compose-integration.yml b/docker-compose-integration.yml
index 1d92650..38d5353 100644
--- a/docker-compose-integration.yml
+++ b/docker-compose-integration.yml
@@ -127,6 +127,7 @@ services:
       retries: 3
 
   test-dbs-filler:
+    image: greenmask-test-dbs-filler:latest
     environment:
       PGPASSWORD: "example"
       FILE_DUMP: "demo-small-en.zip"
@@ -153,6 +154,7 @@ services:
         condition: service_healthy
 
   greenmask:
+    image: greenmask-integration:latest
     volumes:
       - "/tmp"
     environment:
diff --git a/internal/db/postgres/transformers/utils.go b/internal/db/postgres/transformers/utils.go
index 7e9e3db..bd7dd97 100644
--- a/internal/db/postgres/transformers/utils.go
+++ b/internal/db/postgres/transformers/utils.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/greenmaskio/greenmask/internal/db/postgres/transformers/utils"
 	"github.com/greenmaskio/greenmask/internal/generators"
+	commonutils "github.com/greenmaskio/greenmask/internal/utils"
 )
 
 const (
@@ -20,23 +21,12 @@ func getGenerateEngine(ctx context.Context, engineName string, size int) (genera
 	case RandomEngineParameterName:
 		return getRandomBytesGen(size)
 	case HashEngineParameterName:
-		salt, err := getSaltFromCtx(ctx)
-		if err != nil {
-			return nil, fmt.Errorf("error getting salt from context: %w", err)
-		}
+		salt := commonutils.SaltFromCtx(ctx)
 		return generators.GetHashBytesGen(salt, size)
 	}
 	return nil, fmt.Errorf("unknown engine %s", engineName)
 }
 
-func getSaltFromCtx(ctx context.Context) (salt []byte, err error) {
-	saltAny := ctx.Value("salt")
-	if saltAny != nil {
-		salt = saltAny.([]byte)
-	}
-	return salt, nil
-}
-
 func getRandomBytesGen(size int) (generators.Generator, error) {
 	buf := make([]byte, 8)
 	_, err := rand.Read(buf)


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 66c6821..4f5019f 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -33,8 +33,13 @@ jobs:
           path: coverage.out
           key: ${{ runner.os }}-coverage-${{ github.sha }}
 
+      - name: Build integration images
+        run: |
+          docker buildx build --load -t greenmask-test-dbs-filler:latest -f docker/integration/filldb/Dockerfile docker/integration/filldb
+          docker buildx build --load -t greenmask:latest -f docker/integration/tests/Dockerfile .
+
       - name: Run integration tests
         run: |
           docker compose -f docker-compose-integration.yml -p greenmask up \
-          --renew-anon-volumes --force-recreate --build --exit-code-from greenmask \
-          --abort-on-container-exit greenmask
+            --renew-anon-volumes --force-recreate \
+            --exit-code-from greenmask --abort-on-container-exit greenmask
diff --git a/internal/db/postgres/transformers/utils_test.go b/internal/db/postgres/transformers/utils_test.go
new file mode 100644
index 0000000..7072a08
--- /dev/null
+++ b/internal/db/postgres/transformers/utils_test.go
@@ -0,0 +1,59 @@
+package transformers
+
+import (
+	"context"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"github.com/greenmaskio/greenmask/internal/utils"
+)
+
+func Test_getGenerateEngine(t *testing.T) {
+	t.Run("random", func(t *testing.T) {
+		ctx := context.Background()
+		g, err := getGenerateEngine(ctx, RandomEngineParameterName, 32)
+		require.NoError(t, err)
+		a, err := g.Generate([]byte("123"))
+		require.NoError(t, err)
+		b, err := g.Generate([]byte("123"))
+		require.NoError(t, err)
+		require.NotEqual(t, a, b)
+	})
+
+	t.Run("random with the same salt", func(t *testing.T) {
+		salt := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+		ctx := utils.WithSalt(context.Background(), salt)
+
+		g1, err := getGenerateEngine(ctx, HashEngineParameterName, 32)
+		require.NoError(t, err)
+		a, err := g1.Generate([]byte("123"))
+		require.NoError(t, err)
+
+		g2, err := getGenerateEngine(ctx, HashEngineParameterName, 32)
+		require.NoError(t, err)
+		b, err := g2.Generate([]byte("123"))
+		require.NoError(t, err)
+
+		require.Equal(t, a, b)
+	})
+
+	t.Run("random with different salt", func(t *testing.T) {
+		salt1 := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+		ctx1 := utils.WithSalt(context.Background(), salt1)
+
+		g1, err := getGenerateEngine(ctx1, HashEngineParameterName, 32)
+		require.NoError(t, err)
+		a, err := g1.Generate([]byte("123"))
+		require.NoError(t, err)
+
+		salt2 := []byte("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")
+		ctx2 := utils.WithSalt(context.Background(), salt2)
+		g2, err := getGenerateEngine(ctx2, HashEngineParameterName, 32)
+		require.NoError(t, err)
+		b, err := g2.Generate([]byte("123"))
+		require.NoError(t, err)
+
+		require.NotEqual(t, a, b)
+	})
+}