Publish immutable remote commits
This commit is contained in:
@@ -144,11 +144,11 @@ func publishCleanupEligible(cfg *config.Config, sr *manifest.StageRecord) (bool,
|
||||
if uploaded, _ := sr.Metadata["uploaded"].(bool); !uploaded {
|
||||
return false, "publish did not upload run record"
|
||||
}
|
||||
if pointer, _ := sr.Metadata["current_pointer_written"].(bool); !pointer {
|
||||
return false, "publish did not write current pointer"
|
||||
if strings.TrimSpace(asString(sr.Metadata["remote_commit_key"])) == "" {
|
||||
return false, "publish remote commit key is missing"
|
||||
}
|
||||
if strings.TrimSpace(asString(sr.Metadata["current_run_id_key"])) == "" {
|
||||
return false, "publish current run pointer key is missing"
|
||||
if strings.TrimSpace(asString(sr.Metadata["current_commit_pointer_key"])) == "" {
|
||||
return false, "publish current commit pointer key is missing"
|
||||
}
|
||||
return true, ""
|
||||
}
|
||||
|
||||
@@ -25,10 +25,10 @@ func (publishSuccessStage) Name() string { return "publish" }
|
||||
func (publishSuccessStage) Declares() stage.IODecl { return stage.IODecl{} }
|
||||
func (s publishSuccessStage) Run(_ context.Context, _ *stage.Env, _ *manifest.Manifest) (*stage.StageResult, error) {
|
||||
md := map[string]any{
|
||||
"stage": "publish",
|
||||
"uploaded": true,
|
||||
"current_pointer_written": true,
|
||||
"current_run_id_key": "dnd/campaigns/sample-campaign/sessions/2026-05-03/current/run_id.txt",
|
||||
"stage": "publish",
|
||||
"uploaded": true,
|
||||
"remote_commit_key": "dnd/campaigns/sample-campaign/sessions/2026-05-03/runs/20260519T010203Z-a1b2c3d4/commit.json",
|
||||
"current_commit_pointer_key": "dnd/campaigns/sample-campaign/sessions/2026-05-03/current/commit-pointer.json",
|
||||
}
|
||||
for k, v := range s.metadata {
|
||||
md[k] = v
|
||||
@@ -130,12 +130,12 @@ func TestPostPublishCleanupNotRunWhenPublishSkipped(t *testing.T) {
|
||||
assertExists(t, seed.runWorkDir)
|
||||
}
|
||||
|
||||
func TestPostPublishCleanupNotRunWhenCurrentPointerMissing(t *testing.T) {
|
||||
func TestPostPublishCleanupNotRunWhenCommitPointerMissing(t *testing.T) {
|
||||
cfg, seed := cleanupFixtureConfig(t)
|
||||
cfg.Pipeline.Spool.DeleteAudioAfterPublish = true
|
||||
cfg.Pipeline.Workspace.CleanupAfterPublish = true
|
||||
|
||||
if _, err := executeStages(context.Background(), cfg, []stage.Stage{publishSuccessStage{metadata: map[string]any{"current_pointer_written": false}}}, RunOptions{Env: &Env{ObjectStore: &storage.FakeBackend{}}}); err != nil {
|
||||
if _, err := executeStages(context.Background(), cfg, []stage.Stage{publishSuccessStage{metadata: map[string]any{"current_commit_pointer_key": ""}}}, RunOptions{Env: &Env{ObjectStore: &storage.FakeBackend{}}}); err != nil {
|
||||
t.Fatalf("executeStages() error = %v", err)
|
||||
}
|
||||
|
||||
@@ -216,11 +216,11 @@ func TestPostPublishCleanupNotRunWhenOutputIsMissing(t *testing.T) {
|
||||
assertExists(t, artifacts.SessionRunRootForCampaign(cfg.Pipeline.Workspace.Root, cfg.Session.Campaign, cfg.Session.SessionID, runID))
|
||||
}
|
||||
|
||||
func TestPostPublishCleanupNotRunWhenCurrentManifestUploadFails(t *testing.T) {
|
||||
func TestPostPublishCleanupNotRunWhenCommittedManifestUploadFails(t *testing.T) {
|
||||
cfg, seed, _ := publishStageCleanupFixture(t)
|
||||
cfg.Pipeline.Spool.DeleteAudioAfterPublish = true
|
||||
cfg.Pipeline.Workspace.CleanupAfterPublish = true
|
||||
failKey := seed.sessionPrefix + "current/manifest.json"
|
||||
failKey := artifacts.S3RunSessionManifestKey(seed.sessionPrefix, seed.runID)
|
||||
|
||||
publishStageImpl, err := stage.Select("publish")
|
||||
if err != nil {
|
||||
@@ -229,19 +229,19 @@ func TestPostPublishCleanupNotRunWhenCurrentManifestUploadFails(t *testing.T) {
|
||||
_, err = executeStages(context.Background(), cfg, []stage.Stage{publishStageImpl}, RunOptions{
|
||||
Env: &Env{ObjectStore: &failKeyStore{delegate: &storage.FakeBackend{}, failKey: failKey}},
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "current manifest") {
|
||||
t.Fatalf("executeStages() error = %v, want current-manifest failure", err)
|
||||
if err == nil || !strings.Contains(err.Error(), "immutable object") {
|
||||
t.Fatalf("executeStages() error = %v, want committed-manifest failure", err)
|
||||
}
|
||||
|
||||
assertExists(t, seed.spoolAudioDir)
|
||||
assertExists(t, seed.runWorkDir)
|
||||
}
|
||||
|
||||
func TestPostPublishCleanupNotRunWhenCurrentPointerUploadFails(t *testing.T) {
|
||||
func TestPostPublishCleanupNotRunWhenCommitPointerUploadFails(t *testing.T) {
|
||||
cfg, seed, _ := publishStageCleanupFixture(t)
|
||||
cfg.Pipeline.Spool.DeleteAudioAfterPublish = true
|
||||
cfg.Pipeline.Workspace.CleanupAfterPublish = true
|
||||
failKey := seed.sessionPrefix + "current/run_id.txt"
|
||||
failKey := artifacts.S3CurrentCommitPointerKey(seed.sessionPrefix)
|
||||
|
||||
publishStageImpl, err := stage.Select("publish")
|
||||
if err != nil {
|
||||
@@ -250,8 +250,8 @@ func TestPostPublishCleanupNotRunWhenCurrentPointerUploadFails(t *testing.T) {
|
||||
_, err = executeStages(context.Background(), cfg, []stage.Stage{publishStageImpl}, RunOptions{
|
||||
Env: &Env{ObjectStore: &failKeyStore{delegate: &storage.FakeBackend{}, failKey: failKey}},
|
||||
})
|
||||
if err == nil || !strings.Contains(err.Error(), "current run pointer") {
|
||||
t.Fatalf("executeStages() error = %v, want current-run-pointer failure", err)
|
||||
if err == nil || !strings.Contains(err.Error(), "current commit pointer") {
|
||||
t.Fatalf("executeStages() error = %v, want current-commit-pointer failure", err)
|
||||
}
|
||||
|
||||
assertExists(t, seed.spoolAudioDir)
|
||||
@@ -259,6 +259,7 @@ func TestPostPublishCleanupNotRunWhenCurrentPointerUploadFails(t *testing.T) {
|
||||
}
|
||||
|
||||
type cleanupSeed struct {
|
||||
runID string
|
||||
runWorkDir string
|
||||
otherRunDir string
|
||||
spoolAudioDir string
|
||||
@@ -312,6 +313,7 @@ func cleanupFixtureConfig(t *testing.T) (*config.Config, cleanupSeed) {
|
||||
}
|
||||
|
||||
return cfg, cleanupSeed{
|
||||
runID: runID,
|
||||
runWorkDir: runWorkDir,
|
||||
otherRunDir: otherRunDir,
|
||||
spoolAudioDir: spoolAudioDir,
|
||||
|
||||
Reference in New Issue
Block a user