Monitoring AWS CodeBuild With CloudWatch Alarms in the CDK - amazon-web-services

Info: The AWS Console offers CloudWatch metrics for CodeBuild, such as FailedBuilds, Duration, InstallDuration, FinalizingDuration... There are roughly 40 metric options.
Problem: When creating with the pipelines in the CDK, I cannot find the equivalent monitoring solution for the CodeBuildStep (Link).
Typically, for example, the NodejsFunction has metric props which I can use to create AlarmProps and thus monitor.
CDK Pipeline Code:
this.codePipeline = new CodePipeline(this, `${environment}-${appName}-`, {
pipelineName: `${environment}-${appName}-`,
selfMutation: true,
crossAccountKeys: false,
role: this.codePipelineRole,
cliVersion: "21.0.0",
synth: new CodeBuildStep("Deployment", {
input: CodePipelineSource.codeCommit(this.codeRepository, environment),
env: {environment},
installCommands: ["npm uninstall -g aws-cdk", "npm i -g npm#latest", "npm install -g aws-cdk"],
commands: [
"cd backend",
"npm ci",
"npm run build",
"npx cdk synth",
],
primaryOutputDirectory: "backend/cdk.out",
buildEnvironment: {
computeType: ComputeType.SMALL,
},
})
});
Desired Alarm Props:
const codeBuildPostBuildDuration = (codeBuild: CodeBuildStep): AlarmProps => ({
alarmName: "codeBuildPostBuildDuration",
comparisonOperator: ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD,
threshold: 1,
evaluationPeriods: 1,
metric: codeBuild.FailedBuilds()
});
What can I do to monitor and create alarms for my CDK CI/CD Pipeline?

Related

Update config.json file for a static frontend React site, using AWS CodePipeline and CDK

I'm building a CDK Pipeline that with update another CDK template.
This CDK template is a static frontend react app.
The backend uses an AWS Lambda, API Gateway, and CloudFront Distribution to host the site.
I want to put the api's in the config.json file as I normally would if I were building it manually one service at a time.
The problem seems to be in the cdk pipeline-stack, which builds the static-frontend-stack.
When you initialize a new pipeline, it wants you to add shell steps first, (npm i, cd into correct folder, npm run build, etc) which creates the distribution folder I need.
As well as turning the whole thing into a CF template.
Then you can drop that into different stages you want, e.g., test and prod.
However, I won't receive CfnOutputs until the stages are built. And the CfnOutputs hold the api's and other info I need to put into the config.json file (which was already built first, and created empty values).
There is even a envFromCfnOutputs param to add to the initial codebuild pipeline, but since they are initialized/created later, typescript yells at me for putting it in there before. I understand why that errors, but I can't figure a clever way to fix this issue.
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as pipelines from "aws-cdk-lib/pipelines";
import * as codecommit from "aws-cdk-lib/aws-codecommit";
import { Stages } from "./stages";
import { Stack, Stage } from "aws-cdk-lib";
interface PipelineStackProps extends cdk.StackProps {
env: {
account: string;
region: string;
stage: string;
};
}
export class PipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: PipelineStackProps) {
super(scope, id, props);
/************ Grab Repo ************/
const source = codecommit.Repository.fromRepositoryName(
this,
"PreCallbackSMSSolution",
"PreCallbackSMSSolution"
);
/************ Define Pipeline & Build ShellStep (for Frontend) ************/
const Pipeline = new pipelines.CodePipeline(this, "Pipeline", {
pipelineName: `CodePipeline`,
selfMutation: true,
crossAccountKeys: true,
synthCodeBuildDefaults: {
rolePolicy: [
// #desc Policy to allow CodeBuild to use CodeArtifact
// #external https://docs.aws.amazon.com/codeartifact/latest/ug/using-npm-packages-in-codebuild.html
new cdk.aws_iam.PolicyStatement({
actions: [
"codeartifact:GetAuthorizationToken",
"codeartifact:GetRepositoryEndpoint",
"codeartifact:ReadFromRepository",
],
resources: ["*"],
}),
new cdk.aws_iam.PolicyStatement({
actions: ["sts:GetServiceBearerToken"],
resources: ["*"],
conditions: {
StringEquals: {
"sts:AWSServiceName": "codeartifact.amazonaws.com",
},
},
}),
],
},
synth: new pipelines.ShellStep("Synth", {
input: pipelines.CodePipelineSource.codeCommit(source, "master"),
installCommands: [
"cd $CODEBUILD_SRC_DIR/deployment",
"npm install -g typescript",
"npm run co:login",
"npm i",
],
env: {
stage: props.env.stage,
},
envFromCfnOutputs: {
// TODO: cfn outputs need to go here!
// CcpUrlOutput: TestStage.CcpUrlOutput,
// loginUrlOutput: TestStage.LoginUrlOutput,
// regionOutput: TestStage.RegionOutput,
// apiOutput: TestStage.ApiOutput
},
commands: [
"cd $CODEBUILD_SRC_DIR/frontend",
"pwd",
"apt-get install jq -y",
"chmod +x ./generate-config.sh",
"npm i",
"npm run build-prod",
"pwd",
"cat ./src/config-prod.json",
"cd ../deployment",
"npx cdk synth",
],
primaryOutputDirectory: "$CODEBUILD_SRC_DIR/deployment/cdk.out", // $CODEBUILD_SRC_DIR = starts root path
}),
});
/************ Initialize Test Stack & Add Stage************/
const TestStage = new Stages(this, "TestStage", {
env: { account: "***********", region: "us-east-1", stage: "test" },
}); // Aspen Sandbox
Pipeline.addStage(TestStage);
/************ Initialize Prod Stack & Add Stage ************/
const ProdStage = new Stages(this, "ProdStage", {
env: { account: "***********", region: "us-east-1", stage: "prod" },
}); // Aspen Sandbox
Pipeline.addStage(ProdStage);
/************ Build Pipeline ************/
Pipeline.buildPipeline();
/************ Manual Approve Stage ************/
const ApproveStage = Pipeline.pipeline.addStage({
stageName: "PromoteToProd",
placement: {
justAfter: Pipeline.pipeline.stage("TestStage"),
},
});
ApproveStage.addAction(
new cdk.aws_codepipeline_actions.ManualApprovalAction({
actionName: "Approve",
additionalInformation: "Approve this deployment for production.",
})
);
}
/****/
}

