Files
narratio/internal/artifacts/previous_requirements.go

113 lines
2.8 KiB
Go

package artifacts
import (
"fmt"
"sort"
"strings"
"gitea.maximumdirect.net/eric/narratio/internal/config"
)
// PreviousArtifactRequirement describes one previous-session artifact dependency.
type PreviousArtifactRequirement struct {
Name string
Required bool
Sources []string
}
// CollectPreviousArtifactRequirements scans enabled Scriptorium artifacts and returns
// deduplicated previous-session artifact requirements in deterministic order.
func CollectPreviousArtifactRequirements(
artifactsCfg map[string]config.ScriptoriumArtifactConfig,
) []PreviousArtifactRequirement {
if len(artifactsCfg) == 0 {
return nil
}
artifactNames := sortedScriptoriumArtifactNames(artifactsCfg)
byName := map[string]PreviousArtifactRequirement{}
for _, artifactName := range artifactNames {
artifactCfg := artifactsCfg[artifactName]
if !artifactCfg.Enabled {
continue
}
inputNames := sortedScriptoriumInputKeys(artifactCfg.Inputs)
for _, inputName := range inputNames {
inputCfg := artifactCfg.Inputs[inputName]
previousName, ok := PreviousSessionArtifactName(inputCfg.Source)
if !ok {
continue
}
location := fmt.Sprintf(
"pipeline.scriptorium.artifacts.%s.inputs.%s.source",
artifactName,
inputName,
)
requirement := byName[previousName]
requirement.Name = previousName
requirement.Required = requirement.Required || inputCfg.Required
requirement.Sources = append(requirement.Sources, location)
byName[previousName] = requirement
}
}
if len(byName) == 0 {
return nil
}
requirements := make([]PreviousArtifactRequirement, 0, len(byName))
for _, requirement := range byName {
requirement.Sources = dedupeAndSortStrings(requirement.Sources)
requirements = append(requirements, requirement)
}
sort.Slice(requirements, func(i, j int) bool {
return requirements[i].Name < requirements[j].Name
})
return requirements
}
func sortedScriptoriumArtifactNames(artifactsCfg map[string]config.ScriptoriumArtifactConfig) []string {
names := make([]string, 0, len(artifactsCfg))
for name := range artifactsCfg {
names = append(names, name)
}
sort.Strings(names)
return names
}
func sortedScriptoriumInputKeys(inputs map[string]config.ScriptoriumInputConfig) []string {
if len(inputs) == 0 {
return nil
}
names := make([]string, 0, len(inputs))
for name := range inputs {
names = append(names, name)
}
sort.Strings(names)
return names
}
func dedupeAndSortStrings(values []string) []string {
if len(values) == 0 {
return nil
}
seen := map[string]struct{}{}
out := make([]string, 0, len(values))
for _, value := range values {
trimmed := strings.TrimSpace(value)
if trimmed == "" {
continue
}
if _, ok := seen[trimmed]; ok {
continue
}
seen[trimmed] = struct{}{}
out = append(out, trimmed)
}
sort.Strings(out)
return out
}