projen

AWS CDK Construct Library

AWS CDK library projects produce artifacts with reusable constructs which can be consumed by other AWS CDK libraries or apps. Library artifacts are published to private or public package managers under a semantic version.

By default, for every commit to the default branch, a new version is released (trunk-based development). This includes the following steps:

  1. Compile, lint and test the code.
  2. Use JSII to produce library artifacts for all target languages.
  3. Determine the next minor/patch version based on conventional commits. Major versions must be explicitly bumped to protect consumers against breaking changes.
  4. A changelog entry is generated based on commit history.
  5. Packages are published to all target package managers.

Getting Started

Start like all projen projects:

npx projen new awscdk-construct

Review the resulting .projenrc.js file and make changes as needed. The following are some specific areas you may want to set explicitly.

Module Metadata

These fields are your basic Node module setup:

authorAddress: 'benisrae@amazon.com',
authorName: 'Elad Ben-Israel',
description: 'Watching your CDK apps since 2019',
name: 'cdk-watchful',
license: 'MIT',
repository: 'https://github.com/eladb/cdk-watchful.git',
keywords: ['cloudwatch', 'monitoring']

All are pretty standard setup and nothing CDK-specific at this point. The keywords automatically gets ‘cdk’ so you don’t need to specify it.

Dependencies

Depending on AWS CDK modules

Next are getting CDK dependencies added:

cdkVersion: '1.67.0',
cdkDependencies: ['@aws-cdk/aws-ec2'],
cdkTestDependencies: ['@aws-cdk/assert'],

cdkDependencies will add both dependencies and peerDependencies to your package.json file with a caret semver requirement (e.g. ^1.67.0). CDK dependencies must be both direct and peer dependencies, see this issue. You can set cdkVersionPinning to true to use a fixed version, but this means that any consumer of your library will have to use this exact CDK version. Likewise, cdkTestDependencies will add dependencies to the devDependencies.

Additionally, you can add CDK dependencies using the methods:

project.addCdkDependencies('aws-cdk/aws-sqs', 'aws-cdk/aws-sns');
project.addCdkTestDependencies('aws-cdk/something-else');

The @aws-cdk/assert library is already added to the cdkTestDependencies for you.

Depending on other modules

If your library consumes other jsii modules, you should declare them thorugh the deps or peerDeps options. deps should be used if types from the consumed module is not part of the public API of the library (the module is used as an implementation detail), while peerDeps must be used if types from the consumed module are exported as part of your library’s API. You can read more here.

deps: [ 'cdk-time-bomb' ]

A dependabot file will be added unless dependabot is set to ‘false’.

Publishing

As this is a jsii project, it will cross-compile to other languages. You can set up any number of jsii target languages.

  publishToNuget: {
    dotNetNamespace: 'Acme.HelloNamespace',
    packageId: 'Acme.HelloPackage'
  },
  publishToMaven: {
    javaPackage: 'com.acme.hello',
    mavenArtifactId: 'hello-jsii',
    mavenGroupId: 'com.acme.hello'
    serverId: 'github',
    repositoryUrl: 'https://maven.pkg.github.com/example/hello-jsii',
  },
  publishToPypi: {
    distName: 'acme.hello-jsii',
    module: 'acme.hello_jsii'
  },

jsii-release is used for publishing, and requires uploading Github project secrets based on the repositories you wish to publish to:

For help in getting these secrets for your project, read the jsii-release.

If you don’t want to publish a particular package, do not include the dotnet, java, or python field.

Workflows

Two workflows will be created as Github Actions:

Tasks

There are a number of package scripts that are created for you. Any of them can be overwritten using the addScript* methods.

script description
start starts an interactive command menu
projen regenerates the projen config. Run this if you edit .projenrc.js
no-changes a helper script to prevent unnecessary releases.
bump bumps the package version number
release bumps the library’s version and pushes to origin
projen:upgrade upgrades the projen cli tool
compile builds the library and generates docs
watch compiles and then re-compiles of further changes
package runs jsii-pacmak to package your library for publishing
test compiles and runs automated tests
test:watch watches for file changes, re-compiles and re-tests
test:update update any test snapshots
eslint runs eslint against all src and test .ts files
compat checks for jsii compatibility. See here for more info.
docgen generate documentation

As you develop your library you’ll likely be using the test:watch command the most.

API Documentation

Docs will be generated from Typescript comments and saved in the API.md file. Please review this file regularly and document your constructs liberally.

Project structure

.
|--lib/ (build output)
|--src/
   |--index.ts
|--test/
   |--hello.test.ts

Source .ts files should reside in the src directory. Constructs should be exported from the index.ts file. Compiled files will be put in the lib directory. Tests are in the test directory. If you need additional resources that are packaged with your library, add those to a resources directory that is besides the src directory and modify your references accordingly:

const thing = require('../resources/some-resource.json')

Migrating existing projects

Your existing CDK constructs likely have a different file structure than what this projen project expects. Projen projects are highly opinionated. There are a few expectations of this project you should modify your existing library to conform to:

export * from './our-s3-bucket'