CodeBuild execution continues after build fails instead of stopping

Viewed 24682

I'm building a CI/CD pipeline using git, codebuild and elastic beanstalk.

During codebuild execution when build fails due to syntax error of a test case, I see codebuild progress to next stage and ultimately go on to produce the artifacts.

My understanding was if the build fails, execution should stop. is this a correct behavior ?

Please see the buildspec below.

    version: 0.2

    phases:
      install:
        commands:
          - echo Installing package.json..
          - npm install
          - echo Installing Mocha...
          - npm install -g mocha
      pre_build:
        commands:
          - echo Installing source NPM placeholder dependencies...
      build:
        commands:
          - echo Build started on `date`
          - echo Compiling the Node.js code
          - mocha modules/**/tests/*.js
      post_build:
        commands:
          - echo Build completed on `date`
    artifacts:
      files:
        - modules/*
        - node_modules/*
        - package.json
        - config/*
        - server.js
6 Answers

CodeBuild detects build failures by exit codes. You should ensure that your test execution returns a non-zero exit code on failure.

POST_BUILD will always run as long as BUILD was also run (regardless of BUILD's success or failure.) The same goes for UPLOAD_ARTIFACTS. This is so you can retrieve debug information/artifacts.

If you want to do something different in POST_BUILD depending on the success or failure of BUILD, you can test the builtin environment variable CODEBUILD_BUILD_SUCCEEDING, which is set to 1 if BUILD succeeded, and 0 if it failed.

CodeBuild uses the environment variable CODEBUILD_BUILD_SUCCEEDING to show if the build process seems to go right.

the best way I found right now is to create a small script in the install secion and then alway use this like:

phases:
  install:
    commands:
      - echo '#!/bin/bash' > /usr/local/bin/ok; echo 'if [[ "$CODEBUILD_BUILD_SUCCEEDING" == "0" ]]; then exit 1; else exit 0; fi' >> /usr/local/bin/ok; chmod +x /usr/local/bin/ok
  post_build:
    commands:
      - ok && echo Build completed on `date`

The post_build section is run even if the build section might fail. Expanding on the previous answers, you can use the variable CODEBUILD_BUILD_SUCCEEDING in the post_build section of the buildspec.yml file. You can make the post_build section to run if and only if the build section completed successfully. Below is an example of how this can be achieved:

version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region $AWS_DEFAULT_REGION)
      - CODEBUILD_RESOLVED_SOURCE_VERSION="${CODEBUILD_RESOLVED_SOURCE_VERSION:-$IMAGE_TAG}"
      - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_URI="$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG"
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $IMAGE_URI .
  post_build:
    commands:
      - bash -c "if [ /"$CODEBUILD_BUILD_SUCCEEDING/" == /"0/" ]; then exit 1; fi"
      - echo Build stage successfully completed on `date`
      - docker push $IMAGE_URI
      - printf '[{"name":"clair","imageUri":"%s"}]' "$IMAGE_URI" > images.json
artifacts:
  files: images.json

I just wanted to point out that if you want the whole execution to stop when a command fails, you may specify the -e option:

  • When running a bash file

      - /bin/bash -e ./commands.sh
    
  • Or when running a set of commands/bash file

    #!/bin/bash
    
    set -e
    
    # ... commands
    

add this in build section

build:
     on-failure: ABORT

The post_build stage will be executed and the artifacts will be produced. The post_build is good to properly shut down the build environment, if necessary, and the artifacts could be useful even if the build failed. E.g. extra logs, intermediate files, etc.

I would suggest to use post_build only for commands what are agnostic to the result of your build, and properly de-initialise the build environment. Otherwise you can just exclude that step.

Related