100 lines
2.4 KiB
Go
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
|
|
}
|