20

I'm setup AWS CodeBuild to build automatically from GitHub. Other CI services provide an environment variable for the branch, but I can't find one for AWS CodeBuild. There is a CODEBUILD_SOURCE_VERSION that is set to either pr/7 where 7 is the pull request number or the git commit sha.

Given the commit sha, I've been trying to get the branch name, but no luck so far.

git branch --contains <commitsha> doesn't work because it is a detached head. How do I get the git branch for the commit from CodeBuild?

Yves M.
  • 26,153
  • 20
  • 93
  • 125
Cameron Taggart
  • 5,047
  • 3
  • 35
  • 62

5 Answers5

21

You can get inspired by https://github.com/thii/aws-codebuild-extras

⚠️I don't recommend to run the curl command for security sake! If some vilain stole access to the thii/aws-codebuild-extras repo, you are screwed!

Just copy paste the script (understand it!) and add it to your docker image and then call it from your file system.

#!/bin/bash

export CI=true
export CODEBUILD=true

export CODEBUILD_GIT_BRANCH=`git symbolic-ref HEAD --short 2>/dev/null`
if [ "$CODEBUILD_GIT_BRANCH" == "" ] ; then
  CODEBUILD_GIT_BRANCH=`git branch -a --contains HEAD | sed -n 2p | awk '{ printf $1 }'`
  export CODEBUILD_GIT_BRANCH=${CODEBUILD_GIT_BRANCH#remotes/origin/}
fi

export CODEBUILD_GIT_MESSAGE=`git log -1 --pretty=%B`
export CODEBUILD_GIT_AUTHOR=`git log -1 --pretty=%an`
export CODEBUILD_GIT_AUTHOR_EMAIL=`git log -1 --pretty=%ae`
export CODEBUILD_GIT_COMMIT=`git log -1 --pretty=%H`
export CODEBUILD_GIT_TAG=`git describe --tags --abbrev=0`

export CODEBUILD_PULL_REQUEST=false
if [[ $CODEBUILD_GIT_BRANCH == pr-* ]] ; then
  export CODEBUILD_PULL_REQUEST=${CODEBUILD_GIT_BRANCH#pr-}
fi

export CODEBUILD_PROJECT=${CODEBUILD_BUILD_ID%:$CODEBUILD_LOG_PATH}
export CODEBUILD_BUILD_URL=https://$AWS_DEFAULT_REGION.console.aws.amazon.com/codebuild/home?region=$AWS_DEFAULT_REGION#/builds/$CODEBUILD_BUILD_ID/view/new

echo "==> AWS CodeBuild Extra Environment Variables:"
echo "==> CI = $CI"
echo "==> CODEBUILD = $CODEBUILD"
echo "==> CODEBUILD_GIT_AUTHOR = $CODEBUILD_GIT_AUTHOR"
echo "==> CODEBUILD_GIT_AUTHOR_EMAIL = $CODEBUILD_GIT_AUTHOR_EMAIL"
echo "==> CODEBUILD_GIT_BRANCH = $CODEBUILD_GIT_BRANCH "
echo "==> CODEBUILD_GIT_COMMIT = $CODEBUILD_GIT_COMMIT"
echo "==> CODEBUILD_GIT_MESSAGE = $CODEBUILD_GIT_MESSAGE"
echo "==> CODEBUILD_GIT_TAG = $CODEBUILD_GIT_TAG"
echo "==> CODEBUILD_PROJECT = $CODEBUILD_PROJECT"
echo "==> CODEBUILD_PULL_REQUEST = $CODEBUILD_PULL_REQUEST"
Yves M.
  • 26,153
  • 20
  • 93
  • 125
  • @joe-bowbeer Can you provide us with a lin the the doc that states that? Thanks! I then will update my answer – Yves M. Jul 17 '18 at 15:06
  • 1
    The CodeBuild spec states: "Do not set any environment variable with a name that begins with CODEBUILD_" -- https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html – Joe Bowbeer Jul 17 '18 at 20:58
  • 3
    Codebuild is no longer happy with this. – Andy Hayden Dec 17 '18 at 23:04
17

It's now possible to obtain this information directly from CodeBuild environmental variables:

  • CODEBUILD_WEBHOOK_BASE_REF: The base reference name of the webhook event that triggers the current build. For a pull request, this is the branch reference.
  • CODEBUILD_WEBHOOK_HEAD_REF: The head reference name of the webhook event that triggers the current build. It can be a branch reference or a tag reference.
  • CODEBUILD_WEBHOOK_TRIGGER: Shows the webhook event that triggered the build. This variable is available only for builds triggered by a webhook. The value is parsed from the payload sent to CodeBuild by Github, Github Enterprise, or Bitbucket. The value's format depends on what type of event triggered the build.
    • For builds triggered by a pull request, it is pr/pull-request-number.
    • For builds triggered by creating a new branch or pushing a commit to a branch, it is branch/branch-name.
    • For builds triggered by a pushing a tag to a repository, it is tag/tag-name.
Zdenek F
  • 1,079
  • 1
  • 9
  • 24
  • 2
    Are there prerequisites to have access to those env vars? I tried logging them in a build but they're all coming back as empty https://imgur.com/a/pgEu8DQ – Pat Needham May 27 '20 at 01:41
  • 1
    These probably only appear when the build is actually triggered by a webhook -- manually triggering, or retrying a build that you stopped won't have them. (/guessing) – ankon Feb 05 '21 at 11:37
  • 1
    @ankon yes, that's true – Zdenek F Feb 07 '21 at 21:28
15

Add the following command to the install or pre_build phase of your buildspec.yml:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/thii/aws-codebuild-extras/master/install)"

You can get more information about the build via the following environment variables: CI, CODEBUILD, CODEBUILD_GIT_AUTHOR, CODEBUILD_GIT_AUTHOR_EMAIL, CODEBUILD_GIT_BRANCH, CODEBUILD_GIT_COMMIT, CODEBUILD_GIT_MESSAGE, CODEBUILD_GIT_TAG, CODEBUILD_PROJECT, CODEBUILD_PULL_REQUEST.

Thi
  • 1,848
  • 1
  • 14
  • 12
  • This is such a lifesaver-- thanks Thi! I was dreading building really solid Slack notifications and you just did all the heavy lifting :) – Tom Frost Jan 05 '18 at 15:34
  • 3
    ⚠️Nice! But I don't recommend to run the `curl` command for [security sake](https://en.wikipedia.org/wiki/Social_engineering_(security))! If some vilain stole access to the [thii/aws-codebuild-extras](https://github.com/thii/aws-codebuild-extras) repo, you are screwed! See https://stackoverflow.com/a/50379791/1480391 for full copy/pasted script – Yves M. May 16 '18 at 20:59
  • If you don't want to keep a local copy, at least pin to a specific version like this: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/thii/aws-codebuild-extras/b9e1d1ef105378349c2c50ee60e3af4a72d77d7b/install)"` – mahemoff Mar 12 '19 at 10:10
