Skip to content
This repository was archived by the owner on May 4, 2021. It is now read-only.

Commit 965c18c

Browse files
author
pchico83
committed
Merge pull request #52 from tutumcloud/staging
v0.16.21
2 parents 77a526a + 5cd1fbc commit 965c18c

File tree

4 files changed

+108
-42
lines changed

4 files changed

+108
-42
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ MAINTAINER [email protected]
44
# Store github.com SSH fingerprint
55
RUN mkdir -p ~/.ssh && ssh-keyscan -H github.com | tee -a ~/.ssh/known_hosts
66

7-
ADD https://github.com/docker/compose/releases/download/1.3.2/docker-compose-linux-x86_64 /usr/local/bin/docker-compose
7+
ADD https://github.com/docker/compose/releases/download/1.3.3/docker-compose-linux-x86_64 /usr/local/bin/docker-compose
88
RUN chmod +x /usr/local/bin/docker-compose
99

1010

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ Apache License
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright {yyyy} {name of copyright owner}
189+
Copyright 2015 Tutum, Inc.
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ tutum/builder
22
=============
33

44
A docker image that builds, tests and pushes docker images from code repositories.
5+
It is used by the Tutum platform to automate build and tests. Implementation details can be found in this [blog post](http://blog.tutum.co/2015/07/21/cicd-the-docker-way/).
56

67

78
# Usage
@@ -10,7 +11,7 @@ A docker image that builds, tests and pushes docker images from code repositorie
1011

1112
Run the following docker command in the folder that you want to build and push:
1213

13-
docker run --rm -it --privileged -v $(pwd):/app -v $HOME/.dockercfg:/.dockercfg:ro tutum/builder $IMAGE_NAME
14+
docker run --rm -it --privileged -v $HOME/.dockercfg:/.dockercfg:ro -v $(pwd):/app tutum/builder $IMAGE_NAME
1415

1516
Where:
1617

@@ -23,7 +24,7 @@ This will use the `~/.dockercfg` file which should be prepopulated with credenti
2324

2425
Run the following docker command:
2526

26-
docker run --rm -it --privileged -e GIT_REPO=$GIT_REPO -e USERNAME=$USERNAME -e PASSWORD=$PASSWORD -e EMAIL=$EMAIL -e DOCKERFILE_PATH=$DOCKERFILE_PATH tutum/builder $IMAGE_NAME
27+
docker run --rm -it --privileged -v $HOME/.dockercfg:/.dockercfg:ro -e GIT_REPO=$GIT_REPO -e USERNAME=$USERNAME -e PASSWORD=$PASSWORD -e EMAIL=$EMAIL -e DOCKERFILE_PATH=$DOCKERFILE_PATH tutum/builder $IMAGE_NAME
2728

2829
Where:
2930

@@ -42,7 +43,7 @@ If you want to use a SSH key to clone your repository, mount your SSH private ke
4243

4344
Run the following docker command:
4445

45-
docker run --rm -it --privileged -e TGZ_URL=$TGZ_URL -e DOCKERFILE_PATH=$DOCKERFILE_PATH -e USERNAME=$USERNAME -e PASSWORD=$PASSWORD -e EMAIL=$EMAIL tutum/builder $IMAGE_NAME
46+
docker run --rm -it --privileged -v $HOME/.dockercfg:/.dockercfg:ro -e TGZ_URL=$TGZ_URL -e DOCKERFILE_PATH=$DOCKERFILE_PATH -e USERNAME=$USERNAME -e PASSWORD=$PASSWORD -e EMAIL=$EMAIL tutum/builder $IMAGE_NAME
4647

4748
Where:
4849

@@ -70,6 +71,8 @@ Example `docker-compose.test.yml` file for a Django app that depends on a Redis
7071
environment:
7172
- REDIS_PASS=password
7273

74+
To speed up testing, you can replace `build: .` in your `sut` service with `image: this`, which is the name of the image that is built just before running the tests. This way you can avoid building the same image twice.
75+
7376

7477
# Hooks
7578

build.sh

Lines changed: 100 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,127 +3,161 @@ set -e
33

44
IMAGE_NAME=${IMAGE_NAME:-$1}
55

6+
print_msg() {
7+
echo -e "\e[1m${1}\e[0m"
8+
}
9+
610
run_hook() {
711
HOOK=hooks/$1
812
if [ -f "$HOOK" ]; then
9-
echo "=> Executing $HOOK hook"
13+
print_msg "=> Executing $HOOK hook"
1014
./$HOOK
1115
if [ $? -ne 0 ]; then
12-
echo "ERROR: $HOOK failed with exit code $?"
16+
print_msg "ERROR: $HOOK failed with exit code $?"
1317
exit 1
1418
fi
1519
fi
1620
}
1721

1822
run_docker() {
19-
echo "=> Starting docker"
23+
print_msg "=> Starting docker"
2024
wrapdocker > /dev/null 2>&1 &
21-
echo "=> Checking docker daemon"
25+
print_msg "=> Checking docker daemon"
2226
LOOP_LIMIT=60
2327
for (( i=0; ; i++ )); do
2428
if [ ${i} -eq ${LOOP_LIMIT} ]; then
25-
echo " Failed to start docker (did you use --privileged when running this container?"
29+
print_msg " Failed to start docker (did you use --privileged when running this container?"
2630
exit 1
2731
fi
2832
sleep 1
2933
docker version > /dev/null 2>&1 && break
3034
done
3135
}
3236

37+
#
38+
# Start docker-in-docker or use an external docker daemon via mounted socket
39+
#
40+
DOCKER_USED=""
3341
EXTERNAL_DOCKER=no
3442
MOUNTED_DOCKER_FOLDER=no
3543
if [ -S /var/run/docker.sock ]; then
36-
echo "=> Detected unix socket at /var/run/docker.sock"
37-
echo "=> Testing if docker version matches"
44+
print_msg "=> Detected unix socket at /var/run/docker.sock"
45+
print_msg "=> Testing if docker version matches"
3846
if ! docker version > /dev/null 2>&1 ; then
39-
export DOCKER_VERSION=$(cat version_list | grep -P "^$(docker version 2>&1 > /dev/null | grep -iF "client and server don't have same version" | grep -oP 'server: *\d*\.\d*' | grep -oP '\d*\.\d*') .*$" | cut -d " " -f2)
47+
export DOCKER_VERSION=$(cat version_list | grep -P "^$(docker version 2>&1 > /dev/null | grep -iF "client and server don't have same version" | grep -oP 'server: *\d*\.\d*' | grep -oP '\d*\.\d*') .*$" | cut -d " " -f2)
4048
if [ "${DOCKER_VERSION}" != "" ]; then
41-
echo "=> Downloading Docker ${DOCKER_VERSION}"
49+
print_msg "=> Downloading Docker ${DOCKER_VERSION}"
4250
curl -o /usr/bin/docker https://get.docker.com/builds/Linux/x86_64/docker-${DOCKER_VERSION}
4351
fi
4452
fi
45-
docker version > /dev/null 2>&1 || { echo " Failed to connect to docker daemon at /var/run/docker.sock" && exit 1; }
53+
docker version > /dev/null 2>&1 || { print_msg " Failed to connect to docker daemon at /var/run/docker.sock" && exit 1; }
4654
EXTERNAL_DOCKER=yes
55+
DOCKER_USED="Using external docker version ${DOCKER_VERSION} mounted at /var/run/docker.sock"
4756
else
57+
DOCKER_USED="Using docker-in-docker"
4858
if [ "$(ls -A /var/lib/docker)" ]; then
49-
echo "=> Detected pre-existing /var/lib/docker folder"
59+
print_msg "=> Detected pre-existing /var/lib/docker folder"
5060
MOUNTED_DOCKER_FOLDER=yes
61+
DOCKER_USED="Using docker-in-docker with an external /var/lib/docker folder"
5162
fi
5263
run_docker
5364
fi
5465

55-
echo "=> Loading docker auth configuration"
66+
67+
#
68+
# Detect docker credentials for pulling private images and for pushing the built image
69+
#
70+
print_msg "=> Loading docker auth configuration"
5671
if [ -f /.dockercfg ]; then
57-
echo " Using existing configuration in /.dockercfg"
72+
print_msg " Using existing configuration in /.dockercfg"
5873
ln -s /.dockercfg /root/.dockercfg
5974
elif [ ! -z "$DOCKERCFG" ]; then
60-
echo " Detected configuration in \$DOCKERCFG"
75+
print_msg " Detected configuration in \$DOCKERCFG"
6176
echo "$DOCKERCFG" > /root/.dockercfg
6277
unset DOCKERCFG
6378
elif [ ! -z "$USERNAME" ] && [ ! -z "$PASSWORD" ]; then
6479
REGISTRY=$(echo $IMAGE_NAME | tr "/" "\n" | head -n1 | grep "\." || true)
65-
echo " Logging into registry using $USERNAME"
80+
print_msg " Logging into registry using $USERNAME"
6681
docker login -u $USERNAME -p $PASSWORD -e ${EMAIL-no-email@test.com} $REGISTRY
6782
else
68-
echo " WARNING: no \$USERNAME/\$PASSWORD or \$DOCKERCFG found - unable to load any credentials for pushing/pulling"
83+
print_msg " WARNING: no \$USERNAME/\$PASSWORD or \$DOCKERCFG found - unable to load any credentials for pushing/pulling"
6984
fi
7085

86+
#
87+
# Clone the specified git repository or use the mounted code in /app
88+
#
89+
SOURCE=""
7190
rm -fr /src && mkdir -p /src
72-
echo "=> Detecting application"
91+
print_msg "=> Detecting application"
7392
if [ ! -d /app ]; then
7493
if [ ! -z "$GIT_REPO" ]; then
75-
echo " Cloning repo from ${GIT_REPO##*@}"
76-
git clone $GIT_REPO /src
94+
print_msg " Cloning repo from ${GIT_REPO##*@}"
95+
git clone --recursive $GIT_REPO /src
7796
if [ $? -ne 0 ]; then
78-
echo " ERROR: Error cloning $GIT_REPO"
97+
print_msg " ERROR: Error cloning $GIT_REPO"
7998
exit 1
8099
fi
81-
unset GIT_REPO
82100
cd /src
83101
git checkout $GIT_TAG
84-
export GIT_SHA1=$(git rev-list $GIT_TAG | head -n 1)
102+
export GIT_SHA1=$(git rev-parse HEAD)
85103
export GIT_MSG=$(git log --format=%B -n 1 $GIT_SHA1)
104+
print_msg " Building commit ${GIT_SHA1}"
105+
SOURCE="Building ${GIT_REPO##*@}@${GIT_SHA1}"
106+
unset GIT_REPO
86107
elif [ ! -z "$TGZ_URL" ]; then
87-
echo " Downloading $TGZ_URL"
108+
print_msg " Downloading $TGZ_URL"
88109
curl -sL $TGZ_URL | tar zx -C /src
110+
SOURCE="Building $TGZ_URL"
89111
else
90-
echo " ERROR: No application found in /app, and no \$GIT_REPO defined"
112+
print_msg " ERROR: No application found in /app, and no \$GIT_REPO defined"
91113
exit 1
92114
fi
93115
run_hook post_checkout
94116
else
95-
echo " Using existing app in /app"
117+
SOURCE="Building mounted app in /app"
118+
print_msg " $SOURCE"
96119
cp -r /app/. /src
97120
fi
98121
cd /src${DOCKERFILE_PATH:-/}
99122
if [ -d "hooks" ]; then
100123
chmod +x hooks/*
101124
fi
102-
103125
if [ ! -f Dockerfile ]; then
104-
echo " WARNING: no Dockerfile detected! Created one using tutum/buildstep"
126+
print_msg " WARNING: no Dockerfile detected! Created one using tutum/buildstep"
105127
echo "FROM tutum/buildstep" >> Dockerfile
106128
fi
107129

108-
echo "=> Building repository"
130+
131+
#
132+
# (1/3) Build step
133+
#
134+
print_msg "=> Building repository"
135+
START_DATE=$(date +"%s")
109136
run_hook pre_build
110137
if [ -f "hooks/build" ]; then
111138
run_hook build
112139
else
113140
docker build --rm --force-rm -t this .
114141
fi
115142
run_hook post_build
143+
END_DATE=$(date +"%s")
144+
DATE_DIFF=$(($END_DATE-$START_DATE))
145+
BUILD="Image built in $(($DATE_DIFF / 60)) minutes and $(($DATE_DIFF % 60)) seconds"
116146

147+
#
148+
# (2/3) Test step
149+
#
150+
START_DATE=$(date +"%s")
117151
run_hook pre_test
118152
if [ -f "hooks/test" ]; then
119153
run_hook test
120154
else
155+
TEST="No tests found"
121156
shopt -s nullglob
122157
for TEST_FILENAME in *{.test.yml,-test.yml}
123158
do
124-
echo "=> Executing tests in $TEST_FILENAME"
125-
# Next command is to workaround the fact that docker-compose does not use .dockercfg to pull images
126-
IMAGES=$(cat ./${TEST_FILENAME} | grep "image:" | awk '{print $2}')
159+
print_msg "=> Executing tests in $TEST_FILENAME"
160+
IMAGES=$(cat ./${TEST_FILENAME} | grep -v "image: *this" | grep "image:" | awk '{print $2}')
127161
if [ ! -z "$IMAGES" ]; then
128162
echo $IMAGES | xargs -n1 docker pull
129163
fi
@@ -141,18 +175,26 @@ else
141175
docker-compose -f ${TEST_FILENAME} -p $PROJECT_NAME kill
142176
docker-compose -f ${TEST_FILENAME} -p $PROJECT_NAME rm --force -v
143177
if [ "$RET" != "0" ]; then
144-
echo " Tests in $TEST_FILENAME FAILED: $RET"
178+
print_msg " Tests in $TEST_FILENAME FAILED: $RET"
145179
exit 1
146180
else
147-
echo " Tests in $TEST_FILENAME PASSED"
181+
print_msg " Tests in $TEST_FILENAME PASSED"
182+
unset TEST
148183
fi
149184
done
150185
fi
151186
run_hook post_test
187+
END_DATE=$(date +"%s")
188+
DATE_DIFF=$(($END_DATE-$START_DATE))
189+
TEST=${TEST:-"Tests passed in $(($DATE_DIFF / 60)) minutes and $(($DATE_DIFF % 60)) seconds"}
152190

191+
#
192+
# (3/3) Push step
193+
#
194+
START_DATE=$(date +"%s")
153195
if [ ! -z "$IMAGE_NAME" ]; then
154196
if [ ! -z "$USERNAME" ] || [ -f /root/.dockercfg ]; then
155-
echo "=> Pushing image $IMAGE_NAME"
197+
print_msg "=> Pushing image $IMAGE_NAME"
156198
run_hook pre_push
157199
if [ -f "hooks/push" ]; then
158200
run_hook push
@@ -165,13 +207,34 @@ if [ ! -z "$IMAGE_NAME" ]; then
165207
# sleep 1
166208
# done
167209
run_hook post_push
168-
echo "=> Pushed image $IMAGE_NAME"
210+
print_msg " Pushed image $IMAGE_NAME"
169211
if [ "$EXTERNAL_DOCKER" == "no" ] && [ "$MOUNTED_DOCKER_FOLDER" == "no" ]; then
170-
echo "=> Cleaning up images"
212+
print_msg " Cleaning up images"
171213
docker rmi -f $(docker images -q --no-trunc -a) > /dev/null 2>&1 || true
172214
fi
173215
fi
174216
fi
175217
else
176-
echo " Skipping push"
218+
PUSH="Skipping push"
219+
print_msg " $PUSH"
177220
fi
221+
END_DATE=$(date +"%s")
222+
DATE_DIFF=$(($END_DATE-$START_DATE))
223+
PUSH=${PUSH:-"Image $IMAGE_NAME pushed in $(($DATE_DIFF / 60)) minutes and $(($DATE_DIFF % 60)) seconds"}
224+
225+
#
226+
# Final summary
227+
#
228+
echo -e "\e[1m"
229+
cat <<EOF
230+
231+
Build summary
232+
=============
233+
234+
$DOCKER_USED
235+
$SOURCE
236+
$BUILD
237+
$TEST
238+
$PUSH
239+
240+
EOF

0 commit comments

Comments
 (0)