Merge "adding --atime-preseve to try and fix caching"
[apex.git] / ci / build.sh
1 #!/bin/bash
2 set -e
3 ##############################################################################
4 # Copyright (c) 2015 Ericsson AB and others.
5 # stefan.k.berg@ericsson.com
6 # jonas.bjurel@ericsson.com
7 # dradez@redhat.com
8 # All rights reserved. This program and the accompanying materials
9 # are made available under the terms of the Apache License, Version 2.0
10 # which accompanies this distribution, and is available at
11 # http://www.apache.org/licenses/LICENSE-2.0
12 ##############################################################################
13
14 trap 'echo "Exiting ..."; \
15 if [ -f ${LOCK_FILE} ]; then \
16    if [ $(cat ${LOCK_FILE}) -eq $$ ]; then \
17       rm -f ${LOCK_FILE}; \
18    fi; \
19 fi;' EXIT
20
21 ############################################################################
22 # BEGIN of usage description
23 #
24 usage ()
25 {
26 cat << EOF
27 $0 Builds the Apex OPNFV Deployment Toolchain
28
29 usage: $0 [-s spec-file] [-c cache-URI] [-l log-file] [-f Flags] build-directory
30
31 OPTIONS:
32   -s spec-file ($BUILD_SPEC), define the build-spec file, default ../build/config.mk
33   -c cache base URI ($BUILD_CACHE_URI), specifies the base URI to a build cache to be used/updated - the name is automatically generated from the md5sum of the spec-file, http://, ftp://, file://[absolute path] suported.
34
35   -l log-file ($BUILD_LOG), specifies the output log-file (stdout and stderr), if not specified logs are output to console as normal
36   -v version tag to be applied to the build result
37   -r alternative remote access method script/program. curl is default.
38   -t run small build-script unit test.
39   -T run large build-script unit test.
40   -f build flags ($BUILD_FLAGS):
41      o s: Do nothing, succeed
42      o f: Do nothing, fail
43      o t: run build unit tests
44      o M: Use master branch code
45      o i: run interactive (-t flag to docker run)
46      o P: Populate a new local cache and push it to the (-c cache-URI) cache artifactory if -c option is present, currently file://, http:// and ftp:// are supported
47      o d: Detatch - NOT YET SUPPORTED
48
49   build-directory ($BUILD_DIR), specifies the directory for the output artifacts (.iso file).
50
51   -h help, prints this help text
52
53 Description:
54 build.sh builds opnfv .iso artifact.
55 To reduce build time it uses build cache on a local or remote location. The cache is rebuilt and uploaded if either of the below conditions are met:
56 1) The P(opulate) flag is set and the -c cache-base-URI is provided, if -c is not provided the cache will stay local.
57 2) If the cache is invalidated by one of the following conditions:
58    - The config spec md5sum does not compare to the md5sum for the spec which the cache was built.
59    - The git Commit-Id on the remote repos/HEAD defined in the spec file does not correspont with the Commit-Id for what the cache was built with.
60 3) A valid cache does not exist on the specified -c cache-base-URI.
61
62 The cache URI object name is apex_cache-"md5sum(spec file)"
63
64 Logging by default to console, but can be directed elsewhere with the -l option in which case both stdout and stderr is redirected to that destination.
65
66 Built in unit testing of components is enabled by adding the t(est) flag.
67
68 Return codes:
69  - 0 Success!
70  - 1-99 Unspecified build error
71  - 100-199 Build system internal error (not build it self)
72    o 101 Build system instance busy
73  - 200 Build failure
74
75 Examples:
76 build -c http://opnfv.org/artifactory/apex/cache -d ~/jenkins/genesis/apex/ci/output -f ti
77 NOTE: At current the build scope is set to the git root of the repository, -d destination locations outside that scope will not work
78 EOF
79 }
80 #
81 # END of usage description
82 ############################################################################
83
84 ############################################################################
85 # BEGIN of variables to customize
86 #
87 BUILD_BASE=$(readlink -e ../build/)
88 RESULT_DIR="${BUILD_BASE}/release"
89 BUILD_SPEC="${BUILD_BASE}/config.mk"
90 CACHE_DIR="cache"
91 LOCAL_CACHE_ARCH_NAME="apex-cache"
92 REMOTE_CACHE_ARCH_NAME="apex_cache-$(md5sum ${BUILD_SPEC}| cut -f1 -d " ")"
93 REMOTE_ACCESS_METHD=curl
94 INCLUDE_DIR=../include
95 #
96 # END of variables to customize
97 ############################################################################
98
99 ############################################################################
100 # BEGIN of script assigned variables
101 #
102 SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
103 LOCK_FILE="${SCRIPT_DIR}/.build.lck"
104 CACHE_TMP="${SCRIPT_DIR}/tmp"
105 TEST_SUCCEED=0
106 TEST_FAIL=0
107 UNIT_TEST=0
108 USE_MASTER=0
109 UPDATE_CACHE=0
110 POPULATE_CACHE=0
111 RECURSIV=0
112 DETACH=0
113 DEBUG=0
114 INTEGRATION_TEST=0
115 FULL_INTEGRATION_TEST=0
116 INTERACTIVE=0
117 BUILD_CACHE_URI=
118 BUILD_SPEC=
119 BUILD_DIR=
120 BUILD_LOG=
121 BUILD_VERSION=
122 MAKE_ARGS=
123 #
124 # END of script assigned variables
125 ############################################################################
126
127 ############################################################################
128 # BEGIN of include pragmas
129 #
130 source ${INCLUDE_DIR}/build.sh.debug
131 #
132 # END of include
133 ############################################################################
134
135 ############################################################################
136 # BEGIN of main
137 #
138 while getopts "s:c:d:v:f:l:r:RtTh" OPTION
139 do
140     case $OPTION in
141         h)
142             usage
143             rc=0
144             exit $rc
145             ;;
146
147         s)
148             BUILD_SPEC=${OPTARG}
149             ;;
150
151         c)
152             BUILD_CACHE_URI=${OPTARG}
153             ;;
154
155         d)
156             BUILD_DIR=${OPTARG}
157             ;;
158
159         l)
160             BUILD_LOG=${OPTARG}
161             ;;
162
163         v)
164             BUILD_VERSION=${OPTARG}
165             ;;
166
167         f)
168             BUILD_FLAGS=${OPTARG}
169             ;;
170
171         r)  REMOTE_ACCESS_METHD=${OPTARG}
172             ;;
173
174         R)
175             RECURSIVE=1
176             ;;
177
178         t)
179             INTEGRATION_TEST=1
180             ;;
181
182         T)
183             INTEGRATION_TEST=1
184             FULL_INTEGRATION_TEST=1
185             ;;
186
187         *)
188             echo "${OPTION} is not a valid argument"
189             rc=100
190             exit $rc
191             ;;
192     esac
193 done
194
195 if [ -z $BUILD_DIR ]; then
196     BUILD_DIR=$(echo $@ | cut -d ' ' -f ${OPTIND})
197 fi
198
199 for ((i=0; i<${#BUILD_FLAGS};i++)); do
200     case ${BUILD_FLAGS:$i:1} in
201         s)
202             rc=0
203             exit $rc
204             ;;
205
206         f)
207             rc=1
208             exit $rc
209             ;;
210
211         t)
212             UNIT_TEST=1
213             ;;
214
215         M)
216             USE_MASTER=1
217             ;;
218
219         i)
220             INTERACTIVE=1
221             ;;
222
223         P)
224             POPULATE_CACHE=1
225             ;;
226
227         d)
228             DETACH=1
229             echo "Detach is not yet supported - exiting ...."
230             rc=100
231             exit $rc
232             ;;
233
234         D)
235             DEBUG=1
236             ;;
237
238         *)
239             echo "${BUILD_FLAGS:$i:1} is not a valid build flag - exiting ...."
240             rc=100
241             exit $rc
242             ;;
243     esac
244 done
245
246 shift $((OPTIND-1))
247
248 if [ ${INTEGRATION_TEST} -eq 1 ]; then
249     integration-test
250     rc=0
251     exit $rc
252 fi
253
254 if [ ! -f ${BUILD_SPEC} ]; then
255     echo "spec file does not exist: $BUILD_SPEC - exiting ...."
256     rc=100
257     exit $rc
258 fi
259
260 if [ -z ${BUILD_DIR} ]; then
261     echo "Missing build directory - exiting ...."
262     rc=100
263     exit $rc
264 fi
265
266 if [ ! -z ${BUILD_LOG} ]; then
267     if [[ ${RECURSIVE} -ne 1 ]]; then
268         set +e
269         eval $0 -R $@ > ${BUILD_LOG} 2>&1
270         rc=$?
271         set -e
272         if [ $rc -ne 0]; then
273             exit $rc
274         fi
275     fi
276 fi
277
278 if [ ${TEST_SUCCEED} -eq 1 ]; then
279     sleep 1
280     rc=0
281     exit $rc
282 fi
283
284 if [ ${TEST_FAIL} -eq 1 ]; then
285     sleep 1
286     rc=1
287     exit $rc
288 fi
289
290 if [ -e ${LOCK_FILE} ]; then
291     echo "A build job is already running, exiting....."
292     rc=101
293     exit $rc
294 fi
295
296 echo $$ > ${LOCK_FILE}
297
298 if [ ! -z ${BUILD_CACHE_URI} ]; then
299     if [ ${POPULATE_CACHE} -ne 1 ]; then
300         rm -rf ${CACHE_TMP}/cache
301         mkdir -p ${CACHE_TMP}/cache
302         echo "Downloading cach file ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME} ..."
303         set +e
304         ${REMOTE_ACCESS_METHD} -o ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME}.tgz
305         rc=$?
306         set -e
307         if [ $rc -ne 0 ]; then
308                 echo "Remote cache does not exist, or is not accessible - a new cache will be built ..."
309                 POPULATE_CACHE=1
310         else
311             echo "Unpacking cache file ..."
312             tar --atime-preserve -C ${CACHE_TMP}/cache -xvf ${CACHE_TMP}/cache/${LOCAL_CACHE_ARCH_NAME}.tgz
313             cp ${CACHE_TMP}/cache/cache/.versions ${BUILD_BASE}/.
314             set +e
315             make -C ${BUILD_BASE} validate-cache;
316             rc=$?
317             set -e
318
319             if [ $rc -ne 0 ]; then
320                 echo "Cache invalid - a new cache will be built "
321                 POPULATE_CACHE=1
322             else
323                 cp -rf ${CACHE_TMP}/cache/cache/. ${BUILD_BASE}
324             fi
325             rm -rf ${CACHE_TMP}/cache
326         fi
327     fi
328 fi
329
330 if [ ${POPULATE_CACHE} -eq 1 ]; then
331     if [ ${DEBUG} -eq 0 ]; then
332         set +e
333         cd ${BUILD_BASE} && make clean
334         rc=$?
335         set -e
336         if [ $rc -ne 0 ]; then
337             echo "Build - make clean failed, exiting ..."
338             rc=100
339             exit $rc
340         fi
341     fi
342 fi
343
344 if [ ! -z ${BUILD_VERSION} ]; then
345     MAKE_ARGS+="REVSTATE=${BUILD_VERSION} "
346 fi
347
348 if [ ${UNIT_TEST} -eq 1 ]; then
349     MAKE_ARGS+="UNIT_TEST=TRUE "
350 else
351     MAKE_ARGS+="UNIT_TEST=FALSE "
352 fi
353
354 if [ ${USE_MASTER} -eq 1 ]; then
355     MAKE_ARGS+="USE_MASTER=-master "
356 fi
357
358 if [ ${INTERACTIVE} -eq 1 ]; then
359     MAKE_ARGS+="INTERACTIVE=TRUE "
360 else
361     MAKE_ARGS+="INTERACTIVE=FALSE "
362 fi
363
364 MAKE_ARGS+=all
365
366 if [ ${DEBUG} -eq 0 ]; then
367     set +e
368     cd ${BUILD_BASE} && make ${MAKE_ARGS}
369     rc=$?
370     set -e
371     if [ $rc -gt 0 ]; then
372         echo "Build: make all failed, exiting ..."
373         rc=200
374         exit $rc
375     fi
376 else
377 debug_make
378 fi
379 set +e
380 make -C ${BUILD_BASE} prepare-cache
381 rc=$?
382 set -e
383
384 if [ $rc -gt 0 ]; then
385     echo "Build: make prepare-cache failed - exiting ..."
386     rc=100
387     exit $rc
388 fi
389 echo "Copying built OPNFV .iso file to target directory ${BUILD_DIR} ..."
390 rm -rf ${BUILD_DIR}
391 mkdir -p ${BUILD_DIR}
392 cp ${BUILD_BASE}/.versions ${BUILD_DIR}
393 cp ${RESULT_DIR}/*.iso* ${BUILD_DIR}
394 echo "Copying built OPNFV .rpm files to target directory ${BUILD_DIR} ..."
395 cp ${BUILD_BASE}/*.rpm ${BUILD_DIR}
396 cp ${BUILD_BASE}/noarch/*.rpm ${BUILD_DIR}
397
398 if [ $POPULATE_CACHE -eq 1 ]; then
399     if [ ! -z ${BUILD_CACHE_URI} ]; then
400         echo "Building cache ..."
401         tar --atime-preserve --dereference -C ${BUILD_BASE} -caf ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz ${CACHE_DIR}
402         echo "Uploading cache ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME}"
403         ${REMOTE_ACCESS_METHD} -T ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz ${BUILD_CACHE_URI}/${REMOTE_CACHE_ARCH_NAME}.tgz
404         rm ${BUILD_BASE}/${LOCAL_CACHE_ARCH_NAME}.tgz
405     fi
406 fi
407 echo "Success!!!"
408 exit 0
409 #
410 # END of main
411 ############################################################################