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:
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.
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.
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 thecdkTestDependencies
for you.
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’.
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:
NPM_TOKEN
(docs)NUGET_API_KEY
(docs)MAVEN_GPG_PRIVATE_KEY
, MAVEN_GPG_PRIVATE_KEY_PASSPHRASE
, MAVEN_PASSWORD
, MAVEN_USERNAME
, MAVEN_STAGING_PROFILE_ID
(docs)TWINE_USERNAME
, TWINE_PASSWORD
(docs)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.
Two workflows will be created as Github Actions:
buildWorkflow
field. On a ‘pull_request’ or ‘workflow_dispatch’ the library
will be built and checked for anti-tamper (ensure no manual changes to generated files).releaseWorkflow
field. On a push to main
(overridden at
props.defaultReleaseBranch
) the library is built, anti-tampered, version bumped with a commit, pushed back to git,
and then published to the configured artifact repositories (e.g. npm, pypi).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.
Docs will be generated from Typescript comments and saved in the API.md
file.
Please review this file regularly and document your constructs liberally.
.
|--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')
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:
src/
directory. Existing constructs should all be moved there. However,
you can override this directory by setting srcdir
.lib/
directory. This directory will be removed and rebuilt each build.
Do not store source .ts files in your lib/
or ‘libdir’.src/index.ts
. If your existing library is not in the index.ts file,
you can add the following to export it:export * from './our-s3-bucket'