Validate portable workspace identifiers
This commit is contained in:
@@ -385,7 +385,7 @@ func TestAnalyzeIncludesCanonicalPreviousRecapWhenPreparedCacheExists(t *testing
|
||||
paths := sessionPathsForEnv(env, m.SessionID)
|
||||
writeAnalyzeFile(t, filepath.Join(paths.TranscriptsDir, "polished.json"), `{"segments":[]}`)
|
||||
|
||||
previousRecapPath := artifacts.SessionPreviousArtifactPath(paths, "artifacts/session_recap.md")
|
||||
previousRecapPath := mustPreviousArtifactPath(t, paths, "artifacts/session_recap.md")
|
||||
writeAnalyzeFile(t, previousRecapPath, "previous recap\n")
|
||||
|
||||
env.Config.Pipeline.Scriptorium.Artifacts["session_recap"] = config.ScriptoriumArtifactConfig{
|
||||
@@ -776,7 +776,7 @@ func TestAnalyzeResolvesCanonicalPreviousSessionArtifactFromManifestInput(t *tes
|
||||
paths := sessionPathsForEnv(env, m.SessionID)
|
||||
writeAnalyzeFile(t, filepath.Join(paths.TranscriptsDir, "final.trimmed.json"), `{"segments":[]}`)
|
||||
|
||||
previousPath := artifacts.SessionPreviousArtifactPath(paths, "artifacts/session_recap.md")
|
||||
previousPath := mustPreviousArtifactPath(t, paths, "artifacts/session_recap.md")
|
||||
writeAnalyzeFile(t, previousPath, "previous recap\n")
|
||||
m.Inputs = append(m.Inputs, manifest.InputRecord{
|
||||
Kind: "previous_artifact",
|
||||
@@ -832,7 +832,7 @@ func TestAnalyzeRenderDebugWithCanonicalPreviousSessionInput(t *testing.T) {
|
||||
writeAnalyzeFile(t, filepath.Join(paths.TranscriptsDir, "final.trimmed.json"), `{"segments":[]}`)
|
||||
env.Config.Pipeline.Scriptorium.RenderDebug = true
|
||||
|
||||
previousPath := artifacts.SessionPreviousArtifactPath(paths, "artifacts/session_recap.md")
|
||||
previousPath := mustPreviousArtifactPath(t, paths, "artifacts/session_recap.md")
|
||||
writeAnalyzeFile(t, previousPath, "previous recap\n")
|
||||
m.Inputs = append(m.Inputs, manifest.InputRecord{
|
||||
Kind: "previous_artifact",
|
||||
@@ -866,7 +866,7 @@ func TestAnalyzeDoesNotCallObjectStoreForCanonicalPreviousSessionInput(t *testin
|
||||
paths := sessionPathsForEnv(env, m.SessionID)
|
||||
writeAnalyzeFile(t, filepath.Join(paths.TranscriptsDir, "final.trimmed.json"), `{"segments":[]}`)
|
||||
|
||||
previousPath := artifacts.SessionPreviousArtifactPath(paths, "artifacts/session_recap.md")
|
||||
previousPath := mustPreviousArtifactPath(t, paths, "artifacts/session_recap.md")
|
||||
writeAnalyzeFile(t, previousPath, "previous recap\n")
|
||||
m.Inputs = append(m.Inputs, manifest.InputRecord{
|
||||
Kind: "previous_artifact",
|
||||
@@ -1552,13 +1552,13 @@ func setupAnalyzeEnv(t *testing.T) (*Env, *manifest.Manifest, *scriptorium.FakeR
|
||||
},
|
||||
Session: &config.SessionConfig{
|
||||
SessionID: "2026-05-03",
|
||||
Campaign: "Icewind Dale",
|
||||
Campaign: "icewind-dale",
|
||||
Date: "2026-05-03",
|
||||
},
|
||||
}
|
||||
|
||||
store := artifacts.NewLocalStore(workspace)
|
||||
if _, err := store.EnsureLayoutFor("sample-campaign", "2026-05-03"); err != nil {
|
||||
if _, err := store.EnsureLayoutFor("icewind-dale", "2026-05-03"); err != nil {
|
||||
t.Fatalf("EnsureLayout() error = %v", err)
|
||||
}
|
||||
|
||||
|
||||
16
internal/stage/paths_test_helpers_test.go
Normal file
16
internal/stage/paths_test_helpers_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package stage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
|
||||
)
|
||||
|
||||
func mustPreviousArtifactPath(t *testing.T, paths artifacts.SessionPaths, relative string) string {
|
||||
t.Helper()
|
||||
path, err := artifacts.SessionPreviousArtifactPath(paths, relative)
|
||||
if err != nil {
|
||||
t.Fatalf("SessionPreviousArtifactPath() error = %v", err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func TestHydratePreviousSessionArtifactsDownloadsManifestAndRequiredArtifact(t *
|
||||
if _, err := os.Stat(sessionPaths.PreviousManifestPath); err != nil {
|
||||
t.Fatalf("previous manifest missing: %v", err)
|
||||
}
|
||||
recapPath := artifacts.SessionPreviousArtifactPath(sessionPaths, "artifacts/session_recap.md")
|
||||
recapPath := mustPreviousArtifactPath(t, sessionPaths, "artifacts/session_recap.md")
|
||||
if _, err := os.Stat(recapPath); err != nil {
|
||||
t.Fatalf("previous artifact missing: %v", err)
|
||||
}
|
||||
|
||||
@@ -508,7 +508,7 @@ func TestPrepareStageHydratesRequiredPreviousArtifactAndRecordsInputs(t *testing
|
||||
if _, err := os.Stat(paths.PreviousManifestPath); err != nil {
|
||||
t.Fatalf("expected previous manifest: %v", err)
|
||||
}
|
||||
recapPath := artifacts.SessionPreviousArtifactPath(paths, "artifacts/session_recap.md")
|
||||
recapPath := mustPreviousArtifactPath(t, paths, "artifacts/session_recap.md")
|
||||
if _, err := os.Stat(recapPath); err != nil {
|
||||
t.Fatalf("expected previous artifact: %v", err)
|
||||
}
|
||||
@@ -556,7 +556,7 @@ func TestPrepareStageRerunOverwritesPreviousCache(t *testing.T) {
|
||||
if _, err := (prepareStage{}).Run(context.Background(), env, m); err != nil {
|
||||
t.Fatalf("first prepare run error = %v", err)
|
||||
}
|
||||
recapPath := artifacts.SessionPreviousArtifactPath(paths, "artifacts/session_recap.md")
|
||||
recapPath := mustPreviousArtifactPath(t, paths, "artifacts/session_recap.md")
|
||||
firstBytes, err := os.ReadFile(recapPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read first hydrated artifact: %v", err)
|
||||
|
||||
@@ -54,6 +54,12 @@ func resolveRunStageLayout(
|
||||
if runID == "" || campaign == "" {
|
||||
return runStageLayout{}, nil
|
||||
}
|
||||
if err := artifacts.ValidateSessionIdentity(campaign, sessionID); err != nil {
|
||||
return runStageLayout{}, err
|
||||
}
|
||||
if err := artifacts.ValidateRunIdentity(runID); err != nil {
|
||||
return runStageLayout{}, err
|
||||
}
|
||||
|
||||
root := artifacts.SessionRunStageDirForCampaign(
|
||||
env.Config.Pipeline.Workspace.Root,
|
||||
|
||||
Reference in New Issue
Block a user