~nskaggs/juju-release-tools/generate-release-notes

179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
1
#!/usr/bin/python
198.2.6 by Curtis Hovey
Convert the --series LIVING into a list of licing series.
2
"""Script for building source and binary debian packages."""
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
3
4
from __future__ import print_function
5
6
from argparse import ArgumentParser
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
7
from collections import namedtuple
8
import os
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
9
import re
179.2.10 by Curtis Hovey
Copy source_files to the build dir. Added helper to make test source files.
10
import shutil
179.2.12 by Curtis Hovey
Fleshed out setup_lxc.
11
import subprocess
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
12
import sys
13
221.1.1 by Aaron Bentley
Fix lint.
14
__metaclass__ = type
15
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
16
243 by Curtis Hovey
Return DEBS_NOT_FOUND when debs are not moved to the build dir.
17
DEBS_NOT_FOUND = 3
18
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
19
# This constant defines the location of the base source package branch.
198.2.1 by Curtis Hovey
Added arguments to create source packages.
20
DEFAULT_SPB = 'lp:~juju-qa/juju-release-tools/packaging-juju-core-default'
346 by Nicholas Skaggs
Restore old CI packaging branch
21
DEFAULT_SPB2 = 'lp:~juju-qa/juju-release-tools/packaging-juju-core2-default'
198.2.1 by Curtis Hovey
Added arguments to create source packages.
22
23
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
24
# This constant defines the status of the series supported by CI and Releases.
25
SUPPORTED_RELEASES = """\
26
12.04 precise LTS
27
12.10 quantal HISTORIC
28
13.10 saucy HISTORIC
29
14.04 trusty LTS
30
14.10 utopic HISTORIC
246.1.1 by Curtis Hovey
Desupport vivid.
31
15.04 vivid HISTORIC
343 by Nicholas Skaggs
fix typo in wily hitoric
32
15.10 wily HISTORIC
302 by Curtis Hovey
Added Yakety to the supported release.
33
16.04 xenial LTS
345 by Nicholas Skaggs
Add zesty to supported releases, update default branch for juju2
34
16.10 yakkety SUPPORTED
35
17.04 zesty DEVEL
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
36
"""
37
38
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
39
SourceFile = namedtuple('SourceFile', ['sha256', 'size', 'name', 'path'])
40
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
41
179.2.14 by Curtis Hovey
Use bash scripts instead of separate commands to make editing easy.
42
CREATE_LXC_TEMPLATE = """\
43
set -eu
241.1.1 by Curtis Hovey
Use lxc cloud-images to build binary packages.
44
sudo lxc-create -t ubuntu-cloud -n {container} -- -r {series} -a {arch}
179.2.14 by Curtis Hovey
Use bash scripts instead of separate commands to make editing easy.
45
sudo mkdir /var/lib/lxc/{container}/rootfs/workspace
46
echo "lxc.mount.entry = {build_dir} workspace none bind 0 0" |
47
    sudo tee -a /var/lib/lxc/{container}/config
48
"""
49
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
50
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
51
BUILD_DEB_TEMPLATE = """\
179.2.25 by Curtis Hovey
Script/timing fixes for lxc build.
52
sudo lxc-attach -n {container} -- bash <<"EOT"
53
    set -eu
179.2.27 by Curtis Hovey
Refine and document build phases.
54
    echo "\nInstalling common build deps.\n"
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
55
    cd workspace
241.1.2 by Curtis Hovey
Added comments to explain the guards.
56
    # Wait for Cloud-init to complete to indicate the machine is in a ready
57
    # state with network to do work,
241.1.1 by Curtis Hovey
Use lxc cloud-images to build binary packages.
58
    while ! tail -1 /var/log/cloud-init-output.log | \
241.1.3 by Curtis Hovey
Use case-insentive check for cloud-init finish.
59
            egrep -q -i 'Cloud-init .* finished'; do
241.1.1 by Curtis Hovey
Use lxc cloud-images to build binary packages.
60
        echo "Waiting for Cloud-init to finish."
61
        sleep 5
179.2.25 by Curtis Hovey
Script/timing fixes for lxc build.
62
    done
63
    set +e
295 by Curtis Hovey
Use ports with s390x.
64
    # The cloud-init breaks arm64, ppc64el. s390x /etc/apt/sources.list.
65
    if [[ $(dpkg --print-architecture) =~ ^(arm64|ppc64el|s390x)$ ]]; then
241.1.1 by Curtis Hovey
Use lxc cloud-images to build binary packages.
66
        sed -i \
67
            -e 's,archive.ubuntu.com/ubuntu,ports.ubuntu.com/ubuntu-ports,' \
68
            /etc/apt/sources.list
69
    fi
182.1.7 by Curtis Hovey
Added comment about --force-yes.
70
    # Adding the ppa directly to sources.list without the archive key
71
    # requires apt to be run with --force-yes
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
72
    echo "{ppa}" >> /etc/apt/sources.list
179.2.28 by Curtis Hovey
Run scripts in shell.
73
    export DEBIAN_FRONTEND=noninteractive
179.2.25 by Curtis Hovey
Script/timing fixes for lxc build.
74
    apt-get update
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
75
    apt-get install -y --force-yes build-essential devscripts equivs
179.2.26 by Curtis Hovey
This works, though it is ugly.
76
EOT
77
sudo lxc-attach -n {container} -- bash <<"EOT"
78
    set -eux
179.2.27 by Curtis Hovey
Refine and document build phases.
79
    echo "\nInstalling build deps from dsc.\n"
179.2.26 by Curtis Hovey
This works, though it is ugly.
80
    cd workspace
179.2.28 by Curtis Hovey
Run scripts in shell.
81
    export DEBIAN_FRONTEND=noninteractive
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
82
    mk-build-deps -i --tool 'apt-get --yes --force-yes' *.dsc
179.2.26 by Curtis Hovey
This works, though it is ugly.
83
EOT
84
sudo lxc-attach -n {container} -- bash <<"EOT"
85
    set -eux
179.2.27 by Curtis Hovey
Refine and document build phases.
86
    echo "\nBuilding the packages.\n"
179.2.26 by Curtis Hovey
This works, though it is ugly.
87
    cd workspace
194 by Curtis Hovey
Some versions of mk-build-deps remove the fake package when done.
88
    rm *build-deps*.deb || true
179.2.27 by Curtis Hovey
Refine and document build phases.
89
    dpkg-source -x *.dsc
90
    cd $(basename *.orig.tar.gz .orig.tar.gz | tr _ -)
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
91
    dpkg-buildpackage -us -uc
179.2.26 by Curtis Hovey
This works, though it is ugly.
92
EOT
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
93
"""
94
95
198.2.8 by Curtis Hovey
Added create_source_package_branch().
96
CREATE_SPB_TEMPLATE = """\
198.2.13 by Curtis Hovey
Added test for create_source_package and fixed broken call to make_changelog_message.
97
set -eux
198.2.8 by Curtis Hovey
Added create_source_package_branch().
98
bzr branch {branch} {spb}
99
cd {spb}
100
bzr import-upstream {version} {tarfile_path}
101
bzr merge . -r upstream-{version}
102
bzr commit -m "Merged upstream-{version}."
103
"""
104
105
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
106
BUILD_SOURCE_TEMPLATE = """\
198.2.13 by Curtis Hovey
Added test for create_source_package and fixed broken call to make_changelog_message.
107
set -eux
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
108
bzr branch {spb} {source}
109
cd {source}
198.2.22 by Curtis Hovey
Added docstrings.
110
dch --newversion {ubuntu_version} -D {series} --force-distribution "{message}"
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
111
debcommit
112
bzr bd -S -- -us -uc
113
"""
114
198.2.16 by Curtis Hovey
Sign packges when gpgcmd is provided.
115
DEBSIGN_TEMPLATE = 'debsign -p {gpgcmd} *.changes'
116
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
117
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
118
UBUNTU_VERSION_TEMPLATE_EPOCH = \
119
    '{epoch}:{version}-0ubuntu1~{release}.{upatch}~juju1'
