Actions
Actions are the executable units of a Polycrate block: action schema, playbook vs. script, prompts, interactive mode, labels, action config, runtime overrides with --set and data persistence.
Actions
Actions are the executable units of a block. They define what a block can actually do – e.g. install, uninstall, status or backup.
Action schema
An action is defined in block.poly under the actions: list:
# block.poly
actions:
- name: install # Required: unique name
description: "Installs the application" # Optional: description
playbook: install.yml # Either playbook OR script
# script: # Alternative to playbook
# - echo "Hello"
prompt: # Optional: user confirmation
message: "Do you want to start the installation?"
interactive: false # Optional: TTY mode
labels: # Optional: metadata
category: deployment
risk: low
config: # Optional: action-specific config
timeout: 300
Fields in detail
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | ✅ | Unique identifier; the CLI validates action names as a slug (see Naming conventions) |
description |
string | ❌ | Human-readable description of the action |
playbook |
string | ⚠️ | Path to the Ansible playbook (relative to block.poly) |
script |
list | ⚠️ | List of shell commands |
prompt |
object | ❌ | User confirmation before execution |
interactive |
bool | ❌ | TTY mode for interactive commands (default: false) |
labels |
map | ❌ | Key-value pairs for metadata |
config |
map | ❌ | Action-specific configuration |
⚠️ = playbook and script are mutually exclusive. One of the two is required.
Playbook vs. script
Playbook (recommended)
Ansible playbooks offer the best integration with Polycrate:
actions:
- name: install
playbook: install.yml
Advantages:
- Access to the
workspace,block,actionvariables via Jinja2 - Idempotent execution
- Structured error handling
- Extensive modules for cloud, K8s, etc.
Script (not recommended)
For trivial commands without variable access:
actions:
- name: status
script:
- kubectl get pods
- echo "Status check complete"
Limitations:
- No structured error handling
- No idempotent execution
- Only suitable for commands without configuration dependencies
Prompt (user confirmation)
Actions can request a confirmation from the user:
actions:
- name: destroy
playbook: destroy.yml
prompt:
message: "⚠️ This action irrevocably deletes all resources. Continue?"
Behavior:
- Polycrate shows the message and waits for
y/n - On
nthe action is aborted - On
ythe action is executed
Skipping the prompt
# Auto-confirm a single action
polycrate run my-block destroy --force
# Globally for all actions
polycrate --force run my-block destroy
Interactive mode
For actions that need TTY interaction (e.g. password input, vim):
actions:
- name: shell
interactive: true
playbook: shell.yml
actions:
- name: edit-config
interactive: true
playbook: edit-config.yml
Use cases:
- Debug shells
- Interactive editors
- Password prompts in playbooks
Labels
Metadata for categorization and filtering:
actions:
- name: backup
labels:
category: maintenance
risk: low
duration: long
playbook: backup.yml
- name: destroy
labels:
category: cleanup
risk: high
requires-confirmation: "true"
playbook: destroy.yml
Labels can be used in workflows or external tools for filtering.
Action-specific config
Actions can have their own configuration parameters:
actions:
- name: backup
config:
retention_days: 30
compress: true
playbook: backup.yml
Available in the playbook as {{ action.config.retention_days }}.
Complete example
# blocks/my-app/block.poly
name: my-app
kind: k8sapp
version: 1.0.0
config:
namespace: production
replicas: 3
actions:
- name: install
description: "Installs the application in the Kubernetes cluster"
playbook: install.yml
labels:
category: deployment
- name: uninstall
description: "Removes the application from the cluster"
playbook: uninstall.yml
prompt:
message: "Do you really want to uninstall the application?"
labels:
category: cleanup
risk: medium
- name: status
description: "Shows the current status of the application"
playbook: status.yml
- name: shell
description: "Opens a shell in the first pod"
interactive: true
playbook: shell.yml
- name: logs
description: "Shows the application logs"
config:
tail: 100
follow: false
playbook: logs.yml
Running actions
# Default
polycrate run my-block install
# With workspace path
polycrate run my-block install -w /path/to/workspace
# With force (skips prompts)
polycrate run my-block destroy --force
# With increased log level
polycrate run my-block install --loglevel 2
# Interactive
polycrate run my-block shell
Runtime config overrides (--set)
The --set flag lets you override action.config values at runtime without changing workspace.poly or block.poly. The syntax follows the Helm standard.
# Simple value
polycrate run my-block migrate --set database.host=prod-db.internal
# Multiple overrides
polycrate run my-block deploy \
--set replicas=5 \
--set namespace=production \
--set image.tag=v2.1.0
# Array values
polycrate run my-block backup \
--set targets[0]=cluster-a \
--set targets[1]=cluster-b
Priority (from low to high)
block.poly– defaults in the block definitionworkspace.poly– partial overrides in the workspace--setflag – runtime overrides at execution (highest priority)
Notes
- All values are strings (as with Helm):
--set replicas=3→"3"in the playbook. Type conversion in Ansible via| int,| booletc. - Maps are deep-merged:
--set db.host=xoverrides onlydb.host; other keys underdbare preserved. - Lists are replaced completely:
--set items[0]=xreplaces the whole list with["x"]. - Escape dots in keys:
--set 'key\.name=value' --setwrites exclusively toaction.config–block.configis not affected.
# Playbook access
- name: Deploy
ansible.builtin.debug:
msg: "Host: {{ action.config.database.host }}, Replicas: {{ action.config.replicas | int }}"
Naming rules
In the CLI, action names follow the slug pattern (lowercase letters, digits, single hyphens). Details, regex and examples: Naming conventions – slug.
Data persistence
Data is not automatically persisted between action runs, except for:
- Workspace directory: changes in
/workspace(mounted) - Artifacts: the recommended way for persistent data
# Example: store data as an artifact
# block.artifacts.path automatically selects local_path or container_path (depending on --local / container)
- name: Generate state in Ansible
copy:
content: "{{ state_data | to_nice_yaml }}"
dest: "{{ block.artifacts.path }}/state.yml"
Relation to other concepts
- Naming conventions: slug rules for
name - Blocks: actions are part of blocks
- Workflows: orchestrate multiple actions
- Artifacts: persistence between action runs
- Ansible: playbook integration