# Review AWS CDK Pull Requests

Yes. An agent checks out the CDK pull request, runs npm test and cdk synth, diffs the templates and reviews IAM grants, removal policies and replacements.

[Run this on Rush](https://cloud.getrush.ai/run/review-cdk-changes/aws-cdk/), in a Project that has your repository.

## What the agent does

The agent starts from the pull request's own branch in a fresh sandbox and works out which CDK app the change touches. In a repository shaped like aws-samples/aws-cdk-examples that matters, because the root holds `csharp/`, `go/`, `java/`, `python/` and `typescript/`, each a folder of independent apps with their own `package.json`, `cdk.json` and lockfile. It reads `scripts/build-typescript.sh` to see how the project itself builds a change: walk up from the changed file to the first `package.json`, skip the directory if it holds a `DO_NOT_AUTOTEST` file, run `npm ci` or `yarn install --frozen-lockfile` depending on the lockfile, then `npm run build`, `npm run --if-present test`, and finally `scripts/synth.sh`.

It runs that same sequence for each changed app rather than inventing one. `scripts/synth.sh` copies `scripts/fake.context.json` into place as `cdk.context.json` when the app has none and sets `AWS_DEFAULT_REGION=us-east-1`, which is what lets `cdk synth` run with no AWS account at all. In an app like `typescript/static-site`, `cdk.json` sets the app command to `npx tsc && npx tsx index.ts`, `package.json` pins `aws-cdk` 2.1133.0 and `aws-cdk-lib` 2.262.1, and there is no `test` script, so `npm run --if-present test` does nothing and the synthesized template is the only evidence. In an app like `typescript/amazon-mq-rabbitmq-lambda`, `npm test` runs Jest assertions built on `Template.fromStack`, and the agent reads which properties they pin before deciding whether the change is covered.

Then it synthesizes twice: once on the pull request's base commit and once on its head, and compares the `cdk.out/*.template.json` files. A logical ID that disappears from one side and appears renamed on the other is a delete and a create, and so is a change to a property CloudFormation cannot update in place, such as a DynamoDB table's key schema or an explicit bucket name. `cdk diff --template` against the base template gives the same comparison in CDK's own format, again without credentials. This is how the review catches a refactor that moves a construct to a new scope and quietly replaces a table with data in it.

With the templates in hand, the agent reads the change the way a security reviewer would. It looks for `grant*` calls that widen access (`grantReadWrite` where the code only reads, `grantFullAccess`), `addToPolicy` statements with `*` resources or actions, and `RemovalPolicy.DESTROY` with `autoDeleteObjects: true`, which `typescript/static-site/static-site.ts` uses with the comment `NOT recommended for production code`. It checks the result against `cdk.json` flags such as `@aws-cdk/aws-iam:minimizePolicies`, which changes how statements are merged in the template, and then posts one review on the pull request with file and line for each finding.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "Review the open pull request on this repository. For each CDK app the change touches, run the project's own build: npm ci or yarn install from the lockfile, npm run build, npm test if it exists, then cdk synth with scripts/fake.context.json when there is no cdk.context.json. Synthesize the base commit too and compare the templates in cdk.out: list every resource that would be replaced or deleted, every IAM statement that widens access, and every RemovalPolicy.DESTROY or autoDeleteObjects on stateful resources. Post one review that cites file and line for every finding, with the command whose output shows it. Do not push commits.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-cdk-app/pull/123"
    }
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is one review on the pull request, not a branch. Each comment sits on the changed line in the stack file (`lib/*-stack.ts` or the app's entry file) and says what the synthesized template shows: the logical ID that changes and the resource type behind it, the IAM action and resource the new statement grants, or the removal policy a stateful resource now has. Findings are grouped by app when one pull request touches several, and the review summary lists the commands it ran in each directory.

The proof is in the session. Its transcript keeps the output of `npm ci`, `npm run build`, the Jest run and both `cdk synth` runs, plus the template comparison the replacement findings come from, so a reviewer can open the exact output behind any comment. When a change has no test and synth passes, the review says that the template is the only check and names which resource it compared, instead of calling the change safe.

Before merging, a reviewer confirms each replacement is intended or asks for the construct ID to be pinned, checks that widened grants match what the code really calls, and decides whether `RemovalPolicy.DESTROY` belongs on that resource in a real account. A replacement on a table, a bucket or a user pool is the comment to resolve first.

## Run it on every pull request to your CDK app

An automation with a GitHub trigger on `pull_request.opened` and `pull_request.synchronize` starts this review on every push to an open pull request, so a force-pushed fix gets a fresh synth and comparison. From your own server, take GitHub's `pull_request` webhook and send this body with the pull request URL in `resources`, using the head commit SHA as the `Idempotency-Key`, so a redelivered webhook returns the run already started instead of reviewing twice.

Set a webhook URL on the API key to get `run.completed` when the review is posted. If the author pushes a fix, a follow-up message to the same session asks it to synthesize again and re-check its own findings; the parked sandbox wakes with `cdk.out` and `node_modules` still in place.

## Why run it on Rush?

A CDK change is hard to review from the diff because the risk is in what it synthesizes to. A one-line move of a construct into a new parent changes its logical ID, and the diff shows nothing about a table being replaced. Running `npm ci` and `cdk synth` twice for every pull request on a laptop is slow enough that most reviewers skip it. On Rush each review gets its own sandbox with its own clone, so the base and head synths run side by side, and nothing touches your working copy or your AWS profile.

The review is checkable. Every finding points to command output in the session's transcript, and the agent needs no AWS credentials because `synth.sh` and the fake context file already make synthesis work offline. Reviews for pull requests across many apps in the same repository run at once, each in its own sandbox, and each one either cites the output or says what it could not run.

## Frequently asked questions

### Does the agent need AWS credentials?

No. `cdk synth` with the repository's `scripts/fake.context.json` and a fixed `AWS_DEFAULT_REGION` builds the CloudFormation templates without calling AWS, and the replacement check compares two local templates. Plain `cdk diff` against a deployed stack would need credentials, so the agent compares against the base commit's synth instead.

### How does it tell a replacement from an in-place update?

It compares the base and head templates resource by resource. A logical ID that vanishes and reappears under another ID is a delete and a create. A changed property that CloudFormation documents as requiring replacement, such as a table's key schema, is flagged with the property name, so the reviewer can check it against the CloudFormation reference.

### What if the app has no tests?

Many apps in a repository like aws-cdk-examples have no `test` script, and `npm run --if-present test` then does nothing. The review says so and treats the synthesized template as the evidence. It can suggest a `Template.fromStack` assertion for the resource the change touches, but it does not push one, because the prompt forbids commits.

### Does it work for Python, Java, Go or C# CDK apps?

Yes, with that language's build. The repository ships `scripts/build-python.sh`, `build-java.sh`, `build-go.sh` and `build-csharp.sh` beside the TypeScript one, and the agent reads the script for the language of the changed directory. Name the language and its test command in the prompt if your repository has no such script.

### Will it approve or block the pull request?

It posts a review with comments and a summary; the prompt decides whether that review is a plain comment or a request for changes. Branch protection and the human approval rules on your repository stay exactly as they are.