CodeBuild failed for cross-account CI/CD pipeline

I'm trying to follow this guide to setup a cross accounts pipeline: https://taimos.de/blog/create-a-cicd-pipeline-for-your-cdk-app
I have Alpha account 111111 which will hold the pipeline, that is going to deploy to Alpha account 111111 and Prod account 222222. I did the bootstrap below to establish a trust relationship to the CI/CD account to allow cross-account deployments.
cdk bootstrap --profile=eCommerceService-Prod --bootstrap-customer-key --cloudformation-execution-policies 'arn:aws:iam::aws:policy/AdministratorAccess' --trust 111111 --trust-for-lookup 111111 aws://222222/us-east-1
The pipeline is setup correctly, however, the ColdBuild failed:
User: arn:aws:sts::111111:assumed-role/eCommerceDatabaseCdk-Pipe-PipelineBuildSynthCdkBui-JE7GJT5LX3SC/AWSCodeBuild-32197845-1f33-44c4-a9ff-d33aae93448e is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::222222:role/cdk-hnb659fds-lookup-role-222222-us-east-1 . Please make sure that this role exists in the account. If it doesn't exist, (re)-bootstrap the environment with the right '--trust', using the latest version of the CDK CLI.
I checked that arn:aws:iam::222222:role/cdk-hnb659fds-lookup-role-222222-us-east-1 exists in prod account. So it seems to me that there is a missing permission in the codebuild step. However, I did not find anything particular for CodeBuild step in this blog: https://taimos.de/blog/create-a-cicd-pipeline-for-your-cdk-app.
The permissions for role arn:aws:iam::222222:role/cdk-hnb659fds-lookup-role-222222-us-east-1 mentioned in the error message is here:
It's trust entities is:
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111:root"
},
"Action": "sts:AssumeRole"
}
]
}
Any idea what am I missing here?
Code
Pipeline config:
export const pipelineStageInfoList: PipelineStageInfo[] = [
{
stageName: "ALPHA",
awsAccount: "111111",
awsRegion: "us-east-1"
},
{
stageName: "PROD",
awsAccount: "222222",
awsRegion: "us-east-1"
}
]
Pipeline stack:
export class PipelineStack extends Cdk.Stack {
constructor(scope: Cdk.App, id: string, props: PipelineStackProps) {
super(scope, id, props);
// Initialize the pipeline
const pipeline = new pipelines.CodePipeline(this, "Pipeline", {
pipelineName: "eCommerceDatabasePipeline",
// Create KMS keys for the artifact buckets,
// allowing cross-account deployments
crossAccountKeys: true,
// allow the pipeline to reconfigure itself when assets or stages
// are being added to it
selfMutation: true,
// synth is expected to produce the CDK Cloud Assembly as its output
synth: new pipelines.ShellStep("Synth", {
input: pipelines.CodePipelineSource.gitHub(
"pandanyc/eCommerceDatabaseCdk",
"main",
{
authentication: Cdk.SecretValue.secretsManager('github-token')
}
),
// Install dependencies, build and run cdk synth
commands: [
'npm ci',
'npm run build',
'npx cdk synth'
],
}),
});
// Add stages to this pipeline.
pipelineStageInfoList.forEach((pipelineStage: PipelineStageInfo) => {
pipeline.addStage(
new ApplicationStage(this, pipelineStage.stageName, {
stageName: pipelineStage.stageName,
pipelineName: props.pipelineName,
env: {
account: pipelineStage.awsAccount,
region: pipelineStage.awsRegion,
},
})
);
});
}
}
If you want to perform lookups in the pipeline itself, your synth step has to have the explicit permission to assume the lookup role. You would add it like this:
synth: new pipelines.CodeBuildStep("Synth", {
input: pipelines.CodePipelineSource.gitHub(
"pandanyc/eCommerceDatabaseCdk",
"main",
{
authentication: Cdk.SecretValue.secretsManager('github-token')
}
),
// Install dependencies, build and run cdk synth
commands: [
'npm ci',
'npm run build',
'npx cdk synth'
],
rolePolicyStatements: [ iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['sts:AssumeRole'],
resources: ['*'],
conditions: { StringEquals: { 'iam:ResourceTag/aws-cdk:bootstrap-role': 'lookup' } }
}]
}),
It is also worth noting, however, that this is advised against in the Best Practices. Here's an excerpt, but I suggest you check out the whole thing:
AWS CDK includes a mechanism called context providers to record a
snapshot of non-deterministic values, allowing future synthesis
operations produce exactly the same template. The only changes in the
new template are the changes you made in your code. When you use a
construct's .fromLookup() method, the result of the call is cached in
cdk.context.json, which you should commit to version control along
with the rest of your code to ensure future executions of your CDK app
use the same value.
What this means in practice is that you should run cdk synth once locally, which will perform all the necessary lookups and store the results in cdk.context.json. You should then commit that, and your pipeline will use these cached values instead of doing the lookup every time.
As a result, your synth step also won't need to assume the lookup role.

