40

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
danronmoon
  • 3,814
  • 5
  • 34
  • 56
pkpk
  • 641
  • 1
  • 7
  • 18

7 Answers7

49

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
  • 9,640
  • 4
  • 43
  • 72
  • 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
  • 3
    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,320
  • 10
  • 20
  • 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
  • That looks convoluted. `[[ $CODEBUILD_BUILD_SUCCEEDING = 1 ]] && echo Build completed on $(date)` is hardly longer and doesn't need a script. – David Ongaro Feb 23 '23 at 21:38
13

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
  • 4,107
  • 5
  • 50
  • 60
  • 2
    Surely, you meant `\"` instead of `/"` for escaping, right? I used backslash and it worked. – Nick Aug 16 '21 at 11:54
7

add this in build section

build:
     on-failure: ABORT
Seifolah
  • 341
  • 3
  • 14
  • IMHO this should be the accepted answer as it's what the official docs are saying => https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html – yactouat Oct 02 '22 at 11:14
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
  • 11,389
  • 6
  • 45
  • 40
1

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
  • 161
  • 5
1

captainblack- I have used his bash command and it worked

bash -c "if [ /"$CODEBUILD_BUILD_SUCCEEDING/" == /"0/" ]; then exit 1; fi"

I have added bash command in the buildspec.yml file from where you want other pipelines to get trigger. so it would first check if that pipeline is getting successful, only then other pipelines that you have mentioned get released.

post_build: commands:

  - bash -c "if [ /"$CODEBUILD_BUILD_SUCCEEDING/" == /"0/" ]; 
    then exit 1; fi"
  - aws codepipeline start-pipeline-execution --name pipelinename
  - aws codepipeline start-pipeline-execution --name pipelinename
  - aws codepipeline start-pipeline-execution --name pipelinename
veena dega
  • 11
  • 4