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