CI and automation

cademi runs without a terminal in CI pipelines, cron jobs, and containers. Give it a credential through an environment variable, pass --yes to commands that confirm, and read the result from the exit code and the JSON output.

Install a pinned version

Pin the version so every run uses the same CLI, and leave the shell startup files unchanged:

curl -fsSL https://cli.cademi.dev/install.sh | CADEMI_VERSION=0.1.4 CADEMI_NO_MODIFY_PATH=1 bash
export PATH="$HOME/.cademi/bin:$PATH"

In GitHub Actions:

- name: Install cademi
  run: |
    curl -fsSL https://cli.cademi.dev/install.sh | CADEMI_VERSION=0.1.4 CADEMI_NO_MODIFY_PATH=1 bash
    echo "$HOME/.cademi/bin" >> "$GITHUB_PATH"

Automatic updates are off whenever the CI variable is set, which most CI services do, and they never start without a terminal. See Installation.

Credentials

Store the credential secret in your CI secret store and expose it as CADEMI_API_KEY. The CLI then runs in autonomous mode, without profiles or a keychain:

env:
  CADEMI_API_KEY: ${{ secrets.CADEMI_API_KEY }}
  • Use a credential whose auth_mode allows autonomous mode (autonomous or both). A human_required credential cannot be used without an administrator session.
  • Grant it only the permissions the job needs (Permissions and scope).
  • Use sandbox credentials (ck_test_...) for test pipelines (Sandbox).
  • Set CADEMI_BASE_URL only if you call a platform URL other than https://api.cademi.com.br.

Check the setup at the start of the job:

cademi credentials current --jq '.environment'

If CADEMI_API_KEY is empty or not set and the machine has no saved profile, the check exits with code 3, like any other command that needs a credential (Exit codes).

Non-interactive behavior

Without a terminal, the CLI never waits for input:

  • Commands that ask for confirmation (delete commands, cademi config apply, cademi sandbox reset) fail with exit code 2 unless you pass --yes.
  • Responses that would print as a table in a terminal print as JSON.
  • Status messages, warnings, and progress go to standard error. Standard output carries only data.

Reading results

Use --json or --jq to parse output, and the exit code to decide what to do next (Exit codes). With --json, -o json, or --jq, errors also print as JSON on standard error.

product_id=$(cademi products create -f name="Course A" -f format=course -f showcase_id=shw_01J8Z1... --jq .id)
cademi products publications create "$product_id" --wait --wait-timeout 30m

--wait makes the command wait for an asynchronous operation. It exits with 1 if the operation ends as failed or canceled, or if --wait-timeout runs out first. An operation that ends as partially_succeeded exits with 0 and a warning, so check status in the JSON output when partial failures matter. Without --wait, the job continues as soon as the operation is created.

Scripts and agents can describe the whole CLI in one call with cademi commands --json, or cademi commands --brief --json for a smaller index, instead of running --help on each command (Commands).

Safe retries

The CLI retries network errors and 429, 500, 502, 503, and 504 responses on its own, with the same Idempotency-Key (Commands). To make a rerun of a whole job safe as well, derive the key from something stable, such as the pipeline run and step:

cademi users create --idempotency-key "run-${GITHUB_RUN_ID}-create-ana" \
  -f name="Ana Souza" -f [email protected]

A rerun within 48 hours with the same key and the same body returns the stored result instead of creating a second user. See Asynchronous operations, batches, and idempotency.

Configuration as code

Plan on every change and apply on merge:

# review step
cademi config validate catalog.yaml
cademi config plan catalog.yaml --out plan.json

# deploy step
cademi config apply catalog.yaml --yes

cademi config validate exits with code 6 when the manifest is invalid, which fails the review step. cademi config apply computes a fresh plan, so it applies the manifest as it is at deploy time. To apply exactly the reviewed plan instead, pass it with --plan plan.json, within 24 hours and with the same credentials that created it. Pass the manifest as well when the plan contains secrets. See Declarative configuration.

Events in automated tests

cademi listen --forward-to works in CI to deliver events to a service under test. Without a profile, set CADEMI_LISTEN_SECRET so the signing secret matches the one your service expects:

export CADEMI_LISTEN_SECRET=whsec_local_...
cademi listen --forward-to localhost:3000/webhooks/cademi --json > events.jsonl &
cademi sandbox run scn_01J8Z3...

Unless you pass --replay, cademi listen receives only the events emitted after its event stream is created. Start it before the step that produces events, and wait for its Ready! line on standard error. See Events with cademi listen.

On this page