Implement catalog idempotent publish skips

This commit is contained in:
2026-06-19 16:57:38 +00:00
parent 484fda2514
commit 2e0d903626
7 changed files with 365 additions and 6 deletions

View File

@@ -231,6 +231,7 @@ func planExistingCatalog(ctx context.Context, req Request, catalog state.Catalog
Action: actionForWorkflow(workflow),
CatalogOutputsToWrite: catalogOutputsForPlan(req, outputs, catalog.Outputs, scope, now),
}
allPlannedOutputsMatch := catalogContainsMatchingOutputs(req, catalog.Outputs, outputs, scope)
for _, output := range catalog.Outputs {
if _, exists := planned[output.Path]; exists {
continue
@@ -241,9 +242,43 @@ func planExistingCatalog(ctx context.Context, req Request, catalog state.Catalog
}
details.CatalogOutputsToRetain = append(details.CatalogOutputsToRetain, output)
}
if allPlannedOutputsMatch && (workflow == config.WorkflowAdditive || len(details.CatalogOutputsToDelete) == 0) {
details.Action = ActionSkipSame
details.CatalogOutputsToWrite = nil
details.CatalogOutputsToDelete = nil
}
return details, nil
}
func catalogContainsMatchingOutputs(req Request, existing []state.CatalogOutputFile, outputs []Output, scope state.OwnerScope) bool {
for _, output := range outputs {
catalogOutput, ok := state.FindCatalogOutputByPath(existing, output.DestinationPath)
if !ok || !catalogOutputMatchesPlan(req, catalogOutput, output, scope) {
return false
}
}
return true
}
func catalogOutputMatchesPlan(req Request, catalogOutput state.CatalogOutputFile, output Output, scope state.OwnerScope) bool {
if catalogOutput.PipelineID != scope.PipelineID ||
catalogOutput.DestinationID != scope.DestinationID ||
catalogOutput.Source.ID != req.SourceBundle.Manifest.ID ||
catalogOutput.Source.Digest != req.SourceBundle.Manifest.Digest ||
!catalogOutput.Source.Created.Equal(req.SourceBundle.Manifest.Created) ||
catalogOutput.Path != output.DestinationPath ||
catalogOutput.Kind != output.Kind ||
catalogOutput.URL != output.URL ||
catalogOutput.SHA256 != output.SHA256 ||
catalogOutput.Size != output.Size {
return false
}
if output.Kind == state.OutputKindGenerated {
return catalogOutput.SourcePath == output.SourcePath && catalogOutput.Transform == output.Transform
}
return catalogOutput.SourcePath == "" && catalogOutput.Transform == ""
}
func planSupersededLegacy(req Request, outputs []Output, workflow string, scope state.OwnerScope, now time.Time) catalogPlanDetails {
details := catalogPlanDetails{
Action: actionForWorkflow(workflow),