1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
#! /usr/bin/python
import os
import sys
import time
import smtplib
from datetime import datetime
from os.path import basename
from launchpadlib.launchpad import Launchpad
from email.mime.text import MIMEText
# where failure mails go
mailreceivers = ['ogra@ubuntu.com']
# basic data
arches = ['amd64', 'i386', 'armhf', 'arm64', 'ppc64el', 's390x']
series = 'xenial'
# basic paths
home = os.getenv("HOME")
workdir = home+"/ubuntu-core-builds"
# we need to store credentials once for cronned builds
cachedir = workdir+"/cache"
creds = workdir+"/credentials"
def sendMail(arch, stamp, failure, buildlog):
# send failure mails to defined recipients
sender = 'ogra@canonical.com'
if buildlog:
mailtext = "ubuntu-core {} snap\nBuild requested at {}\nFailed for id: {}\nLink to build log: {}".format(arch, stamp, failure, buildlog)
mailtext = "build-ubuntu-core: {} ".format(failure)
message = MIMEText(mailtext)
message['Subject'] = '%s ubuntu-core snap failed to build !' % arch
message['From'] = 'Snap Auto Builder <%s>' % sender
message['To'] = ", ".join(mailreceivers)
try:
smtpObj = smtplib.SMTP('localhost')
smtpObj.sendmail(sender, mailreceivers, message.as_string())
print ("Successfully sent failure email to {}".format(mailreceivers))
except Exception:
print ("Error: unable to send failure email")
# make sure we dont clash with an older build attempt
pid = str(os.getpid())
pidfile = workdir+"/build.pid"
if os.path.isfile(pidfile):
print "A pid file %s already exists, it seems like" % pidfile
print "there is already a build-ubuntu-core running."
print "exiting !"
sendMail("","","pid exists","")
sys.exit()
file(pidfile, 'w').write(pid)
# log in
launchpad = Launchpad.login_with('Ubuntu Core Builds',
'production', cachedir,
credentials_file=creds,
version='devel')
# get snappy-dev team data and ppa
snappydev = launchpad.people['snappy-dev']
imageppa = snappydev.getPPAByName(name='image')
# get snap
ubuntucore = launchpad.snaps.getByName(name='ubuntu-core',
owner=snappydev)
# get distro info
ubuntu = launchpad.distributions['ubuntu']
release = ubuntu.getSeries(name_or_version=series)
# print a stamp
stamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print("Trying to trigger builds at: {}".format(stamp))
# loop over arches and trigger builds
mybuilds = []
for buildarch in arches:
arch = release.getDistroArchSeries(archtag=buildarch)
request = ubuntucore.requestBuild(archive=imageppa,
distro_arch_series=arch,
pocket='Proposed')
buildid = str(request).rsplit('/', 1)[-1]
mybuilds.append(buildid)
print("Arch: {} is building under: {}".format(buildarch,
request))
# check the status each minute til all builds have finished
failures = []
while len(mybuilds):
for build in mybuilds:
try:
response = ubuntucore.getBuildSummariesForSnapBuildIds(snap_build_ids=[build])
except:
print ("could not get response for {} (was there an LP timeout ?)".format(build))
continue
status = response[build]['status']
if status == "FULLYBUILT":
mybuilds.remove(build)
continue
elif status == "FAILEDTOBUILD":
failures.append(build)
mybuilds.remove(build)
continue
elif status == "CANCELLED":
mybuilds.remove(build)
continue
time.sleep(60)
# if we had failures, print them and send mails
if len(failures):
for failure in failures:
try:
response = ubuntucore.getBuildSummariesForSnapBuildIds(snap_build_ids=[failure])
except:
print ("could not get failure data for {} (was there an LP timeout ?)".format(build))
continue
buildlog = response[build]['build_log_url']
if buildlog != 'None':
print(buildlog)
arch = str(buildlog).split('_')[4]
print("ubuntu-core snap {} build at {} failed for id: {} log: {}".format(arch, stamp, failure, buildlog))
sendMail(arch, stamp, failure, buildlog)
# tell the log we are done and remove pid file
print("done")
os.unlink(pidfile)
|