@operacloud/action-cli
v0.1.1
Published
opera-action — author, check and run an Opera action locally. No Opera account required.
Downloads
162
Maintainers
Readme
opera-action
Author an Opera action on your laptop — scaffold it, validate it, and run it for real in the production runner image — without pushing anything or signing in.
npx @operacloud/[email protected] init --id yourteam/restart-web-tierWhat this is
Opera is a governed cloud-operations control plane: it runs operational scripts against your cloud with approvals, least-privilege short-lived credentials, an allowlisted network, and a full audit trail.
An action is the unit it runs — a script, plus a declaration of what that script is allowed to do: which parameters it takes, which cloud permissions it needs, whether it can reach the network, how risky it is, and whether it can be rolled back.
opera-action is the local half of that. It scaffolds an action that already works, validates
it with the same validator the server runs, and executes a phase inside the same container
image production uses. Three of its four commands need no Opera account and no network.
Why it exists. Before this, writing an action meant: create a Git repo, install a GitHub
App, hand-write a 25-field manifest and a parameter schema, push, import, and discover your
mistakes in production. The first real package took five review cycles — and the defect that
blocked it (a PowerShell variable followed by ?, which reads as a variable named Name?,
expands to nothing, and silently drops the value) was found in two minutes by running the
script outside the platform. Nothing in the product offered that. This does.
Requirements
- Node.js 20 or newer — for
init,checkandpublish. - Docker — for
testonly. - An Opera account — for
publishonly.
Install
npx @operacloud/[email protected] <command> # no install
npm install -g @operacloud/action-cli # or install the `opera-action` binPin the version your Opera deployment shows you on its Author page rather than tracking
@latest — the CLI validates against a contract that ships with the control plane.
The four verbs
| | | Needs |
| --- | --- | --- |
| init [dir] | Scaffold a working action. It passes check and test immediately. | — |
| check | Validate it. Offline — no network, no cloud, no account. | — |
| test | Run one phase in the real Opera runner image. | Docker |
| publish | Upload it as an authored version. | An account |
opera-action --help lists every flag.
A worked example
Scaffold a PowerShell action, look at what you got, validate it, and run it locally:
$ npx @operacloud/[email protected] init restart-web-tier \
--id acme/restart-web-tier \
--interpreter powershell \
--yes
restart-web-tier/
action.yaml the declaration: parameters, permissions, risk, rollback
run/main.ps1 what actually runs
README.md
$ cd restart-web-tier
$ opera-action check
check /home/you/restart-web-tier
✓ No problems found.
$ export OPERA_RUNNER_IMAGE=<the image your Opera runs> # the Author page shows it
$ opera-action test --phase run --param resourceGroup=rg-prod --dry-runtest writes result.json the way a real run does, and validates it with the control plane's
own validator — so a result Opera would reject fails on your laptop first.
init
Asks for three things, because nothing else needs a decision: the id, a display name, and the
interpreter (powershell / bash / python). Everything else gets a safe default — risk level
high, no rollback, no network, no secrets — written into a complete action.yaml you can see
and edit. validate/ and rollback/ ship commented out, so enabling a phase is uncommenting
rather than authoring.
It never overwrites an existing file.
check
Runs the same validator the server runs — literally the same function, shipped inside this
package. Import never rejects something check accepted; a test drives a shared fixture corpus
through both and fails if that stops being true.
On top of the validator it runs the authoring lint, which catches things a schema cannot express:
$Name?in PowerShell — reads as a variable calledName?, expands to nothing, and the value silently disappears. The one that cost five review cycles.- An entrypoint file that does not exist for the declared interpreter (
run/main.shwithruntime.name: powershell). - A parameter that
dependsOnone declared after it — the run form would ask for a VM before the resource group that scopes the list. - A permission for a provider the package does not declare, or one nothing in the code touches.
- Network declared with an empty allowlist.
Every finding names the file, the line, and the fix.
Add --strict to fail on warnings too, for CI.
What check does NOT claim. Three things depend on the deployment, not the package —
whether its runner ships your interpreter, whether it can broker outbound network, and whether
organization packages are enabled. Your laptop cannot know them, so check does not pretend to.
They are answered at import.
test
Runs one phase in the published runner image, with the same /opera/* layout, the same
OPERA_* environment, and the same result.json validator the control plane uses.
export OPERA_RUNNER_IMAGE=<the image your Opera runs> # the Author page shows it
opera-action test --phase validate
opera-action test --phase run --dry-run
opera-action test --phase run --param resourceGroup=rg-prodNeeds Docker. Uses your own az login credential (written to a file at
/opera/creds/azure-token, never an environment variable — the same way production does it).
Two things are deliberately different from production, and printed on every run so you never have to guess:
- the credential is yours, not Opera's brokered least-privilege lease, so a local pass does not prove the connector has the permissions;
- egress is your machine's, not the allowlisting proxy, so a declared allowlist is not enforced locally.
publish
export OPERA_URL=https://your-opera.example.com
export OPERA_TOKEN=…
opera-action publishUploads the directory as an authored package version — organization tier, on the strength of
the authenticated principal rather than a Git source. It runs check first and refuses on any
error, including a lint error the server cannot reject.
Publishing does not adopt. Nobody can run it until somebody chooses to.
Supply chain
Every release is published from CI on a tag, with npm provenance — a signed attestation binding the tarball to the commit and the workflow that built it. You can verify what you installed came from this repository:
npm audit signaturesLinks
- Issues: https://github.com/Mousling1992/opera-cloud/issues
- Source: https://github.com/Mousling1992/opera-cloud/tree/main/packages/action-cli
License
Apache-2.0
