opinionated-ci-pipeline
Version:
CI/CD on AWS with feature-branch builds, developer-environment deployments, and build status notifications.
282 lines (281 loc) • 10.3 kB
TypeScript
import { ComputeType } from 'aws-cdk-lib/aws-codebuild';
import { IRole } from 'aws-cdk-lib/aws-iam';
import { CodeBuildOptions, DockerCredential } from 'aws-cdk-lib/pipelines';
import { Construct } from 'constructs';
import { Duration } from 'aws-cdk-lib/core';
export interface ApplicationProps {
/**
* An object with a create() method to create Stacks for the application.
*
* The same Stacks will be deployed with main pipeline, feature-branch builds, and local deployments.
*/
readonly stacks: IStacksCreation;
readonly repository: RepositoryProps;
/**
* Package manager used in the repository.
* If provided, the install commands will be set to install dependencies using given package manager.
*/
readonly packageManager?: 'npm' | 'pnpm';
/**
* Commands executed to build and deploy the application.
*/
readonly commands?: BuildCommands;
/**
* The location where CDK outputs synthetized files.
* Corresponds to the CDK Pipelines ShellStepProps#primaryOutputDirectory.
* @default cdk.out
*/
readonly cdkOutputDirectory?: string;
/**
* CodePipeline deployment pipeline for the main repository branch.
*
* Can contain environments to deploy
* and waves that deploy multiple environments in parallel.
*
* Each environment and wave can have pre and post commands
* that will be executed before and after the environment or wave deployment.
*/
readonly pipeline: (WaveDeployment | EnvironmentDeployment)[];
/**
* Override CodeBuild properties, used for the main pipeline Build step
* as well as feature branch ephemeral environments deploys and destroys.
*
* @default 1 hour timeout, compute type MEDIUM with Linux build image Standard 7.0
*/
readonly codeBuild?: CodeBuildOptions;
/**
* Override CodePipeline properties.
*
* @default Don't use change sets
*/
readonly codePipeline?: CodePipelineOverrides;
/**
* Configuration for Slack notifications.
* Requires configuring AWS Chatbot client manually first.
*/
readonly slackNotifications?: SlackNotifications;
/**
* Whether to prefix the CI Stack Construct ID with the project name.
* Prefixing assures the ID is unique, required in projects deploying multiple CI Pipelines.
*
* No-prefixing is for backwards compatibility with existing projects,
* where changing the Construct ID of the CI Stack would change the Logical IDs of some constructs
* (like Lambda EventSourceMapping, API Gateway ApiMapping)
* causing CloudFormation to try re-creating them and fail.
*
* @default true
*/
readonly prefixStackIdWithProjectName?: boolean;
/**
* Whether to remove the CI resources from the beginning of the aws:cdk:path metadata.
*
* Enabling it results in the same tree view in the CloudFormation Console as with manual deployment though the CLI.
* Without it, the tree view for the stacks deployed through the CI starts with the 3 extra levels.
*
* This also prevents updating all resources just to change their metadata
* when deploying the stack alternately from the CI and CLI.
*
* This DOES NOT change the paths themselves, only the metadata.
* The resources that use the full path in their logical IDs
* (like the `EventSourceMapping` created with `lambda.addEventSource()`) will still change.
*
* @default false
*/
readonly fixPathsMetadata?: boolean;
}
/**
* To provide a method as parameter, jsii requires creating a behavioral interface, prefixed with "I".
* Mixing structural and behavioral interfaces is not always possible, hence we extract stacks creation
* to a separate object described by this behavioral interface.
*/
export interface IStacksCreation {
/**
* Create Stacks for the application.
*
* Use provided scope as stacks' parent (first constructor argument).
*
* Stacks must include provided environment name in their names
* to distinguish them when deploying multiple environments
* (like feature-branch environments) to the same account.
*/
create(scope: Construct, projectName: string, envName: string): void;
}
export interface RepositoryProps {
/**
* Repository hosting.
*/
readonly host: 'github' | 'bitbucket';
/** Like "my-comapny/my-repo". */
readonly name: string;
/**
* Branch to deploy the environments from in the main pipeline.
* @default main
*/
readonly defaultBranch?: string;
/**
* Configure the prefix branch names that should be automatically deployed as feature branches
* @default deploy all branches
*/
readonly featureBranchPrefixes?: string[];
}
export interface BuildCommands {
/**
* Executed at the beginning of the Build step and feature branch deployment and destruction.
*/
readonly preInstall?: string[];
/**
* Executed after `preInstall` in the Build step and feature branch deployment and destruction.
* By default, installs `aws-cdk@2` globally and `npm` or `pnpm` dependencies if `packageManager` is set.
*/
readonly install?: string[];
/**
* Executed after `install` in the Build step and feature branch deployment.
*/
readonly buildAndTest?: string[];
/**
* Executed after the Build step. By default, synths the CDK app.
*/
readonly synthPipeline?: string[];
/**
* Executed after `buildAndTest` in the feature branch deployment.
*/
readonly preDeployEnvironment?: string[];
/**
* Executed after `preDeployEnvironment` in the feature branch deployment.
* By default, deploys all CDK app stacks to the environment.
*/
readonly deployEnvironment?: string[];
/**
* Executed after `deployEnvironment` in the feature branch deployment.
*/
readonly postDeployEnvironment?: string[];
/**
* Executed after `install` in the feature branch destruction.
*/
readonly preDestroyEnvironment?: string[];
/**
* Executed after `preDestroyEnvironment` in the feature branch destruction.
*/
readonly destroyEnvironment?: string[];
/**
* Executed after `destroyEnvironment` in the feature branch destruction.
*/
readonly postDestroyEnvironment?: string[];
}
export interface WaveDeployment {
/**
* Wave name.
*/
readonly wave: string;
/**
* List of environments to deploy in parallel.
*/
readonly environments: EnvironmentDeployment[];
/**
* Flag indicating whether environment deployment requires manual approval.
*/
readonly manualApproval?: boolean;
/**
* Commands to execute before the wave deployment.
*/
readonly pre?: string[];
/**
* Commands to execute after the wave deployment.
*/
readonly post?: string[];
/**
* Commands to execute before each environment deployment.
*
* If environment configuration also contains commands to execute pre-deployment,
* they will be executed after the commands defined here.
*/
readonly preEachEnvironment?: string[];
/**
* Commands to execute after environment deployment.
*
* If environment configuration also contains commands to execute post-deployment,
* they will be executed before the commands defined here.
*/
readonly postEachEnvironment?: string[];
}
export interface EnvironmentDeployment {
/**
* Environment name.
*
* Environment will be deployed to AWS account and region
* defined in cdk.json file `context/environments` properties,
* falling back to the `default` environment settings if given environment configuration is not found.
*/
readonly environment: string;
/**
* Flag indicating whether environment deployment requires manual approval.
*/
readonly manualApproval?: boolean;
/**
* Commands to execute before the environment deployment.
*/
readonly pre?: string[];
/**
* Commands to execute after the environment deployment.
*/
readonly post?: string[];
}
/**
* Since jsii does not support Partial or Omit,
* we have to define all properties from CodePipelineProps that may be overriden manually.
*/
export interface CodePipelineOverrides {
readonly pipelineName?: string;
readonly selfMutation?: boolean;
readonly dockerEnabledForSelfMutation?: boolean;
readonly dockerEnabledForSynth?: boolean;
readonly codeBuildDefaults?: CodeBuildOptions;
readonly synthCodeBuildDefaults?: CodeBuildOptions;
readonly assetPublishingCodeBuildDefaults?: CodeBuildOptions;
readonly selfMutationCodeBuildDefaults?: CodeBuildOptions;
readonly publishAssetsInParallel?: boolean;
readonly dockerCredentials?: DockerCredential[];
readonly reuseCrossRegionSupportStacks?: boolean;
readonly role?: IRole;
readonly useChangeSets?: boolean;
readonly enableKeyRotation?: boolean;
}
export interface SlackChannelConfig {
readonly workspaceId: string;
readonly channelId: string;
}
export interface SlackNotifications {
/**
* Slack notifications configuration for main pipeline failures.
* @default Slack notifications are not being sent
*/
readonly mainPipelineFailures?: SlackChannelConfig;
/**
* Slack notifications configuration for feature branch deployment failures.
* @default Slack notifications are not being sent
*/
readonly featureBranchFailures?: SlackChannelConfig;
}
export declare const defaultProps: {
repository: {
defaultBranch: string;
};
commands: {
install: string[];
synthPipeline: string[];
deployEnvironment: string[];
destroyEnvironment: string[];
};
codePipeline: {
useChangeSets: false;
};
codeBuild: {
timeout: Duration;
buildEnvironment: {
computeType: ComputeType.MEDIUM;
buildImage: import("aws-cdk-lib/aws-codebuild").IBuildImage;
};
};
prefixStackIdWithProjectName: true;
};
export type ResolvedApplicationProps = ApplicationProps & typeof defaultProps;