Require committed remote current state
This commit is contained in:
@@ -106,9 +106,8 @@ func Resolve(
|
||||
ValidateRunID: true,
|
||||
})
|
||||
if err != nil {
|
||||
var runPointerMissing *artifacts.CurrentRunPointerMissingError
|
||||
var manifestMissing *artifacts.CurrentManifestMissingError
|
||||
if errors.As(err, &runPointerMissing) || errors.As(err, &manifestMissing) {
|
||||
var pointerMissing *artifacts.CurrentCommitPointerMissingError
|
||||
if errors.As(err, &pointerMissing) {
|
||||
if len(requiredNames) > 0 {
|
||||
return nil, fmt.Errorf("required previous-session artifacts unavailable: remote %w", err)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
func TestBuildPlanResolvesPublishedArtifactFromPreviousManifest(t *testing.T) {
|
||||
cfg, paths := previousCacheTestConfig(t)
|
||||
store := &storage.FakeBackend{}
|
||||
seedPreviousCurrent(t, store, cfg, previousManifestWithOutput(t, cfg, "artifacts/session_recap.md", []string{"artifacts/session_recap.md"}))
|
||||
seedCommittedPreviousState(t, store, cfg, previousManifestWithOutput(t, cfg, "artifacts/session_recap.md", []string{"artifacts/session_recap.md"}), []artifacts.RemoteArtifact{committedPublishedArtifactForTest("narratio.artifact.session_recap", "artifacts/session_recap.md", []byte("# recap\n"), "recap-generation")})
|
||||
previousPrefix := artifacts.S3SessionPrefix("dnd", cfg.Session.Campaign, cfg.Session.PreviousSessionID)
|
||||
store.SeedObject(storage.FakeObject{Key: previousPrefix + "artifacts/session_recap.md", Data: []byte("# recap\n")})
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestBuildPlanResolvesPublishedArtifactFromPreviousManifest(t *testing.T) {
|
||||
func TestBuildPlanFallsBackToConfiguredOutputPath(t *testing.T) {
|
||||
cfg, paths := previousCacheTestConfig(t)
|
||||
store := &storage.FakeBackend{}
|
||||
seedPreviousCurrent(t, store, cfg, previousManifestWithOutput(t, cfg, "", nil))
|
||||
seedCommittedPreviousState(t, store, cfg, previousManifestWithOutput(t, cfg, "", nil), []artifacts.RemoteArtifact{committedPublishedArtifactForTest("narratio.artifact.session_recap", "artifacts/session_recap.md", []byte("# recap\n"), "recap-generation")})
|
||||
previousPrefix := artifacts.S3SessionPrefix("dnd", cfg.Session.Campaign, cfg.Session.PreviousSessionID)
|
||||
store.SeedObject(storage.FakeObject{Key: previousPrefix + "artifacts/session_recap.md", Data: []byte("# recap\n")})
|
||||
|
||||
@@ -105,7 +105,7 @@ func TestResolveDoesNotUseCommittedBasenameFallback(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveRejectsAmbiguousLegacyCandidates(t *testing.T) {
|
||||
func TestResolveRejectsUndeclaredPublishedCandidates(t *testing.T) {
|
||||
cfg, paths := previousCacheTestConfig(t)
|
||||
store := &storage.FakeBackend{}
|
||||
seedPreviousCurrent(t, store, cfg, previousManifestWithOutput(t, cfg, "artifacts/session_recap.md", []string{"archive/session_recap.md"}))
|
||||
@@ -114,8 +114,8 @@ func TestResolveRejectsAmbiguousLegacyCandidates(t *testing.T) {
|
||||
store.SeedObject(storage.FakeObject{Key: prefix + "archive/session_recap.md", Data: []byte("published candidate")})
|
||||
|
||||
_, err := Resolve(context.Background(), cfg, paths, []artifacts.PreviousArtifactRequirement{{Name: "session_recap", Required: true}}, store)
|
||||
if err == nil || !strings.Contains(err.Error(), "matches multiple published candidates") {
|
||||
t.Fatalf("Resolve() error = %v, want legacy ambiguity error", err)
|
||||
if err == nil || !strings.Contains(err.Error(), "object missing from published candidate keys") {
|
||||
t.Fatalf("Resolve() error = %v, want undeclared-candidate error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ func TestBuildPlanValidatesPreviousManifestIdentity(t *testing.T) {
|
||||
_, err := BuildPlan(context.Background(), cfg, paths, []artifacts.PreviousArtifactRequirement{
|
||||
{Name: "session_recap", Required: true},
|
||||
}, store)
|
||||
if err == nil || !strings.Contains(err.Error(), "does not match expected session_id") {
|
||||
if err == nil || !strings.Contains(err.Error(), "identity does not match") {
|
||||
t.Fatalf("BuildPlan() error = %v, want identity validation error", err)
|
||||
}
|
||||
}
|
||||
@@ -199,17 +199,14 @@ func TestBuildPlanMissingCurrentRunPointerFailsRequiredRequirements(t *testing.T
|
||||
_, err := BuildPlan(context.Background(), cfg, paths, []artifacts.PreviousArtifactRequirement{
|
||||
{Name: "session_recap", Required: true},
|
||||
}, store)
|
||||
if err == nil || !strings.Contains(err.Error(), `required previous-session artifacts unavailable: remote current run pointer missing`) {
|
||||
t.Fatalf("BuildPlan() error = %v, want required missing run pointer error", err)
|
||||
if err == nil || !strings.Contains(err.Error(), `required previous-session artifacts unavailable: remote current commit pointer missing`) {
|
||||
t.Fatalf("BuildPlan() error = %v, want required missing commit pointer error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPlanMissingCurrentManifestSkipsOptionalRequirements(t *testing.T) {
|
||||
func TestBuildPlanMissingCurrentCommitPointerSkipsOptionalRequirements(t *testing.T) {
|
||||
cfg, paths := previousCacheTestConfig(t)
|
||||
store := &storage.FakeBackend{}
|
||||
previousPrefix := artifacts.S3SessionPrefix("dnd", cfg.Session.Campaign, cfg.Session.PreviousSessionID)
|
||||
_, runIDKey := artifacts.ResolveCurrentStateKeys(previousPrefix)
|
||||
store.SeedObject(storage.FakeObject{Key: runIDKey, Data: []byte("previous-run\n")})
|
||||
|
||||
plan, err := BuildPlan(context.Background(), cfg, paths, []artifacts.PreviousArtifactRequirement{
|
||||
{Name: "session_recap", Required: false},
|
||||
@@ -222,18 +219,15 @@ func TestBuildPlanMissingCurrentManifestSkipsOptionalRequirements(t *testing.T)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildPlanMissingCurrentManifestFailsRequiredRequirements(t *testing.T) {
|
||||
func TestBuildPlanMissingCurrentCommitPointerFailsRequiredRequirements(t *testing.T) {
|
||||
cfg, paths := previousCacheTestConfig(t)
|
||||
store := &storage.FakeBackend{}
|
||||
previousPrefix := artifacts.S3SessionPrefix("dnd", cfg.Session.Campaign, cfg.Session.PreviousSessionID)
|
||||
_, runIDKey := artifacts.ResolveCurrentStateKeys(previousPrefix)
|
||||
store.SeedObject(storage.FakeObject{Key: runIDKey, Data: []byte("previous-run\n")})
|
||||
|
||||
_, err := BuildPlan(context.Background(), cfg, paths, []artifacts.PreviousArtifactRequirement{
|
||||
{Name: "session_recap", Required: true},
|
||||
}, store)
|
||||
if err == nil || !strings.Contains(err.Error(), `required previous-session artifacts unavailable: remote current manifest missing`) {
|
||||
t.Fatalf("BuildPlan() error = %v, want required missing manifest error", err)
|
||||
if err == nil || !strings.Contains(err.Error(), `required previous-session artifacts unavailable: remote current commit pointer missing`) {
|
||||
t.Fatalf("BuildPlan() error = %v, want required missing commit pointer error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,14 +259,26 @@ func previousCacheTestConfig(t *testing.T) (*config.Config, artifacts.SessionPat
|
||||
|
||||
func seedPreviousCurrent(t *testing.T, store *storage.FakeBackend, cfg *config.Config, m *manifest.Manifest) {
|
||||
t.Helper()
|
||||
previousPrefix := artifacts.S3SessionPrefix(cfg.Pipeline.Storage.S3.RootPrefix, cfg.Session.Campaign, cfg.Session.PreviousSessionID)
|
||||
manifestKey, runIDKey := artifacts.ResolveCurrentStateKeys(previousPrefix)
|
||||
store.SeedObject(storage.FakeObject{Key: runIDKey, Data: []byte("previous-run\n")})
|
||||
data, err := marshalManifestForPreviousCacheTest(m)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal manifest: %v", err)
|
||||
}
|
||||
store.SeedObject(storage.FakeObject{Key: manifestKey, Data: data})
|
||||
prefix := artifacts.S3SessionPrefix(cfg.Pipeline.Storage.S3.RootPrefix, cfg.Session.Campaign, cfg.Session.PreviousSessionID)
|
||||
manifestKey := artifacts.S3RunSessionManifestKey(prefix, m.RunID)
|
||||
manifestGeneration := "manifest-generation"
|
||||
commit := artifacts.RemoteCommitManifest{FormatVersion: artifacts.RemoteCommitFormatVersion, Campaign: cfg.Session.Campaign, SessionID: cfg.Session.PreviousSessionID, RunID: m.RunID, Artifacts: []artifacts.RemoteArtifact{{Type: artifacts.RemoteArtifactTypeSessionManifest, Source: "session.manifest", DestinationKey: manifestKey, SHA256: sha256ForPreviousCacheTest(data), Size: int64(len(data)), Generation: manifestGeneration}}}
|
||||
commitData, err := artifacts.EncodeRemoteCommitManifest(commit)
|
||||
if err != nil {
|
||||
t.Fatalf("encode previous commit: %v", err)
|
||||
}
|
||||
commitKey := artifacts.S3RunCommitKey(prefix, m.RunID)
|
||||
pointerData, err := artifacts.EncodeCurrentCommitPointer(artifacts.CurrentCommitPointer{FormatVersion: artifacts.RemoteCommitFormatVersion, Campaign: cfg.Session.Campaign, SessionID: cfg.Session.PreviousSessionID, RunID: m.RunID, CommitKey: commitKey, CommitSHA256: sha256ForPreviousCacheTest(commitData), CommitSize: int64(len(commitData)), CommitGeneration: "commit-generation"})
|
||||
if err != nil {
|
||||
t.Fatalf("encode previous pointer: %v", err)
|
||||
}
|
||||
store.SeedObject(storage.FakeObject{Key: artifacts.S3CurrentCommitPointerKey(prefix), Data: pointerData})
|
||||
store.SeedObject(storage.FakeObject{Key: commitKey, Data: commitData, ETag: "commit-generation"})
|
||||
store.SeedObject(storage.FakeObject{Key: manifestKey, Data: data, ETag: manifestGeneration})
|
||||
}
|
||||
|
||||
func previousManifestWithOutput(t *testing.T, cfg *config.Config, rel string, publishedPaths []string) *manifest.Manifest {
|
||||
|
||||
Reference in New Issue
Block a user