120
DAILY_VERSION_TEMPLATE_EPOCH = \
121
    '{epoch}:{version}-{date}+{build}+{revid}~{release}'
122
UBUNTU_VERSION_TEMPLATE = '{version}-0ubuntu1~{release}.{upatch}~juju1'
123
DAILY_VERSION_TEMPLATE = '{version}-{date}+{build}+{revid}~{release}'
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
124
125
198.2.26 by Curtis Hovey
upatch is '1' not 0 per the rule we current build with. Added test for LIVING.
126
VERSION_PATTERN = re.compile('(\d+)\.(\d+)\.(\d+)')
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
127
128
198.2.17 by Curtis Hovey
Moved JujuSeries into build_package.py.
129
Series = namedtuple('Series', ['version', 'name', 'status'])
130
131
198.2.24 by Curtis Hovey
_JujuSeries is a singleton.
132
class _JujuSeries:
198.2.17 by Curtis Hovey
Moved JujuSeries into build_package.py.
133
134
    LIVING_STATUSES = ('DEVEL', 'SUPPORTED', 'LTS')
135
198.2.18 by Curtis Hovey
Inlined SUPPORTED_RELEASES.
136
    def __init__(self):
198.2.17 by Curtis Hovey
Moved JujuSeries into build_package.py.
137
        self.all = {}
198.2.18 by Curtis Hovey
Inlined SUPPORTED_RELEASES.
138
        for line in SUPPORTED_RELEASES.splitlines():
198.2.17 by Curtis Hovey
Moved JujuSeries into build_package.py.
139
            series = Series(*line.split())
140
            self.all[series.name] = series
141
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
142
    def get_devel_version(self):
143
        for series in self.all.values():
144
            if series.status == 'DEVEL':
145
                return series.version
146
        else:
147
            raise AssertionError(
148
                "SUPPORTED_RELEASES is missing the DEVEL series")
149
198.2.17 by Curtis Hovey
Moved JujuSeries into build_package.py.
150
    def get_living_names(self):
