Overview
The starter kit includes two stacks: FoundationStack for OIDC and tooling setup, and StarterStack for your application resources. Projen generates pnpm scripts for each environment.
Learn how to create AWS CDK stacks before exploring these patterns.
Mermaid diagram loading.Starter Kit Stacks Generated Scripts
FoundationStack
Source: src/stacks/foundation-stack.ts
Sets up GitHub OpenID Connect (OIDC) and an IAM role for GitHub Actions deployments through the GitHubActionsOidcConstruct. Also adds a CloudFormation Toolkit cleaner to remove old CDK assets.
Constructor
new FoundationStack(scope: Construct, id: string, props: FoundationStackProps)
| Parameter | Type | Description |
|---|
scope | Construct | Parent app scope |
id | string | Stack identifier |
props | FoundationStackProps | Stack configuration |
FoundationStackProps
| Property | Type | Required | Description |
|---|
environment | string | Yes | Environment label for the OIDC subject (test, production, etc.) |
githubActionsOidc | FoundationStackGitHubActionsOidcProps | No | Optional OIDC role settings passed to GitHubActionsOidcConstruct (additionalRepositories, maxSessionDuration, roleName). The stack always scopes the trust policy to environment. |
Resources created
| Resource | Type | Description |
|---|
| OIDC Provider | iam.OpenIdConnectProvider | For token.actions.githubusercontent.com with client ID sts.amazonaws.com |
| IAM Role | iam.Role | Named GitHubActionsServiceRole (or custom via GITHUB_DEPLOY_ROLE). Trusts GitHub OIDC with subject repo:<owner>/<repo>:environment:<ENV> |
| Toolkit Cleaner | ToolkitCleaner | From cloudstructs package. Automatically cleans up old CDK assets |
Deployment behavior
- Excluded from branch deployments - guarded by
if (!process.env.GIT_BRANCH_REF) in src/main.ts
- Deploy once per account/region - enables OIDC deployments for that environment
- Creates GitHub environment link - IAM role subject matches GitHub environment name
Usage
pnpm run test:deploy:all
pnpm run test:deploy:stack FoundationStack
StarterStack
Source: src/stacks/starter-stack.ts
Your application entry stack. Add constructs and resources here. Includes a commented example using NetworkConstruct for a secure VPC.
Constructor
new StarterStack(scope: Construct, id: string, props?: StarterStackProps)
| Parameter | Type | Description |
|---|
scope | Construct | Parent app scope |
id | string | Stack identifier |
props | StarterStackProps | Optional stack configuration |
StarterStackProps
| Property | Type | Required | Description |
|---|
environment | string | No | Used for tagging and resource naming |
Usage
pnpm run test:synth
pnpm run test:diff:stack StarterStack
pnpm run test:deploy:stack StarterStack
pnpm run test:branch:deploy:stack StarterStack
Adding resources
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';
export class StarterStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
new s3.Bucket(this, 'DataBucket', {
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
encryption: s3.BucketEncryption.S3_MANAGED,
});
}
}
Generated pnpm scripts
Projen generates scripts for each environment defined in .projenrc.ts. The examples below assume test (with branch deploys enabled) and production (branch deploys disabled).
Test environment (regular)
| Script | Description |
|---|
pnpm run test:synth | Synthesize all stacks |
pnpm run test:ls | List all stacks |
pnpm run test:deploy:all | Deploy all stacks |
pnpm run test:deploy:stack <StackName> | Deploy specific stack |
pnpm run test:destroy:all | Destroy all stacks |
pnpm run test:destroy:stack <StackName> | Destroy specific stack |
pnpm run test:diff:all | Show diff for all stacks |
pnpm run test:diff:stack <StackName> | Show diff for specific stack |
Test environment (branch)
| Script | Description |
|---|
pnpm run test:branch:synth | Synthesize all branch stacks |
pnpm run test:branch:ls | List all branch stacks |
pnpm run test:branch:deploy:all | Deploy all branch stacks |
pnpm run test:branch:deploy:stack <StackName> | Deploy specific branch stack |
pnpm run test:branch:destroy:all | Destroy all branch stacks |
pnpm run test:branch:destroy:stack <StackName> | Destroy specific branch stack |
pnpm run test:branch:diff:all | Show diff for all branch stacks |
pnpm run test:branch:diff:stack <StackName> | Show diff for specific branch stack |
Production environment
| Script | Description |
|---|
pnpm run production:synth | Synthesize all stacks |
pnpm run production:ls | List all stacks |
pnpm run production:deploy:all | Deploy all stacks |
pnpm run production:deploy:stack <StackName> | Deploy specific stack |
pnpm run production:destroy:all | Destroy all stacks |
pnpm run production:destroy:stack <StackName> | Destroy specific stack |
pnpm run production:diff:all | Show diff for all stacks |
pnpm run production:diff:stack <StackName> | Show diff for specific stack |
Script behavior
:all scripts operate on all stacks in the app
:stack scripts accept stack names as arguments
- Branch tasks automatically inject
GIT_BRANCH_REF from current git branch
- FoundationStack is excluded from branch deploys by design
Adding a new stack
- Create the stack file:
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
export class AppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
}
}
- Export from index:
export { FoundationStack } from './foundation-stack';
export { StarterStack } from './starter-stack';
export { AppStack } from './app-stack';
- Instantiate in
src/main.ts:
import { AppStack } from './stacks';
new AppStack(app, createEnvResourceName('AppStack'), { env: awsAccountConfig });
- Verify:
pnpm run test:synth
pnpm run test:ls
Next steps