Skip to main content
Workflows allow you to define multi-step automation sequences in a .asc/workflow.json file. This is useful for complex release processes that involve multiple commands.

Workflow file structure

Create a .asc/workflow.json file in your project root:
{
  "env": {
    "APP_ID": "123456789",
    "VERSION": "1.2.0"
  },
  "before_all": "echo 'Starting workflow'",
  "after_all": "echo 'Workflow complete'",
  "error": "echo 'Workflow failed' && exit 1",
  "workflows": {
    "testflight": {
      "description": "Upload build to TestFlight",
      "steps": [
        "asc builds upload --app $APP_ID --file MyApp.ipa",
        "asc builds list --app $APP_ID --limit 1",
        "asc testflight builds list --app $APP_ID --limit 1"
      ]
    },
    "submit": {
      "description": "Submit build for App Store review",
      "steps": [
        "asc validate --app $APP_ID --version $VERSION",
        "asc submit --app $APP_ID --version $VERSION"
      ]
    }
  }
}

Running workflows

Execute a workflow by name:
asc workflow run --file .asc/workflow.json --workflow testflight
Or use the short form:
asc workflow run testflight
When --file is omitted, the CLI looks for .asc/workflow.json in the current directory.

Workflow schema

Top-level fields

env
object
Global environment variables available to all workflows
"env": {
  "APP_ID": "123456789",
  "API_KEY": "secret-value"
}
before_all
string
Command to run before any workflow executesUseful for validation or setup tasks.
after_all
string
Command to run after a workflow completes successfullyUseful for cleanup or notifications.
error
string
Command to run if a workflow failsUseful for error notifications or rollback.
workflows
object
required
Map of workflow names to workflow definitions

Workflow fields

description
string
Human-readable description of the workflow
private
boolean
Hide this workflow from asc workflow listDefault: false
env
object
Workflow-specific environment variablesThese override global env variables.
steps
array
required
List of steps to execute (see step format below)

Step formats

Steps can be defined in two formats: Short form (string):
"steps": [
  "asc apps list",
  "asc builds list --app 123456789"
]
Long form (object):
"steps": [
  {
    "name": "Upload build",
    "run": "asc builds upload --app $APP_ID --file MyApp.ipa"
  },
  {
    "name": "Verify upload",
    "run": "asc builds list --app $APP_ID --limit 1",
    "if": "$VERIFY == true"
  },
  {
    "name": "Run sub-workflow",
    "workflow": "notify",
    "with": {
      "MESSAGE": "Build uploaded"
    }
  }
]

Step fields

name
string
Step name (displayed during execution)
run
string
Shell command to execute
workflow
string
Name of another workflow to run (sub-workflow)Mutually exclusive with run.
if
string
Condition expression (evaluated as shell command)Step runs only if the command exits with code 0.
with
object
Environment variables passed to the stepOnly applies to workflow steps.

Environment variable precedence

Environment variables are resolved in this order (highest to lowest):
  1. Runtime parameters (--with flag)
  2. Step with field (for sub-workflows)
  3. Workflow env field
  4. Global env field
  5. System environment variables
Example:
asc workflow run testflight --with APP_ID=987654321
This overrides the APP_ID defined in the workflow file.

Conditional steps

Use the if field to conditionally execute steps:
{
  "steps": [
    {
      "name": "Upload build",
      "run": "asc builds upload --app $APP_ID --file MyApp.ipa"
    },
    {
      "name": "Submit for review",
      "run": "asc submit --app $APP_ID --version $VERSION",
      "if": "test \"$AUTO_SUBMIT\" = \"true\""
    }
  ]
}
The if condition is evaluated as a shell command. The step runs only if the command exits with code 0.

Sub-workflows

Call other workflows from within a workflow:
{
  "workflows": {
    "notify": {
      "description": "Send notification",
      "steps": [
        "asc notify slack --message \"$MESSAGE\""
      ]
    },
    "release": {
      "description": "Full release process",
      "steps": [
        "asc builds upload --app $APP_ID --file MyApp.ipa",
        {
          "workflow": "notify",
          "with": {
            "MESSAGE": "Build uploaded to TestFlight"
          }
        },
        "asc submit --app $APP_ID --version $VERSION",
        {
          "workflow": "notify",
          "with": {
            "MESSAGE": "Submitted for App Store review"
          }
        }
      ]
    }
  }
}