151
        return sorted(s.name for s in self.all.values()
152
                      if s.status in self.LIVING_STATUSES)
153
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
154
    def get_name(self, version):
155
        for series in self.all.values():
156
            if series.version == version:
157
                return series.name
158
        else:
159
            raise KeyError("'%s' is not a known series" % version)
160
161
    def get_name_from_package_version(self, package_version):
162
        """Return the series name associated with the package version.
163
164
        The series is matched to the series version commonly embedded in
165
        backported package versions. Official juju package versions always
166
        contain the series version to indicate the tool-chain used to build.
167
168
        Ubuntu devel packages do not have series versions, they cannot be
169
        matched to a series. As Ubuntu packages are not built with ideal rules,
170
        they are not suitable for building agents.
171
        """
172
        for series in self.all.values():
173
            if series.version in package_version:
174
                return series.name
245.1.2 by Curtis Hovey
Exit 1 when a --series-name-from-package-version has no match.
175
        return None
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
176
198.2.17 by Curtis Hovey
Moved JujuSeries into build_package.py.
177
    def get_version(self, name):
178
        return self.all[name].version
179
180
198.2.24 by Curtis Hovey
_JujuSeries is a singleton.
181
juju_series = _JujuSeries()
182
183
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
184
def parse_dsc(dsc_path, verbose=False):
179.2.22 by Curtis Hovey
Added doc
185
    """Return the source files need to build a binary package."""
179.2.9 by Curtis Hovey
Include the dsc in the source_files so it is copied.
186
    there = os.path.dirname(dsc_path)
187
    dsc_name = os.path.basename(dsc_path)
188
    dcs_source_file = SourceFile(None, None, dsc_name, dsc_path)
189
    files = [dcs_source_file]
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
190
    with open(dsc_path) as f:
191
        content = f.read()
192
    found = False
193
    for line in content.splitlines():
194
        if found and line.startswith(' '):
195
            data = line.split()
196
            data.append(os.path.join(there, data[2]))
197
            files.append(SourceFile(*data))
179.2.13 by Curtis Hovey
Added verbosity.
198
            if verbose:
199
                print("Found %s" % files[-1].name)
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
200
        elif found:
201
            # All files were found.
202
            break
203
        if not found and line.startswith('Checksums-Sha256:'):
204
            found = True
205
    return files
206
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
207
179.2.7 by Curtis Hovey
Pass series and arch to setup_local.
208
def setup_local(location, series, arch, source_files, verbose=False):
179.2.22 by Curtis Hovey
Added doc
209
    """Create a directory to build binaries in.
210
211
    The directoy has the source files required to build binaries.
212
    """
179.2.12 by Curtis Hovey
Fleshed out setup_lxc.
213
    build_dir = os.path.abspath(
214
        os.path.join(location, 'juju-build-{}-{}'.format(series, arch)))
179.2.13 by Curtis Hovey
Added verbosity.
215
    if verbose:
216
        print('Creating %s' % build_dir)
179.2.8 by Curtis Hovey
setup_local creates a build_dir.
217
    os.makedirs(build_dir)
179.2.10 by Curtis Hovey
Copy source_files to the build dir. Added helper to make test source files.
218
    for sf in source_files:
219
        dest_path = os.path.join(build_dir, sf.name)
179.2.13 by Curtis Hovey
Added verbosity.
220
        if verbose:
221
            print('Copying %s to %s' % (sf.name, build_dir))
179.2.10 by Curtis Hovey
Copy source_files to the build dir. Added helper to make test source files.
222
        shutil.copyfile(sf.path, dest_path)
179.2.8 by Curtis Hovey
setup_local creates a build_dir.
223
    return build_dir
179.2.3 by Curtis Hovey
Added skeleton of setup_local.
224
225
179.2.11 by Curtis Hovey
Created skeletion of setup_lxc.
226
def setup_lxc(series, arch, build_dir, verbose=False):
179.2.22 by Curtis Hovey
Added doc
227
    """Create an LXC container to build binaries.
228
229
    The local build_dir with the source files is bound to the container.
230
    """
179.2.12 by Curtis Hovey
Fleshed out setup_lxc.
231
    container = '{}-{}'.format(series, arch)
179.2.14 by Curtis Hovey
Use bash scripts instead of separate commands to make editing easy.
232
    lxc_script = CREATE_LXC_TEMPLATE.format(
233
        container=container, series=series, arch=arch, build_dir=build_dir)
179.2.25 by Curtis Hovey
Script/timing fixes for lxc build.
234
    if verbose:
235
        print('Creating %s container' % container)
179.2.28 by Curtis Hovey
Run scripts in shell.
236
    output = subprocess.check_output([lxc_script], shell=True)
179.2.12 by Curtis Hovey
Fleshed out setup_lxc.
237
    if verbose:
238
        print(output)
239
    return container
179.2.11 by Curtis Hovey
Created skeletion of setup_lxc.
240
241
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
242
def build_in_lxc(container, build_dir, ppa=None, verbose=False):
179.2.22 by Curtis Hovey
Added doc
243
    """Build the binaries from the source files in the container."""
