10
votes

I have an Issue with CodeDeploy and AWS Lambda when they work inside AWS CodePipeline. This is my setup:

  1. Source GitHub
  2. AWS CodeBuild
  3. AWS CodeDeploy

The Issue

Step 1. and 2. work without a problem, but when it comes to CodeDeploy I get the following error:

Action execution failed BundleType must be either YAML or JSON

If I unzip the Artifact generated by CodeBuild all the files are in place.

If I try to manually deploy to AWS Lambda from CodeDeploy I then get a different message...

Deployment Failed The deployment failed because either the target Lambda function FUNCTION_NAME does not exist or the specified function version or alias cannot be found

This is very confusion as to which Error message is valid, or if they are the same but have a different Error message.

The Setup

The ARN of the function is:

arn:aws:lambda:us-east-1:239748505547:function:email_submition

The ARN for the Alias is:

arn:aws:lambda:us-east-1:239748505547:function:email_submition:default

And my appspec.yml file has the following content

version: 0.0
Resources:
  - email_submition:
      Type: AWS::Lambda::Function
      Properties:
        Name: "email_submition"
        Alias: "default"
        CurrentVersion: "1"
        TargetVersion: "2"

And the folder structure of the project is:

.gitignore
appspec.yml
buildspec.yml
index.js
README.md

Question

What am I missing in this configuration?

2
Is that definately the alias you created? The default is normally :latestPandelis
This is what I have arn:aws:lambda:us-east-1:239748505547:function:email_submition:defaultDavid Gatti
Its odd, but for Lambda or ECS deployments the file should be "appspec.yaml". For EC2/On prem its "appspec.yml"steve y

2 Answers

10
votes

So really this should be a comment not an answer. I do not have 50 rep yet so it's here.

I am having the same issues as you. I'm not sure if you found a solution or not. I was able to successfully execute a deployment with the following appspec.yml:

version: 0.0
Resources:
    - mylambdafunction:
        Type: AWS::Lambda::Function
        Properties:
            Name: "mylambdafunction"
            Alias: "staging"
            CurrentVersion: "2"
            TargetVersion: "3"

Both the current version and target version had to exist before CodeDeploy would work. Of course I've tested this by doing a manual deployment.

I think what is needed here is something that actually updates the code and creates a new version. Which is what I would have thought CodeDeploy would do.

Edit: Further research has yielded information about CodePipeline I hadn't realized.

Per here it looks like to run through the Pipeline you need your buildspec, appspec, and a cft. The reason the pipeline fails is because you need to include a CloudFormation Template for the lambda function, this is what deploys the actual code. The appspec.yml is there to migrate traffic from the old version to the new version but the cft is what does the deployment of new code.

Edit2: This example app got me squared away. Use CodeBuild to build your app but also to generate your CFT for doing actual deployment. This means you build your CFT with the lambda resource. This removes appspec completely from the resources and instead you use a CFT to define the Lambda function. Here is a link to the SAM docs.

6
votes

I can not help you with the CodeBuild part as I use a 3rd party CI solution but maybe I can help with the rest.

I think there is a mistake in the AWS documentation as I've never been able to get this to work either. They say to call "aws deploy push" on the command line and give it your appspec.yml file instead of a zip for Lambda, but no matter what you do, you will always get the error:

Action execution failed BundleType must be either YAML or JSON

I think this is because push automatically calls "register-application-revision" after it uploads. If you split this into separate parts, this will work.

Your appspec.yml should look like the

version: 0.0 Resources: - YourFunctionName: Type: "AWS::Lambda::Function" Properties: Name: "YourFunctionName" Alias: "YourFunctionNameAlias" CurrentVersion: "CurrentAliasVersionGoesHere" TargetVersion: "NewlyPublishedVersionGoesHere"

The version you use should be the version the current alias is attached to. The target version should be the new version you just published (see below) This part still confusing me a bit. I don't understand why it can't figure out what the current version the alias is pointing to by itself.

Also, note that you can always just upload new code for your Lambda code with update-function-code and it will overwrite the latest version. Or you can publish which will create a new version and always just call the latest version. CodeDeploy is only necessary if you want to do some fancy gradually deployment or have different versions for test and live code.

I'd try the following:

  1. Publish your lambda function:

aws lambda update-function-code --function-name YourFunction --zip-file fileb://~/your-code.zip --publish

Take note of the version number it created

  1. Upload your appspec.yml file to S3

aws s3 cp appspec.yml s3://your-deploy-bucket/your-deploy-dir/appspec.yml

  1. Register your application revision:

aws deploy register-application-revision --application-name YourApplcationName --s3-location bucket=your-deploy-bucket,key=your-deploy-dir/appspec.yml,bundleType=YAML

From the CLI this won't appear to do anything, but it did.

  1. Get the application revision to make sure it worked

aws deploy get-application-revision --application-name YourApplcationName --s3-location bucket=your-deploy-bucket,key=your-deploy-dir/appspec.yml,bundleType=YAML

  1. Create a deployment to deploy your code

aws deploy create-deployment --s3-location bucket=your-deploy-bucket,key=your-deploy-dir/appspec.yml,bundleType=YAML