Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated trigger policies with tests #53

Merged
merged 4 commits into from
Jan 29, 2024
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
6 changes: 5 additions & 1 deletion trigger/automated-retries.rego
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package spacelift

import future.keywords.contains
import future.keywords.if
import future.keywords.in

# Sometimes Terraform or Pulumi deployments fail for a reason that has nothing to do
# with the code - think eventual consistency between various cloud subsystems, transient
# API errors etc. It would be great if you could restart the failed run. Oh, and let's
# make sure new runs are not created in a crazy loop - since policy-triggered runs
# trigger another policy evaluation:

trigger[stack.id] {
trigger contains stack.id if {
stack := input.stack
input.run.state == "FAILED"
input.run.type == "TRACKED"
Expand Down
43 changes: 43 additions & 0 deletions trigger/automated-retries_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package spacelift_test

import data.spacelift
import future.keywords.contains
import future.keywords.if
import future.keywords.in

# Test Case 1: Failed and Tracked Run Without Trigger
test_failed_tracked_run_without_trigger if {
result := spacelift.trigger with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"triggered_by": null,
},
"stack": {"id": "stack-one"},
}
result["stack-one"]
}

# Test Case 2: Failed and Tracked Run With Trigger
test_failed_tracked_run_with_trigger if {
count(spacelift.trigger) == 0 with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"triggered_by": "some-policy",
},
"stack": {"id": "stack-one"},
}
}

# Test Case 3: Non-Failed Run or Non-Tracked Run
test_non_failed_or_non_tracked_run if {
count(spacelift.trigger) == 0 with input as {
"run": {
"state": "SUCCESS",
"type": "TRACKED",
"triggered_by": null,
},
"stack": {"id": "stack-one"},
}
}
11 changes: 8 additions & 3 deletions trigger/trigger-dependencies-via-labels-with-state.rego
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package spacelift

import future.keywords.contains
import future.keywords.if
import future.keywords.in

# This policy will cause every stack that declares dependency on the current stack
# and state to get triggered when the conditions are met.
#
# You can read more about trigger policies here:
# https://docs.spacelift.io/concepts/policy/trigger-policy

trigger[stack.id] {
stack := input.stacks[_]
trigger contains stack.id if {
some stack in input.stacks
input.run.type == "TRACKED"
stack.labels[_] == concat("", [
some label in stack.labels
label == concat("", [
"depends-on:", input.stack.id,
"|state:", input.run.state,
])
Expand Down
36 changes: 36 additions & 0 deletions trigger/trigger-dependencies-via-labels-with-state_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package spacelift

import data.spacelift
import future.keywords.contains
import future.keywords.if
import future.keywords.in

# Test Case 1: Dependency and State Match
test_dependency_and_state_match if {
spacelift.trigger with input as {
"run": {
"state": "FINISHED",
"type": "TRACKED",
},
"stack": {"id": "stack-one"},
"stacks": [{
"id": "stack-two",
"labels": ["depends-on:stack-one|state:FINISHED"],
}],
}
}

# Test Case 2: Dependency Match but State Mismatch
test_dependency_match_state_mismatch if {
count(spacelift.trigger) == 0 with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
},
"stack": {"id": "stack-one"},
"stacks": [{
"id": "stack-two",
"labels": ["depends-on:stack-one|state:FINISHED"],
}],
}
}
11 changes: 8 additions & 3 deletions trigger/trigger-dependencies-via-labels.rego
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package spacelift

import future.keywords.contains
import future.keywords.if
import future.keywords.in

# This example trigger policy will cause every stack that declares dependency on
# the current one to get triggered when the current one is successfully updated.
#
# You can read more about trigger policies here:
# https://docs.spacelift.io/concepts/policy/trigger-policy

trigger[stack.id] {
stack := input.stacks[_]
trigger contains stack.id if {
some stack in input.stacks
input.run.state == "FINISHED"
stack.labels[_] == concat("", ["depends-on:", input.stack.id])
some label in stack.labels
label == concat("", ["depends-on:", input.stack.id])
}

# Learn more about sampling policy evaluations here:
Expand Down
43 changes: 43 additions & 0 deletions trigger/trigger-dependencies-via-labels_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package spacelift_test

import data.spacelift
import future.keywords.contains
import future.keywords.if
import future.keywords.in

# Test when run is finished and dependent stack is present
test_trigger_dependency_present if {
result := spacelift.trigger with input as {
"run": {"state": "FINISHED"},
"stack": {"id": "debugtest"},
"stacks": [{
"id": "dependentstack",
"labels": ["depends-on:debugtest"],
}],
}
result.dependentstack
}

# Test when run is finished but no dependent stack is present
test_trigger_no_dependency if {
count(spacelift.trigger) == 0 with input as {
"run": {"state": "FINISHED"},
"stack": {"id": "debugtest"},
"stacks": [{
"id": "independentstack",
"labels": ["no-dependency"],
}],
}
}

# Test when run is not finished but dependent stack is present
test_trigger_run_not_finished if {
count(spacelift.trigger) == 0 with input as {
"run": {"state": "UNCONFIRMED"},
"stack": {"id": "debugtest"},
"stacks": [{
"id": "dependentstack",
"labels": ["depends-on:debugtest"],
}],
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package spacelift

import future.keywords.contains
import future.keywords.if
import future.keywords.in

# This policy triggers a predefined list of Stacks when a Run finishes successfully
# to create a complex workflow that spans multiple Stacks.

trigger["stack-one"] {
trigger contains "stack-one" if {
finished
}

trigger["stack-two"] {
trigger contains "stack-two" if {
finished
}

trigger["stack-three"] {
trigger contains "stack-three" if {
finished
}

finished {
finished if {
input.run.state == "FINISHED"
input.run.type == "TRACKED"
}
21 changes: 21 additions & 0 deletions trigger/trigger-hardcoded-dependencies_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package spacelift_test

import data.spacelift
import future.keywords.contains
import future.keywords.if
import future.keywords.in

# Test setup for finished runs
test_trigger_success if {
spacelift.trigger with input as {"run": {
"state": "FINISHED",
"type": "TRACKED",
}}
}

test_trigger_failure_non_finished_state if {
count(spacelift.trigger) == 0 with input as {"run": {
"state": "UNCONFIRMED",
"type": "TRACKED",
}}
}