Rename publish runtime terminology to published outputs

This commit is contained in:
2026-05-23 04:42:08 +00:00
parent df2c765b7f
commit 79737edf79
32 changed files with 354 additions and 354 deletions

View File

@@ -239,13 +239,13 @@ func Status(ctx context.Context, args []string, out io.Writer) error {
store, storeErr := objectStoreIfConfigured(ctx, cfg)
if storeErr != nil {
fmt.Fprintf(out, "Remote archive: unavailable: %v\n", storeErr)
fmt.Fprintf(out, "Remote publish: unavailable: %v\n", storeErr)
} else if store != nil {
current, err := discoverRemoteCurrentStateFn(ctx, cfg, store)
if err != nil {
fmt.Fprintf(out, "Remote archive: missing or unavailable: %v\n", err)
fmt.Fprintf(out, "Remote publish: missing or unavailable: %v\n", err)
} else {
fmt.Fprintf(out, "Remote archive: current run %s\n", current.RunID)
fmt.Fprintf(out, "Remote publish: current run %s\n", current.RunID)
fmt.Fprintf(out, "Remote manifest: %s\n", current.CurrentManifestKey)
}
}
@@ -261,15 +261,15 @@ func Status(ctx context.Context, args []string, out io.Writer) error {
All: staticArchiveLocks(cfg),
}
}
promotedRemoteState := map[string]string{}
publishedRemoteState := map[string]string{}
if store != nil {
promotedRemoteState = remotePromotionAvailability(ctx, cfg, store, catalog)
publishedRemoteState = remotePublishedOutputAvailability(ctx, cfg, store, catalog)
}
fmt.Fprintln(out, "Remote outputs:")
writeArtifactList(out, cfg, catalog, catalogLocks, promotedRemoteState)
writeArtifactList(out, cfg, catalog, catalogLocks, publishedRemoteState)
}
if err != nil {
fmt.Fprintf(out, "Archive locks: error: %v\n", err)
fmt.Fprintf(out, "Publish locks: error: %v\n", err)
} else {
writeLocks(out, cfg, locks)
}
@@ -437,11 +437,11 @@ func ArtifactsList(ctx context.Context, args []string, out io.Writer) error {
if err != nil {
return fmt.Errorf("artifacts list: %w", err)
}
promotedRemoteState := map[string]string{}
publishedRemoteState := map[string]string{}
if remote && store != nil {
promotedRemoteState = remotePromotionAvailability(ctx, cfg, store, catalog)
publishedRemoteState = remotePublishedOutputAvailability(ctx, cfg, store, catalog)
}
writeArtifactList(out, cfg, catalog, locks, promotedRemoteState)
writeArtifactList(out, cfg, catalog, locks, publishedRemoteState)
return nil
}
@@ -532,7 +532,7 @@ func LocksAdd(ctx context.Context, args []string, out io.Writer) error {
if err != nil {
return fmt.Errorf("locks add: %w", err)
}
if _, err := config.ValidateArchiveLockRules([]config.ArchiveLockRule{{Source: source}}, cfg.Pipeline.Scriptorium, "locks add"); err != nil {
if _, err := config.ValidatePublishLockRules([]config.PublishLockRule{{Source: source}}, cfg.Pipeline.Scriptorium, "locks add"); err != nil {
return fmt.Errorf("locks add: %w", err)
}
if _, ok := lockSourceSet(locks.Static)[source]; ok {
@@ -542,12 +542,12 @@ func LocksAdd(ctx context.Context, args []string, out io.Writer) error {
if _, exists := remoteSet[source]; exists && !force {
return fmt.Errorf("locks add: remote lock for %q already exists; pass --force to update", source)
}
remoteSet[source] = config.ArchiveLockRule{Source: source, Reason: strings.TrimSpace(reason)}
remoteSet[source] = config.PublishLockRule{Source: source, Reason: strings.TrimSpace(reason)}
remoteLocks := lockMapValues(remoteSet)
if _, err := config.ValidateArchiveLockRules(remoteLocks, cfg.Pipeline.Scriptorium, "locks"); err != nil {
if _, err := config.ValidatePublishLockRules(remoteLocks, cfg.Pipeline.Scriptorium, "locks"); err != nil {
return fmt.Errorf("locks add: %w", err)
}
if err := uploadRemoteLockStore(ctx, store, locks.Key, &config.ArchiveLockStore{Locks: remoteLocks}); err != nil {
if err := uploadRemoteLockStore(ctx, store, locks.Key, &config.PublishLockStore{Locks: remoteLocks}); err != nil {
return fmt.Errorf("locks add: %w", err)
}
_, err = fmt.Fprintf(out, "narratio session locks add: locked %s\n", source)
@@ -589,7 +589,7 @@ func LocksRemove(ctx context.Context, args []string, out io.Writer) error {
if err != nil {
return fmt.Errorf("locks remove: %w", err)
}
if _, err := config.ValidateArchiveLockRules([]config.ArchiveLockRule{{Source: source}}, cfg.Pipeline.Scriptorium, "locks remove"); err != nil {
if _, err := config.ValidatePublishLockRules([]config.PublishLockRule{{Source: source}}, cfg.Pipeline.Scriptorium, "locks remove"); err != nil {
return fmt.Errorf("locks remove: %w", err)
}
remoteSet := lockSourceSet(locks.Remote)
@@ -601,7 +601,7 @@ func LocksRemove(ctx context.Context, args []string, out io.Writer) error {
}
delete(remoteSet, source)
remoteLocks := lockMapValues(remoteSet)
if err := uploadRemoteLockStore(ctx, store, locks.Key, &config.ArchiveLockStore{Locks: remoteLocks}); err != nil {
if err := uploadRemoteLockStore(ctx, store, locks.Key, &config.PublishLockStore{Locks: remoteLocks}); err != nil {
return fmt.Errorf("locks remove: %w", err)
}
_, err = fmt.Fprintf(out, "narratio session locks remove: unlocked %s\n", source)
@@ -980,7 +980,7 @@ func buildHelperArtifactCatalog(cfg *config.Config) (*artifacts.ArtifactCatalog,
return catalog, nil
}
func writeArtifactList(out io.Writer, cfg *config.Config, catalog *artifacts.ArtifactCatalog, locks *effectiveLocks, promotedRemoteState map[string]string) {
func writeArtifactList(out io.Writer, cfg *config.Config, catalog *artifacts.ArtifactCatalog, locks *effectiveLocks, publishedRemoteState map[string]string) {
lockSet := lockSourceSet(locks.All)
fmt.Fprintln(out, "Built-in:")
for _, id := range []string{
@@ -1000,13 +1000,13 @@ func writeArtifactList(out io.Writer, cfg *config.Config, catalog *artifacts.Art
for _, req := range artifacts.CollectPreviousArtifactRequirements(configuredScriptoriumArtifacts(cfg)) {
fmt.Fprintf(out, "- narratio.previous_session.artifact.%s required=%t\n", req.Name, req.Required)
}
fmt.Fprintln(out, "Promoted:")
for _, rule := range cfg.Pipeline.Publish.PromoteArtifacts {
writePromotedArtifactLine(out, rule, catalog, lockSet, promotedRemoteState)
fmt.Fprintln(out, "Published:")
for _, rule := range cfg.Pipeline.Publish.Outputs {
writePublishedOutputLine(out, rule, catalog, lockSet, publishedRemoteState)
}
}
func writeArtifactLine(out io.Writer, source string, lockSet map[string]config.ArchiveLockRule) {
func writeArtifactLine(out io.Writer, source string, lockSet map[string]config.PublishLockRule) {
parts := []string{source}
if _, ok := lockSet[source]; ok {
parts = append(parts, "locked")
@@ -1014,13 +1014,13 @@ func writeArtifactLine(out io.Writer, source string, lockSet map[string]config.A
fmt.Fprintf(out, "- %s\n", strings.Join(parts, " "))
}
func writePromotedArtifactLine(out io.Writer, rule config.ArchivePromotionRule, catalog *artifacts.ArtifactCatalog, lockSet map[string]config.ArchiveLockRule, remoteState map[string]string) {
func writePublishedOutputLine(out io.Writer, rule config.PublishOutputRule, catalog *artifacts.ArtifactCatalog, lockSet map[string]config.PublishLockRule, remoteState map[string]string) {
source := strings.TrimSpace(rule.Source)
parts := []string{source}
if _, ok := lockSet[source]; ok {
parts = append(parts, "locked")
}
dest, showDest, err := helperPromotionDest(rule, catalog)
dest, showDest, err := helperPublishedOutputDest(rule, catalog)
if err != nil {
parts = append(parts, "remote=error")
fmt.Fprintf(out, "- %s\n", strings.Join(parts, " "))
@@ -1029,35 +1029,35 @@ func writePromotedArtifactLine(out io.Writer, rule config.ArchivePromotionRule,
if showDest {
parts = append(parts, "dest="+dest)
}
if state := remoteState[promotionRemoteStateKey(source, dest)]; state != "" {
if state := remoteState[publishedOutputRemoteStateKey(source, dest)]; state != "" {
parts = append(parts, state)
}
fmt.Fprintf(out, "- %s\n", strings.Join(parts, " "))
}
func remotePromotionAvailability(ctx context.Context, cfg *config.Config, store storage.ObjectStore, catalog *artifacts.ArtifactCatalog) map[string]string {
func remotePublishedOutputAvailability(ctx context.Context, cfg *config.Config, store storage.ObjectStore, catalog *artifacts.ArtifactCatalog) map[string]string {
out := map[string]string{}
sessionPrefix := artifacts.S3SessionPrefix(cfg.Pipeline.Storage.S3.RootPrefix, cfg.Session.Campaign, cfg.Session.SessionID)
for _, rule := range cfg.Pipeline.Publish.PromoteArtifacts {
for _, rule := range cfg.Pipeline.Publish.Outputs {
source := strings.TrimSpace(rule.Source)
dest, _, err := helperPromotionDest(rule, catalog)
dest, _, err := helperPublishedOutputDest(rule, catalog)
if err != nil {
out[promotionRemoteStateKey(source, "")] = "remote=error"
out[publishedOutputRemoteStateKey(source, "")] = "remote=error"
continue
}
key := artifacts.S3PromotedArtifactKey(sessionPrefix, dest)
key := artifacts.S3PublishedOutputKey(sessionPrefix, dest)
if exists, err := store.Exists(ctx, key); err == nil && exists {
out[promotionRemoteStateKey(source, dest)] = "remote=promoted"
out[publishedOutputRemoteStateKey(source, dest)] = "remote=published"
} else if err != nil {
out[promotionRemoteStateKey(source, dest)] = "remote=error"
out[publishedOutputRemoteStateKey(source, dest)] = "remote=error"
} else {
out[promotionRemoteStateKey(source, dest)] = "remote=missing"
out[publishedOutputRemoteStateKey(source, dest)] = "remote=missing"
}
}
return out
}
func helperPromotionDest(rule config.ArchivePromotionRule, catalog *artifacts.ArtifactCatalog) (string, bool, error) {
func helperPublishedOutputDest(rule config.PublishOutputRule, catalog *artifacts.ArtifactCatalog) (string, bool, error) {
source := strings.TrimSpace(rule.Source)
dest := strings.TrimSpace(rule.Dest)
if dest == "" {
@@ -1094,20 +1094,20 @@ func normalizeHelperArchiveRelativePath(rel string) (string, error) {
return cleaned, nil
}
func promotionRemoteStateKey(source, dest string) string {
func publishedOutputRemoteStateKey(source, dest string) string {
return strings.TrimSpace(source) + "\x00" + strings.TrimSpace(dest)
}
func writeLocks(out io.Writer, cfg *config.Config, locks *effectiveLocks) {
if locks == nil || len(locks.All) == 0 {
fmt.Fprintln(out, "Archive locks: none")
fmt.Fprintln(out, "Publish locks: none")
return
}
fmt.Fprintln(out, "Archive locks:")
promoted := map[string]config.ArchivePromotionRule{}
fmt.Fprintln(out, "Publish locks:")
published := map[string]config.PublishOutputRule{}
if cfg != nil && cfg.Pipeline != nil && cfg.Pipeline.Publish != nil {
for _, rule := range cfg.Pipeline.Publish.PromoteArtifacts {
promoted[strings.TrimSpace(rule.Source)] = rule
for _, rule := range cfg.Pipeline.Publish.Outputs {
published[strings.TrimSpace(rule.Source)] = rule
}
}
staticSet := lockSourceSet(locks.Static)
@@ -1116,9 +1116,9 @@ func writeLocks(out io.Writer, cfg *config.Config, locks *effectiveLocks) {
if _, ok := staticSet[lock.Source]; ok {
origin = "pipeline"
}
promo := "not-promoted"
if _, ok := promoted[lock.Source]; ok {
promo = "promoted"
promo := "not-published"
if _, ok := published[lock.Source]; ok {
promo = "published"
}
reason := strings.TrimSpace(lock.Reason)
if reason == "" {
@@ -1128,13 +1128,13 @@ func writeLocks(out io.Writer, cfg *config.Config, locks *effectiveLocks) {
}
}
func lockMapValues(in map[string]config.ArchiveLockRule) []config.ArchiveLockRule {
func lockMapValues(in map[string]config.PublishLockRule) []config.PublishLockRule {
keys := make([]string, 0, len(in))
for key := range in {
keys = append(keys, key)
}
sort.Strings(keys)
out := make([]config.ArchiveLockRule, 0, len(keys))
out := make([]config.PublishLockRule, 0, len(keys))
for _, key := range keys {
item := in[key]
item.Source = key

View File

@@ -423,7 +423,7 @@ inputs:
}
fake := &storage.FakeBackend{}
audioKey := artifacts.S3PromotedArtifactKey(artifacts.S3AudioPrefix(artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03"), "audio/"), "alice.flac")
audioKey := artifacts.S3PublishedOutputKey(artifacts.S3AudioPrefix(artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03"), "audio/"), "alice.flac")
fake.SeedObject(storage.FakeObject{Key: audioKey, Data: []byte("audio")})
origStoreFn := newObjectStoreFromConfigFn
newObjectStoreFromConfigFn = func(context.Context, *config.Config) (storage.ObjectStore, error) {
@@ -501,9 +501,9 @@ func TestExecuteLocksAddListAndRemoveUseRemoteLockStore(t *testing.T) {
if code != 0 {
t.Fatalf("locks remove exit code = %d, want 0; stderr=%q", code, stderr.String())
}
store, err := config.LoadArchiveLockStoreBytes("locks.yml", fake.Objects[key].Data, nil)
store, err := config.LoadPublishLockStoreBytes("locks.yml", fake.Objects[key].Data, nil)
if err != nil {
t.Fatalf("LoadArchiveLockStoreBytes() error = %v", err)
t.Fatalf("LoadPublishLockStoreBytes() error = %v", err)
}
if len(store.Locks) != 0 {
t.Fatalf("locks after remove = %#v, want empty", store.Locks)
@@ -693,7 +693,7 @@ func TestExecuteArtifactsListRemoteReportsPromotedAvailability(t *testing.T) {
required: true
`)
fake := &storage.FakeBackend{}
trimmedKey := artifacts.S3PromotedArtifactKey(
trimmedKey := artifacts.S3PublishedOutputKey(
artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03"),
"transcripts/final.trimmed.json",
)
@@ -713,7 +713,7 @@ func TestExecuteArtifactsListRemoteReportsPromotedAvailability(t *testing.T) {
if code != 0 {
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
if !strings.Contains(stdout.String(), "narratio.transcript.final_trimmed remote=promoted") {
if !strings.Contains(stdout.String(), "narratio.transcript.final_trimmed remote=published") {
t.Fatalf("stdout = %q, want promoted remote availability", stdout.String())
}
}
@@ -732,8 +732,8 @@ func TestExecuteArtifactsListRemoteUsesPromotionDestinations(t *testing.T) {
`)
fake := &storage.FakeBackend{}
sessionPrefix := artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03")
fake.SeedObject(storage.FakeObject{Key: artifacts.S3PromotedArtifactKey(sessionPrefix, "transcripts/full.json"), Data: []byte(`{"segments":[]}`)})
fake.SeedObject(storage.FakeObject{Key: artifacts.S3PromotedArtifactKey(sessionPrefix, "transcripts/bounds.json"), Data: []byte(`{}`)})
fake.SeedObject(storage.FakeObject{Key: artifacts.S3PublishedOutputKey(sessionPrefix, "transcripts/full.json"), Data: []byte(`{"segments":[]}`)})
fake.SeedObject(storage.FakeObject{Key: artifacts.S3PublishedOutputKey(sessionPrefix, "transcripts/bounds.json"), Data: []byte(`{}`)})
var storeInitCalls int
restoreAppConfigTestGlobals(t, fake, &storeInitCalls, []string{sessionPath})
@@ -759,8 +759,8 @@ func TestExecuteArtifactsListRemoteUsesPromotionDestinations(t *testing.T) {
}
}
for _, want := range []string{
"narratio.transcript.final dest=transcripts/full.json remote=promoted",
"narratio.bounds.session dest=transcripts/bounds.json remote=promoted",
"narratio.transcript.final dest=transcripts/full.json remote=published",
"narratio.bounds.session dest=transcripts/bounds.json remote=published",
} {
if !strings.Contains(out, want) {
t.Fatalf("stdout = %q, want %q", out, want)
@@ -783,8 +783,8 @@ func TestExecuteStatusReportsRemoteArtifactCatalog(t *testing.T) {
fake := &storage.FakeBackend{}
sessionPrefix := artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03")
manifestKey, runIDKey := artifacts.ResolveArchiveCurrentStateKeys(sessionPrefix)
trimmedKey := artifacts.S3PromotedArtifactKey(sessionPrefix, "transcripts/final.trimmed.json")
fullKey := artifacts.S3PromotedArtifactKey(sessionPrefix, "transcripts/full.json")
trimmedKey := artifacts.S3PublishedOutputKey(sessionPrefix, "transcripts/final.trimmed.json")
fullKey := artifacts.S3PublishedOutputKey(sessionPrefix, "transcripts/full.json")
lockKey := artifacts.S3SessionLocksKey(sessionPrefix)
fake.SeedObject(storage.FakeObject{Key: runIDKey, Data: []byte("20260519T010203Z-a1b2c3d4\n")})
fake.SeedObject(storage.FakeObject{Key: manifestKey, Data: restoreManifestJSON(t, "2026-05-03", "sample-campaign")})
@@ -811,10 +811,10 @@ func TestExecuteStatusReportsRemoteArtifactCatalog(t *testing.T) {
"Built-in:",
"Configured:",
"Previous-session:",
"Promoted:",
"Published:",
"narratio.transcript.final_trimmed locked",
"narratio.transcript.final_trimmed locked remote=promoted",
"narratio.transcript.final dest=transcripts/full.json remote=promoted",
"narratio.transcript.final_trimmed locked remote=published",
"narratio.transcript.final dest=transcripts/full.json remote=published",
} {
if !strings.Contains(out, want) {
t.Fatalf("stdout = %q, want %q", out, want)
@@ -850,13 +850,13 @@ func TestExecuteStatusReportsRemoteArtifactCatalogErrorsWithoutFailing(t *testin
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
out := stdout.String()
if !strings.Contains(out, "Remote archive: missing or unavailable:") {
if !strings.Contains(out, "Remote publish: missing or unavailable:") {
t.Fatalf("stdout = %q, want remote archive unavailable state", out)
}
if !strings.Contains(out, "Remote outputs:") || !strings.Contains(out, "narratio.transcript.final_trimmed remote=error") {
t.Fatalf("stdout = %q, want remote output error state", out)
}
if !strings.Contains(out, "Archive locks: error:") {
if !strings.Contains(out, "Publish locks: error:") {
t.Fatalf("stdout = %q, want archive locks error", out)
}
}
@@ -883,7 +883,7 @@ func TestExecuteArchiveLoadsRemoteLocks(t *testing.T) {
if code != 0 {
t.Fatalf("exit code = %d, want 0; stderr=%q", code, stderr.String())
}
promotedKey := artifacts.S3PromotedArtifactKey(artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03"), "transcripts/final.trimmed.json")
promotedKey := artifacts.S3PublishedOutputKey(artifacts.S3SessionPrefix("dnd", "sample-campaign", "2026-05-03"), "transcripts/final.trimmed.json")
if _, ok := fake.Objects[promotedKey]; ok {
t.Fatalf("locked promoted key %q was uploaded", promotedKey)
}

View File

@@ -196,7 +196,7 @@ func TestPostArchiveCleanupNotRunWhenPromotionIsMissing(t *testing.T) {
cfg, seed, runID := archiveStageCleanupFixture(t)
cfg.Pipeline.Spool.DeleteAudioAfterPublish = true
cfg.Pipeline.Workspace.CleanupAfterPublish = true
cfg.Pipeline.Publish.PromoteArtifacts = []config.ArchivePromotionRule{
cfg.Pipeline.Publish.Outputs = []config.PublishOutputRule{
{Source: "narratio.transcript.base", Dest: "transcripts/base.json", Required: boolPtr(true)},
}
@@ -205,8 +205,8 @@ func TestPostArchiveCleanupNotRunWhenPromotionIsMissing(t *testing.T) {
t.Fatalf("Select(publish) error = %v", err)
}
_, err = executeStages(context.Background(), cfg, []stage.Stage{archiveStageImpl}, RunOptions{Env: &Env{ObjectStore: &storage.FakeBackend{}}})
if err == nil || !strings.Contains(err.Error(), "required promotion source unavailable") {
t.Fatalf("executeStages() error = %v, want promotion-missing failure", err)
if err == nil || !strings.Contains(err.Error(), "required output source unavailable") {
t.Fatalf("executeStages() error = %v, want required output source unavailable failure", err)
}
assertExists(t, seed.spoolAudioDir)
@@ -270,7 +270,7 @@ func cleanupFixtureConfig(t *testing.T) (*config.Config, cleanupSeed) {
t.Helper()
cfg := testConfig(t)
cfg.Pipeline.Publish = &config.ArchiveConfig{Enabled: boolPtr(true), UploadRun: boolPtr(true)}
cfg.Pipeline.Publish = &config.PublishConfig{Enabled: boolPtr(true), UploadRun: boolPtr(true)}
cfg.Pipeline.Spool.Root = filepath.Join(t.TempDir(), "spool")
runID := "20260516T010203Z-1a2b3c4d"
@@ -329,10 +329,10 @@ func archiveStageCleanupFixture(t *testing.T) (*config.Config, cleanupSeed, stri
Bucket: "my-dnd-archive",
RootPrefix: "dnd",
}
cfg.Pipeline.Publish = &config.ArchiveConfig{
cfg.Pipeline.Publish = &config.PublishConfig{
Enabled: boolPtr(true),
UploadRun: boolPtr(true),
PromoteArtifacts: []config.ArchivePromotionRule{
Outputs: []config.PublishOutputRule{
{Source: "narratio.transcript.final_trimmed", Dest: "transcripts/final.trimmed.json", Required: boolPtr(true)},
{Source: "narratio.artifact.session_recap", Dest: "artifacts/session_recap.md", Required: boolPtr(true)},
},

View File

@@ -13,9 +13,9 @@ import (
)
type effectiveLocks struct {
Static []config.ArchiveLockRule
Remote []config.ArchiveLockRule
All []config.ArchiveLockRule
Static []config.PublishLockRule
Remote []config.PublishLockRule
All []config.PublishLockRule
Key string
}
@@ -34,7 +34,7 @@ func remoteLocksKey(cfg *config.Config) (string, error) {
return artifacts.S3SessionLocksKey(sessionPrefix), nil
}
func loadRemoteLockStore(ctx context.Context, cfg *config.Config, store storage.ObjectStore) (*config.ArchiveLockStore, string, error) {
func loadRemoteLockStore(ctx context.Context, cfg *config.Config, store storage.ObjectStore) (*config.PublishLockStore, string, error) {
key, err := remoteLocksKey(cfg)
if err != nil {
return nil, "", err
@@ -44,7 +44,7 @@ func loadRemoteLockStore(ctx context.Context, cfg *config.Config, store storage.
return nil, key, fmt.Errorf("check remote locks %q: %w", key, err)
}
if !exists {
return &config.ArchiveLockStore{}, key, nil
return &config.PublishLockStore{}, key, nil
}
tmp, err := downloadObjectToTemp(ctx, store, key, "narratio-locks-*.yml")
if err != nil {
@@ -55,7 +55,7 @@ func loadRemoteLockStore(ctx context.Context, cfg *config.Config, store storage.
if err != nil {
return nil, key, fmt.Errorf("read remote locks %q: %w", key, err)
}
lockStore, err := config.LoadArchiveLockStoreBytes("s3://"+s3BucketName(cfg.Pipeline)+"/"+key, data, cfg.Pipeline.Scriptorium)
lockStore, err := config.LoadPublishLockStoreBytes("s3://"+s3BucketName(cfg.Pipeline)+"/"+key, data, cfg.Pipeline.Scriptorium)
if err != nil {
return nil, key, err
}
@@ -67,41 +67,41 @@ func loadEffectiveLocks(ctx context.Context, cfg *config.Config, store storage.O
if store == nil {
return &effectiveLocks{
Static: staticLocks,
All: append([]config.ArchiveLockRule(nil), staticLocks...),
All: append([]config.PublishLockRule(nil), staticLocks...),
}, nil
}
lockStore, key, err := loadRemoteLockStore(ctx, cfg, store)
if err != nil {
return nil, err
}
remoteLocks := append([]config.ArchiveLockRule(nil), lockStore.Locks...)
remoteLocks := append([]config.PublishLockRule(nil), lockStore.Locks...)
return &effectiveLocks{
Static: staticLocks,
Remote: remoteLocks,
All: config.MergeArchiveLockRules(staticLocks, remoteLocks),
All: config.MergePublishLockRules(staticLocks, remoteLocks),
Key: key,
}, nil
}
func staticArchiveLocks(cfg *config.Config) []config.ArchiveLockRule {
func staticArchiveLocks(cfg *config.Config) []config.PublishLockRule {
if cfg == nil || cfg.Pipeline == nil || cfg.Pipeline.Publish == nil {
return nil
}
return append([]config.ArchiveLockRule(nil), cfg.Pipeline.Publish.Locks...)
return append([]config.PublishLockRule(nil), cfg.Pipeline.Publish.Locks...)
}
func applyEffectiveLocks(cfg *config.Config, locks []config.ArchiveLockRule) {
func applyEffectiveLocks(cfg *config.Config, locks []config.PublishLockRule) {
if cfg == nil || cfg.Pipeline == nil {
return
}
if cfg.Pipeline.Publish == nil {
cfg.Pipeline.Publish = &config.ArchiveConfig{}
cfg.Pipeline.Publish = &config.PublishConfig{}
}
cfg.Pipeline.Publish.Locks = append([]config.ArchiveLockRule(nil), locks...)
cfg.Pipeline.Publish.Locks = append([]config.PublishLockRule(nil), locks...)
}
func uploadRemoteLockStore(ctx context.Context, store storage.ObjectStore, key string, lockStore *config.ArchiveLockStore) error {
data, err := config.MarshalArchiveLockStore(lockStore)
func uploadRemoteLockStore(ctx context.Context, store storage.ObjectStore, key string, lockStore *config.PublishLockStore) error {
data, err := config.MarshalPublishLockStore(lockStore)
if err != nil {
return err
}
@@ -124,8 +124,8 @@ func uploadRemoteLockStore(ctx context.Context, store storage.ObjectStore, key s
return nil
}
func lockSourceSet(locks []config.ArchiveLockRule) map[string]config.ArchiveLockRule {
out := make(map[string]config.ArchiveLockRule, len(locks))
func lockSourceSet(locks []config.PublishLockRule) map[string]config.PublishLockRule {
out := make(map[string]config.PublishLockRule, len(locks))
for _, lock := range locks {
source := strings.TrimSpace(lock.Source)
if source == "" {

View File

@@ -254,10 +254,10 @@ func TestExecuteStagesArchiveSkipsRequiredUnselectedConfiguredPromotion(t *testi
Bucket: "my-dnd-archive",
RootPrefix: "dnd",
}
cfg.Pipeline.Publish = &config.ArchiveConfig{
cfg.Pipeline.Publish = &config.PublishConfig{
Enabled: boolPtr(true),
UploadRun: boolPtr(true),
PromoteArtifacts: []config.ArchivePromotionRule{
Outputs: []config.PublishOutputRule{
{Source: "narratio.artifact.session_recap", Dest: "artifacts/session_recap.md", Required: boolPtr(true)},
},
}
@@ -312,9 +312,9 @@ func TestExecuteStagesArchiveSkipsRequiredUnselectedConfiguredPromotion(t *testi
t.Fatalf("Load manifest error = %v", err)
}
meta := loadedManifest.Stages["publish"].Metadata
skipped, ok := meta["skipped_unselected_promotions"].([]any)
skipped, ok := meta["skipped_unselected_outputs"].([]any)
if !ok || len(skipped) != 1 {
t.Fatalf("skipped_unselected_promotions = %#v, want one item", meta["skipped_unselected_promotions"])
t.Fatalf("skipped_unselected_outputs = %#v, want one item", meta["skipped_unselected_outputs"])
}
item, ok := skipped[0].(map[string]any)
if !ok {
@@ -950,7 +950,7 @@ func TestAdapterBackedStageFailureMarksManifestFailed(t *testing.T) {
}
}
if tc.name == "publish" {
cfg.Pipeline.Publish = &config.ArchiveConfig{
cfg.Pipeline.Publish = &config.PublishConfig{
Enabled: boolPtr(true),
UploadRun: boolPtr(true),
}

View File

@@ -246,7 +246,7 @@ func TestExecuteSessionSubcommandsAcceptPositionalSessionID(t *testing.T) {
{
name: "locks",
args: []string{"session", "locks", "2026-05-03", "--config", pipelinePath, "--campaign-file", campaignPath, "--session", sessionPath},
want: "Archive locks:",
want: "Publish locks:",
},
}
@@ -325,9 +325,9 @@ func TestExecuteSessionLocksMutationAcceptsPositionalSessionID(t *testing.T) {
if code != 0 {
t.Fatalf("locks remove exit code = %d, want 0; stderr=%q", code, stderr.String())
}
store, err := config.LoadArchiveLockStoreBytes("locks.yml", fake.Objects[key].Data, nil)
store, err := config.LoadPublishLockStoreBytes("locks.yml", fake.Objects[key].Data, nil)
if err != nil {
t.Fatalf("LoadArchiveLockStoreBytes() error = %v", err)
t.Fatalf("LoadPublishLockStoreBytes() error = %v", err)
}
if len(store.Locks) != 0 {
t.Fatalf("locks after remove = %#v, want empty", store.Locks)