179.2.17 by Curtis Hovey
Added test to verify lxcs are not left running.
244
    returncode = 1
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
245
    if ppa:
246
        path = ppa.split(':')[1]
247
        series = container.split('-')[0]
248
        ppa = 'deb http://ppa.launchpad.net/{}/ubuntu {} main'.format(
249
            path, series)
250
    else:
251
        ppa = '# No PPA added.'
182.1.3 by Curtis Hovey
Added --ppa as an option.
252
    # The work in the container runs as a different user. Care is needed to
253
    # ensure permissions and ownership are correct before and after the build.
182.1.1 by Curtis Hovey
Move cleanup out of script and into build_in_lxc to manage flow control.
254
    os.chmod(build_dir, 0o777)
179.2.16 by Curtis Hovey
Added build_in_lxc.
255
    subprocess.check_call(['sudo', 'lxc-start', '-d', '-n', container])
256
    try:
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
257
        build_script = BUILD_DEB_TEMPLATE.format(container=container, ppa=ppa)
197.1.1 by Curtis Hovey
Use subprocess.call to *wait* for the work to complete.
258
        returncode = subprocess.call([build_script], shell=True)
179.2.16 by Curtis Hovey
Added build_in_lxc.
259
    finally:
260
        subprocess.check_call(['sudo', 'lxc-stop', '-n', container])
182.1.1 by Curtis Hovey
Move cleanup out of script and into build_in_lxc to manage flow control.
261
        user = os.environ.get('USER', 'jenkins')
262
        subprocess.check_call(['sudo', 'chown', '-R', user, build_dir])
263
        os.chmod(build_dir, 0o775)
179.2.16 by Curtis Hovey
Added build_in_lxc.
264
    return returncode
265
266
267
def teardown_lxc(container, verbose=False):
179.2.22 by Curtis Hovey
Added doc
268
    """Destroy the lxc container."""
179.2.24 by Curtis Hovey
improve verbosity.
269
    if verbose:
270
        print('Deleting the lxc container %s' % container)
179.2.16 by Curtis Hovey
Added build_in_lxc.
271
    subprocess.check_call(['sudo', 'lxc-destroy', '-n', container])
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
272
273
179.2.20 by Curtis Hovey
Verify that move_debs is called.
274
def move_debs(build_dir, location, verbose=False):
179.2.22 by Curtis Hovey
Added doc
275
    """Move the debs from the build_dir to the location dir."""
179.2.20 by Curtis Hovey
Verify that move_debs is called.
276
    found = False
277
    files = [f for f in os.listdir(build_dir) if f.endswith('.deb')]
278
    for file_name in files:
179.2.21 by Curtis Hovey
Move built debs to workspace.
279
        file_path = os.path.join(build_dir, file_name)
280
        dest_path = os.path.join(location, file_name)
179.2.20 by Curtis Hovey
Verify that move_debs is called.
281
        if verbose:
282
            print("Found %s" % file_name)
179.2.21 by Curtis Hovey
Move built debs to workspace.
283
        shutil.move(file_path, dest_path)
179.2.20 by Curtis Hovey
Verify that move_debs is called.
284
        found = True
285
    return found
286
287
182.1.4 by Curtis Hovey
Pass ppa from main to build_binary.
288
def build_binary(dsc_path, location, series, arch, ppa=None, verbose=False):
179.2.22 by Curtis Hovey
Added doc
289
    """Build binary debs from a dsc file."""
179.2.3 by Curtis Hovey
Added skeleton of setup_local.
290
    # If location is remote, setup remote location and run.
179.2.2 by Curtis Hovey
Added parse_dsc and SourceFile.
291
    source_files = parse_dsc(dsc_path, verbose=verbose)
179.2.7 by Curtis Hovey
Pass series and arch to setup_local.
292
    build_dir = setup_local(
293
        location, series, arch, source_files, verbose=verbose)
179.2.15 by Curtis Hovey
Added skeleton of build_in_lxc.
294
    container = setup_lxc(series, arch, build_dir, verbose=verbose)
179.2.17 by Curtis Hovey
Added test to verify lxcs are not left running.
295
    try:
182.1.5 by Curtis Hovey
Use a ppa to get build deps.
296
        build_in_lxc(container, build_dir, ppa=ppa, verbose=verbose)
179.2.17 by Curtis Hovey
Added test to verify lxcs are not left running.
297
    finally:
179.2.18 by Curtis Hovey
Added test for teardown_lxc.
298
        teardown_lxc(container, verbose=False)
243 by Curtis Hovey
Return DEBS_NOT_FOUND when debs are not moved to the build dir.
299
    found = move_debs(build_dir, location, verbose=verbose)
300
    if not found:
301
        return DEBS_NOT_FOUND
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
302
    return 0
