Write a Node.js or Python script that imports the Pulumi Automation API and constructs a LocalWorkspace pointing to the Pulumi program directory; use stack.create or LocalWorkspace.createOrSelectStack with the PR number as the stack name suffix
Call stack.setConfig in the script to inject per-PR values such as subdomain prefix, feature flags, and the source branch; these configs propagate into the Pulumi program as config.require calls
Run stack.up({ onOutput: console.info }) and capture the stack outputs including the preview URL; post the URL as a pull request comment using the GitHub REST API from within the same script
On the merge event, run the same script with stack.destroy followed by stack.workspace.removeStack to fully clean up the stack and its state from the Pulumi backend
Wrap the up and destroy calls in try-catch blocks and emit structured logs; on failure, post a comment to the PR with the last 50 lines of output captured from the onOutput stream
Use a Pulumi Stack Reference in a shared monitoring stack that reads the preview environment outputs so alerts and dashboards automatically discover ephemeral stacks
Known gotchas
The Automation API does not isolate concurrent stack operations by default; if two PRs trigger updates simultaneously and share a backend bucket prefix, state locking may cause one to fail with a lock timeout
Stack names in Pulumi must match the regex [a-zA-Z0-9-_.]; PR branch names with slashes or special characters must be sanitized before use as stack name suffixes
Pulumi program code changes are not automatically picked up by the Automation API if the workspace path is a pre-built bundle; you must ensure the program files are present on the runner before calling stack.up
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp