Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### Fixed

- Make Repo 2 deployment actions invoke the lockfile-installed `cdk-cicd` CLI through an npm script
instead of allowing `npx` to resolve a registry version at deployment time.
- Use explicit non-secret placeholders for KMS key examples and test fixtures.
31 changes: 28 additions & 3 deletions MIGRATION.md

Large diffs are not rendered by default.

27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ This provisions the pipeline from `cicd.config.ts` alone — nothing else needs

#### What the pipeline does

**Source** → **Build** (`npm ci`, then your `ci.steps` or the default `npx cdk-cicd check`, then `cdk synth` with CDK Nag) → **self-update** → one **deploy** action per configured stage, in order, each gated by a manual approval except the inner-loop stage names `dev` and `res` (auto-approved by default), unless you set `manualApproval` explicitly. Autopilot reserves no stage names — `dev`/`res` are simply the two that default to auto-approve; every other name is gated.
**Source** → **Build** (`npm ci`, then your `ci.steps` or the default `npx cdk-cicd check`, then `cdk synth` with CDK Nag) → **self-update** → one **deploy** action per configured stage, in order, each gated by a manual approval except the inner-loop stage names `dev` and `res` (auto-approved by default), unless you set `manualApproval` explicitly. `dev`/`res` are simply approval defaults; the flat CodePipeline engine reserves only its plumbing stage names: `Source`, `Build`, and `UpdatePipeline`.

Supporting resources — the encryption key, VPC networking for the pipeline's own CodeBuild projects, a compliance bucket — are **lazily provisioned**, so a pipeline only pays for what its configuration actually references.

Expand All @@ -236,12 +236,35 @@ The `engine` field in `cicd.config.ts` selects how the pipeline is rendered. The
- **`EngineType.CDK_PIPELINES`** — the Blueprint-compatible self-mutating pipeline built on `aws-cdk-lib/pipelines` (Source → Synth → Assets → one wave per stage). Choose it when you want a pipeline shaped like a Blueprint (`0.x`) one, e.g. to keep a migration's topology familiar.
- **`EngineType.GITHUB_ACTIONS`** — renders a GitHub Actions workflow instead of an AWS-hosted pipeline. Requires `repository: Repository.github(...)` and a `githubActions` config block.

#### Deployment contracts

- **`APP_STAGING` is direct-deploy only.** It is valid for local/direct `cdk deploy` (including local
`cdk-cicd deploy --from-image`) and may be preserved while Repo 1 builds a deployer image, because that
pipeline deploys no application stacks. Every wrapper-generated deployment pipeline rejects it: flat
`CODEPIPELINE`, Repo 2, `CDK_PIPELINES`, and `GITHUB_ACTIONS`. On the direct/local path, a custom
bootstrap qualifier and custom `deployRole` / `cfnExecutionRole` identities are supported for
application stacks. The separate staging support stack deploys with caller/base credentials, and
deploy-role `ExternalId` values remain unsupported.
- **Deployment and CloudFormation roles are distinct.** CodeBuild assumes the configured deployment
role. That assumed role passes the CloudFormation execution role to CloudFormation, so
`iam:PassRole` belongs on the deployment role—not directly on the CodeBuild project role.
- **Private ECR build images are environment-bound.** A custom ECR image used as a CodeBuild environment
image must be in the same Region as the project; the flat and CDK Pipelines CI paths also require the
pipeline account. Repo 2's explicit cross-account image path requires an owner-side repository policy
and `crossAccountEcrRepositoryPolicyConfigured: true`; it does not relax the build-image Region rule.
- **GitHub approvals are configured in GitHub.** When `manualApproval` is used, configure required
reviewers on every generated GitHub Environment, then acknowledge that setup with
`githubActions.environmentProtectionConfigured: true`.

```typescript
import { defineCICD, Repository, EngineType } from '@cdklabs/cdk-cicd-wrapper';

export default defineCICD({
application: 'my-app',
repository: Repository.github('my-org/my-app'),
repository: Repository.codestarConnection(
'my-org/my-app',
'arn:aws:codestar-connections:eu-west-1:111111111111:connection/01234567-89ab-cdef-0123-456789abcdef',
),
engine: EngineType.CDK_PIPELINES, // omit for the default CODEPIPELINE
stages: ['dev', 'prod'],
});
Expand Down
7 changes: 6 additions & 1 deletion docs/content/developer_guides/cd.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This iterative process helps reduce the chance that you develop new code based o

### Stage

A stage is a [deployment environment](https://en.wikipedia.org/wiki/Deployment_environment) the solution is deployed to — for example `dev`, `int`, `prod`. Unlike Blueprint (0.x), Autopilot has no reserved stage names (no forced `RES`, no built-in `DEV`/`INT`/`PROD`): every stage you list in `cicd.config.ts`'s `stages` array is deployed, in the order listed, by the pipeline running in whichever account/region your ambient credentials point at when you run `cdk-cicd deploy-ci`.
A stage is a [deployment environment](https://en.wikipedia.org/wiki/Deployment_environment) the solution is deployed to — for example `dev`, `int`, `prod`. Unlike Blueprint (0.x), Autopilot does not force lifecycle names such as `RES`/`DEV`/`INT`/`PROD`: every stage you list in `cicd.config.ts`'s `stages` array is deployed in order. The flat CodePipeline engine reserves only its infrastructure stage names, `Source`, `Build`, and `UpdatePipeline`.

### Stack

Expand Down Expand Up @@ -44,6 +44,11 @@ A stage's `deployment` field can force a specific deploy role / CloudFormation e
{ name: 'prod', env: { account: '333333333333', region: 'eu-west-1' }, deployment: { deployRole: 'arn:aws:iam::333333333333:role/Deployer', cfnExecutionRole: 'arn:aws:iam::333333333333:role/CfnExec' } }
```