303
304
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
305
def create_source_package_branch(build_dir, version, tarfile, branch):
198.2.25 by Curtis Hovey
rename STABLE_PATTERN to VERSION_PATTERN
306
    """Create a new source package branch with the imported release tarfile.
198.2.22 by Curtis Hovey
Added docstrings.
307
308
    The new source package can be pushed to a permanent location if it will
309
    be used as the base for future packages.
310
311
    :param build_dir: The root directory to create the new branch in.
312
    :param version: The upstream version, which is not always the version
313
        in the tarfile name.
314
    :param tarfile: The path to the tarfile to import.
315
    :param branch: The base source package branch to fork and import into.
316
    :return: The path to the source package branch.
317
    """
198.2.8 by Curtis Hovey
Added create_source_package_branch().
318
    spb = os.path.join(build_dir, 'spb')
319
    tarfile_path = os.path.join(build_dir, tarfile)
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
320
    script = CREATE_SPB_TEMPLATE.format(
198.2.8 by Curtis Hovey
Added create_source_package_branch().
321
        branch=branch, spb=spb, tarfile_path=tarfile_path, version=version)
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
322
    subprocess.check_call([script], shell=True, cwd=build_dir)
198.2.8 by Curtis Hovey
Added create_source_package_branch().
323
    return spb
324
325
298.1.4 by Nicholas Skaggs
make everything new optional
326
def make_ubuntu_version(series, version, upatch=1,
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
327
                        date=None, build=None, revid=None, epoch=None):
198.2.22 by Curtis Hovey
Added docstrings.
328
    """Return an Ubuntu package version.
329
330
    :param series: The series codename.
331
    :param version: The upstream version.
298.1.4 by Nicholas Skaggs
make everything new optional
332
    :param upatch: The package patch number for cases where a packaging rules
333
        are updated and the package rebuilt.
298.1.1 by Nicholas Skaggs
add date and build to source
334
    :param date: The date of the build.
335
    :param build: The build number in CI.
298.1.3 by Nicholas Skaggs
add revid too
336
    :param revid: The revid hash of the source.
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
337
    :param epoch: The epoch to pass in version name
198.2.22 by Curtis Hovey
Added docstrings.
338
    :return: An Ubuntu version string.
339
    """
198.2.24 by Curtis Hovey
_JujuSeries is a singleton.
340
    release = juju_series.get_version(series)
298.1.4 by Nicholas Skaggs
make everything new optional
341
    # if daily params are set, we make daily build
342
    if all([date, build, revid]):
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
343
        if epoch:
344
            return DAILY_VERSION_TEMPLATE_EPOCH.format(
345
                epoch=epoch, version=version, release=release, upatch=upatch,
346
                date=date, build=build, revid=revid)
298.1.4 by Nicholas Skaggs
make everything new optional
347
        return DAILY_VERSION_TEMPLATE.format(
368.1.1 by Nicholas Skaggs
Fix lint errors, allow for e402 to support make_image_streams.py
348
            version=version, release=release, upatch=upatch,
349
            date=date, build=build, revid=revid)
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
350
298.1.4 by Nicholas Skaggs
make everything new optional
351
    else:
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
352
        if epoch:
353
            return UBUNTU_VERSION_TEMPLATE_EPOCH.format(
354
                epoch=epoch, version=version, release=release, upatch=upatch)
298.1.4 by Nicholas Skaggs
make everything new optional
355
        return UBUNTU_VERSION_TEMPLATE.format(
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
356
            version=version, release=release, upatch=upatch)
198.2.12 by Curtis Hovey
Exrtacted make_ubuntu_version and fixed it.
357
358
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
359
def make_changelog_message(version, bugs=None):
198.2.22 by Curtis Hovey
Added docstrings.
360
    """Return a changelog message for the version.
361
362
    :param version: The upstream version.
363
    :param bugs: A list of Lp bug numbers or None. They will be formatted
364
        for the changelog.
365
    :return: a changelog message.
366
    """
198.2.26 by Curtis Hovey
upatch is '1' not 0 per the rule we current build with. Added test for LIVING.
367
    match = VERSION_PATTERN.match(version)
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
368
    if match is None:
369
        message = 'New upstream devel release.'
370
    elif match.group(3) == '0':
371
        message = 'New upstream stable release.'
372
    else:
373
        message = 'New upstream stable point release.'
198.2.11 by Curtis Hovey
Added tests for make_changelog_message.
374
    if bugs:
375
        fixes = ', '.join(['LP #%s' % b for b in bugs])
376
        message = '%s (%s)' % (message, fixes)
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
377
    return message
378
379
198.2.21 by Curtis Hovey
Use make_deb_shell_env in tests.
380
def make_deb_shell_env(debemail, debfullname):
198.2.22 by Curtis Hovey
Added docstrings.
381
    """Return a replacement environ suitable for DEB building.
382
383
    :param debemail: The email address to attribute the changelog entry to.
384
    :param debfullname: The name to attribute the changelog entry to.
385
    :return: A modified copy of os.environ that can be passed to subprocesses.
386
    """
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
387
    env = dict(os.environ)
388
    env['DEBEMAIL'] = debemail
389
    env['DEBFULLNAME'] = debfullname
390
    return env
