Production Deploy
CLI Deployment Entry Point
The onestep CLI is the production deployment entry point.
Recommended Module Structure
# tasks.py
from onestep import IntervalSource, OneStepApp
app = OneStepApp("billing-sync")
@app.task(source=IntervalSource.every(hours=1, immediate=True, overlap="skip"))
async def sync_billing(ctx, _):
print("syncing billing data")Running the Application
# Standard run
onestep run your_package.tasks:app
# Shorthand
onestep your_package.tasks:app
# Check configuration
onestep check your_package.tasks:app
# JSON output (suitable for CI/CD)
onestep check --json your_package.tasks:app
# Render the worker topology (Mermaid diagram)
onestep render your_package.tasks:apponestep run writes INFO-level application logs and task lifecycle events to stdout by default, suitable for ingestion by systemd, Docker, or log collectors. Use --log-level DEBUG to see more detailed fetched, started, and sink-success events, or --no-task-events to disable automatic task events. Full rules are documented in Logging & Task Events.
Render the Worker Topology
onestep render prints the topology of any Python or YAML target as a Mermaid flowchart, ready to paste into GitHub READMEs, Notion, or Obsidian:
onestep render worker.yaml # mermaid by default
onestep render pkg.tasks:app --format mermaidgraph LR
%% app: billing-sync
n0["extract_entities<br/>concurrency=4 · retry=NoRetry · timeout=300s"]
n1["sqs-orders<br/>MemoryQueue"]
n2["audit-log<br/>MemoryQueue"]
n3["mysql.meta_sink<br/>MemoryQueue"]
n1 --> n0
n0 -->|"emit"| n2
n0 -->|"when app.predicates:is_valid · app.transforms:to_meta"| n3Task nodes carry concurrency, retry policy, and timeout; edges are labeled emit (plus the transform ref when a binding sets one), when/otherwise for conditional routes, and dashed dead_letter edges. Resources shared across tasks are drawn once, so chained topologies render as connected graphs. YAML targets also support --env-file and --strict-env.
systemd Deployment
Complete deployment templates are available at:
deploy/README.mddeploy/systemd/onestep-app.servicedeploy/env/onestep-app.env.exampledeploy/bin/onestep-preflight.sh
Installation Steps
# Create configuration directory
sudo mkdir -p /etc/onestep
# Copy environment variable template
sudo cp deploy/env/onestep-app.env.example /etc/onestep/onestep-app.env
# Copy systemd service file
sudo cp deploy/systemd/onestep-app.service /etc/systemd/system/onestep-app.service
# Reload systemd
sudo systemctl daemon-reload
# Enable and start the service
sudo systemctl enable --now onestep-appViewing Status and Logs
# Check service status
sudo systemctl status onestep-app
# View logs
sudo journalctl -u onestep-app -fEnvironment Variables
Key configuration variables:
| Variable | Description |
|---|---|
APP_CWD | Application working directory |
PYTHONPATH | Python module search path |
The deployment template automatically adds APP_CWD to PYTHONPATH, ensuring modules within the repository can be imported correctly.
YAML Configuration
Supports YAML application definitions with handler.ref pointing to Python callables:
app:
name: billing-sync
resources:
tick:
type: interval
minutes: 5
immediate: true
processed:
type: memory
tasks:
- name: sync_billing
source: tick
handler:
ref: your_package.handlers.billing:sync_billing
params:
region: cn
emit: [processed]
retry:
type: max_attempts
max_attempts: 3
delay_s: 10Run a YAML application:
onestep check worker.yaml
onestep run worker.yamlTo upload to a worker agent or control plane, build a deployable zip first:
onestep build worker.yaml --strict --out dist/worker.zipContainer deployment can use the official worker runtime image. The image adds the workspace to PYTHONPATH, installs project dependencies, runs onestep check, then starts onestep run:
docker run --rm \
-e ONESTEP_TARGET=/workspace/worker.yaml \
-v "$PWD:/workspace" \
ghcr.io/mic1on/onestep-worker:1.11.0See Worker Runtime Image for details.
Production Recommendations
State Persistence
For production, use db.cursor_store(...) or db.state_store(...) to ensure cursor and task state persists across process restarts:
from onestep_mysql import MySQLConnector
db = MySQLConnector("mysql+pymysql://...")
state = db.cursor_store(table="onestep_cursor")
source = db.incremental(
table="users",
key="id",
cursor=("updated_at", "id"),
state=state, # persist cursor
)Graceful Shutdown
Configure a shutdown timeout to ensure in-flight tasks have enough time to complete:
app = OneStepApp("my-app", shutdown_timeout_s=30.0)Next Steps
- RabbitMQ - distributed message queue
- Redis Streams - lightweight message queue
- MySQL - database integration
- PostgreSQL - PostgreSQL integration
- Kafka - Kafka topic source/sink
- Worker Runtime Image - containerized YAML workers