The common action pack (packs:common)
packs:common
opschain-pack-common is the baseline action pack, included in every tier from Basic up: a LimePoint-maintained
monorepo of general-purpose YAML actions — run a committed script, drive a
terraform workspace, run an ansible playbook, dispatch a GitHub Actions
workflow — and a sha-pinned snapshot of it ships inside the binary as a
built-in pack source. Nothing is installed and nothing is fetched: a
.opschain/packs.yaml declaration that names no remote: or url: (or says
bundled: true) resolves against the embedded snapshot — zero setup, fully
offline, the vendored commit as the tested-together floor. The
packs:common entitlement is baseline-unioned: granted on every licence
tier, whatever the applied documents carry, so applying an enterprise licence
can never silently revoke the bundled pack (the baseline-union paragraph of
entitlements). The pack carries a LimePoint-signed pack
manifest at its repository root declaring no required entitlement
(requires empty — it ships in every tier), so no run-creation door
ever gates it.
How the bundle resolves
- A bundle-resolved pack pins with the recognisable marker
bundled://opschain-pack-commonas its remote URL, revbundled, and the vendored commit as its sha — the step preamble and the stored pin both say where the content came from. - A bundled declaration carries no
rev:— the snapshot has exactly one commit, pinned by the release, and declaring one is a named error telling you to remove it or switch to a git source. - After a server upgrade, a pin taken against an older release's snapshot is a named error telling you to refetch the template version (or recreate the change) so it re-pins against this release — never silently different content.
- An explicit
remote:/url:declaration overrides the bundle entirely, for newer pack content between releases; the same monorepo also mirrors onto an internal git host for estates that want to track it directly.
Declaration mechanics, calling conventions (uses: script:execute), the
development loop and the failure modes are the hands-on runbook's territory:
opschain docs getting-started/2-4-using-packs.
The action catalog
Four families, one subdirectory each, every action a typed-input YAML action
executing the pack's own helper scripts (${{ pack.dir }}).
script — the lowest common building block
| Action | Purpose | Key inputs |
|---|---|---|
script:execute | Run a script committed in the calling repository's workspace. | path (required, workspace-relative), args (one shell-tokenised argument string), shell (interpreter override; empty = the script's shebang, then bash). |
Captures both streams by default and publishes stdout, stderr and
exit_status as step outputs, so later steps consume the script's output
without re-running it.
terraform — plan / apply / destroy / output
All four share workspace (required), dir (terraform root, default .)
and backend (default properties: state rides an opschain.files
property entry, conflict-guarded, materialised onto any runner before the
step starts; external leaves state to the repository's own backend block).
All but output also take state_layer (default environment) and, where
relevant, var_file.
| Action | Purpose | Key inputs |
|---|---|---|
terraform:apply | The default posture: plan-and-apply in one step — no handoff. Pass plan_id from a preceding terraform:plan to apply that reviewed planfile instead (the per-change planfile property is applied and then removed). | workspace, plan_id (empty = plan-and-apply), var_file (only when plan_id is empty). |
terraform:plan | The gated-flow half (plan → review/wait → apply): plans to a per-change planfile property and exports its key as the plan_id output. | workspace, var_file. |
terraform:destroy | Tear down the workspace's resources; the script never prompts — gate it with a wait/approval step at the call site. | workspace, var_file. |
terraform:output | Publish terraform output -json as structured step outputs, one per top-level terraform output, sensitive ones sensitive. | workspace. |
ansible — run committed playbooks
| Action | Purpose | Key inputs |
|---|---|---|
ansible:playbook | Run a playbook committed in the calling repository: colourless, promptless, fail-loud ansible-playbook. | playbook (required, workspace-relative), inventory (path or inline host list), extra_vars, limit, tags, check (any non-empty value = --check dry-run). |
github — dispatch and await GitHub Actions runs
Both actions forward the change identity (project, environment, asset,
action, change id) from the step context automatically, find the triggered
run by the change id the target workflow embeds in its run-name, stream
the watch into the step log, and fail loud unless the run concludes
success. Both export run_id and run_url. GH_TOKEN reaches the step
through the opschain.env properties — preferably a github-app://
reference the server redeems as a short-lived just-in-time installation
token at dispatch (opschain docs integrations-github), else a
vault-held PAT.
| Action | Purpose | Key inputs |
|---|---|---|
github:workflow_run | Dispatch a workflow_dispatch workflow and await its conclusion. | workflow (required, file name in the target repo), repo (required, owner/repo), ref (default main), commit_sha, forward_initiated_by ("true" forwards the OpsChain actor as the initiated_by input — the target must declare it). |
github:repo_dispatch | Fire a repository_dispatch event and await the triggered dispatch.yml run. | event (required, the dispatch event type), repo (required), commit_sha. |
Where the core documentation lives
- Mounting, calling and building packs: the action-packs runbook,
opschain docs getting-started/2-4-using-packs. - The signed pack store for commercially distributed packs (the bundled snapshot never needs it): the pack store.
packs:commonand the baseline union: entitlements.