For CodeBuild-backed deployments, the CodeBuild project assumes `deployRole`. The assumed deployment
role then passes `cfnExecutionRole` to CloudFormation. Grant that deployment role
`iam:PassRole` on the execution role; do not grant the CodeBuild project role direct
`iam:PassRole` merely because an execution role is configured.

## Deploying different stacks per stage

There is no `addStack()`/provider-callback API in Autopilot — `bin/` is plain CDK, so you construct whichever stacks you want directly. `cdk-cicd exec` sets `CDK_STAGE` to the active stage's name (also readable through `stageStackName`'s default), so conditional stacks are ordinary TypeScript:
Expand Down
66 changes: 64 additions & 2 deletions docs/content/developer_guides/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,68 @@ ci: {
},
```

### Custom CI CodeBuild image
### Custom CI build image

`ci.image` is engine-specific:

- `CODEPIPELINE` and `CDK_PIPELINES` use it as the CI/Synth CodeBuild environment image.
- `aws/codebuild/...` selects an AWS-managed image with CodeBuild-managed pull credentials.
- A private ECR image must be in the pipeline account and the same Region as the CodeBuild project.
The wrapper grants the project role permission to pull that repository.
- An external registry image is anonymous by default. For an authenticated registry, configure a
Secrets Manager credential containing the registry `username` and `password`:

```typescript
ci: {
image: 'registry.example.com/private/ci:2026-09',
codeBuildImageCredentials: {
secretArn:
'arn:aws:secretsmanager:eu-west-1:111111111111:secret:ci-registry-AbCdEf',
// Include this only when the secret uses a customer-managed KMS key.
encryptionKeyArn:
'arn:aws:kms:eu-west-1:111111111111:key/EXAMPLE_NOT_A_SECRET',
},
},
```

The wrapper passes the imported secret to
`LinuxBuildImage.fromDockerRegistry(..., { secretsManagerCredentials })`; CDK renders the
CodeBuild registry credential and grants the CI/Synth role secret read. When the secret uses an
imported customer-managed key, the wrapper also grants that role `kms:Decrypt` on the exact key
ARN. `codeBuildImageCredentials` is rejected for managed CodeBuild and private ECR images because
those image classes use different pull-credential models.

- `GITHUB_ACTIONS` uses `ci.image` as the Build-Synth GitHub job container.
- `aws/codebuild/...` is rejected: it is a CodeBuild image ID, not a pullable OCI job-container
reference.
- Private ECR is rejected because GitHub pulls the job container before the workflow can obtain AWS
credentials and exchange them for an ECR authorization token.
- Authenticate an external registry with GitHub Actions secret names:

```typescript
ci: {
image: 'registry.example.com/private/ci:2026-09',
},
githubActions: {
buildContainerCredentials: {
usernameSecretName: 'REGISTRY_USERNAME',
passwordSecretName: 'REGISTRY_PASSWORD',
},
},
```

The workflow contains `${{ secrets.REGISTRY_USERNAME }}` and
`${{ secrets.REGISTRY_PASSWORD }}` expressions, never literal credentials. Secret names may use
letters, numbers, and underscores, must not start with a number, and must not start with
`GITHUB_`.

All engines reject image references containing inline registry userinfo such as
`user:password@registry.example.com/image`.

For the CodeBuild engines, the same-Region ECR requirement is imposed when CodeBuild provisions the
build environment; logging in from the buildspec happens too late to make a cross-Region ECR
environment image usable. Repo 2's cross-account deployer-image acknowledgement is a separate runtime
pull path and does not change this `ci.image` contract.

Set `ci.image` to override the CodeBuild image the CI build project runs on.
For GitHub Actions, `githubActions.publishAssetsAuthRegion` controls the Region used to assume the OIDC
role while publishing assets. When omitted, it defaults to the concrete pipeline stack Region.
Loading