When I add this BucketDeployment to my CDK CodePipeline, cdk synth never finishes

I'm trying to use CDK and CodePipeline to build and deploy a React application to S3. After the CodePipeline phase, in my own stack, I defined the S3 bucket like this:
const bucket = new Bucket(this, "Bucket", {
websiteIndexDocument: "index.html",
websiteErrorDocument: "error.html",
})
which worked. And then I defined the deployment of my built React app like this:
new BucketDeployment(this, "WebsiteDeployment", {
sources: [Source.asset("./")],
destinationBucket: bucket
})
which doesn't seem to work. Is that use of BucketDeployment correct?
Something odd that happens when I add the BucketDeployment lines is that cdk synth or cdk deploy, they never finish and they seem to generate an infinite recursive tree in cdk.out, so something definitely seems wrong there.
And if I change to Source.asset("./build") I get the error:
> cdk synth
C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\core\lib\asset-staging.ts:109
throw new Error(`Cannot find asset at ${this.sourcePath}`);
^
Error: Cannot find asset at C:\Users\pupeno\Code\ww3fe\build
at new AssetStaging (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\core\lib\asset-staging.ts:109:13)
at new Asset (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-assets\lib\asset.ts:72:21)
at Object.bind (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\source.ts:55:23)
at C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\bucket-deployment.ts:170:83
at Array.map (<anonymous>)
at new BucketDeployment (C:\Users\pupeno\Code\ww3fe\node_modules\aws-cdk-lib\aws-s3-deployment\lib\bucket-deployment.ts:170:51)
at new MainStack (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:16:9)
at new DeployStage (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:28:26)
at new PipelineStack (C:\Users\pupeno\Code\ww3fe\infra\pipeline-stack.ts:56:24)
at Object.<anonymous> (C:\Users\pupeno\Code\ww3fe\infra\pipeline.ts:6:1)
Subprocess exited with error 1
which would indicate this is very wrong. Why is it searching for the build directory on my machine? It's supposed to search for it in CodePipeline, after building.
My whole pipeline is:
import {Construct} from "constructs"
import {CodeBuildStep, CodePipeline, CodePipelineSource} from "aws-cdk-lib/pipelines"
import {Stage, CfnOutput, StageProps, Stack, StackProps} from "aws-cdk-lib"
import {Bucket} from "aws-cdk-lib/aws-s3"
import {BucketDeployment, Source} from "aws-cdk-lib/aws-s3-deployment"
export class MainStack extends Stack {
constructor(scope: Construct, id: string, props?: StageProps) {
super(scope, id, props)
const bucket = new Bucket(this, "Bucket", {
websiteIndexDocument: "index.html",
websiteErrorDocument: "error.html",
})
new BucketDeployment(this, "WebsiteDeployment", {
sources: [Source.asset("./")],
destinationBucket: bucket
})
new CfnOutput(this, "BucketOutput", {value: bucket.bucketArn})
}
}
export class DeployStage extends Stage {
public readonly mainStack: MainStack
constructor(scope: Construct, id: string, props?: StageProps) {
super(scope, id, props)
this.mainStack = new MainStack(this, "example")
}
}
export class PipelineStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props)
const pipeline = new CodePipeline(this, id, {
pipelineName: id,
synth: new CodeBuildStep("Synth", {
input: CodePipelineSource.connection("user/example", "main", {
connectionArn: "arn:aws:codestar-connections:....",
}),
installCommands: [
"npm install -g aws-cdk"
],
commands: [
"npm ci",
"npm run build",
"npx cdk synth"
]
}
),
})
const deploy = new DeployStage(this, "Staging")
const deployStage = pipeline.addStage(deploy)
}
}
The actual error I'm experiencing in AWS is this:
[Container] 2022/01/25 20:28:27 Phase complete: BUILD State: SUCCEEDED
[Container] 2022/01/25 20:28:27 Phase context status code: Message:
[Container] 2022/01/25 20:28:27 Entering phase POST_BUILD
[Container] 2022/01/25 20:28:27 Phase complete: POST_BUILD State: SUCCEEDED
[Container] 2022/01/25 20:28:27 Phase context status code: Message:
[Container] 2022/01/25 20:28:27 Expanding base directory path: cdk.out
[Container] 2022/01/25 20:28:27 Assembling file list
[Container] 2022/01/25 20:28:27 Expanding cdk.out
[Container] 2022/01/25 20:28:27 Skipping invalid file path cdk.out
[Container] 2022/01/25 20:28:27 Phase complete: UPLOAD_ARTIFACTS State: FAILED
[Container] 2022/01/25 20:28:27 Phase context status code: CLIENT_ERROR Message: no matching base directory path found for cdk.out
In case it matters, by cdk.json, in the root of my repo, contains:
{
"app": "npx ts-node --project infra/tsconfig.json --prefer-ts-exts infra/pipeline.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"#aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
"#aws-cdk/core:stackRelativeExports": true,
"#aws-cdk/aws-rds:lowercaseDbIdentifier": true,
"#aws-cdk/aws-lambda:recognizeVersionProps": true,
"#aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true
}
}
TL;DR With two changes, the pipeline successfully deploys the React app: (1) Source.asset needs the full path to the build directory and (2) the React build commands need to be added to the synth step.
Give Source.asset the full path to the React build dir:
new BucketDeployment(this, "WebsiteDeployment", {
sources: [Source.asset(path.join(__dirname, './build'))], // relative to the Stack dir
destinationBucket: bucket
})
React build artifacts are typically .gitignored, so CodePipeline needs to build the React app. My version has a separate package.json for the React app, so the build step 1 needs a few more commands:
synth: new pipelines.CodeBuildStep('Synth', {
commands: [
// build react (new)
'cd react-app', // path from project root to React app package.json
'npm ci',
'npm run build',
'cd ..',
// synth cdk (as in OP)
"npm ci",
"npm run build",
"npx cdk synth" // synth must run AFTER the React build step
],
The React app deploys to a S3 URL:
// MainStack
new cdk.CfnOutput(this, 'WebsiteUrl', {
value: `http://${this.websiteBucket.bucketName}.s3-website-${this.region}.amazonaws.com`,
});
(1) pipelines.CodePipeline is an opinionated construct for deploying Stacks. The lower-level codepipeline.Pipeline construct has features many apps will need, such as separating build steps and the passing build-time env vars between steps (e.g. injecting the API URL into the client bundle using a REACT_APP_API_URL env var).
For the first question:
And if I change to Source.asset("./build") I get the error: ... Why is it searching for the build directory on my machine?
This is happening when you run cdk synth locally. Remember, cdk synth will always reference the file system where this command is run. Locally it will be your machine, in the pipeline it will be in the container or environment that is being used by AWS CodePipeline.
Dig a little deeper into BucketDeployment
But also, there is some interesting things that happen here that could be helpful. BucketDeployment doesn't just pull from the source you reference in BucketDeployment.sources and upload it to the bucket you specify in BucketDeployment.destinationBucket. According to the BucketDeployment docs the assets are uploaded to an intermediary bucket and then later merged to your bucket. This matters because it will explain your error received Error: Cannot find asset at C:\Users\pupeno\Code\ww3fe\build because when you run cdk synth it will expect the dir ./build as stated in Source.asset("./build") to exist.
This gets really interesting when trying to use a CodePipeline to build and deploy a single page app like React in your case. By default, CodePipeline will execute a Source step, followed a Synth step, then any of the waves or stages you add after. Adding a wave that builds your react app won't work right away because we now see that the output directory of building you react app is needed during the Synth step because of how BucketDeployment works. We need to be able to have the order be Source -> Build -> Synth -> Deploy. As found in this question, we can control the order of the steps by using inputs and outputs. CodePipeline will order the steps to ensure input/output dependencies are met. So we need the have our Synth step use the Build's output as its input.
Concerns with the currently defined pipeline
I believe that your current pipeline is missing a CodeBuildStep that would bundle your react app and output it to the directory that you specified in BucketDeployment.sources. We also need to set the inputs to order these actions correctly. Below are some updates to the pipeline definition, though some changes may need to be made to have the correct file paths. Also, set BucketDeployment.sources to the dir where your app bundle is written to.
export class PipelineStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props)
const sourceAction = CodePipelineSource.connection("user/example", "main", {
connectionArn: "arn:aws:codestar-connections:....",
});
const buildAction = new CodeBuildStep("Build", {
input: sourceAction, // This places Source first
installCommands: [ "npm ci" ],
commands: [ "npm run build" ], // Change this to your build command for your react app
// We need to output the entire contents of our file structure
// this is both the CDK code needed for synth and the bundled app
primaryOutputDirectory: "./",
});
const synthAction = new ShellStep("Synth", {
input: buildAction, // This places Synth after Build
installCommands: [
"npm install -g aws-cdk"
],
commands: [
"npm ci",
"npm run build",
"npx cdk synth"
],
// Synth step must output to cdk.out
// if your CDK code is nested, this will have to match that structure
primaryOutputDirectory: "./cdk.out",
});
const pipeline = new CodePipeline(this, id, {
pipelineName: id,
synth: synthAction,
});
const deploy = new DeployStage(this, "Staging");
const deployStage = pipeline.addStage(deploy);
}
}
Take a look in your gitignore file if some files like json or html files are not commited to be pushed into Repo.

