111 lines
3.2 KiB
Go
111 lines
3.2 KiB
Go
package stage
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"gitea.maximumdirect.net/eric/narratio/internal/adapters/audita"
|
|
"gitea.maximumdirect.net/eric/narratio/internal/adapters/notarius"
|
|
"gitea.maximumdirect.net/eric/narratio/internal/adapters/notify"
|
|
"gitea.maximumdirect.net/eric/narratio/internal/adapters/scriptorium"
|
|
"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/manifest"
|
|
)
|
|
|
|
// Env is the shared dependency container visible to stages.
|
|
type Env struct {
|
|
Config *config.Config
|
|
SelectedArtifactKeys []string
|
|
ArtifactStore artifacts.Store
|
|
ManifestStore manifest.Store
|
|
Logger *slog.Logger
|
|
|
|
WhisperX whisperx.Client
|
|
Seriatim seriatim.Runner
|
|
Audita audita.Runner
|
|
Notarius notarius.Runner
|
|
Scriptorium scriptorium.Runner
|
|
ObjectStore storage.ObjectStore
|
|
Notifier notify.Sender
|
|
}
|
|
|
|
// IODecl declares the intended input/output artifact kinds for a stage.
|
|
type IODecl struct {
|
|
Inputs []artifacts.Ref
|
|
Outputs []artifacts.Ref
|
|
}
|
|
|
|
// Stage is the pipeline unit contract.
|
|
type Stage interface {
|
|
Name() string
|
|
Declares() IODecl
|
|
Run(ctx context.Context, env *Env, m *manifest.Manifest) (*StageResult, error)
|
|
}
|
|
|
|
const maxResumeReasonLength = 512
|
|
|
|
// ResumeValidation reports whether a previously succeeded stage can be reused.
|
|
type ResumeValidation struct {
|
|
Resumable bool
|
|
Reason string
|
|
}
|
|
|
|
// Normalized returns a result with a bounded reason and no reason on success.
|
|
func (r ResumeValidation) Normalized() ResumeValidation {
|
|
if r.Resumable {
|
|
return Resumable()
|
|
}
|
|
return NonResumable(r.Reason)
|
|
}
|
|
|
|
// ResumeValidator is implemented by stages that validate persisted success before reuse.
|
|
type ResumeValidator interface {
|
|
ValidateResume(ctx context.Context, env *Env, m *manifest.Manifest) (ResumeValidation, error)
|
|
}
|
|
|
|
// Resumable reports a successful resume validation.
|
|
func Resumable() ResumeValidation {
|
|
return ResumeValidation{Resumable: true}
|
|
}
|
|
|
|
// NonResumable reports a bounded reason that persisted success must be rerun.
|
|
func NonResumable(reason string) ResumeValidation {
|
|
reason = strings.TrimSpace(reason)
|
|
if reason == "" {
|
|
reason = "persisted stage result is not reusable"
|
|
}
|
|
if len(reason) > maxResumeReasonLength {
|
|
cutoff := maxResumeReasonLength
|
|
for cutoff > 0 && !utf8.ValidString(reason[:cutoff]) {
|
|
cutoff--
|
|
}
|
|
reason = reason[:cutoff]
|
|
}
|
|
return ResumeValidation{Reason: reason}
|
|
}
|
|
|
|
// StageDisposition describes the outcome of a stage that returned without an error.
|
|
type StageDisposition string
|
|
|
|
const (
|
|
// StageDispositionSucceeded is the zero value so existing stages remain successful.
|
|
StageDispositionSucceeded StageDisposition = ""
|
|
StageDispositionSkipped StageDisposition = "skipped"
|
|
)
|
|
|
|
// StageResult is the declared output of a stage execution.
|
|
type StageResult struct {
|
|
Disposition StageDisposition
|
|
SkipReason string
|
|
Outputs []artifacts.Ref
|
|
Logs []string
|
|
GeneratedConfigs []string
|
|
Metadata map[string]any
|
|
}
|