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