Serverless command "invoke test" not found. Run "serverless help" for a list of all available commands

I have my serverless.yml like below
service: omy-api
provider:
name: aws
runtime: nodejs14.x
region: ${opt:region, 'us-east-1'}
stage: ${opt:stage, 'devint'}
memorySize: 128
timeout: 15
custom:
jest:
collectCoverage: true
functions:
- ${file(config/Customer/delete.yml)}
plugins:
- serverless-jest-plugin
in my package.json I have
{
"name": "omy-api",
"version": "1.0.0",
"scripts": {
"deploy": "sls deploy",
"test": "jest"
},
"jest": {
"collectCoverage": true,
"coverageReporters": ["text-summary"],
"coverageThreshold": {
"global": {
"branches": 90,
"functions": 90,
"lines": 90,
"statements": -10
}
}
},
"author": "",
"license": "ISC",
"devDependencies": {
"serverless": "^1.83.3",
"serverless-jest-plugin": "^0.3.0",
},
"dependencies": {
"jest": "^27.0.6"
}
}
am following the https://github.com/nordcloud/serverless-jest-plugin documentation.
when i run sls invoke test, I get the error
Serverless Error ----------------------------------------
Serverless command "invoke test" not found. Run "serverless help" for a list of all available commands.
I tried sls invoke test --help, but I get the same error.
If you want to run it by entering a command like below, you must first install serverless and the serverless plugins you use globally, for example
npm install -g serverless
npm install -g serverless-jest-plugin
and run
sls invoke test

