3

I have the following AWS CDK pipeline which works. It basically takes source from 2 different GitHub repositories (one for the application code, one for the cdk code) and builds the application code and the cdk code :

import * as cdk from 'aws-cdk-lib';
import * as codepipeline_actions from 'aws-cdk-lib/aws-codepipeline-actions';
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline'
import * as codebuild from 'aws-cdk-lib/aws-codebuild'


import { Construct } from 'constructs';
import { CodePipeline, CodePipelineSource, ShellStep, CodeBuildStep } from 'aws-cdk-lib/pipelines';

export class CdkPipelineStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);

        // parameters
        const ConnectionArn = 'arn:aws:codestar-connections:region:account:connection/xxx-yyyy'


        // Source
        const cdkCodeStarConnection = CodePipelineSource.connection('owner/cdk-repo', 'master', {
            connectionArn: ConnectionArn
        })

        const lambdaCodeStarConnection = CodePipelineSource.connection('owner/lambda-repo', 'master', {
            connectionArn: ConnectionArn
        })

        // Building Lambda
        const lambdaBuildStep = new CodeBuildStep('BuildLambda', {
            buildEnvironment: {
                buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3
            },
            input: lambdaCodeStarConnection,
            commands: ['variouscommands'],
            partialBuildSpec: codebuild.BuildSpec.fromObject({
                phases: {
                    install: {
                        "runtime-versions": {
                            python: "3.9"
                        },
                        "commands": ["python --version"]
                    }
                }
            })
        })

        const pipeline = new CodePipeline(this, 'Pipeline', {
            pipelineName: 'Pipeline',
            synth: new ShellStep('Synth', {
                input: cdkCodeStarConnection,
                commands: ['npm ci', 'npm run build', 'npx cdk synth', 'npx cdk ls'],
                additionalInputs: { 'lambda': lambdaBuildStep.addOutputDirectory('lambda') }
            })
        });
    }
}

Now, what I would like to achieve is to be able to assign the built code (so the output of the lambdaBuildStep) to a Lambda function I have in another stack i.e. in the code snippet below, I want assign_output_CodeBuildStep to be the s3 location where lambdaBuildStep has built my function:

import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';

import { Construct } from 'constructs';
import { Bucket } from 'aws-cdk-lib/aws-s3'

import {backendBuildStep} from 'cdk-pipeline-stack'; 
import {ArtifactMap} from 'aws-cdk-lib/pipelines';


export class LambdaMonolith extends cdk.Stack {
    constructor(scope: Construct, id: string) {
        super(scope, id);

        const s3Code = assign_output_CodeBuildStep

        const LambdaFunction = new lambda.Function(this, 'MyFunction', {
            code: lambdaCode,
            runtime: lambda.Runtime.PYTHON_3_8,
            handler: 'lambda.handler',
          });
    }
};

and I can't seem to find a way to transfer that information from the pipeline stack to the Lambda stack.

Any help would be greatly appreciated.

Thanks!

1
  • Is the LambdaMonolith Stack deployed as a stage in your Pipeline pipeline? Commented Feb 3, 2022 at 9:28

1 Answer 1

1

So I found a solution. Maybe not the solution. Indeed, this seems quite convoluted ... and I am sure there is a better way.

So the solution lies in the fact that the ShellStep in the CodePipeline construct attaches the output of additionalInputs (so the result of the previous CodeBuildStep i.e. lambdaBuildStep) in a specific directory which is dynamically generated but stored in an environment variable called CODEBUILD_SRC_DIR_BuildLambda_lambda_repo so you can see it's a combination of the name of the CodeBuildStep and the repo (with the dash changed to underscores).

So my solution was to use this environment variables as my Lambda code asset.

        const LambdaFunction = new lambda.Function(this, 'MyFunction', {
            code: lambda.Code.fromAsset(process.env.CODEBUILD_SRC_DIR_BuildLambda_lambda_repo || ""),
            runtime: lambda.Runtime.PYTHON_3_8,
            handler: 'lambda.handler',
          });
Sign up to request clarification or add additional context in comments.

1 Comment

Since this post has been one and a half years, I wonder if you could achieve this in a different way without using that cryptic env var.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.