391
392
198.2.22 by Curtis Hovey
Added docstrings.
393
def sign_source_package(source_dir, gpgcmd, debemail, debfullname):
394
    """Sign a source package.
395
396
    The debemail and debfullname must match the identity used in the changelog
397
    and the changes file.
398
399
    :param source_dir: The source package directory.
400
    :param gpgcmd: The path to a gpg signing command to sign with.
401
    :param debemail: The email address to attribute the changelog entry to.
402
    :param debfullname: The name to attribute the changelog entry to.
403
    """
198.2.21 by Curtis Hovey
Use make_deb_shell_env in tests.
404
    env = make_deb_shell_env(debemail, debfullname)
198.2.16 by Curtis Hovey
Sign packges when gpgcmd is provided.
405
    script = DEBSIGN_TEMPLATE.format(gpgcmd=gpgcmd)
198.2.22 by Curtis Hovey
Added docstrings.
406
    subprocess.check_call([script], shell=True, cwd=source_dir, env=env)
407
408
298.1.4 by Nicholas Skaggs
make everything new optional
409
def create_source_package(source_dir, spb, series, version,
298.1.1 by Nicholas Skaggs
add date and build to source
410
                          upatch='1', bugs=None, gpgcmd=None, debemail=None,
298.1.4 by Nicholas Skaggs
make everything new optional
411
                          debfullname=None, verbose=False,
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
412
                          date=None, build=None, revid=None, epoch=None):
198.2.22 by Curtis Hovey
Added docstrings.
413
    """Create a series source package from a source package branch.
414
415
    The new source package can be used to create series source packages.
416
417
    :param source_dir: The source package directory.
418
    :param spb: The path (or location) of the source package branch to create
419
        the new source package with.
420
    :param series: The series codename.
421
    :param version: The upstream version.
422
    :param upatch: The package patch number for cases where a packaging rules
423
        are updated and the package rebuilt.
424
    :param bugs: A list of Lp bug numbers for the changelog or None.
425
    :param gpgcmd: The path to a gpg signing command to sign with.
426
        Source packages will be signed when gpgcmd is not None.
427
    :param debemail: The email address to attribute the changelog entry to.
428
    :param debfullname: The name to attribute the changelog entry to.
198.2.26 by Curtis Hovey
upatch is '1' not 0 per the rule we current build with. Added test for LIVING.
429
    :param verbose: Increase the information about the work performed.
298.1.4 by Nicholas Skaggs
make everything new optional
430
    :param date: The date of the build.
431
    :param build: The build number in CI.
432
    :param revid: The revid hash of the source.
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
433
    :param epoch: The epoch to pass in version name
198.2.22 by Curtis Hovey
Added docstrings.
434
    """
298.1.4 by Nicholas Skaggs
make everything new optional
435
298.1.5 by Nicholas Skaggs
fix ordering and tests
436
    ubuntu_version = make_ubuntu_version(series, version, upatch,
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
437
                                         date, build, revid, epoch)
198.2.13 by Curtis Hovey
Added test for create_source_package and fixed broken call to make_changelog_message.
438
    message = make_changelog_message(version, bugs=bugs)
198.2.23 by Curtis Hovey
Use constant source dir name for jenkins.
439
    source = os.path.join(source_dir, 'source')
198.2.21 by Curtis Hovey
Use make_deb_shell_env in tests.
440
    env = make_deb_shell_env(debemail, debfullname)
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
441
    script = BUILD_SOURCE_TEMPLATE.format(
442
        spb=spb, source=source, series=series, ubuntu_version=ubuntu_version,
443
        message=message)
198.2.22 by Curtis Hovey
Added docstrings.
444
    subprocess.check_call([script], shell=True, cwd=source_dir, env=env)
198.2.16 by Curtis Hovey
Sign packges when gpgcmd is provided.
445
    if gpgcmd:
198.2.22 by Curtis Hovey
Added docstrings.
446
        sign_source_package(source_dir, gpgcmd, debemail, debfullname)
198.2.8 by Curtis Hovey
Added create_source_package_branch().
447
448
298.1.4 by Nicholas Skaggs
make everything new optional
449
def build_source(tarfile_path, location, series, bugs,
198.2.2 by Curtis Hovey
Added shub for build_source.
450
                 debemail=None, debfullname=None, gpgcmd=None,
298.1.4 by Nicholas Skaggs
make everything new optional
451
                 branch=None, upatch=1, verbose=False,
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
452
                 date=None, build=None, revid=None, epoch=None):
