Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func HandleDeploymentVersionCreated(
}

ws.ReleaseManager().ReconcileTargets(ctx, releaseTargets,
releasemanager.WithTrigger(trace.TriggerVersionCreated))
releasemanager.WithTrigger(trace.TriggerVersionCreated),
releasemanager.WithEarliestVersionForEvaluation(deploymentVersion))

return nil
}
Expand Down Expand Up @@ -68,7 +69,8 @@ func HandleDeploymentVersionUpdated(
return err
}
ws.ReleaseManager().ReconcileTargets(ctx, releaseTargets,
releasemanager.WithTrigger(trace.TriggerVersionCreated))
releasemanager.WithTrigger(trace.TriggerVersionCreated),
releasemanager.WithEarliestVersionForEvaluation(deploymentVersion))

return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ func NewPlanner(
type planDeploymentOptions func(*planDeploymentConfig)

type planDeploymentConfig struct {
resourceRelatedEntities map[string][]*oapi.EntityRelation
recorder *trace.ReconcileTarget
resourceRelatedEntities map[string][]*oapi.EntityRelation
recorder *trace.ReconcileTarget
earliestVersionForEvaluation *oapi.DeploymentVersion
}

func WithResourceRelatedEntities(entities map[string][]*oapi.EntityRelation) planDeploymentOptions {
Expand All @@ -72,6 +73,12 @@ func WithTraceRecorder(recorder *trace.ReconcileTarget) planDeploymentOptions {
}
}

func WithEarliestVersionForEvaluation(version *oapi.DeploymentVersion) planDeploymentOptions {
return func(cfg *planDeploymentConfig) {
cfg.earliestVersionForEvaluation = version
}
}

// Returns:
// - *oapi.Release: The desired release to deploy
// - nil: No deployable release (no versions or all blocked by policies)
Expand Down Expand Up @@ -104,7 +111,7 @@ func (p *Planner) PlanDeployment(ctx context.Context, releaseTarget *oapi.Releas

// Step 1: Get candidate versions (sorted newest to oldest)
span.AddEvent("Step 1: Getting candidate versions")
candidateVersions := p.versionManager.GetCandidateVersions(ctx, releaseTarget)
candidateVersions := p.versionManager.GetCandidateVersions(ctx, releaseTarget, cfg.earliestVersionForEvaluation)
span.SetAttributes(attribute.Int("candidate_versions.count", len(candidateVersions)))

if len(candidateVersions) == 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ func (o *DeploymentOrchestrator) Reconcile(
releaseTarget,
deployment.WithResourceRelatedEntities(options.resourceRelationships),
deployment.WithTraceRecorder(recorder),
deployment.WithEarliestVersionForEvaluation(options.earliestVersionForEvaluation),
)
if err != nil {
span.RecordError(err)
Expand Down
13 changes: 10 additions & 3 deletions apps/workspace-engine/pkg/workspace/releasemanager/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import (
// options is a unified options struct for all releasemanager methods
type options struct {
// ReleaseManager options
skipEligibilityCheck bool
trigger trace.TriggerReason
resourceRelationships map[string][]*oapi.EntityRelation
skipEligibilityCheck bool
trigger trace.TriggerReason
resourceRelationships map[string][]*oapi.EntityRelation
earliestVersionForEvaluation *oapi.DeploymentVersion

// StateCache options
bypassCache bool
Expand All @@ -35,6 +36,12 @@ func WithTrigger(trigger trace.TriggerReason) Option {
}
}

func WithEarliestVersionForEvaluation(version *oapi.DeploymentVersion) Option {
return func(opts *options) {
opts.earliestVersionForEvaluation = version
}
}

// StateCache options

func WithResourceRelationships(relationships map[string][]*oapi.EntityRelation) Option {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func New(store *store.Store) *Manager {

// GetCandidateVersions returns all versions for a deployment, sorted newest to oldest.
// The caller is responsible for filtering based on policies or other criteria.
func (m *Manager) GetCandidateVersions(ctx context.Context, releaseTarget *oapi.ReleaseTarget) []*oapi.DeploymentVersion {
func (m *Manager) GetCandidateVersions(ctx context.Context, releaseTarget *oapi.ReleaseTarget, earliestVersionForEvaluation *oapi.DeploymentVersion) []*oapi.DeploymentVersion {
_, span := tracer.Start(ctx, "GetCandidateVersions",
trace.WithAttributes(
attribute.String("deployment.id", releaseTarget.DeploymentId),
Expand Down Expand Up @@ -70,5 +70,17 @@ func (m *Manager) GetCandidateVersions(ctx context.Context, releaseTarget *oapi.
)
}

return filtered
if earliestVersionForEvaluation == nil {
return filtered
}

laterThanEarliestVersion := []*oapi.DeploymentVersion{}
for _, version := range filtered {
if version.CreatedAt.Before(earliestVersionForEvaluation.CreatedAt) {
break
}

laterThanEarliestVersion = append(laterThanEarliestVersion, version)
}
return laterThanEarliestVersion
}
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,11 @@ func TestEngine_EnvironmentProgression_MultipleVersions(t *testing.T) {
engine.PushEvent(ctx, handler.JobUpdate, v2StagingJob)

// Trigger policy re-evaluation
engine.PushEvent(ctx, handler.DeploymentVersionUpdate, version2)
time.Sleep(100 * time.Millisecond)

// send a workspace tick to trigger reconciliation
engine.PushEvent(ctx, handler.WorkspaceTick, nil)

// v2.0.0 production job should NOT be created
// (even though v1.0.0 has past soak time, v2.0.0's own soak time hasn't elapsed)
jobs = engine.Workspace().Jobs().Items()
Expand Down
Loading