Skip to content

Commit

Permalink
feat: add advanced retry policy
Browse files Browse the repository at this point in the history
  • Loading branch information
Apollorion committed Sep 11, 2024
1 parent c81913a commit 3ce7a81
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 0 deletions.
48 changes: 48 additions & 0 deletions trigger/advanced-automated-retries.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package spacelift

# set the maximum number of retries
default max_retries := 3

# label to use for stack specific retries
default retry_count_key := "spacelift_retry"

# FN: gets the value of an array of retry labels
obtain_retries_count(arr) := {x |
new_arr := array.concat(arr, [sprintf("%s:0", [retry_count_key])])
some i
parts := split(new_arr[i], ":")
parts[0] == retry_count_key
x := to_number(parts[1])
}

# Get the value of the highest retry stack label
retry_label := max(obtain_retries_count(input.stack.labels))

# Set the flag for the next iteration
new_retries := max(obtain_retries_count(input.run.flags)) + 1

retry_flag := sprintf("%s:%d", [retry_count_key, new_retries])

flag[retry_flag]

is_failed_and_tracked {
input.run.state == "FAILED"
input.run.type == "TRACKED"
}

# trigger the stack if the max retry label is 0
trigger[stack.id] {
stack := input.stack
is_failed_and_tracked
retry_label <= 0
new_retries <= max_retries
}

# trigger the stack if the max retry label is defined but only up to the maximum retries
trigger[stack.id] {
stack := input.stack
is_failed_and_tracked
retry_label > 0
new_retries <= retry_label
new_retries <= max_retries
}
13 changes: 13 additions & 0 deletions trigger/advanced-automated-retries.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: Advanced Automated Retries
source: advanced-automated-retries.rego
type: trigger
description: |
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.
This trigger policy will restart the failed run up to a maximum number of times. This policy can also be configured
on a per stack basis by setting `spacelift_retry:<number>` on the stacks labels.
labels:
- trigger
- retries
- automated
- failed
100 changes: 100 additions & 0 deletions trigger/advanced-automated-retries_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
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 flags
test_failed_and_tracked_run_without_flags if {
result := spacelift.trigger with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"flags": [],
},
"stack": {
"id": "stack-one",
"labels": [],
},
}
result["stack-one"]
}

# Test Case 2: Failed and Tracked Run with flags
test_failed_and_tracked_run_with_flags if {
result := spacelift.trigger with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"flags": ["spacelift_retry:1"],
},
"stack": {
"id": "stack-one",
"labels": [],
},
}
result["stack-one"]
}

# Test Case 3: Failed and Tracked Run with flags at max
test_failed_and_tracked_run_with_flags_at_max if {
count(spacelift.trigger) == 0 with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"flags": ["spacelift_retry:3"],
},
"stack": {
"id": "stack-one",
"labels": [],
},
}
}

# Test Case 4: LABELS: Failed and Tracked Run without flags
test_failed_and_tracked_run_labels_without_flags if {
result := spacelift.trigger with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"flags": [],
},
"stack": {
"id": "stack-one",
"labels": ["spacelift_retry:2"],
},
}
result["stack-one"]
}

# Test Case 4: LABELS: Failed and Tracked Run with flags
test_failed_and_tracked_run_labels_with_flags if {
result := spacelift.trigger with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"flags": ["spacelift_retry:1"],
},
"stack": {
"id": "stack-one",
"labels": ["spacelift_retry:2"],
},
}
result["stack-one"]
}

# Test Case 5: LABELS: Failed and Tracked Run with flags at max
test_failed_and_tracked_run_labels_with_flags_at_max if {
count(spacelift.trigger) == 0 with input as {
"run": {
"state": "FAILED",
"type": "TRACKED",
"flags": ["spacelift_retry:2"],
},
"stack": {
"id": "stack-one",
"labels": ["spacelift_retry:2"],
},
}
}

0 comments on commit 3ce7a81

Please sign in to comment.