198.2.22 by Curtis Hovey
Added docstrings.
453
    """Build one or more series source packages from a new release tarfile.
454
455
    The packages are unsigned by default, but providing the path to a gpgcmd,
456
    the dsc file will be signed.
457
458
    :param tarfile_path: The path to the upstream tarfile. to import.
459
    :param location: The path to the directory to build packages in.
460
    :param series: The series codename or list of series codenames.
298.1.5 by Nicholas Skaggs
fix ordering and tests
461
    :param bugs: A list of Lp bug numbers the release fixes.
198.2.22 by Curtis Hovey
Added docstrings.
462
    :param gpgcmd: The path to a gpg signing command to sign with.
463
        Source packages will be signed when gpgcmd is not None.
464
    :param debemail: The email address to attribute the changelog entry to.
465
    :param debfullname: The name to attribute the changelog entry to.
466
    :param branch: The path (or location) of the source package branch to
467
        create the new source package with.
468
    :param upatch: The package patch number for cases where a packaging rules
469
        are updated and the package rebuilt.
470
    :param verbose: Increase the verbostiy of output.
298.1.4 by Nicholas Skaggs
make everything new optional
471
    :param date: The date of the build.
472
    :param build: The build number in CI.
298.1.5 by Nicholas Skaggs
fix ordering and tests
473
    :param revid: The revid hash of the source.
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
474
    :param epoch: The epoch to pass in version name
198.2.26 by Curtis Hovey
upatch is '1' not 0 per the rule we current build with. Added test for LIVING.
475
    :return: the exit code (which is 0 or else an exception was raised).
198.2.22 by Curtis Hovey
Added docstrings.
476
    """
198.2.8 by Curtis Hovey
Added create_source_package_branch().
477
    if not isinstance(series, list):
478
        series = [series]
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
479
    tarfile_name = os.path.basename(tarfile_path)
480
    version = tarfile_name.split('_')[-1].replace('.tar.gz', '')
298.1.7 by Nicholas Skaggs
add unique name for daily tarball
481
    if all([date, build, revid]):
482
        daily_version = '{}~{}~{}~{}'.format(version, date, build, revid)
483
        daily_tarfile_name = tarfile_name.replace(version, daily_version)
484
        tarfile_dir = os.path.dirname(tarfile_path)
485
        daily_tarfile_path = os.path.join(tarfile_dir, daily_tarfile_name)
298.1.9 by Nicholas Skaggs
rename
486
        os.rename(tarfile_name, daily_tarfile_name)
298.1.8 by Nicholas Skaggs
just set names; revamp tests
487
        tarfile_path = daily_tarfile_path
488
        tarfile_name = daily_tarfile_name
298.1.11 by Nicholas Skaggs
fix version for orig tarball
489
        version = daily_version
298.1.7 by Nicholas Skaggs
add unique name for daily tarball
490
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
491
    files = [SourceFile(None, None, tarfile_name, tarfile_path)]
198.2.8 by Curtis Hovey
Added create_source_package_branch().
492
    spb_dir = setup_local(
493
        location, 'any', 'all', files, verbose=verbose)
198.2.20 by Curtis Hovey
Extracted get_deb_shell_env.
494
    spb = create_source_package_branch(spb_dir, version, tarfile_name, branch)
198.2.10 by Curtis Hovey
Refactored arguments to create source packages. Extracted logic needs testing.
495
    for a_series in series:
496
        build_dir = setup_local(location, a_series, 'all', [], verbose=verbose)
497
        create_source_package(
298.1.4 by Nicholas Skaggs
make everything new optional
498
            build_dir, spb, a_series, version,
499
            upatch=upatch, bugs=bugs, gpgcmd=gpgcmd,
500
            debemail=debemail, debfullname=debfullname, verbose=verbose,
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
501
            date=date, build=build, revid=revid, epoch=epoch)
198.2.6 by Curtis Hovey
Convert the --series LIVING into a list of licing series.
502
    return 0
198.2.2 by Curtis Hovey
Added shub for build_source.
503
504
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
505
def print_series_info(package_version=None):
245.1.2 by Curtis Hovey
Exit 1 when a --series-name-from-package-version has no match.
506
    exitcode = 1
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
507
    if package_version:
245.1.2 by Curtis Hovey
Exit 1 when a --series-name-from-package-version has no match.
508
        version = juju_series.get_name_from_package_version(package_version)
509
        if version:
510
            print(version)
511
            return 0
512
    return exitcode
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
513
514
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
515
def main(argv):
516
    """Execute the commands from the command line."""
517
    exitcode = 0
518
    args = get_args(argv)
198.2.2 by Curtis Hovey
Added shub for build_source.
519
    if args.command == 'source':
520
        exitcode = build_source(
298.1.4 by Nicholas Skaggs
make everything new optional
521
            args.tar_file, args.location, args.series, args.bugs,
522
            debemail=args.debemail, debfullname=args.debfullname,
198.2.2 by Curtis Hovey
Added shub for build_source.
523
            gpgcmd=args.gpgcmd, branch=args.branch, upatch=args.upatch,
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
524
            verbose=args.verbose, date=args.date, build=args.build,
525
            revid=args.revid, epoch=args.epoch)
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
526
    elif args.command == 'binary':
179.2.6 by Curtis Hovey
Pass series and arch to build_binary.
527
        exitcode = build_binary(
194 by Curtis Hovey
Some versions of mk-build-deps remove the fake package when done.
528
            args.dsc, args.location, args.series, args.arch,
182.1.4 by Curtis Hovey
Pass ppa from main to build_binary.
529
            ppa=args.ppa, verbose=args.verbose)
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
530
    elif args.command == 'print':
