Bram Vandewalle
Bram Vandewalle

Reputation: 1664

Cannot build and deploy Go Lambda using AWS CodePipeline - BundleType must be either YAML or JSON

I am trying to build the most simple of Lambda functions in Go using AWS CodePipeline. Despite playing with it for about 2 weeks I still haven't managed to get it deployed.

main.go

package main

import (
    "context"

    "github.com/aws/aws-lambda-go/lambda"
)

func HandleRequest(ctx context.Context) (string, error) {
    return "Hello from Go!", nil
}

func main() {
    lambda.Start(HandleRequest)
}

buildspec.yml

version: 0.2

env:
  variables:
    S3_BUCKET: dlp-queuetime
    PACKAGE: dlp-queuetime-fetcher

phases:
  install: 
    runtime-versions:
      golang: 1.12
    commands:
      # AWS Codebuild Go images use /go for the $GOPATH so copy the src code into that dir structure
      - mkdir -p "/go/src/$(dirname ${PACKAGE})"
      - ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"
      # Print all environment variables (handy for AWS CodeBuild logs)
      - env
      # Install Lambda Go
      - go get github.com/aws/aws-lambda-go/lambda
  pre_build:
    commands:
      # Make sure we're in the project directory within our GOPATH
      - cd "/go/src/${PACKAGE}"
      # Fetch all dependencies
      - go get -t ./...
  build:
    commands:
      # Build our Go app
      - go build -o main
  post_build:
    commands:
      - echo Build completed on `date`
artifacts:
  type: zip
  files:
    - appspec.yml
    - main

appspec.yml

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

During the deployment CodeDeploy throws the following error: Action execution failed - BundleType must be either YAML or JSON.

It seems like CodeDeploy cannot find my appspec.yml file despite it being defined in the artifacts sections of my buildspec. What am I doing wrong here?

Upvotes: 1

Views: 1063

Answers (1)

shariqmaws
shariqmaws

Reputation: 8890

The problem you are facing is well known when connecting CodePipeline with CodeDeploy for Lambda deployment as CodeDeploy is looking for a Yaml or Json appspec file whereas the artifact presented by CodePipeline is a zip file containing the appspec:

For now, you can use CloudFormation as a Deployment tool for your Lambda function in your Pipeline. The basic idea to deploy a Lambda function will be as follows:

  1. Create a a SAM template of your Lambda function

  2. A basic SAM template looks like:

    AWSTemplateFormatVersion: '2010-09-09'
    Transform: 'AWS::Serverless-2016-10-31'
    Resources:
        FunctionName:
            Type: 'AWS::Serverless::Function'
            Properties:
                Handler: index.handler
                Runtime: nodejs6.10
                CodeUri: ./code
    
  3. Add a directory "code" and keep the lambda code files in this directory

  4. Run the command to package and upload:

    $ aws cloudformation package --template-file template.yaml --output-template packaged.yaml --s3-bucket {your_S3_bucket}
    
  5. Deploy the package:

    $ aws cloudformation deploy --template-file packaged.yaml --stack-name stk1 --capabilities CAPABILITY_IAM
    

You can keep the Template Code (Step1-2) in CodeCommit/Github and do the Step4 in a CodeBuild Step. For Step5, I recommend to do it via a CloudFormation action in CodePipeline that is fed the "packaged.yaml" file as input artifact.

The above process is detailed here: https://docs.aws.amazon.com/en_us/lambda/latest/dg/build-pipeline.html

Upvotes: 2

Related Questions