/breezy-builder/trunk

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy-builder/trunk
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
# ppa support for bzr builder.
#
# Copyright: Canonical Ltd. (C) 2009
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.

# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.

import time

from breezy import (
    errors,
    trace,
    )
from launchpadlib.launchpad import Launchpad


def get_lp():
    return Launchpad.login_with('bzr-builder', 'production')


def watch(owner_name, archive_name, package_name, version):
    """Watch a package build.

    :return: True once the package built and published, or False if it fails
        or there is a timeout waiting.
    """
    version = str(version)
    trace.note("Logging into Launchpad")

    launchpad = get_lp()
    owner = launchpad.people[owner_name]
    archive = owner.getPPAByName(name=archive_name)
    end_states = ['FAILEDTOBUILD', 'FULLYBUILT']
    important_arches = ['amd64', 'i386', 'armel']
    trace.note("Waiting for version %s of %s to build." % (version, package_name))
    start = time.time()
    while True:
        sourceRecords = list(archive.getPublishedSources(
            source_name=package_name, version=version))
        if not sourceRecords:
            if time.time() - 900 > start:
                # Over 15 minutes and no source yet, upload FAIL.
                raise errors.BzrCommandError("No source record in %s/%s for "
                    "package %s=%s after 15 minutes." % (owner_name,
                        archive_name, package_name, version))
                return False
            trace.note("Source not available yet - waiting.")
            time.sleep(60)
            continue
        pkg = sourceRecords[0]
        if pkg.status.lower() not in ('published', 'pending'):
            trace.note("Package status: %s" % (pkg.status,))
            time.sleep(60)
            continue
        # FIXME: LP should export this as an attribute.
        source_id = pkg.self_link.rsplit('/', 1)[1]
        buildSummaries = archive.getBuildSummariesForSourceIds(
            source_ids=[source_id])[source_id]
        if buildSummaries['status'] in end_states:
            break
        if buildSummaries['status'] == 'NEEDSBUILD':
            # We ignore non-virtual PPA architectures that are sparsely
            # supplied with buildds.
            missing = []
            for build in buildSummaries['builds']:
                arch = build['arch_tag']
                if arch in important_arches:
                    missing.append(arch)
            if not missing:
                break
            extra = ' on ' + ', '.join(missing)
        else:
            extra = ''
        trace.note("%s is still in %s%s" % (pkg.display_name,
                    buildSummaries['status'], extra))
        time.sleep(60)
    trace.note("%s is now %s" % (pkg.display_name, buildSummaries['status']))
    result = True
    if pkg.status.lower() != 'published':
        result = False # should this perhaps keep waiting?
    if buildSummaries['status'] != 'FULLYBUILT':
        if buildSummaries['status'] == 'NEEDSBUILD':
            # We're stopping early cause the important_arches are built.
            builds = pkg.getBuilds()
            for build in builds:
                if build.arch_tag in important_arches:
                    if build.buildstate != 'Successfully built':
                        result = False
        else:
            result = False
    return result