Fob
Browse the docs

Get started

This walks you from an empty folder to a step that runs on your machine with fob-worker, then on the Orchestrator through your own worker. The example step checks invoices against an approval limit.

You'll need:

  • Node.js 18 or later and git.
  • An Orchestrator account for parts 5 and 6: sign up, then open the Orchestrator and create an organisation. Parts 1 to 4 work without one.

1. Install the CLIs#

npm install -g @finopsbricks/fob-worker @finopsbricks/fob-orc

See Install fob-worker for details and shell completion.

2. Create a worker repo from the template#

git clone https://github.com/finopsbricks/worker-template.git worker-acme
cd worker-acme
rm -rf .git && git init

The template has placeholders. Replace them with your organisation's short name (here acme); on macOS:

grep -rl '{{' . --include='*.js' --include='*.json' --include='*.md' | xargs sed -i '' \
  -e 's/{{ORG_NAME}}/acme/g' -e 's/{{LOCATION}}/acme/g' \
  -e 's/{{WORKER_NAME}}/worker-acme/g' -e 's/{{WORKER_DESCRIPTION}}/Worker for acme/g'

On Linux, use sed -i instead of sed -i ''. Then install:

cp .env.example .env
npm install

npm install fetches lib-worker from GitHub. You fill in .env in part 5.

3. Write a step#

A step is a file under src/steps/ that exports defineStep(). Create this file:

src/steps/IN1__check_invoices/IN1_01_check.js
import { defineStep } from '@fob/lib-worker';
import { z } from 'zod';

export default defineStep({
  slug: 'IN1_01_check',
  name: 'Check invoices',
  description: 'Flags invoices above the approval limit',
  inputSchema: z.object({
    approval_limit: z.number().default(5000),
    invoices: z.array(z.object({ number: z.string(), amount: z.number() })).default([]),
  }),
  outputSchema: z.object({ checked: z.number(), above_limit: z.array(z.string()) }),
  execute: async (config) => {
    const above_limit = config.invoices
      .filter((invoice) => invoice.amount > config.approval_limit)
      .map((invoice) => invoice.number);
    return { checked: config.invoices.length, above_limit };
  },
});

name and description are required. The folder name IN1__check_invoices is a convention (station short code, then a name); the slug is what identifies the step. See Write steps.

4. Run it on your machine#

fob-worker steps list
SLUG          FOLDER               FILE
-------------------------------------------------------------
IN1_01_check  IN1__check_invoices  IN1_01_check.js

Total: 1 steps

Save a test config as a scenario, in this file:

.orchestrator/scenarios/IN1_01_check/two-invoices.json
{
  "invoices": [
    { "number": "INV-1001", "amount": 1250 },
    { "number": "INV-1002", "amount": 7400 }
  ]
}

And run the step with it:

fob-worker steps run IN1_01_check --scenario two-invoices
Step: IN1_01_check
Config: scenario: two-invoices
…
Output:
------------------------------------------------------------
{
  "checked": 2,
  "above_limit": [
    "INV-1002"
  ]
}

   Output saved: temp/IN1_01_check.json
Step completed successfully

Edit the step, run it again. That's the loop fob-worker is for. Run steps locally covers configs, chaining steps and debugging.

5. Connect to the Orchestrator#

In your organisation in the Orchestrator, open Settings → API Keys and create a key for this worker. Copy the secret; it's shown once.

Fill in .env:

ORCHESTRATOR_URL=https://orchestrator.finopsbricks.com
ORCHESTRATOR_API_KEY=fob_orc_…
ORCHESTRATOR_API_SECRET=…
WORKER_LOCATION=acme

WORKER_LOCATION names where this worker runs. The Orchestrator sends a line's steps to the worker whose location matches the line's.

Give fob-orc the same key, as a profile:

fob-orc config profiles add acme --api-url https://orchestrator.finopsbricks.com \
  --api-key fob_orc_… --api-secret …
fob-orc status

.env is in the template's .gitignore. Don't commit it.

6. Run the station on the Orchestrator#

Describe the line and station as files. .orchestrator/lines/IN.json:

{ "code": "IN", "name": "Invoice checks", "location": "acme" }

And the station, in this file:

.orchestrator/stations/IN1__check_invoices.json
{
  "short_code": "IN1",
  "line": "IN",
  "name": "check_invoices",
  "is_enabled": true,
  "steps": [
    {
      "slug": "IN1_01_check",
      "config": { "approval_limit": 5000, "invoices": [{ "number": "INV-1001", "amount": 1250 }] }
    }
  ]
}

Push both, start the worker, and trigger a run:

fob-orc lines push --all
fob-orc stations push --all
fob-worker procs start          # or: npm start, in another terminal
fob-orc stations run IN1

The worker picks up the step within a couple of seconds. Check the result with fob-orc work-records list or in the Orchestrator. fob-worker procs logs shows the worker's output; fob-worker procs stop stops it.

procs needs pm2 (npm install -g pm2). See Run your worker in the background.

Next#