|
| 1 | +package e2e |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "testing" |
| 6 | + "workspace-engine/pkg/events/handler" |
| 7 | + "workspace-engine/pkg/oapi" |
| 8 | + "workspace-engine/test/integration" |
| 9 | + c "workspace-engine/test/integration/creators" |
| 10 | +) |
| 11 | + |
| 12 | +func TestEngine_PolicyUpdateBlocksNewDeployments(t *testing.T) { |
| 13 | + jobAgentID := "job-agent-1" |
| 14 | + d1ID := "deployment-prod" |
| 15 | + d2ID := "deployment-dev" |
| 16 | + e1ID := "env-1" |
| 17 | + r1ID := "resource-1" |
| 18 | + policyID := "policy-1" |
| 19 | + |
| 20 | + engine := integration.NewTestWorkspace(t, |
| 21 | + integration.WithJobAgent( |
| 22 | + integration.JobAgentID(jobAgentID), |
| 23 | + ), |
| 24 | + integration.WithSystem( |
| 25 | + integration.WithDeployment( |
| 26 | + integration.DeploymentID(d1ID), |
| 27 | + integration.DeploymentName("deployment-prod"), |
| 28 | + integration.DeploymentJobAgent(jobAgentID), |
| 29 | + integration.WithDeploymentVersion( |
| 30 | + integration.DeploymentVersionTag("v1.0.0"), |
| 31 | + ), |
| 32 | + ), |
| 33 | + integration.WithDeployment( |
| 34 | + integration.DeploymentID(d2ID), |
| 35 | + integration.DeploymentName("deployment-dev"), |
| 36 | + integration.DeploymentJobAgent(jobAgentID), |
| 37 | + integration.WithDeploymentVersion( |
| 38 | + integration.DeploymentVersionTag("v1.0.0"), |
| 39 | + ), |
| 40 | + ), |
| 41 | + integration.WithEnvironment( |
| 42 | + integration.EnvironmentID(e1ID), |
| 43 | + integration.EnvironmentJsonResourceSelector(map[string]any{ |
| 44 | + "type": "name", |
| 45 | + "operator": "starts-with", |
| 46 | + "value": "", |
| 47 | + }), |
| 48 | + ), |
| 49 | + ), |
| 50 | + integration.WithResource( |
| 51 | + integration.ResourceID(r1ID), |
| 52 | + ), |
| 53 | + // Create initial policy with no rules (doesn't block anything) |
| 54 | + integration.WithPolicy( |
| 55 | + integration.PolicyID(policyID), |
| 56 | + integration.PolicyName("policy-initial"), |
| 57 | + integration.WithPolicyTargetSelector(), |
| 58 | + ), |
| 59 | + ) |
| 60 | + |
| 61 | + ctx := context.Background() |
| 62 | + |
| 63 | + // Verify 2 jobs were created (v1.0.0 for both deployments) |
| 64 | + pendingJobs := engine.Workspace().Jobs().GetPending() |
| 65 | + if len(pendingJobs) != 2 { |
| 66 | + t.Fatalf("expected 2 pending jobs initially, got %d", len(pendingJobs)) |
| 67 | + } |
| 68 | + |
| 69 | + // Update the policy to add an approval rule and target prod deployments |
| 70 | + policy, _ := engine.Workspace().Policies().Get(policyID) |
| 71 | + |
| 72 | + // Add approval rule requiring 2 approvals |
| 73 | + rule := oapi.PolicyRule{ |
| 74 | + Id: "rule-1", |
| 75 | + PolicyId: policyID, |
| 76 | + CreatedAt: "2024-01-01T00:00:00Z", |
| 77 | + AnyApproval: &oapi.AnyApprovalRule{MinApprovals: 2}, |
| 78 | + } |
| 79 | + policy.Rules = []oapi.PolicyRule{rule} |
| 80 | + |
| 81 | + // Update selector to match only prod deployment |
| 82 | + selector := c.NewPolicyTargetSelector() |
| 83 | + depSelector := &oapi.Selector{} |
| 84 | + _ = depSelector.FromJsonSelector(oapi.JsonSelector{Json: map[string]any{ |
| 85 | + "type": "name", |
| 86 | + "operator": "contains", |
| 87 | + "value": "prod", |
| 88 | + }}) |
| 89 | + selector.DeploymentSelector = depSelector |
| 90 | + policy.Selectors = []oapi.PolicyTargetSelector{*selector} |
| 91 | + |
| 92 | + // Update the policy |
| 93 | + engine.PushEvent(ctx, handler.PolicyUpdate, policy) |
| 94 | + |
| 95 | + // Now create new versions (v2.0.0) for both deployments |
| 96 | + dv1 := c.NewDeploymentVersion() |
| 97 | + dv1.DeploymentId = d1ID |
| 98 | + dv1.Tag = "v2.0.0" |
| 99 | + engine.PushEvent(ctx, handler.DeploymentVersionCreate, dv1) |
| 100 | + |
| 101 | + dv2 := c.NewDeploymentVersion() |
| 102 | + dv2.DeploymentId = d2ID |
| 103 | + dv2.Tag = "v2.0.0" |
| 104 | + engine.PushEvent(ctx, handler.DeploymentVersionCreate, dv2) |
| 105 | + |
| 106 | + // Check all jobs to see which versions have releases/jobs created |
| 107 | + allJobs := engine.Workspace().Jobs().Items() |
| 108 | + |
| 109 | + // Look for jobs by deployment and version |
| 110 | + prodV2ReleaseExists := false |
| 111 | + devV2ReleaseExists := false |
| 112 | + |
| 113 | + for _, job := range allJobs { |
| 114 | + release, ok := engine.Workspace().Releases().Get(job.ReleaseId) |
| 115 | + if !ok { |
| 116 | + continue |
| 117 | + } |
| 118 | + if release.ReleaseTarget.DeploymentId == d1ID && release.Version.Tag == "v2.0.0" { |
| 119 | + prodV2ReleaseExists = true |
| 120 | + } |
| 121 | + if release.ReleaseTarget.DeploymentId == d2ID && release.Version.Tag == "v2.0.0" { |
| 122 | + devV2ReleaseExists = true |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + // Verify: prod v2.0.0 release should NOT be created (blocked by policy requiring approval) |
| 127 | + if prodV2ReleaseExists { |
| 128 | + t.Fatalf("expected NO release for prod v2.0.0 (blocked by policy), but found one") |
| 129 | + } |
| 130 | + |
| 131 | + // Verify: dev v2.0.0 release SHOULD be created (policy doesn't target dev) |
| 132 | + if !devV2ReleaseExists { |
| 133 | + t.Fatalf("expected release for dev v2.0.0 to be created") |
| 134 | + } |
| 135 | +} |
| 136 | + |
0 commit comments