create resources using given template file using CDK with pipeline automation

[![codecommit containing cloudformation template][1]][1]I have a requirement where I need to create pipeline which is responsible for taking template yaml file as an input and create resources accordingly.
The approach which I took is providing the path of template yaml file in codebuild stage with command as:
"aws cloudformation deploy --template-file D:/pipeline/aws-waf.yml --stack-name waf-deployment"
export class PipelineStack extends Stack {
constructor(app: App, id: string, props: PipelineStackProps) {
super(app, id, props);
const code = codecommit.Repository.fromRepositoryName(this, 'ImportedRepo',
props.repoName);
const cdkBuild = new codebuild.PipelineProject(this, 'CdkBuild', {
buildSpec: codebuild.BuildSpec.fromObject({
version: '0.2',
phases: {
install: {
commands: 'npm install',
},
build: {
commands: [
'npm run build',
'npm run cdk synth -- -o dist',
'aws cloudformation deploy --template-file D:/pipeline/aws-waf.yml --stack-name waf-deployment',
'echo $?'
],
},
},
artifacts: {
'base-directory': 'dist',
files: [
'LambdaStack.template.json',
],
},
}),
environment: {
buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3,
},
});
const sourceOutput = new codepipeline.Artifact();
const cdkBuildOutput = new codepipeline.Artifact('CdkBuildOutput');
//const lambdaBuildOutput = new codepipeline.Artifact('LambdaBuildOutput');
new codepipeline.Pipeline(this, 'Pipeline', {
stages: [
{
stageName: 'Source',
actions: [
new codepipeline_actions.CodeCommitSourceAction({
actionName: 'CodeCommit_Source',
repository: code,
output: sourceOutput,
}),
],
},
{
stageName: 'Build',
actions: [
new codepipeline_actions.CodeBuildAction({
actionName: 'CDK_Build',
project: cdkBuild,
input: sourceOutput,
outputs: [cdkBuildOutput],
}),
],
},
],
});
}
}
```[![enter image description here][2]][2]
[1]: https://i.stack.imgur.com/u7rRe.jpg
[2]: https://i.stack.imgur.com/xzk6v.png
Im not fully sure of exactly what you are looking for so maybe consider updating your question to be more specific. However, I took the question as you are looking for the correct way to deploy cloud formation/cdk given a file in a codepipeline?
The way that we handle deployments of cloudformation via codepipeline is by leverage codebuild and codedeploy. The pipeline sources the file / change from a repository (optional, could use many other triggers), codebuild then uploads the file to s3 using the aws cli, once that file has been uploaded to s3 you can use codedeploy to deploy cloudformation from a source file in s3.
So for your example above, I would update the build to upload the new artifact to s3, and then create a new step in your pipeline to use codedeploy to deploy that s3 template.
Its entirely possible to build a script/codebuild commands to do the cloudformation deploy as well but because codedeploy already supports tracking that change, error handling etc I would recommend using a codedeploy for cloudformation deploys.
Note:
if you are not using an existing cloudformation template (json/yaml) and instead using cdk you will need synthesize your cdk into a cloudformation template before uploading to s3.