]> git.pld-linux.org Git - projects/cleanbuild.git/blob - bin/cleanbuild-docker.sh
30bba1e89253dea6c871e21a07ccddba4621afe1
[projects/cleanbuild.git] / bin / cleanbuild-docker.sh
1 #!/bin/sh
2 set -eu
3
4 PROGRAM=${0##*/}
5
6 # defaults
7 : ${PACKAGE_NAME=''}
8 : ${NETWORKING=false}
9 : ${TRACING=false}
10 : ${WITH=}
11 : ${WITHOUT=}
12 : ${KEEP_CONTAINER=true}
13 : ${TMPFS="4G"}
14
15 dir=$(pwd)
16 image=registry.gitlab.com/pld-linux/cleanbuild
17 topdir=$dir/rpm
18 home=/home/builder
19
20 notice() {
21         echo >&2 "[cleanbuild:notice]: $*"
22 }
23
24 die() {
25         local rc=${2:-1}
26         echo >&2 "[cleanbuild:error]: $1"
27         exit $rc
28 }
29
30 is_no() {
31         # Test syntax
32         if [ $# = 0 ]; then
33                 return 2
34         fi
35
36         case "$1" in
37         no|No|NO|false|False|FALSE|off|Off|OFF|N|n|0)
38                 # true returns zero
39                 return 0
40                 ;;
41         *)
42                 # false returns one
43                 return 1
44                 ;;
45         esac
46 }
47
48 tmpfs() {
49         if is_no "${TMPFS:-true}" || [ "$TMPFS" = "0" ]; then
50                 return
51         fi
52
53         echo "--tmpfs $home/rpm/BUILD:rw,exec,nosuid,size=$TMPFS"
54 }
55
56 have_container() {
57     local name="$1" id
58
59     id=$(docker ps -a -f "label=cleanbuild=$name" --format '{{.ID}}')
60
61     test -n "$id"
62 }
63
64 create_container() {
65         if ! $KEEP_CONTAINER; then
66                 notice "Clean up old container: $name"
67                 docker kill $name >/dev/null 2>&1 || :
68                 docker rm $name >/dev/null 2>&1 || :
69         fi
70
71         install -d $topdir/logs
72
73         # start the container
74         if !  have_container "$PACKAGE_NAME"; then
75                 TMPFS_SIZE=$TMPFS \
76                 PACKAGE_NAME=$PACKAGE_NAME \
77                 docker-compose run --rm -d \
78                         --name=$name \
79                         --workdir=$home/rpm/packages/$PACKAGE_NAME \
80                         --label=cleanbuild=$PACKAGE_NAME \
81                         cleanbuild
82         fi
83
84         notice "Setup the homedir"
85         docker exec --user=root -w / $name usermod -d $home builder
86
87         notice "Setup permissions"
88         docker exec --user=root -w / $name sh -c "cd $home && chown builder:builder . rpm rpm/logs rpm/BUILD rpm/RPMS .ccache"
89
90         if [ ! -d $topdir/rpm-build-tools ]; then
91                 notice "Initialize rpm-build-tools"
92                 docker exec -w / $name builder --init-rpm-dir
93         fi
94 }
95
96 package_prepare() {
97         notice "Fetch sources and install dependencies"
98         if [ -d $topdir/packages/$PACKAGE_NAME ]; then
99                 # chown, as it might be different owner (root) modified outside container
100                 notice "Fix ownership of existing package directory"
101                 docker exec --user=root -w / $name chown -R builder:builder $home/rpm/packages/$PACKAGE_NAME
102         fi
103
104         notice "Fetch package sources"
105         docker exec --user=root -w / $name setfacl -x u:builder /etc/resolv.conf
106         docker exec -w / $name builder -g $PACKAGE_NAME
107
108         if ! $NETWORKING; then
109                 notice "Disable networking: Prevent network access for user builder like PLD Linux builders"
110                 docker exec --user=root -w / $name setfacl -m u:builder:--- /etc/resolv.conf
111         fi
112
113         notice "Find latest tag on the branch"
114         git_tag=$(docker exec -w / -e GIT_DIR=$home/rpm/packages/$PACKAGE_NAME/.git $name git describe --tags --always)
115         buildlog=rpm/logs/${git_tag#auto/*/}.log
116         notice "Build log: $buildlog"
117 }
118
119 package_build() {
120         # create default args for builder
121         set -- -nn ${WITH:+--with "${WITH# }"} ${WITHOUT:+--without "${WITHOUT# }"} "$PACKAGE_NAME"
122
123         while true; do
124                 notice "Install dependencies"
125                 docker exec -w / -t $name builder -g -R "$@"
126                 notice "Remove .la dependencies"
127                 docker exec --user=root -w / $name $home/cleanbuild/bin/cleanup-la
128                 notice "Reset findunusedbr state after deps install"
129                 docker exec --user=root -w / $name $home/cleanbuild/bin/findunusedbr -c / $home/rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec
130
131                 notice "Build package"
132                 docker exec -w $home $name cleanbuild/bin/teeboth $buildlog builder -bb --define '__spec_clean_body %{nil}' "$@" && rc=$? || rc=$?
133                 # Kill processes on Ctrl+C
134                 if [ "$rc" = 255 ]; then
135                         docker exec -w / $name pkill -e -u builder
136                         die "Aborted" $rc
137                 fi
138
139                 findbr=$PACKAGE_NAME.findbr.log
140                 builddir=$(docker exec -w $home $name sh -c 'test ! -d rpm/BUILD/* || echo rpm/BUILD/*')
141                 if [ -z "$builddir" ]; then
142                         die "No build dir. Build failed?" 6
143                 fi
144                 notice "Execute findbr"
145                 docker exec --user=root -w / $name sh -c "cd $home && cleanbuild/bin/findbr $builddir $buildlog" > $findbr
146
147                 installed_something=false
148                 while read pkg msg; do
149                         bin/addbr rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec "$pkg" "$msg" || continue
150                         installed_something=true
151                 done < $findbr
152                 rm -f $findbr
153
154                 # go for another try
155                 $installed_something && continue
156
157                 notice "Execute findunusedbr"
158                 docker exec --user=root -w / $name $home/cleanbuild/bin/findunusedbr -c / $home/rpm/packages/$PACKAGE_NAME/$PACKAGE_NAME.spec
159
160                 if [ $rc -eq 0 ] && ! $KEEP_CONTAINER; then
161                         notice "Finished ok, cleanup container"
162                         docker kill $name >/dev/null && docker rm $name >/dev/null || :
163                 fi
164
165                 # propagate error
166                 exit $rc
167         done
168 }
169
170 parse_options() {
171         local t
172         t=$(getopt -o 'x' --long 'network,no-tmpfs,notmpfs,tmpfs:,keep-container:,with:,without:' -n "$PROGRAM" -- "$@")
173         [ $? != 0 ] && exit $?
174         eval set -- "$t"
175
176         while :; do
177                 case "$1" in
178                 -x)
179                         TRACING=true
180                         ;;
181                 --network)
182                         NETWORKING=true
183                         ;;
184                 --no-tmpfs|--notmpfs)
185                         TMPFS=false
186                         ;;
187                 --tmpfs)
188                         shift
189                         TMPFS="$1"
190                         ;;
191                 --keep-container)
192                         shift
193                         [ "$1" = "true" -o "$1" = "false" ] || die "Invalid boolean value: $1"
194                         KEEP_CONTAINER=$1
195                         ;;
196                 --with)
197                         shift
198                         WITH="$WITH,$1"
199                         ;;
200                 --without)
201                         shift
202                         WITHOUT="$WITHOUT,$1"
203                         ;;
204                 --)
205                         shift
206                         break
207                         ;;
208                 *)
209                         die "Internal error: [$1] not recognized!"
210                         ;;
211                 esac
212                 shift
213         done
214
215         test "$#" -eq 1 || die "Package not specified or excess arguments"
216         PACKAGE_NAME="${1%.spec}"
217 }
218
219 main() {
220         parse_options "$@"
221
222         $TRACING && set -x
223         local name="cleanbuild-$PACKAGE_NAME"
224         create_container
225         package_prepare
226         package_build
227 }
228
229 main "$@"
This page took 0.155345 seconds and 2 git commands to generate.