Projen‑first environment configuration
In this starter kit, environments are modeled in .projenrc.ts
using an environmentConfigs
array. Projen then generates npm scripts and GitHub Actions via helper functions so each environment gets the correct account/region and permissions.
Defined in .projenrc.ts
at the repository root:
const environmentConfigs: (EnvironmentConfig & { name: Environment })[] = [
{ name: 'test', accountId: '987654321012', enableBranchDeploy: true },
{ name: 'production', accountId: '123456789012', enableBranchDeploy: false },
];
for (const config of environmentConfigs) {
// Adds npm run scripts for synth/test/deploy/diff per environment
addCdkActionTask(project, {
CDK_DEFAULT_ACCOUNT: config.accountId,
CDK_DEFAULT_REGION: awsRegion,
ENVIRONMENT: config.name,
GITHUB_DEPLOY_ROLE: githubRole, // defaults to 'GitHubActionsServiceRole'
});
// Generate GitHub Actions for this environment (deploy order follows array order)
createCdkDeploymentWorkflows(
project.github,
config.accountId,
awsRegion,
config.name,
githubRole,
nodeVersion,
config.enableBranchDeploy,
orderedEnvironments,
);
}
Your stacks read the environment from app/task-injected variables, for example:
// src/main.ts
import * as cdk from 'aws-cdk-lib';
import { createEnvResourceName } from './bin/env-helper';
import { StarterStack } from './stacks';
const app = new cdk.App();
const env = {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
};
new StarterStack(app, createEnvResourceName('StarterStack'), {
env,
environment: process.env.ENVIRONMENT,
});
After editing .projenrc.ts
, run npx projen
to regenerate tasks and workflows.
Environment variables set by tasks
Each generated npm script sets a consistent set of variables so your stacks can read context at runtime:
CDK_DEFAULT_ACCOUNT
andCDK_DEFAULT_REGION
— identify the AWS target for the current run.ENVIRONMENT
— matches the name fromenvironmentConfigs
(e.g.,test
,production
).GITHUB_DEPLOY_ROLE
— exported when GitHub Actions assumes the OIDC role.GIT_BRANCH_REF
— only present for branch deploy tasks; used by helpers likecreateEnvResourceName
.
You can rely on these in src/main.ts
, constructs, or aspects without manually wiring additional context.
Ephemeral environments
Per‑branch preview environments are built in. Set enableBranchDeploy: true
for an environment in environmentConfigs
to enable branch deploys. The Projen tasks/workflows inject a branch ref (via GIT_BRANCH_REF
) and use it to suffix stack names, creating isolated deployments for each branch.
Typical setup:
- IAM role trust policy for GitHub OIDC allows branch refs like
refs/heads/feature/*
. - Workflows compute a safe branch suffix using
GIT_BRANCH_REF
. - Stacks/names include the suffix (e.g.,
AppStack-${BRANCH}
) to avoid collisions. - On PR close/merge, a cleanup job runs
npx cdk destroy
for the affected suffix.
Why this helps developers:
- Rapid previews: see real infrastructure behavior for a PR without impacting shared environments.
- Parallel testing: multiple feature branches can test changes concurrently.
- Safer changes: experiment freely; easy to destroy when done.
- Clear ownership: resources are tagged/named by branch.
Local branch deploy example
You can exercise branch deploys locally; the generated npm tasks auto‑set GIT_BRANCH_REF
from your current branch.
# create and switch to a feature branch
git checkout -b feature/cool-thing
# preview resources for the branch
npm run test:branch:synth
npm run test:branch:diff:stack StarterStack
# deploy only the StarterStack for this branch
npm run test:branch:deploy:stack StarterStack
# list deployed stacks (shows branch‑suffixed names)
npm run test:branch:ls
# cleanup when done
npm run test:branch:destroy:stack StarterStack
For a task-by-task walkthrough that includes the GitHub Actions workflows, see Guides > Branch-based Development.
Note: The FoundationStack is intentionally excluded from branch deploys.
Bootstrap per environment
Run npx cdk bootstrap
once per account/region pair before the first deploy. This creates the CDK toolkit stack used for assets and deployments. If you have not bootstrapped yet, follow the steps in the Install guide.