Tutorial: Getting Started with iapetus

This tutorial will guide you through installing iapetus, writing and running your first workflow in YAML and Go, using assertions and dependencies, running tasks in Docker, and extending iapetus with a custom backend. Each step explains not just what to do, but why.

Step 1: Installation

Before you can use iapetus, you need Go installed on your system. Go is required to build and run iapetus workflows.

  1. Install Go ([download here](https://golang.org/dl/)) - Verify installation:

    go version
    
  2. Clone the iapetus repository - This gives you access to all examples and the latest code.

    git clone https://github.com/yindia/iapetus.git
    cd iapetus
    go mod tidy  # Download Go dependencies
    
  3. (Optional) Use pixi for reproducible environments - [pixi](https://pixi.sh/) helps you manage dependencies and environments, especially for collaborative or CI/CD setups.

    pixi shell
    

Step 2: Write Your First Workflow in YAML

YAML is a simple way to define workflows without writing Go code. Create a file called workflow.yaml:

name: hello-workflow
backend: bash
steps:
  - name: say-hello
    command: echo
    args: ["Hello, iapetus!"]
    raw_asserts:
      - output_contains: iapetus

Explanation: - name: The workflow’s name. - backend: Where tasks run (“bash” = local shell). - steps: List of tasks. Each task has a name, command, arguments, and assertions. - raw_asserts: Checks that the output contains “iapetus” (verifies success).

Step 3: Run the Workflow

To run a YAML workflow, you need a small Go program to load and execute it. Create main.go:

package main
import (
    "github.com/yindia/iapetus"
    "log"
)
func main() {
    wf, err := iapetus.LoadWorkflowFromYAML("workflow.yaml")
    if err != nil { log.Fatal(err) }
    if err := wf.Run(); err != nil {
        log.Fatalf("Workflow failed: %v", err)
    }
}

Run it:

go run main.go

What happens: - iapetus loads your YAML, runs each step, and prints results. - If the assertion fails, you’ll see an error.

Step 4: Write a Workflow in Go

For more flexibility, you can define workflows in Go. This is useful for dynamic logic, custom hooks, or programmatic task generation.

import (
    "github.com/yindia/iapetus"
    "go.uber.org/zap"
    "time"
)
task := iapetus.NewTask("hello", 5*time.Second, nil).
    AddCommand("echo").
    AddArgs("Hello, iapetus!").
    AssertOutputContains("iapetus")
workflow := iapetus.NewWorkflow("my-wf", zap.NewNop())
workflow.AddTask(*task)
workflow.Run()

Why use Go? - Add custom logic, hooks, or assertions. - Integrate with other Go code or libraries.

Step 5: Add Assertions and Dependencies

Assertions check that your tasks did what you expected. Dependencies let you control execution order.

task1 := iapetus.NewTask("step1", 5*time.Second, nil).
    AddCommand("echo").AddArgs("foo").AssertOutputContains("foo")
task2 := iapetus.NewTask("step2", 5*time.Second, nil).
    AddCommand("echo").AddArgs("bar")
task2.Depends = []string{"step1"}
wf := iapetus.NewWorkflow("demo", zap.NewNop())
wf.AddTask(*task1)
wf.AddTask(*task2)
wf.Run()

Explanation: - AssertOutputContains(“foo”): Checks output of step1. - task2.Depends = [“step1”]: step2 runs only after step1 succeeds.

Step 6: Use the Docker Backend

You can run tasks inside Docker containers for isolation or to match production environments.

task := iapetus.NewTask("docker-echo", 5*time.Second, nil).
    AddCommand("echo").AddArgs("inside container").
    AssertOutputContains("inside container")
task.SetBackend("docker")
task.Image = "alpine:3.18"
wf := iapetus.NewWorkflow("docker-demo", zap.NewNop())
wf.AddTask(*task)
wf.Run()

Tips: - Set task.Image to the Docker image you want. - Use Docker backend for clean, reproducible builds/tests.

Step 7: Extend with a Custom Backend Plugin

You can add your own backend (e.g., run tasks on Kubernetes, SSH, etc) by implementing the Backend interface.

type MyBackend struct{}
func (b *MyBackend) RunTask(task *iapetus.Task) error {
    // Custom logic
    return nil
}
func (b *MyBackend) ValidateTask(task *iapetus.Task) error { return nil }
iapetus.RegisterBackend("my-backend", &MyBackend{})
// Use in workflow or task as shown above

Why plugins? - Integrate with any environment or system. - Add new ways to run or validate tasks.

Debugging and Common Errors

  • “command not found”: Ensure the command exists in your environment or Docker image.

  • “permission denied”: Check file and Docker permissions.

  • “Go not installed”: Install Go from https://golang.org/dl/

  • For more, see the FAQ in the main README or docs.

Next Steps