669dbf020b853374dd957d4c7e5280712e345f8a
[integration/packaging.git] / deb / build.py
1 #!/usr/bin/env python
2 """Build OpenDaylight's .debs using YAML build configs and Jinja2 templates."""
3
4 import argparse
5 import os
6 import shutil
7 from string import Template
8 import subprocess
9 import sys
10
11 import cache.cache as cache
12 import templates.build_debianfiles as build_debfiles
13
14 try:
15     import yaml
16 except ImportError:
17     sys.stderr.write("We recommend using our included Vagrant env.\n")
18     sys.stderr.write("Else, install the Python libs it installs.\n")
19     raise
20
21
22 # Common paths used in this script
23 # This file is assumed to be in the root of the .deb build logic's dir
24 # structure
25 project_root = os.path.dirname(os.path.abspath(__file__))
26
27 # Cache directory for OpenDaylight's release tarball
28 cache_dir = os.path.join(project_root, "cache")
29
30 # Debian templates directory
31 templates_dir = os.path.join(project_root, "templates")
32
33 # Specialized opendaylight directory for each build
34 odl_dir_template = Template("opendaylight/opendaylight-$version_major.$version_minor."
35                             "$version_patch-$pkg_version/")
36 odl_deb_template = Template("opendaylight/opendaylight_$version_major.$version_minor."
37                             "$version_patch-${pkg_version}_all.deb")
38
39
40 def build_deb(build):
41     """Build the .deb described by the given build description.
42
43     :param build: Description of a debian build, typically from build_vars.yaml
44     :type build: dict
45
46     """
47     # Specialize a series of name templates for the given build
48     odl_dir_name = odl_dir_template.substitute(build)
49     odl_dir_path = os.path.join(templates_dir, os.pardir, odl_dir_name)
50     odl_deb = odl_deb_template.substitute(build)
51
52     # Call helper script to build the required debian files
53     build_debfiles.build_debfiles(build)
54
55     # Call a helper function to cache the artifacts required for each build
56     odl_tarball_path = cache.cache_build(build)
57
58     # Move ODL's tarball to the specialized OpenDaylight directory
59     shutil.copy(odl_tarball_path, odl_dir_path)
60
61     # Build debian package
62     os.chdir(odl_dir_path)
63     subprocess.call(["dpkg-buildpackage", "-us -uc -b",
64                      odl_dir_path], shell=True)
65
66     # Install opendaylight's dependencies
67     control_file_path = os.path.join(odl_dir_path, "debian/control")
68     subprocess.call(["sudo mk-build-deps -i " + control_file_path], shell=True)
69
70     os.chdir(project_root)
71
72     # Copy the .debs from their output dir to the cache dir
73     shutil.copy(odl_deb, cache_dir)
74
75
76 # When run as a script, accept a set of builds and execute them
77 if __name__ == "__main__":
78     # Load .deb build variables from a YAML config file
79     build_vars_path = os.path.join(project_root, "build_vars.yaml")
80     with open(build_vars_path) as deb_var_file:
81         build_vars = yaml.load(deb_var_file)
82
83     # Accept the version(s) of the build(s) to perform as args
84     parser = argparse.ArgumentParser()
85     existing_build_group = parser.add_argument_group("Existing build")
86     existing_build_group.add_argument(
87         "-v", "--version", action="append", metavar="major minor patch deb",
88         nargs="*", help="Deb version(s) to build"
89     )
90     new_build_group = parser.add_argument_group("New build")
91     new_build_group.add_argument(
92         "--major", help="Major (element) version to build")
93     new_build_group.add_argument("--minor", help="Minor (SR) version to build")
94     new_build_group.add_argument("--patch", help="Patch version to build")
95     new_build_group.add_argument("--deb",   help="Deb version to build")
96     new_build_group.add_argument(
97         "--sysd_commit", help="Version of ODL unitfile to package")
98     new_build_group.add_argument("--codename", help="Codename for ODL version")
99     new_build_group.add_argument(
100         "--download_url", help="Tarball to repackage into .deb")
101     new_build_group.add_argument(
102         "--java_version", help="Java dependency for the ODL release")
103     new_build_group.add_argument(
104         "--changelog_date", help="Date this .deb was defined")
105     new_build_group.add_argument(
106         "--changelog_time", help="Time this .deb was defined")
107     new_build_group.add_argument(
108         "--changelog_name", help="Name of person who defined .deb")
109     new_build_group.add_argument(
110         "--changelog_email", help="Email of person who defined .deb")
111
112     # Print help if no arguments are given
113     if len(sys.argv) == 1:
114         parser.print_help()
115         sys.exit(1)
116
117     # Parse the given args
118     args = parser.parse_args()
119
120     # Build list of .deb builds to perform
121     builds = []
122     if args.version:
123         # Build a list of requested versions as dicts of version components
124         versions = []
125         version_keys = ["version_major", "version_minor", "version_patch",
126                         "pkg_version"]
127         # For each version arg, match all version components to build_vars name
128         for version in args.version:
129             versions.append(dict(zip(version_keys, version)))
130
131         # Find every .deb build that matches any version argument
132         # A passed version "matches" a build when the provided version
133         # components are a subset of the version components of a build. Any
134         # version components that aren't passed are simply not checked, so
135         # they can't fail the match, effectively wild-carding them.
136         for build in build_vars["builds"]:
137             for version in versions:
138                 # Converts both dicts' key:value pairs to lists of tuples and
139                 # checks that each tuple in the version list is present in the
140                 # build list.
141                 if all(item in build.items() for item in version.items()):
142                     builds.append(build)
143     else:
144         builds.append({"version_major": args.major,
145                        "version_minor": args.minor,
146                        "version_patch": args.patch,
147                        "pkg_version": args.deb,
148                        "sysd_commit": args.sysd_commit,
149                        "codename": args.codename,
150                        "download_url": args.download_url,
151                        "java_version": args.java_version,
152                        "changelog_date": args.changelog_date,
153                        "changelog_time": args.changelog_time,
154                        "changelog_name": args.changelog_name,
155                        "changelog_email": args.changelog_email})
156
157     for build in builds:
158         build_deb(build)