Files
2026-05-07 00:58:53 +03:00

100 lines
2.4 KiB
Go

package testenv
import (
"context"
"fmt"
"os/exec"
"path/filepath"
"runtime"
"sync"
"testing"
"time"
)
const (
BackendImage = "galaxy/backend:integration"
GatewayImage = "galaxy/gateway:integration"
GameImage = "galaxy/game:integration"
)
var (
backendOnce sync.Once
backendErr error
gatewayOnce sync.Once
gatewayErr error
gameOnce sync.Once
gameErr error
)
// EnsureBackendImage builds galaxy/backend:integration once per
// process. Subsequent calls reuse the result.
func EnsureBackendImage(t *testing.T) {
t.Helper()
backendOnce.Do(func() {
backendErr = buildImage(BackendImage, "backend/Dockerfile")
})
if backendErr != nil {
t.Skipf("build %s: %v", BackendImage, backendErr)
}
}
// EnsureGatewayImage builds galaxy/gateway:integration once per
// process.
func EnsureGatewayImage(t *testing.T) {
t.Helper()
gatewayOnce.Do(func() {
gatewayErr = buildImage(GatewayImage, "gateway/Dockerfile")
})
if gatewayErr != nil {
t.Skipf("build %s: %v", GatewayImage, gatewayErr)
}
}
// EnsureGameImage builds galaxy/game:integration once per process.
func EnsureGameImage(t *testing.T) {
t.Helper()
gameOnce.Do(func() {
gameErr = buildImage(GameImage, "game/Dockerfile")
})
if gameErr != nil {
t.Skipf("build %s: %v", GameImage, gameErr)
}
}
// integrationImageLabel is the docker label stamped onto every image
// built from `integration/testenv/images.go`. The pre-clean script
// (`integration/scripts/preclean.sh`) keys off this label to wipe
// stale builds without touching testcontainers-pulled service images
// (postgres, redis, ryuk, mailpit) which we want to keep cached.
const integrationImageLabel = "galaxy.test.kind=integration-image"
func buildImage(tag, dockerfile string) error {
root, err := workspaceRoot()
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, "docker", "build",
"-t", tag,
"-f", filepath.Join(root, dockerfile),
"--label", integrationImageLabel,
root,
)
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("docker build %s: %v\n%s", tag, err, string(out))
}
return nil
}
func workspaceRoot() (string, error) {
_, file, _, ok := runtime.Caller(0)
if !ok {
return "", fmt.Errorf("runtime.Caller failed")
}
// integration/testenv/images.go → workspace root
return filepath.Dir(filepath.Dir(filepath.Dir(file))), nil
}