Merge ~morphis/snappy-hwe-snaps/+git/build-scripts:feature/ephemeral-lp-builds into ~snappy-hwe-team/snappy-hwe-snaps/+git/build-scripts:master
- Git
- lp:~morphis/snappy-hwe-snaps/+git/build-scripts
- feature/ephemeral-lp-builds
- Merge into master
Status: | Merged |
---|---|
Approved by: | Konrad Zapałowicz |
Approved revision: | ecda8713547a287d878a1abe05a4230ee227c243 |
Merged at revision: | 45da531c71d6f7ac545a741397dc87f2e7ab8e09 |
Proposed branch: | ~morphis/snappy-hwe-snaps/+git/build-scripts:feature/ephemeral-lp-builds |
Merge into: | ~snappy-hwe-team/snappy-hwe-snaps/+git/build-scripts:master |
Diff against target: |
372 lines (+144/-125) 3 files modified
dev/null (+0/-111) jobs/generic-build-snap-worker (+63/-0) scripts/trigger-lp-build.py (+81/-14) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
System Enablement Bot | continuous-integration | Approve | |
Konrad Zapałowicz (community) | code | Approve | |
Jim Hodapp (community) | Approve | ||
Review via email: mp+317594@code.launchpad.net |
Commit message
Description of the change
Rework snap-build job to create ephemeral snap builds on launchpad
This makes our build much more reliable as we offload the actual build
to launchpad and can also build for multiple architectures instead of
just building the host architecture our jenkins agents runs as.
We use the jenkins-ci-builds repository on launchpad as staging area
for our builds.
Example build using this is at https:/
This got reworked a bit more. We will now trigger one generic-
See https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:d65825d3492
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:e02bfc1dcc1
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:6d15d3720cc
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:9e4ca884ce5
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:ffbe526031a
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:f7fc8794f33
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:6d17c2793fa
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Konrad Zapałowicz (kzapalowicz) wrote : | # |
LGTM
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:68696845ab9
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Konrad Zapałowicz (kzapalowicz) wrote : | # |
ack
System Enablement Bot (system-enablement-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:ecda8713547
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild:
https:/
Konrad Zapałowicz (kzapalowicz) wrote : | # |
approving on behalf of Jim who is not in the EU timezone and the other maintainer is the author of this MP
Preview Diff
1 | diff --git a/jobs/generic-build-snap b/jobs/generic-build-snap |
2 | deleted file mode 100755 |
3 | index 82c27cf..0000000 |
4 | --- a/jobs/generic-build-snap |
5 | +++ /dev/null |
6 | @@ -1,27 +0,0 @@ |
7 | -#!/bin/sh |
8 | -# |
9 | -# Copyright (C) 2016 Canonical Ltd |
10 | -# |
11 | -# This program is free software: you can redistribute it and/or modify |
12 | -# it under the terms of the GNU General Public License version 3 as |
13 | -# published by the Free Software Foundation. |
14 | -# |
15 | -# This program is distributed in the hope that it will be useful, |
16 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | -# GNU General Public License for more details. |
19 | -# |
20 | -# You should have received a copy of the GNU General Public License |
21 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | - |
23 | -set -x |
24 | - |
25 | -sudo $WORKSPACE/build-scripts/scripts/snap-build \ |
26 | - $WORKSPACE \ |
27 | - $SERIES \ |
28 | - $TARGET_GIT_REPO \ |
29 | - $TARGET_GIT_REPO_BRANCH \ |
30 | - $SOURCE_GIT_REPO \ |
31 | - $SOURCE_GIT_REPO_BRANCH \ |
32 | - $REVISION \ |
33 | - $FORCE |
34 | \ No newline at end of file |
35 | diff --git a/jobs/generic-build-snap-worker b/jobs/generic-build-snap-worker |
36 | new file mode 100755 |
37 | index 0000000..0cfd16e |
38 | --- /dev/null |
39 | +++ b/jobs/generic-build-snap-worker |
40 | @@ -0,0 +1,63 @@ |
41 | +#!/bin/sh |
42 | +# |
43 | +# Copyright (C) 2016 Canonical Ltd |
44 | +# |
45 | +# This program is free software: you can redistribute it and/or modify |
46 | +# it under the terms of the GNU General Public License version 3 as |
47 | +# published by the Free Software Foundation. |
48 | +# |
49 | +# This program is distributed in the hope that it will be useful, |
50 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
51 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
52 | +# GNU General Public License for more details. |
53 | +# |
54 | +# You should have received a copy of the GNU General Public License |
55 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
56 | + |
57 | +set -x |
58 | + |
59 | +[ -e $WORKSPACE/src ] && rm -rf $WORKSPACE/src |
60 | + |
61 | +git clone -b $TARGET_GIT_REPO_BRANCH $TARGET_GIT_REPO $WORKSPACE/src |
62 | +cd $WORKSPACE/src |
63 | + |
64 | +if [ ! -e snapcraft.yaml ] ; then |
65 | + echo "ERROR: Failed to build snap as no snapcraft.yaml exists!" |
66 | + exit 1 |
67 | +fi |
68 | + |
69 | +git config user.name "System Enablement CI Bot" |
70 | +git config user.email "ce-system-enablement@lists.canonical.com" |
71 | + |
72 | +if [ -n "$SOURCE_GIT_REPO" ]; then |
73 | + git remote add other $SOURCE_GIT_REPO |
74 | + git fetch other |
75 | + git merge \ |
76 | + --no-ff \ |
77 | + -m "Merge remote tracking branch other/$SOURCE_GIT_REPO_BRANCH" \ |
78 | + $REVISION |
79 | +fi |
80 | + |
81 | +SNAP_NAME=$(grep "name:" snapcraft.yaml | awk '{print $2}') |
82 | +SNAP_REV=$(git rev-parse --short HEAD) |
83 | +CI_BRANCH=build/$SNAP_NAME-$BUILD_ID-$SNAP_REV |
84 | +git checkout -b $CI_BRANCH |
85 | +git remote add jenkins-ci git+ssh://system-enablement-ci-bot@git.launchpad.net/~snappy-hwe-team/snappy-hwe-snaps/+git/jenkins-ci-builds |
86 | +git push jenkins-ci $CI_BRANCH |
87 | + |
88 | +EXTRA_ARGS= |
89 | +if [ -n "$ARCHITECTURES" ]; then |
90 | + EXTRA_ARGS="$EXTRA_ARGS --architectures=$ARCHITECTURES" |
91 | +fi |
92 | + |
93 | +$WORKSPACE/build-scripts/scripts/trigger-lp-build.py \ |
94 | + -s $SNAP_NAME -n \ |
95 | + --git-repo=https://git.launchpad.net/~snappy-hwe-team/snappy-hwe-snaps/+git/jenkins-ci-builds \ |
96 | + --git-repo-branch=$CI_BRANCH \ |
97 | + $EXTRA_ARGS |
98 | +# When build has finished (regardless of its result) we remove our CI branch |
99 | +# to keep the CI repository clean. |
100 | +git push jenkins-ci :$CI_BRANCH |
101 | +if [ $? -ne 0 ]; then |
102 | + exit 1 |
103 | +fi |
104 | diff --git a/scripts/snap-build b/scripts/snap-build |
105 | deleted file mode 100755 |
106 | index abe40b4..0000000 |
107 | --- a/scripts/snap-build |
108 | +++ /dev/null |
109 | @@ -1,111 +0,0 @@ |
110 | -#!/bin/bash |
111 | -# |
112 | -# Copyright (C) 2016 Canonical Ltd |
113 | -# |
114 | -# This program is free software: you can redistribute it and/or modify |
115 | -# it under the terms of the GNU General Public License version 3 as |
116 | -# published by the Free Software Foundation. |
117 | -# |
118 | -# This program is distributed in the hope that it will be useful, |
119 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
120 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
121 | -# GNU General Public License for more details. |
122 | -# |
123 | -# You should have received a copy of the GNU General Public License |
124 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
125 | - |
126 | -set -x |
127 | -set -e |
128 | - |
129 | -# Fix certain builds that require a locale set |
130 | -export LC_ALL=C |
131 | - |
132 | -WORKSPACE=$1 |
133 | -SERIES=$2 |
134 | -TARGET_GIT_REPO=$3 |
135 | -TARGET_GIT_REPO_BRANCH=$4 |
136 | -SOURCE_GIT_REPO=$5 |
137 | -SOURCE_GIT_REPO_BRANCH=$6 |
138 | -REVISION=$7 |
139 | -FORCE=$8 |
140 | - |
141 | -BUILD_ROOTFS_TARBALL=$WORKSPACE/snap-build-$SERIES.tar |
142 | - |
143 | -if [ ! -e $BUILD_ROOTFS_TARBALL ] || [ "$REBUILD_ROOTFS" -eq "1" ] ; then |
144 | - sudo $WORKSPACE/build-scripts/scripts/build-rootfs-create $SERIES $BUILD_ROOTFS_TARBALL |
145 | -fi |
146 | - |
147 | -cd $WORKSPACE |
148 | - |
149 | -# Cleanup environment a bit |
150 | -[ -e build ] && rm -rf build |
151 | -[ -e results ] && rm -rf results |
152 | - |
153 | -mkdir build |
154 | -mkdir results |
155 | - |
156 | -tar xf $BUILD_ROOTFS_TARBALL -C build |
157 | - |
158 | -cat << EOF > build/rootfs/do-build.sh |
159 | -#!/bin/bash |
160 | -set -x |
161 | -set -e |
162 | - |
163 | -export TERM=linux |
164 | -export DEBIAN_FRONTEND=noninteractive |
165 | - |
166 | -# HACK: As we're not able to talk with parts.snapcraft.io yet |
167 | -# we need to fake the parts registry here as otherwise we can't |
168 | -# process our builds. |
169 | -export SNAPCRAFT_PARTS_URI=http://dev.null |
170 | -export XDG_DATA_HOME=/build/xdg-data |
171 | -mkdir -p /build/xdg-data/snapcraft |
172 | -touch /build/xdg-data/snapcraft/parts.yaml |
173 | -echo "{If-Modified-Since: '`date`'}" > /build/xdg-data/snapcraft/headers.yaml |
174 | - |
175 | -# Add missing package sources to the system to get necessary |
176 | -# updates for snapcraft & co |
177 | -echo "deb http://de.archive.ubuntu.com/ubuntu/ $SERIES-updates main" >> /etc/apt/sources.list |
178 | -echo "deb http://archive.ubuntu.com/ubuntu/ $SERIES-updates universe" >> /etc/apt/sources.list |
179 | - |
180 | -# Make sure all required things are installed |
181 | -apt-get update |
182 | -apt-get -y --force-yes upgrade |
183 | -apt-get -y --force-yes install snapcraft git |
184 | - |
185 | -mkdir -p /build |
186 | -git clone -b $TARGET_GIT_REPO_BRANCH $TARGET_GIT_REPO /build/src |
187 | -cd /build/src |
188 | - |
189 | -git config user.name "System Enablement CI Bot" |
190 | -git config user.email "ce-system-enablement@lists.canonical.com" |
191 | - |
192 | -if [ -n "$SOURCE_GIT_REPO" ]; then |
193 | - git remote add other $SOURCE_GIT_REPO |
194 | - git fetch other |
195 | - git merge \ |
196 | - --no-ff \ |
197 | - -m "Merge remote tracking branch other/$SOURCE_GIT_REPO_BRANCH" \ |
198 | - $REVISION |
199 | -fi |
200 | - |
201 | -# Only attempt to build projects where we have a valid snapcraft project. |
202 | -# For all others we just make sure we can merge source to target. |
203 | -if [ ! -e "/build/src/snapcraft.yaml" ] && [ ! -e "/build/src/.snapcraft.yaml" ] ; then |
204 | - echo "WARNING: Project does not contain a snapcraft.yaml file!" |
205 | - exit 0 |
206 | -fi |
207 | - |
208 | -find /build/src |
209 | -snapcraft --version |
210 | -snapcraft |
211 | -EOF |
212 | - |
213 | -chmod +x build/rootfs/do-build.sh |
214 | -chroot build/rootfs /do-build.sh |
215 | - |
216 | -# Copy snaps to their target directory where jenkins will |
217 | -# pick them up and provide as buid artifacts |
218 | -cp build/rootfs/build/src/*.snap results/ || true |
219 | - |
220 | -rm -rf build |
221 | diff --git a/scripts/trigger-lp-build.py b/scripts/trigger-lp-build.py |
222 | index 7f0f544..ed3d3e8 100755 |
223 | --- a/scripts/trigger-lp-build.py |
224 | +++ b/scripts/trigger-lp-build.py |
225 | @@ -3,7 +3,11 @@ |
226 | import os |
227 | import sys |
228 | import time |
229 | +import random |
230 | import smtplib |
231 | +import string |
232 | +import urllib2 |
233 | +import zlib |
234 | |
235 | from datetime import datetime |
236 | from os.path import basename |
237 | @@ -18,9 +22,21 @@ parser.add_argument('-s', '--snap', required=True, |
238 | help="Name of the snap to build") |
239 | parser.add_argument('-p', '--publish', action='store_true', |
240 | help="Trigger a publish build instead of a daily (default)") |
241 | +parser.add_argument('-n', '--new', action='store_true', help="Create a new ephemeral snap build on launchpad") |
242 | +parser.add_argument('--git-repo', help="Git repository to be used for new ephemeral snap build") |
243 | +parser.add_argument('--git-repo-branch', help="Git repository branch to be used for new ephemeral snap build") |
244 | +parser.add_argument('-a', '--architectures', help="Specify architectures to build for. Separate multiple architectures by ','") |
245 | |
246 | args = vars(parser.parse_args()) |
247 | |
248 | +ephemeral_build=False |
249 | + |
250 | +if args['new']: |
251 | + ephemeral_build=True |
252 | + if not 'git_repo' in args or not 'git_repo_branch' in args: |
253 | + print("ERROR: No git repository or a branch supplied") |
254 | + sys.exit(1) |
255 | + |
256 | series = 'xenial' |
257 | |
258 | lp_app = se_utils.get_config_option("lp_app") |
259 | @@ -29,28 +45,70 @@ credential_store_path = se_utils.get_config_option('credential_store_path') |
260 | launchpad = se_utils.get_launchpad(None, credential_store_path, lp_app, lp_env) |
261 | |
262 | team = launchpad.people['snappy-hwe-team'] |
263 | - |
264 | -build_name = "%s-daily" % args["snap"] |
265 | -if args["publish"] == True: |
266 | - build_name = "%s-publish" % args["snap"] |
267 | - |
268 | -snap = launchpad.snaps.getByName(name=build_name, owner=team) |
269 | ubuntu = launchpad.distributions['ubuntu'] |
270 | release = ubuntu.getSeries(name_or_version=series) |
271 | primary_archive = ubuntu.getArchive(name='primary') |
272 | |
273 | +snap=None |
274 | +if ephemeral_build: |
275 | + snap_arches=[] |
276 | + if 'architectures' in args and len(args['architectures']) > 0: |
277 | + snap_arches = args["architectures"].split(",") |
278 | + |
279 | + if len(snap_arches) == 0: |
280 | + print("WARNING: No architectures to build specified. Will only build for amd64.") |
281 | + snap_arches=["amd64"] |
282 | + |
283 | + processors=[] |
284 | + for arch in snap_arches: |
285 | + try: |
286 | + p = launchpad.processors.getByName(name=arch) |
287 | + processors.append(p.self_link) |
288 | + except: |
289 | + print("ERROR: Failed to find processor for '{}' architecture".format(arch)) |
290 | + sys.exit(1) |
291 | + |
292 | + build_name = 'ci-%s-%s' % (args["snap"], ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(16))) |
293 | + snap = launchpad.snaps.new(name=build_name, |
294 | + processors=processors, |
295 | + auto_build=False, distro_series=release, |
296 | + git_repository_url=args['git_repo'], |
297 | + git_path='%s' % args["git_repo_branch"], |
298 | + owner=team) |
299 | +else: |
300 | + build_name = "%s-daily" % args["snap"] |
301 | + if args["publish"] == True: |
302 | + build_name = "%s-publish" % args["snap"] |
303 | + snap = launchpad.snaps.getByName(name=build_name, owner=team) |
304 | + |
305 | +if snap == None: |
306 | + print("ERROR: Failed to create snap build on launchpad") |
307 | + |
308 | +# Not every snap is build agains all arches. |
309 | +arches = [processor.name for processor in snap.processors] |
310 | +if not ephemeral_build and "architectures" in args: |
311 | + wanted_arches = args["architectures"].split(",") |
312 | + possible_arches = [] |
313 | + for arch in wanted_arches: |
314 | + if not arch in arches: |
315 | + print("WARNING: Can't build snap for architecture {} as it is not enabled in the build job".format(args["snap"])) |
316 | + continue |
317 | + possible_arches.append(arch) |
318 | + arches = possible_arches |
319 | + |
320 | +if len(arches) == 0: |
321 | + print("ERROR: No architectures available to build for") |
322 | + sys.exit(1) |
323 | + |
324 | # Add a big fat warning that we don't really care about fixing things when |
325 | # the job will be canceled after the following lines are printed out. |
326 | -print("!!!!!!! POINT OF NO RETURN !!!!!!!") |
327 | +print("!!!!!!! POINT OF NO RETURN !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") |
328 | print("DO NOT CANCEL THIS JOB AFTER THIS OR BAD THINGS WILL HAPPEN") |
329 | -print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") |
330 | +print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") |
331 | |
332 | stamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') |
333 | print("Trying to trigger builds at: {}".format(stamp)) |
334 | |
335 | -# Not every snap is build agains all arches. |
336 | -arches = [processor.name for processor in snap.processors] |
337 | - |
338 | # We will now trigger a build for each whitelisted architecture, collect the |
339 | # build job url and the wait for all builds to finish and collect their results |
340 | # to vote for a successful or failed build. |
341 | @@ -60,7 +118,7 @@ for build_arch in arches: |
342 | request = snap.requestBuild(archive=primary_archive, distro_arch_series=arch, pocket='Proposed') |
343 | build_id = str(request).rsplit('/', 1)[-1] |
344 | triggered_builds.append(build_id) |
345 | - print("Arch: {} is building under: {}".format(build_arch, request)) |
346 | + print("Arch: {} is building under: {}".format(build_arch, request.web_link)) |
347 | |
348 | failures = [] |
349 | while len(triggered_builds): |
350 | @@ -90,12 +148,21 @@ if len(failures): |
351 | except: |
352 | print ("Could not get failure data for {} (was there an LP timeout?)".format(build)) |
353 | continue |
354 | - buildlog = response[build]['build_log_url'] |
355 | + buildlog = response[failure]['build_log_url'] |
356 | if buildlog != 'None': |
357 | - print(buildlog) |
358 | arch = str(buildlog).split('_')[4] |
359 | print("{} snap {} build at {} failed for id: {} log: {}".format(args["snap"], arch, stamp, failure, buildlog)) |
360 | + # For ephermal builds we need to print out the log file as it will be gone after |
361 | + # the launchpad build is removed. |
362 | + if ephemeral_build: |
363 | + response = urllib2.urlopen(buildlog) |
364 | + log_data = zlib.decompress(response.read(), 16+zlib.MAX_WBITS) |
365 | + print(log_data) |
366 | |
367 | +if ephemeral_build: |
368 | + snap.lp_delete() |
369 | + |
370 | +if len(failures): |
371 | # Let the build fail as at least a single snap has failed to build |
372 | sys.exit(1) |
373 |
PASSED: Continuous integration, rev:0e5ea052de6 9a5e5bfa89a6c63 48e6a5cdbc0a85 /jenkins. canonical. com/system- enablement/ job/generic- build-snap/ 957/ /jenkins. canonical. com/system- enablement/ job/generic- run-snap- spread- tests/662 /jenkins. canonical. com/system- enablement/ job/generic- update- snap-mp/ 865/console
https:/
Executed test runs:
SUCCESS: https:/
None: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/system- enablement/ job/generic- build-snap/ 957/rebuild
https:/