Lifecycle hooks

Workflow hooks run at specific points during execution:
  • before_all: Runs before any workflow starts
  • after_all: Runs after a workflow completes successfully
  • error: Runs if any step fails
Example with Slack notifications:
{
  "before_all": "asc notify slack --message 'Starting release workflow'",
  "after_all": "asc notify slack --message 'Release complete'",
  "error": "asc notify slack --message 'Release failed' && exit 1",
  "workflows": {
    "release": {
      "steps": [
        "asc builds upload --app $APP_ID --file MyApp.ipa",
        "asc submit --app $APP_ID --version $VERSION"
      ]
    }
  }
}

Complete example

Here’s a comprehensive workflow for a full release process:
{
  "env": {
    "APP_ID": "123456789",
    "VERSION": "1.2.0",
    "BUILD_DIR": "build",
    "SLACK_WEBHOOK": "https://hooks.slack.com/services/..."
  },
  "before_all": "echo 'Starting release for v$VERSION'",
  "after_all": "echo 'Release complete for v$VERSION'",
  "error": "curl -X POST $SLACK_WEBHOOK -d '{\"text\":\"Release failed for v$VERSION\"}'  && exit 1",
  "workflows": {
    "beta": {
      "description": "Upload build to TestFlight",
      "steps": [
        {
          "name": "Validate build",
          "run": "test -f $BUILD_DIR/MyApp.ipa"
        },
        {
          "name": "Upload to TestFlight",
          "run": "asc builds upload --app $APP_ID --file $BUILD_DIR/MyApp.ipa"
        },
        {
          "name": "Wait for processing",
          "run": "sleep 60"
        },
        {
          "name": "Verify build available",
          "run": "asc builds list --app $APP_ID --limit 1 --output json | jq -e '.data[0]'"
        },
        {
          "name": "Notify team",
          "workflow": "notify",
          "with": {
            "MESSAGE": "New TestFlight build available: v$VERSION"
          }
        }
      ]
    },
    "submit": {
      "description": "Submit to App Store",
      "steps": [
        {
          "name": "Validate version",
          "run": "asc validate --app $APP_ID --version $VERSION"
        },
        {
          "name": "Submit for review",
          "run": "asc submit --app $APP_ID --version $VERSION"
        },
        {
          "name": "Notify team",
          "workflow": "notify",
          "with": {
            "MESSAGE": "v$VERSION submitted for App Store review"
          }
        }
      ]
    },
    "notify": {
      "description": "Send Slack notification",
      "private": true,
      "steps": [
        "curl -X POST $SLACK_WEBHOOK -d '{\"text\":\"$MESSAGE\"}'"
      ]
    }
  }
}

CI/CD integration

GitHub Actions

name: Release
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - uses: rudrankriyam/setup-asc@v1
        with:
          key-id: ${{ secrets.ASC_KEY_ID }}
          issuer-id: ${{ secrets.ASC_ISSUER_ID }}
          private-key: ${{ secrets.ASC_PRIVATE_KEY }}
      
      - name: Build app
        run: xcodebuild -scheme MyApp -archivePath build/MyApp.xcarchive archive
      
      - name: Run release workflow
        run: asc workflow run release --with VERSION=${{ github.ref_name }}

GitLab CI

release:
  stage: deploy
  script:
    - asc workflow run release --with VERSION=$CI_COMMIT_TAG
  only:
    - tags
  variables:
    ASC_KEY_ID: $ASC_KEY_ID
    ASC_ISSUER_ID: $ASC_ISSUER_ID
    ASC_PRIVATE_KEY_B64: $ASC_PRIVATE_KEY_B64

Security considerations

Workflow files execute arbitrary shell commands. Ensure:
  • .asc/workflow.json is added to .gitignore if it contains secrets
  • Use environment variables for sensitive values
  • Review workflow files before execution
  • Run workflows in trusted environments only

Troubleshooting

Workflow not found

asc workflow list  # List all available workflows
asc workflow run --file .asc/workflow.json testflight  # Specify file explicitly

Environment variable not expanded

Ensure variables are defined in the workflow file or passed via --with:
asc workflow run testflight --with APP_ID=123456789

Step fails silently

Check exit codes and stderr:
asc workflow run testflight --debug

Workflow command

Workflow command reference

Automation guide

Workflow automation patterns