{"id":13514265,"url":"https://github.com/coinbase/step","last_synced_at":"2025-03-31T03:30:18.855Z","repository":{"id":57490789,"uuid":"123670090","full_name":"coinbase/step","owner":"coinbase","description":"step is a framework for building, testing and deploying AWS Step Functions and Lambda","archived":true,"fork":false,"pushed_at":"2020-09-21T18:18:03.000Z","size":706,"stargazers_count":210,"open_issues_count":0,"forks_count":31,"subscribers_count":30,"default_branch":"master","last_synced_at":"2024-11-01T17:37:29.438Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coinbase.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-03T07:33:14.000Z","updated_at":"2024-10-21T16:49:36.000Z","dependencies_parsed_at":"2022-09-14T05:21:24.689Z","dependency_job_id":null,"html_url":"https://github.com/coinbase/step","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fstep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fstep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fstep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coinbase%2Fstep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coinbase","download_url":"https://codeload.github.com/coinbase/step/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246413377,"owners_count":20773053,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T05:00:50.988Z","updated_at":"2025-03-31T03:30:18.473Z","avatar_url":"https://github.com/coinbase.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Step (Beta)\n\n\u003cimg align=\"right\" src=\"./assets/one_small_step_for_gopher.png\" alt=\"One Small Step for Go\"/\u003e\n\nStep is a opinionated implementation of the [AWS State Machine language](./STATE_SPEC.md) in [Go](https://golang.org/) used to build and test [AWS Step Functions](https://docs.aws.amazon.com/step-functions/latest/dg/getting-started.html) and [Lambdas](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html). Step combines the **Structure** of a state machine with the **Code** of a lambda so that the two can be developed, tested and maintained together.\n\nThe three core components of Step are:\n\n1. **Library**: tools for building and deploying Step Functions in Go.\n2. **Implementation**: of the AWS State Machine specification to test with the code together ([README](./machine)).\n3. **Deployer**: to deploy Lambda's and Step Functions securely ([README](./deployer))\n\n### Getting Started\n\nA Step function has two parts:\n\n1. A **State Machine** description in JSON, which outlines the flow of execution.\n2. The **Lambda Function** which executes the `TaskFn` states of the step function.\n\nCreate a State Machine like this:\n\n```go\nfunc StateMachine(lambdaArn string) (machine.StateMachine, error) {\n  state_machine, err := machine.FromJSON([]byte(`{\n    \"Comment\": \"Hello World\",\n    \"StartAt\": \"HelloFn\",\n    \"States\": {\n      \"Hello\": {\n        \"Type\": \"TaskFn\",\n        \"Comment\": \"Deploy Step Function\",\n        \"End\": true\n      }\n    }\n  }`))\n\n  if err != nil {\n      return nil, err\n  }\n\n  // Set the Handlers\n  state_machine.SetTaskFnHandlers(CreateTaskHandlers())\n\n  // Set Lambda Arn to call with Task States\n  state_machine.SetResource(\u0026lambdaArn)\n\n  return state_machine, nil\n}\n```\n\n`TaskFn` is a custom state type that injects `Parameters` to execute the correct handler.\n\nEach `TaskFn` must have a handler that implements `func(context.Context, \u003cinput_type\u003e) (interface{}, error)`. These are defined like:\n\n```go\nfunc CreateTaskFunctions() *handler.TaskHandlers {\n  tm := handler.TaskHandlers{}\n  // Assign Hello state the HelloHandler\n\ttm[\"Hello\"] = HelloHandler\n\treturn \u0026tm\n}\n\ntype Hello struct {\n  Greeting *string\n}\n\n// HelloHandler takes a Hello struct alters its greeting and returns it\nfunc HelloHandler(_ context.Context, hello *Hello) (*Hello, error) {\n  if hello.Greeting == \"\" {\n    hello.Greeting = \"Hello World\"\n  }\n  return hello, nil\n}\n```\n\nTo build a Step Function we then need an executable that can:\n\n1. Be executed in a Lambda\n2. Build the State Machine\n\n```go\nfunc main() {\n  var arg, command string\n  switch len(os.Args) {\n  case 1:\n    fmt.Println(\"Starting Lambda\")\n    run.LambdaTasks(StateMachine(\"lambda\"))\n  case 2:\n    command = os.Args[1]\n    arg = \"\"\n  case 3:\n    command = os.Args[1]\n    arg = os.Args[2]\n  default:\n    printUsage() // Print how to use and exit\n  }\n\n  switch command {\n  case \"json\":\n    run.JSON(StateMachine(arg))\n  case \"exec\":\n    run.Exec(StateMachine(\"\"))(\u0026arg)\n  default:\n    printUsage() // Print how to use and exit\n  }\n\n}\n```\n\n1. `./step-hello-world` will run as a Lambda Function\n2. `./step-hello-world json` will print out the state machine\n\n### Testing\n\nA core benefit when using Step and joining the State Machine and Lambda together is that it makes it possible to test your Step Functions execution.\n\nFor example, a basic test that ensures the correct output and execution path through the Hello World step function looks like:\n\n```go\nfunc Test_HelloWorld_StateMachine(t *testing.T) {\n  state_machine, err := StateMachine(\"\")\n  assert.NoError(t, err)\n\n  exec, err := state_machine.Execute(\u0026Hello{})\n  assert.NoError(t, err)\n  assert.Equal(t, \"Hello World\", exec.Output[\"Greeting\"])\n\n  assert.Equal(t, state_machine.Path(), []string{\n    \"Hello\",\n  })\n}\n```\n\n### Deploying\n\nThere are two ways to get a State Machine into the cloud:\n\n1. **Bootstrap**: Directly upload the Lambda and Step Function to AWS\n2. **Deploy**: Using the Step Deployer which is a Step Function included in this library.\n\nThe Step executable can perform both of these functions.\n\n*Step does not create the Lambda or Step Function in AWS, it only modifies them. So before either bootstrapping or deploying the resources must already be created.*\n\nFirst build and install step with:\n\n```bash\ngo build \u0026\u0026 go install\n```\n\nBootstrap (directly upload to the Step Function and Lambda):\n\n```bash\n# Use AWS credentials or assume-role into AWS\n# Build linux zip for lambda\nGOOS=linux go build -o lambda\nzip lambda.zip lambda\n\n# Tell step to bootstrap this lambda\nstep bootstrap                        \\\n  -lambda \"coinbase-step-hello-world\" \\\n  -step \"coinbase-step-hello-world\"   \\\n  -states \"$(./step-hello-world json)\"\n```\n\nDeploy (via the step-deployer step function):\n\n```bash\nGOOS=linux go build -o lambda\nzip lambda.zip lambda\n\n# Tell step-deployer to deploy this lambda\nstep deploy                           \\\n  -lambda \"coinbase-step-hello-world\" \\\n  -step \"coinbase-step-hello-world\"   \\\n  -states \"$(./step-hello-world json)\"\n```\n\n### Development State\n\nStep is still Beta and its API might change quickly.\n\n### More Links\n\n1. [AWS Step Functions, State Machines, Bifrost, and Building Deployers](https://blog.coinbase.com/aws-step-functions-state-machines-bifrost-and-building-deployers-5e3745fe645b)\n1. [Open Sourcing Coinbase’s Secure Deployment Pipeline](https://engineering.coinbase.com/open-sourcing-coinbases-secure-deployment-pipeline-ae6c78e25517)\n1. https://docs.aws.amazon.com/step-functions/latest/dg/step-functions-dg.pdf\n1. https://github.com/vkkis93/serverless-step-functions-offline\n1. https://github.com/totherik/step\n\n*CC Renee French for the logo, borrowed from GopherCon 2017*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoinbase%2Fstep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoinbase%2Fstep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoinbase%2Fstep/lists"}