32

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 ultimatly 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
shaedrich
  • 1,879
  • 18
  • 24
pkpk
  • 529
  • 1
  • 5
  • 14

6 Answers6

39

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.

Unsigned
  • 8,731
  • 4
  • 40
  • 67
  • I'm trying to use the same logic, but when my tests fail CODEBUILD_BUILD_SUCCEEDING still equals 1. Do you manually update this environment variable upon failing? – Dakota Hipp Sep 01 '18 at 06:56
  • 1
    @DakotaHipp Make sure that whatever `buildspec.yml` command you're using to execute your tests returns a non-zero exit code on failure. `CODEBUILD_BUILD_SUCCEEDING` is informational only, changing it manually will not affect the build outcome. – Unsigned Sep 01 '18 at 17:34
  • I was forced to manually change the CODE_BUILD_SUCCEEDING variable upon test failure, then I am checking that variable at later steps with an if statement similar to the other answer. – Dakota Hipp Sep 02 '18 at 09:33
  • I added a line to the post_build section and let the post_build fail. The CodeBuild logs can provide you the details of the failure in the build section. `post_build: commands: - test "$CODEBUILD_BUILD_SUCCEEDING" = "1"` – bigfoot Mar 23 '21 at 12:13
14

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`
wodka
  • 1,067
  • 8
  • 17
  • I'm trying to use the same logic, but when my tests fail CODEBUILD_BUILD_SUCCEEDING still equals 1. Do you manually update this environment variable upon failing? – Dakota Hipp Sep 01 '18 at 06:56
  • Does your test case return a non zero return code? this is basically the requirement for it to change automatically. – wodka Sep 01 '18 at 08:36
  • Yeah, it fails with exit code 2. As of now, I am changing CODEBUILD_BUILD_SUCCEEDING manually. It works, but it would be better if the exit registered automatically. – Dakota Hipp Sep 01 '18 at 09:00
9

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
captainblack
  • 2,806
  • 5
  • 42
  • 49
2

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
    
EliuX
  • 7,605
  • 4
  • 35
  • 37
0

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.

Ernie Jay
  • 136
  • 5
0

add this in build section

build:
     on-failure: ABORT
Seifolah
  • 43
  • 9