Core Concept

DAG Execution

Shiro uses topological sorting to execute workflows as a Directed Acyclic Graph (DAG), automatically determining the optimal execution order.

How It Works

  1. 1. Parse Dependencies - Shiro reads the depends_on array from each step
  2. 2. Build Graph - Creates a directed graph of step dependencies
  3. 3. Topological Sort - Orders steps so dependencies execute first
  4. 4. Execute - Runs steps in order, tracking outputs for dependent steps

Example

json
{
  "steps": [
    { "id": "checkout", "type": "git.diff", "config": {} },
    { "id": "lint", "type": "shell", "config": {}, "depends_on": ["checkout"] },
    { "id": "test", "type": "shell", "config": {}, "depends_on": ["lint"] },
    { "id": "build", "type": "shell", "config": {}, "depends_on": ["test"] },
    { "id": "deploy", "type": "shell", "config": {}, "depends_on": ["build"] },
    { "id": "notify", "type": "slack.notify", "config": {}, "depends_on": ["deploy"] }
  ]
}

Execution order: checkout → lint → test → build → deploy → notify

Parallel Execution

Steps with no dependencies between them can execute in parallel:

json
{
  "steps": [
    { "id": "checkout", "type": "git.diff", "config": {} },
    { "id": "lint", "type": "shell", "config": {}, "depends_on": ["checkout"] },
    { "id": "test-unit", "type": "shell", "config": {}, "depends_on": ["lint"] },
    { "id": "test-integration", "type": "shell", "config": {}, "depends_on": ["lint"] },
    { "id": "build", "type": "shell", "config": {}, "depends_on": ["test-unit", "test-integration"] }
  ]
}

Execution: checkout → lint → (test-unit ∥ test-integration) → build

Rules

  • • Workflows must not contain circular dependencies
  • • All dependencies must exist as step IDs
  • • Steps with no dependencies execute first
  • • A step only executes after all its dependencies succeed