96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"gitea.maximumdirect.net/eric/narratio/internal/manifest"
|
|
"gitea.maximumdirect.net/eric/narratio/internal/stage"
|
|
)
|
|
|
|
func currentStageSemanticConfig(selected stage.Stage, env *stage.Env) (*manifest.SemanticConfigFingerprint, error) {
|
|
provider, ok := selected.(stage.SemanticConfigFingerprinter)
|
|
if !ok {
|
|
return nil, nil
|
|
}
|
|
record, err := provider.SemanticConfigFingerprint(env)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := record.Validate(); err != nil {
|
|
return nil, fmt.Errorf("invalid current semantic configuration fingerprint: %w", err)
|
|
}
|
|
return cloneSemanticConfig(&record), nil
|
|
}
|
|
|
|
func validateStageSemanticResume(selected stage.Stage, m *manifest.Manifest, current *manifest.SemanticConfigFingerprint) stage.ResumeValidation {
|
|
if current == nil {
|
|
return stage.Resumable()
|
|
}
|
|
var persisted *manifest.SemanticConfigFingerprint
|
|
if m != nil && m.Stages != nil && m.Stages[selected.Name()] != nil {
|
|
persisted = m.Stages[selected.Name()].SemanticConfig
|
|
}
|
|
if persisted == nil {
|
|
return stage.NonResumable("semantic configuration evidence is missing; rerun the stage to establish current evidence")
|
|
}
|
|
if err := persisted.Validate(); err != nil {
|
|
return stage.NonResumable("persisted semantic configuration evidence is malformed; rerun the stage")
|
|
}
|
|
if persisted.Version != current.Version {
|
|
return stage.NonResumable("semantic configuration contract version changed; rerun the stage")
|
|
}
|
|
if persisted.Digest != current.Digest {
|
|
return stage.NonResumable("result-affecting configuration changed; rerun the stage")
|
|
}
|
|
return stage.Resumable()
|
|
}
|
|
|
|
func evaluateStageResume(
|
|
ctx context.Context,
|
|
selected stage.Stage,
|
|
env *stage.Env,
|
|
m *manifest.Manifest,
|
|
current *manifest.SemanticConfigFingerprint,
|
|
) (*stage.ResumeValidation, error) {
|
|
semantic := validateStageSemanticResume(selected, m, current).Normalized()
|
|
if !semantic.Resumable {
|
|
return &semantic, nil
|
|
}
|
|
validator, ok := selected.(stage.ResumeValidator)
|
|
if !ok {
|
|
if current == nil {
|
|
return nil, nil
|
|
}
|
|
return &semantic, nil
|
|
}
|
|
validation, err := validator.ValidateResume(ctx, env, m)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
validation = validation.Normalized()
|
|
return &validation, nil
|
|
}
|
|
|
|
func setSessionStageSemanticConfig(m *manifest.Manifest, name string, value *manifest.SemanticConfigFingerprint) {
|
|
if m == nil || m.Stages == nil || m.Stages[name] == nil {
|
|
return
|
|
}
|
|
m.Stages[name].SemanticConfig = cloneSemanticConfig(value)
|
|
}
|
|
|
|
func setRunStageSemanticConfig(m *manifest.RunManifest, name string, value *manifest.SemanticConfigFingerprint) {
|
|
if m == nil || m.Stages == nil || m.Stages[name] == nil {
|
|
return
|
|
}
|
|
m.Stages[name].SemanticConfig = cloneSemanticConfig(value)
|
|
}
|
|
|
|
func cloneSemanticConfig(value *manifest.SemanticConfigFingerprint) *manifest.SemanticConfigFingerprint {
|
|
if value == nil {
|
|
return nil
|
|
}
|
|
copy := *value
|
|
return ©
|
|
}
|