Skip to content

plywood

llms.txtlists every page for an agent
The plywood board, a pixel-art plywood plank

plywood

Pulumi ops and governance.

Pulumi previews and updates move into your pull requests and run as jobs in the CI you already have. Each stack a change reaches gets its own preview note, and an approval holds only for the exact preview it was shown. Your programs stay as they are, on the backend they use today.

Built on chant. It can run plunge as its engine.

First command

Needs: Node.js 22 and the Pulumi CLI.

npm i -D @intentius/plywood
npx plywood init

The full steps

Your backend
Your repo shape

A pull request that reaches six stacks gets one preview note. Each stack has its own section listing the resources its preview changes, and one command approves the whole change. The note comes from chant’s pull request CI, which plywood switches on with Pulumi’s words. Why previews are grouped.

plywood runs Pulumi in your own CI on GitHub, GitLab or Forgejo. Programs and stack config stay as you have them, and so does the backend.

Where it runs You set Page
GitHub, GitLab or Forgejo CI nothing: init reads the forge from the origin remote Add plywood to a repo
Pulumi Cloud an access token for previews and one for updates Pulumi Cloud stacks
A file, S3, GCS or Azure Blob backend the backend URL your stacks already use Self-managed backends

A change goes out a few stacks at a time, starting with the canary stack. Each wave waits behind its own gate, and an approval covers the exact preview digest it was shown. A preview that moves after review is refused and named. Waves and gates are chant’s gated waves, with plywood’s defaults. Waves and approvals.

A scheduled job reads each stack against the cloud and keeps one issue per stack, naming each drifted URN and attribute, through chant’s drift detection. Turn on drift checks.

plunge is the Pulumi fork from the team behind plywood. With engine: plunge in plywood.yml the pipeline also gets:

You get Page
Two pull requests that change different resources of one stack update side by side, with no stack lock Locking and staleness
A saved plan that carries the version of each record it read, so up refuses a record that moved after review Stages
Drift read one resource at a time, with no program run Turn on drift checks
Guard In practice
Preview and update use separate identities the preview job runs the pull request’s program and never holds the update identity
An approval binds one preview digest a wave whose preview moved updates nothing and names both digests
Policy and approvers are read at base a pull request cannot loosen the gate on its own merge

The threat model lists the reach of each job.

plywood leaves outBecause
Bitbucket and Azure DevOpsinit writes pipelines for GitHub, GitLab and Forgejo.
Accounts and roles of its ownYour forge decides who approves, and your cloud decides each job's reach.
A hosted serviceEvery job runs in your CI and writes to your repository.
Programs and providersPulumi runs your program, in any language it supports.

Paste this into your coding agent in your repository. Updates, approvals and merges stay with a person. Set it up with your agent has the details, and Add plywood to a repo has the same steps by hand.

Setup prompt for your coding agentCopy it into your agent.
Set up plywood in this repository.
Read https://intentius.io/plywood/llms.txt first, then
https://intentius.io/plywood/getting-started/agents/ and follow it.
Ask me which stacks should wait for an approval before they update.
Open a pull request with the result.
Never run `pulumi up`, `plunge up`, `pulumi destroy` or `plywood approve`, override a policy denial, use `--mode up`, or merge; never touch `.chant/allowed_signers` or `chant/lifecycle`.

plywood runs on chant, and its sibling for Terraform and OpenTofu is terragucci. plywood is open source under Apache-2.0.

plywood