Merge "added missing lispflowmapping projects, and updated versions"
[integration.git] / packaging / rpm / buildrpm.sh
1 #!/bin/bash
2 # @License EPL-1.0 <http://spdx.org/licenses/EPL-1.0>
3
4 # shague todo:
5 # - Add -r option for mock to choose the distribution
6 # - add option to pass in spec file name, maybe use spec.in template
7 # - add option to pass in version and release
8
9 #set -vx
10
11 buildtype="snapshot"
12 buildroot=""
13 buildtag=""
14 cleanroot=0
15 cleantmp=0
16 pushrpms=0
17 getsource="buildroot"
18 version=""
19 release=""
20 repourl=""
21 repouser=""
22 repopw=""
23 dist="fedora-19-x86_64"
24 pkg_dist_suffix="fc19"
25 mock_cmd="/usr/bin/mock"
26 vers_controller=""
27 vers_ovsdb=""
28 suff_controller=""
29 suff_ovsdb=""
30 mockdebug=""
31 mockinit=0
32 tmpbuild=""
33 mockmvn=""
34 timesuffix=""
35
36
37 # Maven is not installed at the system wide level but at the Jenkins level
38 # We need to map our Maven call to the Jenkins installed version
39 mvn_cmd="$JENKINS_HOME/tools/hudson.tasks.Maven_MavenInstallation/Maven_3.0.4/bin/mvn"
40
41 # Define our push repositories here. We do it in code since we can't
42 # use a POM file for the RPM pushes (we're doing "one-off" file pushes)
43 #
44 # Repositories will be of the form baseRepositoryId-$dist{-testing}
45 # -testing if it's a snapshot build (not using -snapshot as the name as
46 # -testing is the more common testing repo suffix for yum)
47 baseURL="http://nexus.opendaylight.org/content/repositories/opendaylight-yum-"
48 baseRepositoryId="opendaylight-yum-"
49
50 readonly RCSUCCESS=0
51 readonly RCERROR=64
52 readonly RCPARMSERROR=65
53 readonly RCRPMBUILDERROR=66
54 readonly RCRMOCKERROR=67
55
56 readonly LOGERROR=2
57 readonly LOGINFO=5
58 readonly LOGVERBOSE=7
59 loglevel=$LOGVERBOSE
60
61
62 function log {
63     local level=$1; shift;
64
65     if [ $level -le $loglevel ]; then
66         echo "buildrpm: $@"
67     fi
68 }
69
70 function usage {
71     local rc=$1
72     local outstr=$2
73
74     if [ "$outstr" != "" ]; then
75         echo "$outstr"
76         echo
77     fi
78
79     echo "Usage: `basename $0` [OPTION...]"
80     echo
81     echo "Build options:"
82     echo "  --buildtype TYPE       build type, either snapshot or release"
83     echo "  --buildroot DIRECTORY  build root path"
84     echo "  --buildtag             tag the tmpbuild directory, i.e. Jenkins build number"
85     echo "  --cleanroot            clean buildroot directory before building"
86     echo "  --cleantmp             clean tmpbuild directory before building"
87     echo "  --dist DIST            distribution"
88     echo "  --distsuffix SUFFIX    package distribution suffix"
89     echo "  --getsource METHOD     method for getting source clone|snapshot|buildroot"
90     echo
91     echo "Tag options:"
92     echo "  --release RELEASE      release tag (not used yet)"
93     echo "  --version VERSION      version tag"
94     echo
95     echo "Repo sync options:"
96     echo "  --repourl REPOURL      url of the repo, include http://"
97     echo "  --repouser REPOUSER    user for repo"
98     echo "  --repopw REPOPW        password for repo"
99     echo
100     echo "Deployment options:"
101     echo "  --pushrpms             push the built rpms to a maven repository"
102     echo "  --mvn_cmd              fully qualified path to where the mvn command"
103     echo "                         (defaults to Jenkins installation of Maven 3.0.4)"
104     echo "  --baseURL              base deployment URL. \$dist will be added to the end of this"
105     echo "                         If this is a snapshot build then -testing be added at the end"
106     echo "  --baseRepositoryId     base repository name. \$dist will be added to the end of this"
107     echo "                         If this is a snapshot build then -testing be added at the end"
108     echo
109     echo "Mock options:"
110     echo "  --mockinit             Run mock init"
111     echo "  --mockmvn              replace the maven command used within mock"
112     echo
113     echo "Help options:"
114     echo "  -?, -h, --help  Display this help and exit"
115     echo "  --debug         Enable bash debugging output"
116     echo "  --mockdebug     Enable mock debugging output"
117     exit $rc
118 }
119
120 readonly PJ_INTEGRATION=0
121 readonly PJ_CONTROLLER=1
122 readonly PJ_OVSDB=2
123 readonly PJ_OPENFLOWJAVA=3
124 readonly PJ_OPENFLOWPLUGIN=4
125 readonly PJ_DEPENDENCIES=5
126 readonly PJ_DISTRIBUTION=6
127
128 projects[$PJ_INTEGRATION]="integration"
129 projects[$PJ_CONTROLLER]="controller"
130 projects[$PJ_OVSDB]="ovsdb"
131 projects[$PJ_OPENFLOWJAVA]="openflowjava"
132 projects[$PJ_OPENFLOWPLUGIN]="openflowplugin"
133 projects[$PJ_DEPENDENCIES]="controller-dependencies"
134 projects[$PJ_DISTRIBUTION]="distribution"
135
136 versions[$PJ_INTEGRATION]=""
137 versions[$PJ_CONTROLLER]=""
138 versions[$PJ_OVSDB]=""
139 versions[$PJ_OPENFLOWJAVA]=""
140 versions[$PJ_OPENFLOWPLUGIN]=""
141 versions[$PJ_DEPENDENCIES]=""
142 versions[$PJ_DISTRIBUTION]=""
143
144 suffix[$PJ_INTEGRATION]=""
145 suffix[$PJ_CONTROLLER]=""
146 suffix[$PJ_OVSDB]=""
147 suffix[$PJ_OPENFLOWJAVA]=""
148 suffix[$PJ_OPENFLOWPLUGIN]=""
149 suffix[$PJ_DEPENDENCIES]=""
150 suffix[$PJ_DISTRIBUTION]=""
151
152
153 # Clone the projects.
154 function clone_source {
155     for project in ${projects[*]}; do
156         # We only care about a shallow clone (no need to grab the entire project)
157         git clone --depth 0 https://git.opendaylight.org/gerrit/p/$project.git $buildroot/$project
158     done
159 }
160
161 # Copy the projects from snapshots.
162 # shague: Fill in with the nexus info.
163 # Make mk_snapshot_archives that just sets up the version strings.
164 function snapshot_source {
165     log $LOGINFO "$FUNCNAME: Not implemented yet."
166 }
167
168 # Archive the projects to creates the SOURCES for rpmbuild:
169 # - xz the source for later use by rpmbuild.
170 # - get the version and git hashes to produce a versions and suffix for each project.
171 # - copy the archives to the SOURCES dir
172 # shague: need another archive method for snapshot getsource builds since
173 # the source did not come from a git repo.
174 function mk_git_archives {
175     local timesuffix=$1
176
177     for i in `seq $PJ_INTEGRATION $PJ_OPENFLOWPLUGIN`; do
178         if [ "$version" == "" ]; then
179             cd $buildroot/${projects[$i]}
180             suffix[$i]="snap.$timesuffix.git.$(git log -1 --pretty=format:%h)"
181         else
182             suffix[$i]="snap.$version"
183         fi
184
185         cd $buildroot/integration/packaging/rpm
186         # integration uses the controller.spec because there isn't an integration.spec to query.
187         if [ ${projects[$i]} == ${projects[$PJ_INTEGRATION]} ]; then
188             versions[$i]="$( rpm -q --queryformat="%{version}\n" --specfile opendaylight-${projects[$PJ_CONTROLLER]}.spec | head -n 1 | awk '{print $1}').${suffix[$i]}"
189         else
190             versions[$i]="$( rpm -q --queryformat="%{version}\n" --specfile opendaylight-${projects[$i]}.spec | head -n 1 | awk '{print $1}').${suffix[$i]}"
191         fi
192
193         cd $buildroot/${projects[$i]}
194         git archive --prefix=opendaylight-${projects[$i]}-${versions[$i]}/ HEAD | \
195             xz > $tmpbuild/opendaylight-${projects[$i]}-${versions[$i]}.tar.xz
196
197     done
198
199     # Use the controller versions becuase these projects don't have a repo.
200     for i in `seq $PJ_DEPENDENCIES $PJ_DISTRIBUTION`; do
201         suffix[$i]=${suffix[$PJ_CONTROLLER]}
202         versions[$i]=${versions[$PJ_CONTROLLER]}
203     done
204
205     # Don't forget any patches.
206     cp $buildroot/integration/packaging/rpm/opendaylight-integration-fix-paths.patch $tmpbuild
207 }
208
209 # Pushes rpms to the specified Nexus repository
210 # This only happens if pushrpms is true
211 function push_rpms {
212     if [ $pushrpms = 1 ]; then
213         allrpms=`find $tmpbuild/repo -iname '*.rpm'`
214         echo
215         log $LOGINFO "RPMS found"
216         for i in $allrpms
217         do
218             log $LOGINFO $i
219         done
220
221         log $LOGINFO ":::::"
222         log $LOGINFO "::::: pushing RPMs"
223         log $LOGINFO ":::::"
224         for i in $allrpms
225         do
226             rpmname=`rpm -qp --queryformat="%{name}" $i`
227             rpmversion=`rpm -qp --queryformat="%{version}" $i`
228             distro=`echo $dist | tr - .`
229
230             if [ `echo $i | grep 'src.rpm'` ]; then
231                 rpmrelease=`rpm -qp --queryformat="%{release}.src" $i`
232                 groupId="srpm"
233             else
234                 rpmrelease=`rpm -qp --queryformat="%{release}.%{arch}" $i`
235                 groupId="rpm"
236             fi
237
238
239             if [ "$buildtype" == "snapshot" ]; then
240                 repositoryId="${baseRepositoryId}${dist}-testing"
241                 pushURL="${baseURL}${dist}-testing"
242             else
243                 repositoryId="${baseRepositoryId}${dist}"
244                 pushURL="${baseURL}${dist}"
245             fi
246
247             # Note version is the full version+release+{arch|src}
248             # if it is not configured this way on pushes then a download
249             # of the artifact will result in just the name-version.rpm
250             # instead of name-version-release.{arch|src}.rpm
251             $mvn_cmd org.apache.maven.plugins:maven-deploy-plugin:2.8.1:deploy-file \
252                 -Dfile=$i -DrepositoryId=$repositoryId \
253                 -Durl=$pushURL -DgroupId=$groupId \
254                 -Dversion=$rpmversion-$rpmrelease -DartifactId=$rpmname \
255                 -Dtype=rpm
256         done
257     fi
258 }
259
260 function show_vars {
261      cat << EOF
262 Building controller using:
263 distribution: $dist
264 suffix:       $pkg_dist_suffix
265 buildtype:    $buildtype
266 release:      $release
267 version:      $version
268 getsource:    $getsource
269 buildroot:    $buildroot
270 buildtag:     $buildtag
271 tmpbuild:     $tmpbuild
272 mockmvn:      $mockmvn
273 mockinit:     $mockinit
274 time:         $timesuffix
275 EOF
276 }
277
278 # Build a single project.
279 function build_project {
280     local project=$1
281     local versionmajor="$2"
282     local versionsnapsuffix="$3"
283
284     log $LOGINFO ":::::"
285     log $LOGINFO "::::: building opendaylight-$project.rpm"
286     log $LOGINFO ":::::"
287
288     cp -f $buildroot/integration/packaging/rpm/opendaylight-$project.spec \
289         $tmpbuild
290
291     cd $tmpbuild
292     # Find lines starting with Version: and replace the rest of the line with the versionsnapsuffix
293     sed -r -i -e '/^Version:/s/\s*$/'".$versionsnapsuffix/" opendaylight-$project.spec
294
295     # Set the write values in the spec files.
296     case "$project" in
297     ${projects[$PJ_CONTROLLER]})
298         # Set the version for the integration source.
299         # Find lines with opendaylight-integration-%{version} and replace %{version} with the version.
300         sed -r -i -e '/opendaylight-integration-\%\{version\}/s/\%\{version\}/'"${versions[$PJ_INTEGRATION]}"'/g' \
301             opendaylight-$project.spec
302         ;;
303
304     ${projects[$PJ_DEPENDENCIES]})
305         # Set the version for ovsdb in the dependencies spec.
306         # Find lines with opendaylight-ovsdb-%{version} and replace %{version} with the version.
307         sed -r -i -e '/opendaylight-ovsdb-\%\{version\}/s/\%\{version\}/'"${versions[$PJ_OVSDB]}"'/g' \
308             opendaylight-$project.spec
309         # Find lines with opendaylight-ovsdb-dependencies-%{version} and replace %{version} with the version.
310         sed -r -i -e '/opendaylight-ovsdb-dependencies-\%\{version\}/s/\%\{version\}/'"${versions[$PJ_OVSDB]}"'/g' \
311             opendaylight-$project.spec
312         ;;
313
314     *)
315         ;;
316     esac
317
318     # Rewrite the mvn command in the rpmbuild if the user requests it.
319     if [ "$mockmvn" != "" ]; then
320         # Find lines starting with export MAVEN_OPTS= and repalce the whole line with $mockmvn
321         sed -r -i -e '/^export MAVEN_OPTS=./c\ '"$mockmvn" opendaylight-$project.spec
322     fi
323
324     # Build the source RPM for use by mock later.
325     #rm -f SRPMS/*.src.rpm
326     log $LOGINFO "::::: building opendaylight-$project.src.rpm in rpmbuild"
327     rpmbuild -bs --define '%_topdir '"`pwd`" --define '%_sourcedir %{_topdir}' \
328        --define "%dist .$pkg_dist_suffix" opendaylight-$project.spec
329
330     rc=$?
331     if [ $rc != 0 ]; then
332         log $LOGERROR "rpmbuild of $project.src.rpm failed (rc=$rc)."
333         exit $RCRPMBUILDERROR
334     fi
335
336     log $LOGINFO "::::: building opendaylight-$project.rpm in mock"
337
338     resultdir="repo/$project.$pkg_dist_suffix.noarch.snap"
339
340     # Build the rpm using mock.
341     # Keep the build because we will need the distribution zip file for later
342     # when building the controller-dependencies.rpm.
343     eval $mock_cmd $mockdebug -r $dist --no-clean --no-cleanup-after --resultdir \"$resultdir\" \
344         -D \"dist .$pkg_dist_suffix\" -D \"noclean 1\" \
345         SRPMS/opendaylight-$project-$versionmajor-*.src.rpm
346
347     rc=$?
348     if [ $rc != 0 ]; then
349         log $LOGERROR "mock of $project.rpm failed (rc=$rc)."
350         exit $RCRMOCKERROR
351     fi
352
353     # Copy the distribution zip from the controller and ovsdb projects
354     # for use in the dependencies.rpm.
355     case "$project" in
356     controller)
357         log $LOGINFO "::::: Copying $project distribution.zip."
358         eval $mock_cmd $mockdebug -r $dist --no-clean --no-cleanup-after --resultdir \"$resultdir\" \
359             -D \"dist .$pkg_dist_suffix\" -D \"noclean 1\" \
360             --copyout \"builddir/build/BUILD/opendaylight-$project-$versionmajor/opendaylight/distribution/opendaylight/target/distribution.opendaylight-osgipackage.zip\" \"$resultdir/opendaylight-$project-$versionmajor.zip\"
361         rc1=$?
362         ln -sf $resultdir/opendaylight-$project-$versionmajor.zip $tmpbuild
363         rc2=$?
364         if [ ! -e $tmpbuild/opendaylight-$project-$versionmajor.zip ]; then
365             log $LOGERROR "cannot find $project distribution zip file (rc=$rc1:$rc2)."
366             exit $RCERROR
367         fi
368         ;;
369
370     ovsdb)
371         log $LOGINFO "::::: Copying $project distribution.zip."
372         #todo: Parse pom file to get filename.
373         eval $mock_cmd $mockdebug -r $dist --no-clean --no-cleanup-after --resultdir \"$resultdir\" \
374             -D \"dist .$pkg_dist_suffix\" -D \"noclean 1\" \
375             --copyout \"builddir/build/BUILD/opendaylight-$project-$versionmajor/distribution/opendaylight/target/distribution.$project-1.0.0-SNAPSHOT-osgipackage.zip\" \"$resultdir/opendaylight-$project-$versionmajor.zip\"
376         rc1=$?
377         ln -sf $resultdir/opendaylight-$project-$versionmajor.zip $tmpbuild
378         rc2=$?
379         if [ ! -e $tmpbuild/opendaylight-ovsdb-$versionmajor.zip ]; then
380             log $LOGERROR "cannot find $project distribution zip file (rc=$rc1:$rc2)."
381             exit $RCERROR
382         fi
383         ;;
384
385     *)
386         ;;
387     esac
388 }
389
390 # Main function that builds the rpm's for snapshot's.
391 function build_snapshot {
392     mk_git_archives $timesuffix
393
394     # Initialize our mock build location (we'll be using --no-clean later)
395     # If we don't do the first init we can't build since the environment
396     # doesn't get setup correctly!
397     if [ $mockinit -eq 1 ]; then
398         eval $mock_cmd $mockdebug -r $dist --init
399     fi
400
401     for i in `seq $PJ_CONTROLLER $PJ_DISTRIBUTION`; do
402         build_project ${projects[$i]} ${versions[$i]} ${suffix[$i]}
403     done
404
405     log $LOGINFO ":::::"
406     log $LOGINFO "::::: All projects have been built"
407     log $LOGINFO ":::::"
408
409     push_rpms
410 }
411
412 # Main function that builds the rpm's for release's.
413 # shague: should be similar to snapshot but use a different version or tag.
414 # spec files should be updated with correct version. If so, do
415 function build_release {
416     log $LOGINFO "$FUNCNAME: Not implemented yet."
417 }
418
419 function parse_options {
420     while true ; do
421         case "$1" in
422         --debug)
423             set -vx; shift;
424             ;;
425
426         --mockdebug)
427             mockdebug="-v"; shift;
428             ;;
429
430         --buildtype)
431             shift; buildtype="$1"; shift;
432             if [ "$buildtype" != "snapshot" ] && [ "$buildtype" != "release" ]; then
433                 usage $RCPARMSERROR "Invalid build type.";
434             fi
435             ;;
436
437         --buildroot)
438             shift; buildroot="$1"; shift;
439             if [ "$buildroot" == "" ]; then
440                 usage $RCPARMSERROR "Missing build root.";
441             fi
442             if [ ! -d "$buildroot" ]; then
443                 usage $RCPARMSERROR "Invalid build root path."
444             fi
445             ;;
446
447         --buildtag)
448             shift; buildtag="$1"; shift;
449             if [ "$buildtag" == ""  ]; then
450                 usage $RCPARMSERROR "Missing build tag.";
451             fi
452             ;;
453
454         --cleanroot)
455             cleanroot=1; shift;
456             ;;
457
458         --cleantmp)
459             cleantmp=1; shift;
460             ;;
461
462         --getsource)
463             shift; getsource="$1"; shift;
464             if [ "$getsource" != "clone" ] && [ "$getsource" != "snapshot" ] && \
465                [ "$getsource" != "buildroot" ]; then
466                 usage $RCPARMSERROR "Invalid getsource method.";
467             fi
468             ;;
469
470         --dist)
471             shift; dist="$1"; shift;
472             if [ "$dist" == "" ]; then
473                 $RCPARMSERROR "Missing distribution.";
474             fi
475             ;;
476
477         --distsuffix)
478             shift; pkg_dist_suffix="$1"; shift;
479             if [ "$pkg_dist_suffix" == "" ]; then
480                 $RCPARMSERROR "Missing package distribution suffix.";
481             fi
482             ;;
483
484         --release)
485             shift; release="$1"; shift;
486             if [ "$release" == "" ]; then
487                 $RCPARMSERROR "Missing release.";
488             fi
489             ;;
490
491         --version)
492             shift; version="$1"; shift;
493             if [ "$version" == "" ]; then
494                 $RCPARMSERROR "Missing version.";
495             fi
496             ;;
497
498         --repourl)
499             shift; repourl="$1"; shift;
500             if [ "$repourl" == "" ]; then
501                 $RCPARMSERROR "Missing repo url.";
502             fi
503             ;;
504
505         --repouser)
506             shift; repouser="$1"; shift;
507             if [ "$repouser" == "" ]; then
508                 $RCPARMSERROR "Missing repo user.";
509             fi
510             ;;
511
512         --repopw)
513             shift; repopw="$1"; shift;
514             if [ "$repopw" == "" ]; then
515                 $RCPARMSERROR "Missing repo pw.";
516             fi
517             ;;
518
519         --pushrpms)
520             pushrpms=1; shift;
521             ;;
522
523         --mvn_cmd)
524             shift; mvn_cmd="$1"; shift;
525             if [ "$mvn_cmd" == "" ]; then
526                 $RCPARMSERROR "Missing mvn_cmd.";
527             fi
528             ;;
529
530         --mockmvn)
531             shift; mockmvn="$1"; shift;
532             if [ "$mockmvn" == "" ]; then
533                 $RCPARMSERROR "Missing mockmvn.";
534             fi
535             ;;
536
537         --baseURL)
538             shift; baseURL="$1"; shift;
539             if [ "$baseURL" == "" ]; then
540                 $RCPARMSERROR "Missing baseURL.";
541             fi
542             ;;
543
544         --baseRepositoryId)
545             shift; baseRepositoryId="$1"; shift;
546             if [ "$baseRepositoryId" == "" ]; then
547                 $RCPARMSERROR "Missing baseRepositoryId.";
548             fi
549             ;;
550
551         -? | -h | --help)
552             usage $RCSUCCESS
553             ;;
554         "")
555             break
556             ;;
557         *)
558             log $LOGINFO "Ignoring unknown option: $1"; shift;
559         esac
560     done
561 }
562
563
564 #################### main ####################
565
566 timesuffix="$(date +%F_%T | tr -d .:- | tr _ .)"
567 date_start=$(date +%s)
568
569 parse_options "$@"
570
571 # Some more error checking...
572 if [ -z $buildroot ]; then
573     log $LOGERROR "Mising buildroot"
574     exit $RCPARMSERROR
575 fi
576
577 if [ $cleanroot -eq 1 ] && [ $getsource = "buildroot" ]; then
578     log $LOGERROR "Aborting. You probably do not want to clean the directory" \
579          "containing the source."
580     exit $RCPARMSERROR
581 fi
582
583 # Can change tmpbuild to be an index or other tag
584 if [ -n "$buildtag" ]; then
585     tmpbuild="$buildroot/bld_$buildtag"
586 else
587     tmpbuild="$buildroot/bld"
588 fi
589
590 show_vars
591
592 if [ $cleanroot -eq 1 ]; then
593     rm -rf $buildroot
594     mkdir -p $buildroot
595 fi
596
597 if [ $cleantmp -eq 1 ]; then
598     rm -rf $tmpbuild
599 fi
600
601 # Setup the temp build directory.
602 mkdir -p $tmpbuild/repo
603
604 # Get the source.
605 case "$getsource" in
606 clone)
607     clone_source;
608     ;;
609
610 snapshot)
611     snapshot_source;
612     exit $RCSUCCESS
613     ;;
614
615 buildroot)
616     cd $buildroot
617     for i in `seq $PJ_INTEGRATION $PJ_OPENFLOWPLUGIN`; do
618         if [ ! -d ${projects[$i]} ]; then
619             log $LOGERROR "Missing ${projects[$i]}"
620             exit $RCPARMSERROR
621         fi
622     done
623     ;;
624 esac
625
626 if [ "$buildtype" = "snapshot" ]; then
627     log $LOGINFO "Building a snapshot build"
628     build_snapshot
629 else
630     log $LOGINFO "Release builds are not supported yet."
631     build_release
632 fi
633
634 date_end=$(date +%s)
635 diff=$(($date_end - $date_start))
636 log $LOGINFO "Build took $(($diff / 3600 % 24)) hours $(($diff / 60 % 60)) minutes and $(($diff % 60)) seconds."
637
638 exit $RCSUCCESS