Skip to main content
Version: v5.6.1

8.2 Definitions under change control

Included from Basic tier

After this you can: export and import definitions as backup and change control — one trigger or workflow, or the whole estate — build the zero-secrets support bundle, and treat the OpenAPI document as your integration contract.

Before you start — tick each one:

  • Lesson 3.1 — Your first change (opschain learn 3.1)

In the GUI: the project page's Triggers and Workflows tabs are the definitions this lesson exports; the Diagnostics panel in the Operations area downloads the same redacted support bundle.

Lesson 8.1 kept the server's data recoverable. This lesson keeps its definitions reviewable: in git, diffed between releases, restorable onto a fresh server — plus the two documents that keep a support case and an integration honest.

1. One definition at a time​

Your triggers (lesson 5.2) and workflows (lesson 4.1) live in the server's database — that stays the single source of truth. But their definitions belong in a git repository too. The export/import verbs are that bridge:

mkdir -p backup/triggers backup/workflows
opschain triggers export acme/promote_on_success --out backup/triggers/promote_on_success.yaml
opschain workflows export acme/env_start --out backup/workflows/env_start.yaml
exported trigger acme/promote_on_success to backup/triggers/promote_on_success.yaml
exported workflow acme/env_start to backup/workflows/env_start.yaml

Exports are deterministic — stable key order, trailing newline — so a re-export of an unchanged resource is byte-identical and your backup repo's git diff shows real changes only. Restoring goes through the same authorised create/update path a GUI edit uses:

opschain triggers import acme -f backup/triggers/promote_on_success.yaml
Error: trigger acme/promote_on_success already exists — pass --update to replace its definition from backup/triggers/promote_on_success.yaml
opschain triggers import acme -f backup/triggers/promote_on_success.yaml --update
opschain workflows import acme -f backup/workflows/env_start.yaml --update
updated trigger acme/promote_on_success from backup/triggers/promote_on_success.yaml
  • Without --update, importing an existing code is a named error and writes nothing — safe to run against a server whose state you are unsure of.
  • With --update, a trigger's definition is replaced in place (the document fully replaces the stored definition, defaults included), and a workflow gains its next version — history is never rewritten.
  • Prove a backup round-trips: export → import --update → export again must be byte-identical.

The loop doubles as promotion between servers: export from staging, review the diff, import into production.

2. The whole estate's definitions​

The system-scope cousin moves every definition between estates — each live project subtree plus the records a subtree cannot carry: local users and groups, authorisation rules and policies, the global settings document and scheduled maintenance windows. Secret values are always excluded (git remote credentials, secured settings values, password hashes never travel; secret-vault:// references travel as references). The export needs the source quiesced — the archive must describe a still estate — and the import needs the target not quiesced, because the barrier would refuse the import's own writes:

# on the source
opschain admin platform quiesce --reason "estate export"
opschain admin database export --out estate.zip
opschain admin platform resume
exported the estate to estate.zip (3 project(s))
excluded: git remote credentials, secured settings values, password hashes
# on the target
opschain admin database import estate.zip --into-empty
imported the estate archive into this server:
TYPE CREATED SKIPPED
users 4 0
groups 2 0
authorisation_rules 6 0
policies 3 0
projects 3 0
maintenance_windows 1 0
secrets never travel: re-enter git remote credentials, secured settings values and local user passwords
local users were created with generated passwords — reset each with `opschain admin users reset-password`

Import is ordinary authorised creation on the target: it skips — never overwrites — anything that already exists, and --into-empty asserts the target holds no projects yet and applies the archive's global settings too. Run history, events and artifacts do not travel with an export — they belong to the source estate's backup (lesson 8.1), not to interchange.

3. The support bundle​

When you need help, collect one archive instead of twenty screenshots:

opschain support bundle --server https://opschain.example.com --out bundle.tar.gz
wrote bundle.tar.gz (14 files; secrets redacted, key material excluded)

Your own opschain login session is the credential (then --auth-token / OPSCHAIN_ADMIN_TOKEN / the stored admin token, for automation). The bundle carries the server configuration with every secret value replaced by [REDACTED], a note of which keys exist (names only, never values), the CLI build identity, and live diagnostics: health and readiness, the admin status and queue views, the licence usage report, the runner fleet, recent events and the metrics exposition. The zero-secrets property is test-enforced — no credential, token or key material can reach the bundle. Without --server it degrades gracefully to an offline config-only bundle, and any unfetchable item is recorded as an error file rather than failing the collection.

4. The OpenAPI document: your integration contract​

Everything the CLI has done across these lessons went over the server's HTTP API, and the API describes itself (lesson 0.3):

opschain api spec --out openapi.yaml # the targeted server's document
opschain api spec --local # the copy embedded in this binary
opschain api routes --contains triggers # the route table, filtered
wrote the OpenAPI document to openapi.yaml

Build integrations on the served document, and treat it as the contract it is: the spec is generated from the same route table the server mounts — a route cannot exist without appearing in the document. Against a server, the document is stamped with that server's version (v5.6.1) and commit, so "which API am I actually talking to" is always answerable; --local describes this binary instead, for offline work.

Check yourself​

  • What does a definitions export leave out, and what does the support bundle never contain?
  • Which side of an estate export must be quiesced, and which must not?

What you learned​

  • Trigger and workflow exports are deterministic YAML; import without --update never overwrites.
  • The estate export carries every definition and no secret; import creates, skips the existing, and leaves history behind.
  • The support bundle is redacted by construction and degrades to config-only offline.
  • The OpenAPI document is generated from the route table and stamped with the server's version.

Next: lesson 8.3 — Decommission (opschain learn 8.3), or back to your track (opschain learn).