Define adapter interfaces and fake implementations

This commit is contained in:
2026-05-02 11:16:27 -05:00
parent 78e7e4f41b
commit 2854da48c2
24 changed files with 876 additions and 73 deletions

View File

@@ -7,6 +7,12 @@ import (
"os"
"path/filepath"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/analyzer"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/audita"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/notify"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/seriatim"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/storage"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/whisperx"
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
"gitea.maximumdirect.net/eric/narratio/internal/config"
"gitea.maximumdirect.net/eric/narratio/internal/logging"
@@ -16,6 +22,7 @@ import (
type RunOptions struct {
Force bool
Env *Env
}
type RunSummary struct {
@@ -25,36 +32,64 @@ type RunSummary struct {
}
func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage, opts RunOptions) (*RunSummary, error) {
store := artifacts.NewLocalStore(cfg.Pipeline.Workspace.Root)
paths, err := store.EnsureLayout(cfg.Session.SessionID)
env := opts.Env
if env == nil {
env = &Env{}
}
if env.Config == nil {
env.Config = cfg
}
if env.ArtifactStore == nil {
env.ArtifactStore = artifacts.NewLocalStore(cfg.Pipeline.Workspace.Root)
}
if env.ManifestStore == nil {
env.ManifestStore = &manifest.LocalStore{}
}
if env.Logger == nil {
env.Logger = logging.NewLogger(os.Stderr, slog.LevelInfo)
}
if env.WhisperX == nil {
env.WhisperX = &whisperx.NoopClient{}
}
if env.Seriatim == nil {
env.Seriatim = &seriatim.NoopRunner{}
}
if env.Audita == nil {
env.Audita = &audita.NoopRunner{}
}
if env.Analyzer == nil {
env.Analyzer = &analyzer.NoopRunner{}
}
if env.Storage == nil {
env.Storage = &storage.NoopBackend{}
}
if env.Notifier == nil {
env.Notifier = &notify.NoopSender{}
}
artifactStore := env.ArtifactStore
paths, err := artifactStore.EnsureLayout(cfg.Session.SessionID)
if err != nil {
return nil, fmt.Errorf("prepare workdir: %w", err)
}
lock, err := store.AcquireSessionLock(cfg.Session.SessionID)
lock, err := artifactStore.AcquireSessionLock(cfg.Session.SessionID)
if err != nil {
return nil, fmt.Errorf("acquire session lock: %w", err)
}
defer func() {
_ = store.ReleaseSessionLock(lock)
_ = artifactStore.ReleaseSessionLock(lock)
}()
manifestStore := &manifest.LocalStore{}
manifestPath := paths.ManifestPath
m, err := loadOrCreateManifest(ctx, manifestStore, manifestPath, cfg.Session.SessionID)
m, err := loadOrCreateManifest(ctx, env.ManifestStore, manifestPath, cfg.Session.SessionID)
if err != nil {
return nil, err
}
env := &Env{
Config: cfg,
ArtifactStore: store,
Logger: logging.NewLogger(os.Stderr, slog.LevelInfo),
}
stageEnv := toStageEnv(env)
_ = opts // TODO: use --force behavior in future skip/stale logic.
_ = opts.Force // TODO: use --force behavior in future skip/stale logic.
runNames := make([]string, 0, len(stages))
for _, s := range stages {
@@ -62,14 +97,14 @@ func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage
now := nowUTC()
m.MarkStageRunning(s.Name(), now)
if err := manifestStore.Save(ctx, manifestPath, m); err != nil {
if err := env.ManifestStore.Save(ctx, manifestPath, m); err != nil {
return nil, fmt.Errorf("save manifest before stage %q: %w", s.Name(), err)
}
result, err := s.Run(ctx, stageEnv, m)
if err != nil {
m.MarkStageFailed(s.Name(), nowUTC(), err.Error())
if saveErr := manifestStore.Save(ctx, manifestPath, m); saveErr != nil {
if saveErr := env.ManifestStore.Save(ctx, manifestPath, m); saveErr != nil {
return nil, fmt.Errorf("stage %q failed (%v) and manifest save failed (%v)", s.Name(), err, saveErr)
}
return nil, fmt.Errorf("stage %q failed: %w", s.Name(), err)
@@ -79,7 +114,7 @@ func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage
m.MarkStageSucceeded(s.Name(), nowUTC(), outputs)
applyStageResultToManifest(m, s.Name(), result)
if err := manifestStore.Save(ctx, manifestPath, m); err != nil {
if err := env.ManifestStore.Save(ctx, manifestPath, m); err != nil {
return nil, fmt.Errorf("save manifest after stage %q: %w", s.Name(), err)
}
}
@@ -91,7 +126,7 @@ func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage
}, nil
}
func loadOrCreateManifest(ctx context.Context, store *manifest.LocalStore, path, sessionID string) (*manifest.Manifest, error) {
func loadOrCreateManifest(ctx context.Context, store manifest.Store, path, sessionID string) (*manifest.Manifest, error) {
exists, err := fileExists(path)
if err != nil {
return nil, fmt.Errorf("check manifest existence %q: %w", path, err)