feat: funciones infra — Docker, deploy, build y health check

Funciones impuras para gestión de contenedores: docker_build_image,
docker_compose_up/down, docker_volume_create/list/remove,
generate_dockerfile, write_dockerfile, go_build_binary, health_check_http,
deploy_app y stop_app. Todas con tests unitarios donde aplica.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 14:24:12 +02:00
parent b5a6711c64
commit 90693fb32f
34 changed files with 1386 additions and 0 deletions
@@ -0,0 +1,58 @@
package infra
import (
"os"
"path/filepath"
"testing"
)
func TestDockerBuildImage(t *testing.T) {
t.Run("build sin build args retorna image ID", func(t *testing.T) {
// Crear un Dockerfile temporal minimo
dir := t.TempDir()
dockerfile := filepath.Join(dir, "Dockerfile")
if err := os.WriteFile(dockerfile, []byte("FROM scratch\n"), 0644); err != nil {
t.Skip("no se pudo crear Dockerfile temporal:", err)
}
id, err := DockerBuildImage(dir, "test-fn-registry-scratch:latest", nil)
if err != nil {
// Docker puede no estar disponible en CI — skip en vez de fail
t.Skipf("docker build no disponible: %v", err)
}
if id == "" {
t.Error("se esperaba un image ID no vacio")
}
// Limpiar
_ = DockerRemoveImage("test-fn-registry-scratch:latest", true)
})
t.Run("build con build args incluye --build-arg", func(t *testing.T) {
dir := t.TempDir()
dockerfile := filepath.Join(dir, "Dockerfile")
content := "FROM scratch\nARG MY_VERSION\n"
if err := os.WriteFile(dockerfile, []byte(content), 0644); err != nil {
t.Skip("no se pudo crear Dockerfile:", err)
}
id, err := DockerBuildImage(dir, "test-fn-registry-args:latest", map[string]string{
"MY_VERSION": "42",
})
if err != nil {
t.Skipf("docker build no disponible: %v", err)
}
if id == "" {
t.Error("se esperaba un image ID no vacio")
}
_ = DockerRemoveImage("test-fn-registry-args:latest", true)
})
t.Run("error si contextDir no existe", func(t *testing.T) {
_, err := DockerBuildImage("/ruta/que/no/existe/nunca", "test:latest", nil)
if err == nil {
t.Error("se esperaba error para directorio inexistente")
}
})
}