feat: unify installation model catalog

This commit is contained in:
Codex
2026-09-02 18:45:33 +02:00
parent ae053961a3
commit 7b7927bfe5
169 changed files with 3696 additions and 4572 deletions
+5
View File
@@ -13,12 +13,14 @@ import (
"github.com/aritmolab/thothii/tools/tht/internal/authconfig"
"github.com/aritmolab/thothii/tools/tht/internal/compose"
"github.com/aritmolab/thothii/tools/tht/internal/config"
"github.com/aritmolab/thothii/tools/tht/internal/modelprojection"
)
const healthTimeout = 5 * time.Minute
var healthPollInterval = time.Second
var requireRuntimeAuthProjectionReady = authconfig.RequireRuntimeAuthProjectionReady
var generateModelProjections = modelprojection.Generate
// HealthFailure identifies the last non-ready service after a bounded health wait.
type HealthFailure struct {
@@ -46,6 +48,9 @@ func Start(ctx context.Context, installation config.Installation, runner compose
if err := requireRuntimeAuthProjectionReady(installation); err != nil {
return errors.New("runtime authentication projection is unavailable")
}
if err := generateModelProjections(installation); err != nil {
return fmt.Errorf("model runtime projection: %w", err)
}
if build {
if err := runCompose(ctx, installation, runner, "build"); err != nil {
return fmt.Errorf("image build: %w", err)
@@ -13,6 +13,7 @@ import (
// Catches --build being ignored, which would run stale images after a checkout update.
func TestStartBuildsBeforeStartingAndCheckingHealth(t *testing.T) {
stubModelProjection(t, nil)
runner := &recordingRunner{}
installation := testInstallation()
@@ -26,6 +27,7 @@ func TestStartBuildsBeforeStartingAndCheckingHealth(t *testing.T) {
// Catches a normal start unnecessarily rebuilding images.
func TestStartSkipsBuildUnlessRequested(t *testing.T) {
stubModelProjection(t, nil)
runner := &recordingRunner{}
installation := testInstallation()
@@ -38,6 +40,7 @@ func TestStartSkipsBuildUnlessRequested(t *testing.T) {
}
func TestStartRefusesProjectedAuthenticationBeforeComposeWhenNotReady(t *testing.T) {
stubModelProjection(t, nil)
for _, state := range []string{"missing", "blocked", "divergent"} {
t.Run(state, func(t *testing.T) {
previous := requireRuntimeAuthProjectionReady
@@ -61,6 +64,26 @@ func TestStartRefusesProjectedAuthenticationBeforeComposeWhenNotReady(t *testing
}
}
func TestStartRefusesProjectionFailureBeforeCompose(t *testing.T) {
stubModelProjection(t, errors.New("synthetic projection failure"))
runner := &recordingRunner{}
err := Start(context.Background(), testInstallation(), runner, false)
if err == nil || !strings.Contains(err.Error(), "model runtime projection") {
t.Fatalf("Start() error = %v", err)
}
if len(runner.stages) != 0 {
t.Fatalf("Start() reached Compose: %v", runner.stages)
}
}
func stubModelProjection(t *testing.T, result error) {
t.Helper()
previous := generateModelProjections
generateModelProjections = func(config.Installation) error { return result }
t.Cleanup(func() { generateModelProjections = previous })
}
type recordingRunner struct{ stages []string }
func (r *recordingRunner) Run(_ context.Context, args []string, _ io.Reader) (compose.Result, error) {