Define named, multi-step automation sequences in .asc/workflow.json. Each workflow composes existing asc commands and shell commands.
Quick Start
asc workflow list
asc workflow validate
asc workflow run beta
Subcommands
list - List available workflows
validate - Validate workflow.json for errors and cycles
run - Run a named workflow
Workflows are defined in .asc/workflow.json:
{
"env": {
"APP_ID": "123456789",
"VERSION": "1.0.0"
},
"before_all": "asc auth status",
"after_all": "echo workflow_done",
"error": "echo workflow_failed",
"workflows": {
"beta": {
"description": "Distribute a build to a TestFlight group",
"env": {
"GROUP_ID": ""
},
"steps": [
{
"name": "list_builds",
"run": "asc builds list --app $APP_ID --sort -uploadedDate --limit 5"
},
{
"name": "list_groups",
"run": "asc testflight beta-groups list --app $APP_ID --limit 20"
},
{
"name": "add_build_to_group",
"if": "BUILD_ID",
"run": "asc builds add-groups --build $BUILD_ID --group $GROUP_ID"
}
]
},
"release": {
"description": "Submit a version for App Store review",
"steps": [
{
"workflow": "preflight",
"with": {
"NOTE": "running private sub-workflow"
}
},
{
"name": "submit",
"run": "asc submit create --app $APP_ID --version $VERSION --build $BUILD_ID --confirm"
}
]
},
"preflight": {
"private": true,
"description": "Private helper workflow (callable only via workflow steps)",
"steps": [
{
"name": "preflight",
"run": "echo \"$NOTE\""
}
]
}
}
}
Features
Environment Variables
Define environment variables at the top level or per-workflow:
{
"env": {
"APP_ID": "123456789"
},
"workflows": {
"my-workflow": {
"env": {
"VERSION": "1.0.0"
}
}
}
}
Hooks
Run commands before/after all workflows or on error:
before_all - Runs before any workflow executes
after_all - Runs after successful workflow completion
error - Runs if any step or hook fails
Conditional Steps
Skip steps based on environment variable presence:
{
"name": "optional_step",
"if": "BUILD_ID",
"run": "asc builds get --build $BUILD_ID"
}
Sub-workflows
Call other workflows as steps:
{
"workflow": "preflight",
"with": {
"NOTE": "running checks"
}
}
Private Workflows
Mark workflows as private to prevent direct execution:
{
"preflight": {
"private": true,
"steps": [...]
}
}
Commands
workflow list
List available workflows:
asc workflow list
asc workflow list --all # Include private workflows
asc workflow list --file ./custom-workflows.json
Flags:
--file - Path to workflow.json (default: .asc/workflow.json)
--all - Include private workflows in listing
--pretty - Pretty-print JSON output
workflow validate
Validate workflow.json for errors and cycles:
asc workflow validate
asc workflow validate --file ./custom-workflows.json
Flags:
--file - Path to workflow.json (default: .asc/workflow.json)
--pretty - Pretty-print JSON output
workflow run
Run a named workflow:
asc workflow run beta
asc workflow run beta BUILD_ID:123456789 GROUP_ID:abcdef
asc workflow run release VERSION:2.1.0
asc workflow run --dry-run beta
Flags:
--file - Path to workflow.json (default: .asc/workflow.json)
--dry-run - Preview steps without executing
--pretty - Pretty-print JSON output
Arguments:
name - Workflow name to run
KEY:VALUE ... - Override environment variables
Output
All commands output JSON to stdout. Step/hook output streams to stderr to keep stdout machine-parseable.
Example output:
{
"workflow": "beta",
"status": "ok",
"hooks": {
"before_all": {
"command": "asc auth status",
"status": "ok",
"duration_ms": 150
}
},
"steps": [
{
"index": 1,
"name": "list_builds",
"command": "asc builds list --app 123456789 --sort -uploadedDate --limit 5",
"status": "ok",
"duration_ms": 500
}
],
"duration_ms": 1200
}
Security Notes
Workflows intentionally execute arbitrary shell commands. Only run workflow files you trust.
- Treat
.asc/workflow.json like code: review it before running
- Steps inherit your process environment; be careful with secrets
- In CI, avoid running workflows on untrusted PRs with secrets/tokens
asc workflow validate checks structure, not safety of commands
- When using
--file, verify the file path and contents
Execution Details
- Commands run via bash (with pipefail) when available, otherwise sh
- At least one shell must be in PATH
- stdout is JSON-only; step/hook command output streams to stderr
- On failure, stdout remains JSON-only and includes a top-level error message plus hook results
- Maximum call depth for sub-workflows: 16