531
        exitcode = print_series_info(
532
            package_version=args.series_name_from_package_version)
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
533
    return exitcode
534
535
536
def get_args(argv=None):
537
    """Return the arguments for this program."""
538
    parser = ArgumentParser("Build debian packages.")
539
    parser.add_argument(
540
        "-v", "--verbose", action="store_true", default=False,
541
        help="Increase the verbosity of the output")
542
    subparsers = parser.add_subparsers(help='sub-command help', dest="command")
198.2.1 by Curtis Hovey
Added arguments to create source packages.
543
    src_parser = subparsers.add_parser('source', help='Build source packages')
544
    src_parser.add_argument(
545
        '--debemail', default=os.environ.get("DEBEMAIL"),
546
        help="Your email address; Environment: DEBEMAIL.")
547
    src_parser.add_argument(
548
        '--debfullname', default=os.environ.get("DEBFULLNAME"),
549
        help="Your full name; Environment: DEBFULLNAME.")
550
    src_parser.add_argument(
347 by Nicholas Skaggs
Allow building packages without epoch sanely; add old templates without epoch, set default epoch value to None
551
        '--epoch', default=None, help="The epoch for package version")
342 by Nicholas Skaggs
Restore epoch changes. The version used in CI should use tilda from now on; however, the job works around it if needed. The source tarball needs a tilda in order to build. If the launchpad upload contains a dash in the version, and a proper tarball is not provided, this script will fail.
552
    src_parser.add_argument(
198.2.14 by Curtis Hovey
The default value of gpgcmd is None; only sign when it is provided.
553
        '--gpgcmd', default=None,
554
        help="Path to a gpg signing command to make signed packages.")
198.2.1 by Curtis Hovey
Added arguments to create source packages.
555
    src_parser.add_argument(
262 by Curtis Hovey
Select DEFAULT_SPB2 when tar file version starts with 2..
556
        '--branch', help="The base/previous source package branch.")
198.2.1 by Curtis Hovey
Added arguments to create source packages.
557
    src_parser.add_argument(
198.2.26 by Curtis Hovey
upatch is '1' not 0 per the rule we current build with. Added test for LIVING.
558
        '--upatch', default='1', help="The Ubuntu patch number.")
198.2.1 by Curtis Hovey
Added arguments to create source packages.
559
    src_parser.add_argument('tar_file', help="The release tar file.")
560
    src_parser.add_argument("location", help="The location to build in.")
561
    src_parser.add_argument(
562
        'series', help="The destination Ubuntu release or LIVING for all.")
563
    src_parser.add_argument(
298.1.4 by Nicholas Skaggs
make everything new optional
564
        '--date', default=None, help="A datestamp to apply to the build")
565
    src_parser.add_argument(
566
        '--build', default=None, help="The build number from CI")
567
    src_parser.add_argument(
568
        '--revid', default=None, help="The short hash for revid")
298.1.1 by Nicholas Skaggs
add date and build to source
569
    src_parser.add_argument(
198.2.1 by Curtis Hovey
Added arguments to create source packages.
570
        'bugs', nargs='*', help="Bugs this version will fix in the release.")
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
571
    bin_parser = subparsers.add_parser('binary', help='Build a binary package')
182.1.3 by Curtis Hovey
Added --ppa as an option.
572
    bin_parser.add_argument(
573
        '--ppa', default=None, help="The PPA that provides package deps.")
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
574
    bin_parser.add_argument("dsc", help="The dsc file to build")
575
    bin_parser.add_argument("location", help="The location to build in.")
179.2.5 by Curtis Hovey
Pass series and arch to create the right lxc.
576
    bin_parser.add_argument("series", help="The series to build in.")
198.2.7 by Curtis Hovey
Rearrwnge tests.
577
    bin_parser.add_argument("arch", help="The dpkg architecture to build in.")
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
578
    print_parser = subparsers.add_parser('print', help='Print series info')
579
    print_parser.add_argument(
580
        '--series-name-from-package-version',
581
        help="Print the series name associated with the package version.")
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
582
    args = parser.parse_args(argv[1:])
245.1.1 by Curtis Hovey
Remove supported-releases.txt; call build_package.py --print instead.
583
    if getattr(args, 'series', None) and args.series == 'LIVING':
198.2.24 by Curtis Hovey
_JujuSeries is a singleton.
584
        args.series = juju_series.get_living_names()
262 by Curtis Hovey
Select DEFAULT_SPB2 when tar file version starts with 2..
585
    if args.command == 'source' and args.branch is None:
586
        tarfile_name = os.path.basename(args.tar_file)
587
        version = tarfile_name.split('_')[-1].replace('.tar.gz', '')
588
        if version.startswith('2.'):
589
            args.branch = DEFAULT_SPB2
590
        else:
591
            args.branch = DEFAULT_SPB
179.2.1 by Curtis Hovey
Adding new build_package.py script to build in lxc.
592
    return args
593
594
595
if __name__ == '__main__':
596
    sys.exit(main(sys.argv))