DevOps
Infrastructure-automation node for running configuration-management and provisioning tasks as part of a workflow. Today this is a single node type — ansible — designed to be combined with the code node, the agent's terminal/file tools, and infrastructure connectors (GitHub Actions, SSH) to build CI/CD-style and ops-automation pipelines.
ansible
Runs an Ansible playbook with ansible-playbook and returns its recap stats and full output. The playbook, inventory, and private key are written to temporary files for the duration of the run; the ansible-playbook binary executes directly on the worker host (this node does not use the code/terminal sandbox — ensure ansible is installed on worker hosts that will run this node).
{
"id": "deploy_app",
"type": "ansible",
"config": {
"playbook": "---\n- hosts: web\n become: true\n tasks:\n - name: Deploy release\n copy:\n src: \"{{ release_path }}\"\n dest: /opt/app/current\n",
"inventory": "[web]\nweb1.example.com\nweb2.example.com ansible_user=deploy\n",
"extra_vars": "{{ vars.ansible_extra_vars }}",
"private_key": "{{ secret.DEPLOY_SSH_KEY }}",
"hosts": "web1.example.com",
"dry_run": false
}
}
| Field | Type | Default | Description |
|---|---|---|---|
playbook | string | — | Required. Playbook YAML content (not a file path). Written to a temporary .yml file and run with ansible-playbook <file> -v. |
inventory | string | — | Inventory content or a path. If the value is an existing path on the worker filesystem it's passed directly via -i; otherwise it's written to a temp file and that file's path is used. |
extra_vars | string | — | Passed through as -e <extra_vars> — typically a JSON object or key=value string. Supports {{ }} expressions, so it can be built from vars/steps/input. |
private_key | string | — | SSH private key content (e.g. {{ secret.DEPLOY_SSH_KEY }}). Written to a temp file with 0600 permissions and passed as --private-key. |
hosts | string | — | Limits the run to specific hosts/groups via -l <hosts> (Ansible's --limit). |
dry_run | boolean | false | When true, adds --check so Ansible reports what would change without applying it. |
All string fields support {{ }} expressions and are resolved against steps, trigger, vars, secret, and input before the run.
Temporary playbook, inventory, and key files are removed after the step finishes regardless of outcome.
Output: steps.<id>.output is the parsed PLAY RECAP plus the full combined stdout/stderr:
| Field | Type | Description |
|---|---|---|
ok | number | Total ok= count across all hosts in the recap. |
changed | number | Total changed= count across all hosts. |
failed | number | Total failed= count across all hosts. |
skipped | number | Total skipped= count across all hosts. |
output | string | Full combined stdout+stderr from ansible-playbook -v, including per-task and per-host results — parse this for host-by-host detail. |
If ansible-playbook exits non-zero and the output contains no PLAY RECAP (e.g. a syntax error or connection failure before any play ran), the step fails with an error containing the raw output. If a PLAY RECAP is present — even with failed > 0 — the step succeeds and returns the recap counts, so check steps.<id>.output.failed explicitly to branch on per-host failures with a condition step.
:::tip Storing SSH keys
Store the playbook's SSH private key as a secret (e.g. DEPLOY_SSH_KEY) and reference it as {{ secret.DEPLOY_SSH_KEY }} in private_key rather than embedding it in the workflow definition or inventory.
:::
Building DevOps workflows
ansible is typically the apply/deploy step in a larger pipeline. Common building blocks:
| Step type | Role |
|---|---|
code | Lint/validate config, parse terraform plan JSON, generate dynamic inventory or extra_vars before the playbook runs. |
ansible | Apply the playbook against the target hosts (provisioning, deploys, config drift fixes). |
connector (tool-github-actions) | Trigger or poll a CI workflow run — e.g. kick off a build before deploying, or report deploy status back to a GitHub Actions run. |
connector (tool-ssh) | Run one-off remote commands (health checks, log tailing) that don't warrant a full playbook. |
sftp | Push build artifacts or config files to a host ahead of an ansible run. |
condition | Branch on steps.deploy.output.failed to trigger rollback or alerting. |
Example: lint, deploy, verify
{
"steps": [
{
"id": "lint_config",
"type": "code",
"config": {
"language": "javascript",
"code": "if (!inputs.vars.release_path) { throw new Error('release_path is required'); } return { ok: true };"
}
},
{
"id": "deploy",
"type": "ansible",
"depends_on": ["lint_config"],
"config": {
"playbook": "{{ vars.deploy_playbook }}",
"inventory": "{{ vars.deploy_inventory }}",
"private_key": "{{ secret.DEPLOY_SSH_KEY }}",
"extra_vars": "{\"release_path\": \"{{ vars.release_path }}\"}"
}
},
{
"id": "check_deploy",
"type": "condition",
"depends_on": ["deploy"],
"config": {
"expression": "{{ steps.deploy.output.failed }} > 0"
}
},
{
"id": "notify_failure",
"type": "connector",
"branch_deps": [{ "step_id": "check_deploy", "branch": "true" }],
"config": {
"connector_type": "tool-github-actions",
"action": "create_issue_comment",
"params": {
"body": "Deploy failed: ok={{ steps.deploy.output.ok }} changed={{ steps.deploy.output.changed }} failed={{ steps.deploy.output.failed }}"
}
}
}
]
}
lint_config validates inputs cheaply before the (slower, infrastructure-touching) ansible step runs; check_deploy and notify_failure turn the recap counts into an alert when any host fails.