AWS codebuild - getting the git info

Problem

  • Codebuild works only with a zip, not cloning the repository.
  • Tools like sonar-scanner don not have the access to the .git directory out of the box, so the git blame commands on code analysis fail.

Step by step solution

Allow CodeBuild to clone your repository

Give your CodeBuild execution role the permission codecommit:GitPull into the repository:

1
2
3
4
5
6
7
8
9
{
"Effect": "Allow",
"Action": [
"codecommit:GitPull"
],
"Resource": [
"arn:aws:codecommit:*:*:<YOUR_REPOSITORY_NAME>"
]
},

Give CodeBuild the git credential helper

On buildspec.yml, start like this:

1
2
version: 0.2env:
git-credential-helper: yes

Cloning the repository

Clone the repository at the right branch

1
2
TEMP_FOLDER="$(mktemp -d)"
git clone --quiet "$REPO_URL" "$TEMP_FOLDER"

Wind the repository back to the commit that is being built

Otherwise you will have a race condition between commits and builds, which could result in the wrong git metadata being used.

1
2
3
4
5
6
cd "$TEMP_FOLDER"
git fetch --tags
if [ ! -z "${BRANCH:-}" ]; then
git checkout "$BRANCH"
fi
git reset --hard "$CODEBUILD_RESOLVED_SOURCE_VERSION"

Copy the .git directory to the source tree.

1
mv .git "$WORKING_DIR"

Full shell example

Shell script

Cloning the repository is complex enough to be in a separate script which deals with this single concern and performs some error checking.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# called used environment variables come from the CFN stack
# - scripts/codebuild-git-wrapper.sh "$REPO_URL" "$REPO_BRANCH"

# This function prints the usage
function usage {
{
echo "Usage:"
echo " ${BASH_SOURCE[0]} <REPO_URL> <BRANCH>"
echo " REPO_URL - the URL for the CodeCommit repository"
echo " BRANCH - (optional) the branch to check out."
echo " Defaults to the default branch."
} >&2
}

# Confirm that there are at least two arguments
if [ "$#" -lt 1 ]; then
usage
exit 1
fi

# Confirm that CODEBUILD_RESOLVED_SOURCE_VERSION is set
if [ -z "${CODEBUILD_RESOLVED_SOURCE_VERSION:-}" ]; then
{
echo "Error: CODEBUILD_RESOLVED_SOURCE_VERSION is not set"
} >&2
usage
exit 1
fi

# Read arguments
REPO_URL="$1"
if [ ! -z "${2:-}" ]; then
BRANCH=$2
fi

# Remember the working directory
WORKING_DIR="$(pwd)"

# Check out the repository to a temporary directory
# Note that --quiet doesn't work on the current CodeBuild agents, but
# hopefully it will in the future
TEMP_FOLDER="$(mktemp -d)"
git clone --quiet "$REPO_URL" "$TEMP_FOLDER"

# Wind the repository back to the specified branch and commit
cd "$TEMP_FOLDER"
git fetch --tags
if [ ! -z "${BRANCH:-}" ]; then
git checkout "$BRANCH"
fi
git reset --hard "$CODEBUILD_RESOLVED_SOURCE_VERSION"

# Confirm that the git checkout worked
if [ ! -d .git ] ; then
{
echo "Error: .git directory missing. Git checkout probably failed"
} >&2
exit 1
fi

mv .git "$WORKING_DIR"

Buildspec

You may call that script on the buildspec.yml that uses the script and then prints the top of the git log.

1
2
3
4
5
6
version: 0.2env:
git-credential-helper: yesphases:
build:
commands:
- scripts/codebuild-git-wrapper.sh <REPO_URL> <REPO_BRANCH>
- git log | head -100