Skip to Content

Complex scenarios, as one workflow.

Probe runs workflows defined in YAML. The definition looks like GitHub Actions, and the actions come built in: HTTP, DB, Shell, SSH, gRPC, SMTP, IMAP, Browser. The result of an action can be checked, so the same file serves for testing and monitoring too.

An example sign-up scenario

Create accounthttpPost the formDatabasedbRow is pendingMailboximapConfirmation arrivedActivatehttpFollow the link

Create account posts the form and publishes the id that comes back. Database and Mailbox both depend on it, so Probe runs them at the same time — one asks SQLite for the row, the other opens the mailbox over IMAP. Activate waits for both before following the confirmation link.

signup-flow.yml
1name: Sign-up Flow2 3vars:4  api: https://api.example.com5  mail_user: ada@example.com6  mail_pass: "{{MAIL_PASS}}"7 8jobs:9- name: Create account10  id: signup11  defaults:12    http:13      url: "{{vars.api}}"14  steps:15  - name: Post the form16    id: create17    uses: http18    with:19      post: /signup20    test: res.code == 201 && res.body.status == "pending"21    outputs:22      user_id: res.body.id23 24- name: Database25  id: db26  needs: [signup]27  defaults:28    db:29      dsn: file:./app.db30  steps:31  - name: Row is pending32    uses: db33    with:34      query: SELECT status FROM users WHERE id = ?35      params: ["{{outputs.create.user_id}}"]36    test: res.code == 0 && res.rows[0].status == "pending"37 38- name: Mailbox39  id: mailbox40  needs: [signup]41  defaults:42    imap:43      host: imap.example.com44      username: "{{vars.mail_user}}"45      password: "{{vars.mail_pass}}"46  steps:47  - name: Confirmation arrived48    uses: imap49    with:50      commands:51      - name: select52        mailbox: INBOX53      - name: fetch54        sequence: "1"55        dataitem: ALL56    test: |57      res.code == 0 &&58      res.data.fetch.messages[0].subject == "Confirm your address" &&59      res.data.fetch.messages[0].to == vars.mail_user60 61- name: Activate62  needs: [db, mailbox]63  defaults:64    http:65      url: "{{vars.api}}"66  steps:67  - name: Follow the link68    uses: http69    with:70      get: "/users/{{outputs.create.user_id}}"71    test: res.code == 200 && res.body.status == "active"
$ probe signup-flow.yml
Sign-up Flow ⏺ Create account (Completed in 0.11s)  ⎿ 0. ✓  Post the form ⏺ Database (Completed in 0.02s)  ⎿ 0. ✓  Row is pending ⏺ Mailbox (Completed in 0.03s)  ⎿ 0. ✓  Confirmation arrived ⏺ Activate (Completed in 0.01s)  ⎿ 0. ✓  Follow the link Total workflow time: 0.15s ✓ All jobs succeeded

What a workflow is made of

A workflow is a set of jobs, and a job is a sequence of steps. Steps run one after another, in the order you wrote them. Jobs run in parallel by default; only the ones with needs wait for what they depend on. Add repeat to a job and the same file runs on an interval and reports a success rate.

WorkflowneedsJobStepStepStepJobStepStepJobStep
Read the jobs and steps guide

Supported actions

A step names an action in uses, and Probe starts that action as its own process and talks to it over gRPC. The built-in actions go through exactly the same handshake an out-of-tree plugin does, so none of them is a special case. What Probe cannot reach yet, you can add.

gRPCprobeworkflow runnerBuilt inhttpdbbrowsershellsshsmtpimapgrpcembeddedYoursgraphqljmap
Read the actions reference

What a step can say

Whatever action a step names, these fields are available to it.

test

A step passes when the expression is true. Everything about the response is in scope.

yaml
1test: res.code == 200 && res.body.status == "ok"

outputs

Name a value once, then read it from any later step or job.

yaml
1outputs:2  token: res.body.access_token

iteration

Run one step once per set of variables, without copying it.

yaml
1iteration:2- {name: Alice, role: admin}3- {name: Bob, role: user}

retry

Give a flaky step another go, after a pause.

yaml
1retry:2  max_attempts: 33  interval: 5s

skipif

Leave the step out when the condition holds.

yaml
1skipif: vars.env == "local"

wait

Pause before the step runs, for whatever has to settle first.

yaml
1wait: 5s

Install

Probe is a single Go binary with no runtime dependencies.

$ go install github.com/linyows/probe/cmd/probe@latest

Or build from source

git clone https://github.com/linyows/probe.git
cd probe
go build -o probe ./cmd/probe
Read the installation guide