Skip to content

Instantly share code, notes, and snippets.

@jnbdz
Created March 19, 2026 21:14
Show Gist options
  • Select an option

  • Save jnbdz/e840767f51c39f475f97953ab2aa5b36 to your computer and use it in GitHub Desktop.

Select an option

Save jnbdz/e840767f51c39f475f97953ab2aa5b36 to your computer and use it in GitHub Desktop.
# ──────────────────────────────────────────────
# Step Functions State Machine
#
# Uses .sync:2 integration so Step Functions
# waits for each ECS task to finish before
# moving to the next state — no polling needed.
#
# Each step overrides the container command to
# run a different Python file. All share the
# same task definition and Docker image.
# ──────────────────────────────────────────────
locals {
# Reusable network config block for all ECS steps
ecs_network_config = {
AwsvpcConfiguration = {
Subnets = var.subnet_ids
SecurityGroups = var.security_group_ids
AssignPublicIp = "DISABLED"
}
}
}
resource "aws_sfn_state_machine" "main" {
name = "${local.prefix}-state-machine"
role_arn = aws_iam_role.sfn.arn
type = "STANDARD"
logging_configuration {
log_destination = "${aws_cloudwatch_log_group.sfn.arn}:*"
include_execution_data = true
level = "ERROR"
}
definition = jsonencode({
Comment = "Runs script_1, script_2, script_3 sequentially on Fargate"
StartAt = "RunScript1"
States = {
RunScript1 = {
Type = "Task"
Resource = "arn:aws:states:::ecs:runTask.sync:2"
Parameters = {
LaunchType = "FARGATE"
Cluster = aws_ecs_cluster.main.arn
TaskDefinition = aws_ecs_task_definition.app.arn
NetworkConfiguration = local.ecs_network_config
Overrides = {
ContainerOverrides = [{
Name = "app"
Command = ["script_1.py"]
}]
}
}
ResultPath = "$.script1Result"
Retry = [{
ErrorEquals = ["States.TaskFailed"]
IntervalSeconds = 30
MaxAttempts = 2
BackoffRate = 2.0
}]
Catch = [{
ErrorEquals = ["States.ALL"]
Next = "JobFailed"
ResultPath = "$.error"
}]
Next = "RunScript2"
}
RunScript2 = {
Type = "Task"
Resource = "arn:aws:states:::ecs:runTask.sync:2"
Parameters = {
LaunchType = "FARGATE"
Cluster = aws_ecs_cluster.main.arn
TaskDefinition = aws_ecs_task_definition.app.arn
NetworkConfiguration = local.ecs_network_config
Overrides = {
ContainerOverrides = [{
Name = "app"
Command = ["script_2.py"]
}]
}
}
ResultPath = "$.script2Result"
Retry = [{
ErrorEquals = ["States.TaskFailed"]
IntervalSeconds = 30
MaxAttempts = 2
BackoffRate = 2.0
}]
Catch = [{
ErrorEquals = ["States.ALL"]
Next = "JobFailed"
ResultPath = "$.error"
}]
Next = "RunScript3"
}
RunScript3 = {
Type = "Task"
Resource = "arn:aws:states:::ecs:runTask.sync:2"
Parameters = {
LaunchType = "FARGATE"
Cluster = aws_ecs_cluster.main.arn
TaskDefinition = aws_ecs_task_definition.app.arn
NetworkConfiguration = local.ecs_network_config
Overrides = {
ContainerOverrides = [{
Name = "app"
Command = ["script_3.py"]
}]
}
}
ResultPath = "$.script3Result"
Retry = [{
ErrorEquals = ["States.TaskFailed"]
IntervalSeconds = 30
MaxAttempts = 2
BackoffRate = 2.0
}]
Catch = [{
ErrorEquals = ["States.ALL"]
Next = "JobFailed"
ResultPath = "$.error"
}]
Next = "JobSucceeded"
}
JobSucceeded = {
Type = "Succeed"
}
JobFailed = {
Type = "Fail"
Error = "JobFailed"
Cause = "A script step failed after retries. Check CloudWatch logs."
}
}
})
}
# ──────────────────────────────────────────────
# Outputs
# ──────────────────────────────────────────────
output "state_machine_arn" {
description = "ARN of the Step Functions state machine"
value = aws_sfn_state_machine.main.arn
}
output "state_machine_name" {
description = "Name of the Step Functions state machine"
value = aws_sfn_state_machine.main.name
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment