English | 日本語
A powerful YAML-based workflow automation tool designed for testing, monitoring, and automation tasks. Probe uses plugin-based actions to execute workflows, making it highly flexible and extensible.
name: API Health Check
jobs:
- name: Check API Status
steps:
- name: Ping API
uses: http
with:
url: https://api.example.com
get: /health
test: res.code == 200
probe health-check.yml
- Simple YAML Syntax: Easy-to-read workflow definitions
- Plugin Architecture: Built-in HTTP, Database, Browser, Shell, SSH, SMTP, IMAP, and Hello actions with extensibility
- Job Dependencies: Control execution order with
needs
- Step Outputs: Share data between steps and jobs using
outputs
- Repetition: Repeat jobs with configurable intervals
- Iteration: Execute steps with different variable sets
- Expression Engine: Powerful templating and condition evaluation
- Testing Support: Built-in assertion system
- Timing Controls: Wait conditions and delays
- Rich Output: Buffered, consistent output formatting
- Security: Safe expression evaluation with timeout protection
go install github.com/linyows/probe/cmd/probe@latest
git clone https://github.com/linyows/probe.git
cd probe
go build -o probe ./cmd/probe
# Run a workflow
probe ./workflow.yml
# Verbose output
probe ./workflow.yml --verbose
# Show response times
probe ./workflow.yml --rt
<workflow>
: Specify YAML workflow file path--verbose
: Enable detailed output--rt
: Show response times--help
: Show help information
name: Workflow Name
description: Optional description
vars:
global_var: value
jobs:
- name: Job Name
steps:
- name: Step Name
uses: action_name
with:
param: value
Jobs are executed in parallel by default. Use needs
for dependencies:
jobs:
- name: Setup
id: setup
steps:
- name: Initialize
uses: http
with:
post: /setup
- name: Test
needs: [setup] # Wait for setup to complete
steps:
- name: Run test
uses: http
with:
get: /test
Steps within a job execute sequentially:
steps:
- name: Login
id: login
uses: http
with:
post: /auth/login
body:
username: admin
password: secret
outputs:
token: res.body.token
- name: Get Profile
uses: http
with:
get: /profile
headers:
authorization: "Bearer {{outputs.login.token}}"
test: res.code == 200
Use {{expression}}
syntax for dynamic values:
vars:
api_url: https://api.example.com
user_id: 123
steps:
- name: Get User
uses: http
with:
url: "{{vars.api_url}}"
get: "/users/{{vars.user_id}}"
test: res.body.id == vars.user_id
test: |
res.code == 200 &&
match_json(res.body, vars.expected) &&
random_int(10) > 5
Available functions:
match_json(actual, expected)
: JSON pattern matching with regex supportdiff_json(actual, expected)
: Show differences between JSON objectsrandom_int(max)
: Generate random integerrandom_str(length)
: Generate random stringunixtime()
: Current Unix timestamp
Share data between steps and jobs:
- name: Get Token
id: auth
uses: http
with:
post: /auth
outputs:
token: res.body.access_token
expires: res.body.expires_in
- name: Use Token
uses: http
with:
get: /protected
headers:
authorization: "Bearer {{outputs.auth.token}}"
Execute steps with different variable sets:
- name: Test Multiple Users
uses: http
with:
post: /users
body:
name: "{{vars.name}}"
role: "{{vars.role}}"
test: res.code == 201
iteration:
- {name: "Alice", role: "admin"}
- {name: "Bob", role: "user"}
- {name: "Carol", role: "editor"}
Repeat entire jobs with intervals:
- name: Health Check
repeat:
count: 10
interval: 30s
steps:
- name: Ping
uses: http
with:
get: /health
test: res.code == 200
Skip steps based on conditions:
- name: Conditional Step
uses: http
with:
get: /api/data
skipif: vars.skip_test == true
test: res.code == 200
- name: Wait and Check
uses: http
with:
get: /status
wait: 5s # Wait before execution
test: res.code == 200
- name: HTTP Request
uses: http
with:
url: https://api.example.com
# GET, POST, PUT, DELETE, etc.
post: /
headers:
content-type: application/json
authorization: Bearer token
body:
key: value
timeout: 30s
- name: Send Email
uses: smtp
with:
addr: smtp.example.com:587
from: [email protected]
to: [email protected]
subject: Test Email
body: Email content
my-hostname: localhost
- name: Database Query
uses: db
with:
dsn: "mysql://user:password@localhost:3306/database"
query: "SELECT * FROM users WHERE active = ?"
params: [true]
timeout: 30s
test: res.code == 0 && res.rows_affected > 0
Supported databases:
- MySQL:
mysql://user:pass@host:port/database
- PostgreSQL:
postgres://user:pass@host:port/database?sslmode=disable
- SQLite:
file:./testdata/sqlite.db
or/absolute/path/database
- name: Web Automation
uses: browser
with:
action: navigate
url: "https://example.com"
headless: true
timeout: 30s
test: res.success == "true"
Supported actions:
- navigate: Navigate to URL
- text: Extract text content from elements
- value: Get input field values
- get_attribute: Get element attribute values
- get_html: Extract HTML content from elements
- click: Click on elements
- double_click: Double-click on elements
- right_click: Right-click on elements
- hover: Hover over elements
- focus: Set focus to elements
- type / send_keys: Type text into input fields
- select: Select dropdown options
- submit: Submit forms
- scroll: Scroll elements into view
- screenshot: Capture element screenshots
- capture_screenshot: Capture full page screenshots
- full_screenshot: Capture full page screenshots with quality settings
- wait_visible: Wait for elements to become visible
- wait_not_visible: Wait for elements to become invisible
- wait_ready: Wait for page to be ready
- wait_text: Wait for specific text to appear
- wait_enabled: Wait for elements to become enabled
- name: Run Build Script
uses: shell
with:
cmd: "npm run build"
workdir: "/app"
shell: "/bin/bash"
timeout: "5m"
env:
NODE_ENV: production
test: res.code == 0 && (res.stdout | contains("Build successful"))
- name: Deploy Application
uses: ssh
with:
host: "prod.example.com"
port: 22
user: "deploy"
# Authentication methods (use either password or key_file)
password: "secure_password"
# key_file: "~/.ssh/deploy_key"
# key_passphrase: "key_passphrase" # if key is encrypted
cmd: |
cd /opt/myapp
git pull origin main
systemctl restart myapp
timeout: "300s"
workdir: "/opt/myapp"
# Environment variables
env:
DEPLOY_ENV: production
APP_VERSION: v1.2.3
# Security settings
strict_host_check: true
known_hosts: "~/.ssh/known_hosts"
test: res.code == 0 && !contains(res.stderr, "error")
- name: Email Operations
uses: imap
with:
host: "imap.example.com"
port: 993
username: "[email protected]"
password: "password"
tls: true
timeout: 30s
strict_host_check: true
insecure_skip_tls: false
commands:
- name: "select"
mailbox: "INBOX"
- name: "search"
criteria:
since: "today"
flags: ["unseen"]
- name: "fetch"
sequence: "*"
dataitem: "ALL"
test: res.code == 0 && res.data.search.count > 0
Supported IMAP commands:
- select: Select a mailbox for read-write operations
- examine: Select a mailbox for read-only operations
- search: Search messages using criteria
- uid search: Search using UID instead of sequence numbers
- list: List available mailboxes
- fetch: Fetch message data
- uid fetch: Fetch using UID instead of sequence numbers
- store: Store message flags (basic implementation)
- uid store: Store using UID (basic implementation)
- copy: Copy messages to another mailbox (basic implementation)
- uid copy: Copy using UID (basic implementation)
- create: Create a new mailbox
- delete: Delete a mailbox
- rename: Rename a mailbox
- subscribe: Subscribe to a mailbox
- unsubscribe: Unsubscribe from a mailbox
- noop: No operation (keepalive)
Search criteria support:
- seq_nums: Sequence number ranges (e.g., "1:10", "*")
- uids: UID ranges for UID search commands
- since: Messages received since date ("today", "yesterday", "2024-01-01", "1 hour ago")
- before: Messages received before date
- sent_since: Messages sent since date
- sent_before: Messages sent before date
- headers: Header field matches (e.g., {"from": "[email protected]"})
- bodies: Body text contains
- texts: Text (headers + body) contains
- flags: Message flags (e.g., ["seen", "answered"])
- not_flags: Messages without these flags
- name: Test Action
uses: hello
with:
name: World
name: User API Test
vars:
base_url: https://api.example.com
admin_token: "{{env.ADMIN_TOKEN}}"
jobs:
- name: User CRUD Operations
defaults:
http:
url: "{{vars.base_url}}"
headers:
authorization: "Bearer {{vars.admin_token}}"
content-type: application/json
steps:
- name: Create User
id: create
uses: http
with:
post: /users
body:
name: Test User
email: [email protected]
test: res.code == 201
outputs:
user_id: res.body.id
- name: Get User
uses: http
with:
get: "/users/{{outputs.create.user_id}}"
test: |
res.code == 200 &&
res.body.name == "Test User"
- name: Update User
uses: http
with:
put: "/users/{{outputs.create.user_id}}"
body:
name: Updated User
test: res.code == 200
- name: Delete User
uses: http
with:
delete: "/users/{{outputs.create.user_id}}"
test: res.code == 204
name: Load Test
jobs:
- name: Concurrent Requests
repeat:
count: 100
interval: 100ms
steps:
- name: API Call
uses: http
with:
url: https://api.example.com
get: /endpoint
test: res.code == 200
name: E2E Test
jobs:
- name: Setup Database
id: db-setup
steps:
- name: Initialize
uses: http
with:
post: http://db-service/init
- name: API Tests
needs: [db-setup]
steps:
- name: Test API
uses: http
with:
get: http://api-service/data
test: res.code == 200
- name: Cleanup
needs: [db-setup]
steps:
- name: Reset Database
uses: http
with:
post: http://db-service/reset
vars.*
: Workflow and step variables (including environment variables defined in vars)res.*
: Previous step responsereq.*
: Previous step requestoutputs.*
: Step outputs
res:
code: 200
status: "200 OK"
headers:
content-type: application/json
body: {...} # Parsed JSON or raw string
rawbody: "..." # Original response body
- Arithmetic:
+
,-
,*
,/
,%
- Comparison:
==
,!=
,<
,<=
,>
,>=
- Logical:
&&
,||
,!
- Ternary:
condition ? true_value : false_value
Probe supports custom actions through Protocol Buffers. Create your own actions to extend functionality beyond the built-in HTTP, SMTP, and Hello actions.
- Environment variables can be accessed by defining them in the root
vars
section
Use YAML anchors for common configurations:
x_defaults: &api_defaults
http:
url: https://api.example.com
headers:
authorization: Bearer token
jobs:
- name: Test Job
defaults: *api_defaults
Expression Evaluation Errors
- Check syntax:
{{expression}}
not{expression}
- Verify variable names and paths
- Use quotes around string values
HTTP Action Issues
- Verify URL format and accessibility
- Check headers and authentication
- Review timeout settings
Job Dependencies
- Ensure job IDs are unique
- Check
needs
references - Avoid circular dependencies
Use --verbose
flag for detailed execution information:
probe test.yml --verbose
- Use descriptive names for workflows, jobs, and steps
- Leverage outputs for data sharing between steps
- Implement proper testing with meaningful assertions
- Use defaults to reduce repetition
- Structure workflows logically with clear dependencies
- Handle errors gracefully with appropriate tests
- Use variables for configuration management
Common questions about Probe.
While CWL and WDL are powerful workflow languages designed for scientific computing and bioinformatics with complex data processing pipelines, Probe takes a different approach by specializing in web-based use cases.
Key Differences:
- Target Use Cases: CWL focuses on scientific data processing with Docker-based distributed execution, while WDL targets genomics pipelines with strong type systems and cloud-based distributed computing. Probe is designed specifically for API monitoring, test automation, and operational tasks.
- Internet Protocol Focus: Probe specializes in web use cases, providing built-in support for HTTP, SMTP, SSH, IMAP, and browser automation. This specialization allows you to define and execute workflows with minimal configuration for internet protocol-based tasks.
- Simplicity vs. Flexibility: While Probe offers less general-purpose flexibility compared to CWL or WDL, this is an intentional design choice. By focusing on web and internet protocols, Probe dramatically improves productivity in its target domain. The plugin-based architecture using Protocol Buffers still allows for extensibility when needed.
- Execution Model: Unlike CWL and WDL which are designed for distributed computing environments, Probe is optimized for lightweight, local execution with real-time monitoring capabilities.
- Syntax: Probe uses intuitive YAML-based configuration instead of the more complex type systems found in CWL and WDL, making it accessible to operations teams and developers working with web services.
Probe's value lies in providing the most efficient path for web-based automation tasks while maintaining the ability to extend functionality through custom actions when necessary. For more examples and advanced usage, check the examples directory.
We welcome contributions! Please feel free to submit issues, feature requests, or pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.