6

You can run:

git branch -a --contains <sha>

-a means all branches. If your sha is in no branch, which could happen in some cases, you won't see anything.

Rico
  • 48,741
  • 12
  • 84
  • 107
2

CodeBuild strips git information from the filesystem. There is no .git folder, so running a git command will be fruitless.

I have added a parameter to my CI/CD CloudFormation template:

  GitBranch:
    Description: Github branch to be deployed
    Type: String
    Default: master

And I have a Bash script that creates / updates the CI/CD stack:

readonly git_branch=$(git branch 2>/dev/null | grep "^*" | colrm 1 2)

aws cloudformation create-stack \
  --stack-name ${cicd_stack_name} \
  --parameters ParameterKey=GitBranch,ParameterValue=${git_branch}

I then export the value as an environment variable to CodeBuild machine:

CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
  Environment:
    Type: LINUX_CONTAINER
    Image: aws/codebuild/java:openjdk-8
    EnvironmentVariables:
      - Name: GIT_BRANCH
        Value: !Ref GitBranch

Now I have access to it in my buildspec.yml:

post_build:
  commands:
    - echo [PHASE] Entered the post_build phase...
    - echo "[DEBUG] Git branch ${GIT_BRANCH}"
Vadym Tyemirov
  • 6,978
  • 2
  • 39
  • 37
  • This is great, but in the reference architecture for codebuild (reference architecture for ecs continuous deployment, anyway) you must specify a fixed branch. I want codebuild to build any branch that I push, and any PRs and tags as well. Is there a reference architecture which handles all of this? (FYI the solution you proposed worked for me, within the reference architecture which has these limitations.) It would be great to get a reference architecture for CI Docker Builds from AWS which does not push ECS or Fargate, and only builds the docker images. – Kingdon Aug 21 '19 at 03:26
  • @Kingdon Thanks for the kind words! I do have a design that builds the whole stack for any given branch, not sure how referential it is but it works for me ;-) – Vadym Tyemirov Aug 21 '19 at 16:18
  • I understand now after talking to coworkers who have gone deeper that my issue is a limitation of CodePipeline, not with CodeBuild. Thanks for reply – Kingdon Aug 22 '19 at 18:11