State Management
Plexr provides powerful state management capabilities to share data between steps, track execution progress, and maintain workflow context.
Overview
State in Plexr is a key-value store that persists throughout the execution of a plan. It allows steps to:
- Share data with subsequent steps
- Store execution results
- Make conditional decisions
- Track workflow progress
State File
Plexr stores state in .plexr/state.json in your project directory:
{
"variables": {
"version": "1.2.3",
"build_id": "abc123",
"environment": "production"
},
"steps": {
"build": {
"status": "completed",
"start_time": "2024-01-20T10:00:00Z",
"end_time": "2024-01-20T10:05:00Z",
"outputs": {
"artifact_path": "/dist/app.tar.gz"
}
}
}
}Setting State Variables
From Command Output
Capture command output into state variables:
steps:
- name: "Get version"
command: "git describe --tags --always"
outputs:
- name: version
from: stdoutFrom JSON Output
Parse JSON output and extract specific fields:
steps:
- name: "Get build info"
command: "npm run build --json"
outputs:
- name: build_id
from: stdout
json_path: "$.buildId"
- name: build_time
from: stdout
json_path: "$.timestamp"Using Regular Expressions
Extract data using regex patterns:
steps:
- name: "Parse deployment URL"
command: "deploy.sh"
outputs:
- name: app_url
from: stdout
regex: "Deployed to: (https://.*)"
regex_group: 1Multiple Outputs
Capture multiple values from a single step:
steps:
- name: "System info"
command: |
echo "OS: $(uname -s)"
echo "Arch: $(uname -m)"
echo "Host: $(hostname)"
outputs:
- name: os
from: stdout
regex: "OS: (.*)"
- name: arch
from: stdout
regex: "Arch: (.*)"
- name: hostname
from: stdout
regex: "Host: (.*)"Using State Variables
Variable Substitution
Reference state variables using Go template syntax:
steps:
- name: "Build with version"
command: "docker build -t myapp:`{{.version}}` ."
- name: "Deploy"
command: "kubectl set image deployment/app app=myapp:`{{.version}}`"Default Values
Provide defaults for missing variables:
steps:
- name: "Configure environment"
command: "setup.sh"
env:
ENVIRONMENT: "`{{.environment | default \"development\"}}`"
DEBUG: "`{{.debug | default \"false\"}}`"Conditional Logic
Use state variables in conditions:
steps:
- name: "Production deployment"
command: "deploy-prod.sh"
condition: '`{{.environment}}` == "production" && `{{.tests_passed}}` == "true"'Advanced State Management
Nested Variables
Work with complex data structures:
steps:
- name: "Get config"
command: "cat config.json"
outputs:
- name: config
from: stdout
json_parse: true
- name: "Use nested config"
command: "connect.sh"
env:
DB_HOST: "`{{.config.database.host}}`"
DB_PORT: "`{{.config.database.port}}`"Arrays and Loops
Handle array data:
steps:
- name: "Get services"
command: "kubectl get services -o json"
outputs:
- name: services
from: stdout
json_path: "$.items[*].metadata.name"
- name: "Process services"
command: "check-service.sh `{{.service}}`"
for_each:
items: "`{{.services}}`"
var: serviceState Mutations
Transform state variables:
steps:
- name: "Increment version"
command: |
current=`{{.build_number | default "0"}}`
echo $((current + 1))
outputs:
- name: build_number
from: stdoutState Persistence
Saving State
State is automatically saved after each step. You can also manually checkpoint:
steps:
- name: "Critical operation"
command: "important-task.sh"
save_state: true # Force immediate state saveLoading Previous State
Continue from a previous execution:
# Resume from last state
plexr execute --resume
# Load specific state file
plexr execute --state-file backup-state.jsonResetting State
Clear all state data:
# Reset state for current plan
plexr reset
# Reset and remove state file
plexr reset --cleanState Scoping
Global Variables
Set variables available to all steps:
vars:
project_name: "myapp"
region: "us-east-1"
steps:
- name: "Deploy"
command: "deploy.sh `{{.project_name}}` `{{.region}}`"Step-Local Variables
Variables scoped to specific steps:
steps:
- name: "Build variants"
parallel:
- name: "Build debug"
command: "build.sh"
env:
BUILD_TYPE: "debug"
- name: "Build release"
command: "build.sh"
env:
BUILD_TYPE: "release"Environment Variable Integration
Mix environment and state variables:
steps:
- name: "Deploy"
command: "deploy.sh"
env:
APP_VERSION: "`{{.version}}`" # From state
API_KEY: "${DEPLOY_API_KEY}" # From environmentState Templates
String Manipulation
steps:
- name: "Format message"
command: |
echo "`{{.message | upper}}`"
echo "`{{.path | base}}`"
echo "`{{.text | replace \" \" \"_\"}}`"Arithmetic Operations
steps:
- name: "Calculate"
command: |
echo "Total: `{{add .value1 .value2}}`"
echo "Difference: `{{sub .value1 .value2}}`"Date and Time
steps:
- name: "Timestamp"
command: "echo `{{now | date \"2006-01-02 15:04:05\"}}`"
outputs:
- name: build_time
from: stdoutBest Practices
1. Variable Naming
Use clear, descriptive names:
# Good
outputs:
- name: docker_image_tag
- name: deployment_url
- name: test_coverage_percent
# Avoid
outputs:
- name: tag
- name: url
- name: coverage2. State Validation
Validate state before using:
steps:
- name: "Check prerequisites"
command: |
if [ -z "`{{.api_key}}`" ]; then
echo "Error: api_key not set"
exit 1
fi3. State Documentation
Document expected state variables:
# This plan expects the following variables:
# - environment: Target environment (dev, staging, prod)
# - version: Application version to deploy
# - region: AWS region for deployment
requires:
- environment
- version
- region4. State Cleanup
Clean sensitive data:
steps:
- name: "Cleanup secrets"
command: "echo ''"
outputs:
- name: api_key
value: "" # Clear sensitive data
always_run: trueDebugging State
View Current State
# Show all state
plexr status
# Show specific variable
plexr status --var version
# Export state as JSON
plexr status --json > state-backup.jsonState History
Track state changes:
steps:
- name: "Log state change"
command: |
echo "Previous: `{{.version | default \"none\"}}`"
echo "New: `{{.new_version}}`"
debug: trueInteractive State Updates
Modify state during development:
# Set variable
plexr state set version "1.2.3"
# Remove variable
plexr state unset debug_mode
# Import state
plexr state import < custom-state.jsonCommon Patterns
Feature Flags
vars:
features:
new_ui: true
beta_api: false
steps:
- name: "Deploy with features"
command: "deploy.sh"
env:
ENABLE_NEW_UI: "`{{.features.new_ui}}`"
ENABLE_BETA_API: "`{{.features.beta_api}}`"Build Matrix
vars:
platforms: ["linux", "darwin", "windows"]
architectures: ["amd64", "arm64"]
steps:
- name: "Build matrix"
command: "build.sh -os `{{.platform}}` -arch `{{.arch}}`"
for_each:
platforms: "`{{.platforms}}`"
architectures: "`{{.architectures}}`"
as:
platform: platform
arch: archWorkflow State Machine
steps:
- name: "Check state"
command: "get-workflow-state.sh"
outputs:
- name: workflow_state
- name: "Process pending"
command: "process.sh"
condition: '`{{.workflow_state}}` == "pending"'
- name: "Handle error"
command: "error-handler.sh"
condition: '`{{.workflow_state}}` == "error"'