cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #01092
[Merge] ~smoser/cloud-init:version-info into cloud-init:master
Scott Moser has proposed merging ~smoser/cloud-init:version-info into cloud-init:master.
Requested reviews:
cloud init development team (cloud-init-dev)
For more details, see:
https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/302176
--
Your team cloud init development team is requested to review the proposed merge of ~smoser/cloud-init:version-info into cloud-init:master.
diff --git a/cloudinit/version.py b/cloudinit/version.py
index 3d1d1d2..01785eb 100644
--- a/cloudinit/version.py
+++ b/cloudinit/version.py
@@ -16,12 +16,17 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from distutils import version as vr
+__VERSION__ = "0.7.6"
+__EXPORT_VERSION__ = "@@EXPORT_VERSION@@"
-def version():
- return vr.StrictVersion("0.7.7")
+def version_string():
+ if not __EXPORT_VERSION__.startswith("@@"):
+ return __EXPORT_VERSION__
+ return __VERSION__
-def version_string():
- return str(version())
+def full_version_string():
+ if __EXPORT_VERSION__.startswith("@@"):
+ raise ValueError("No full version available")
+ return __EXPORT_VERSION__
diff --git a/packages/bddeb b/packages/bddeb
index 46c07c8..6892616 100755
--- a/packages/bddeb
+++ b/packages/bddeb
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
-import glob
+import argparse
+import json
import os
import shutil
import sys
@@ -15,15 +16,16 @@ def find_root():
if os.path.isfile(os.path.join(top_dir, 'setup.py')):
return os.path.abspath(top_dir)
raise OSError(("Unable to determine where your cloud-init topdir is."
- " set CLOUD_INIT_TOP_D?"))
-
-# Use the util functions from cloudinit
-sys.path.insert(0, find_root())
+ " set CLOUD_INIT_TOP_D?"))
-from cloudinit import templater
-from cloudinit import util
+try:
+ # Use the util functions from cloudinit
+ sys.path.insert(0, find_root())
-import argparse
+ from cloudinit import templater
+ from cloudinit import util
+except:
+ raise
# Package names that will showup in requires to what we can actually
# use in our debian 'control' file, this is a translation of the 'requires'
@@ -58,27 +60,37 @@ NONSTD_NAMED_PACKAGES = {
DEBUILD_ARGS = ["-S", "-d"]
-def write_debian_folder(root, version, revno, pkgmap,
- pyver="3", append_requires=[]):
+def run_helper(helper, args=None, strip=True):
+ if args is None:
+ args = []
+ cmd = [util.abs_join(find_root(), 'tools', helper)] + args
+ (stdout, _stderr) = util.subp(cmd)
+ if strip:
+ stdout = stdout.strip()
+ return stdout
+
+
+def write_debian_folder(root, version_data, pkgmap, pyver="3",
+ append_requires=[]):
deb_dir = util.abs_join(root, 'debian')
- os.makedirs(deb_dir)
+
+ # Just copy debian/ dir and then update files
+ pdeb_d = util.abs_join(find_root(), 'packages', 'debian')
+ util.subp(['cp', '-a', pdeb_d, deb_dir])
# Fill in the change log template
templater.render_to_file(util.abs_join(find_root(),
'packages', 'debian', 'changelog.in'),
util.abs_join(deb_dir, 'changelog'),
- params={
- 'version': version,
- 'revision': revno,
- })
+ params=version_data)
# Write out the control file template
- cmd = [util.abs_join(find_root(), 'tools', 'read-dependencies')]
- (stdout, _stderr) = util.subp(cmd)
- pypi_pkgs = [p.lower().strip() for p in stdout.splitlines()]
+ reqs = run_helper('read-dependencies').splitlines()
+ test_reqs = run_helper(
+ 'read-dependencies', ['test-requirements.txt']).splitlines()
- (stdout, _stderr) = util.subp(cmd + ['test-requirements.txt'])
- pypi_test_pkgs = [p.lower().strip() for p in stdout.splitlines()]
+ pypi_pkgs = [p.lower().strip() for p in reqs]
+ pypi_test_pkgs = [p.lower().strip() for p in test_reqs]
# Map to known packages
requires = append_requires
@@ -109,11 +121,10 @@ def write_debian_folder(root, version, revno, pkgmap,
util.abs_join(deb_dir, 'rules'),
params={'python': python, 'pyver': pyver})
- # Just copy any other files directly (including .in)
- pdeb_d = util.abs_join(find_root(), 'packages', 'debian')
- for f in [os.path.join(pdeb_d, f) for f in os.listdir(pdeb_d)]:
- if os.path.isfile(f):
- shutil.copy(f, util.abs_join(deb_dir, os.path.basename(f)))
+
+
+def read_version():
+ return json.loads(run_helper('read-version', ['--json']))
def main():
@@ -140,11 +151,10 @@ def main():
default=os.environ.get("INIT_SYSTEM",
"upstart,systemd"))
-
for ent in DEBUILD_ARGS:
parser.add_argument(ent, dest="debuild_args", action='append_const',
- const=ent, help=("pass through '%s' to debuild" % ent),
- default=[])
+ const=ent, default=[],
+ help=("pass through '%s' to debuild" % ent))
parser.add_argument("--sign", default=False, action='store_true',
help="sign result. do not pass -us -uc to debuild")
@@ -181,53 +191,31 @@ def main():
with util.tempdir() as tdir:
# output like 0.7.6-1022-g36e92d3
- cmd = ['git', 'describe', '--long']
- (sysout, _stderr) = util.subp(cmd)
- version, extra = sysout.strip().split("-", 1)
+ ver_data = read_version()
# This is really only a temporary archive
# since we will extract it then add in the debian
# folder, then re-archive it for debian happiness
print("Creating a temporary tarball using the 'make-tarball' helper")
- cmd = [util.abs_join(find_root(), 'tools', 'make-tarball')]
- (sysout, _stderr) = util.subp(cmd)
- arch_fn = sysout.strip()
- tmp_arch_fn = util.abs_join(tdir, os.path.basename(arch_fn))
- shutil.move(arch_fn, tmp_arch_fn)
-
- print("Extracting temporary tarball %r" % (tmp_arch_fn))
- cmd = ['tar', '-xvzf', tmp_arch_fn, '-C', tdir]
+ tarball = "cloud-init_%s.orig.tar.gz" % ver_data['version_long']
+ tarball_fp = util.abs_join(tdir, tarball)
+ run_helper('make-tarball', ['--long', '--output=' + tarball_fp])
+
+ print("Extracting temporary tarball %r" % (tarball))
+ cmd = ['tar', '-xvzf', tarball_fp, '-C', tdir]
util.subp(cmd, capture=capture)
- extracted_name = tmp_arch_fn[:-len('.tar.gz')]
- os.remove(tmp_arch_fn)
+ extracted_name = tarball[:-len('.tar.gz')]
- xdir = util.abs_join(tdir, 'cloud-init')
- shutil.move(extracted_name, xdir)
+ xdir = util.abs_join(tdir, "cloud-init-%s" % ver_data['version_long'])
print("Creating a debian/ folder in %r" % (xdir))
if args.cloud_utils:
- append_requires=['cloud-utils | cloud-guest-utils']
+ append_requires = ['cloud-utils | cloud-guest-utils']
else:
- append_requires=[]
- write_debian_folder(xdir, version, extra, pkgmap,
+ append_requires = []
+ write_debian_folder(xdir, ver_data, pkgmap,
pyver=pyver, append_requires=append_requires)
- # The naming here seems to follow some debian standard
- # so it will whine if it is changed...
- tar_fn = "cloud-init_%s+%s~bddeb.orig.tar.gz" % (version, extra)
- print("Archiving the adjusted source into %r" %
- (util.abs_join(tdir, tar_fn)))
- cmd = ['tar', '-czvf',
- util.abs_join(tdir, tar_fn),
- '-C', xdir]
- cmd.extend(os.listdir(xdir))
- util.subp(cmd, capture=capture)
-
- # Copy it locally for reference
- shutil.copy(util.abs_join(tdir, tar_fn),
- util.abs_join(os.getcwd(), tar_fn))
- print("Copied that archive to %r for local usage (if desired)." %
- (util.abs_join(os.getcwd(), tar_fn)))
print("Running 'debuild %s' in %r" % (' '.join(args.debuild_args),
xdir))
diff --git a/packages/brpm b/packages/brpm
index 5d16eb7..c7b6fdf 100755
--- a/packages/brpm
+++ b/packages/brpm
@@ -2,11 +2,11 @@
import argparse
import glob
+import json
import os
import shutil
import sys
import tempfile
-import time
def find_root():
@@ -21,11 +21,13 @@ def find_root():
" set CLOUD_INIT_TOP_D?"))
-# Use the util functions from cloudinit
-sys.path.insert(0, find_root())
-
-from cloudinit import templater
-from cloudinit import util
+try:
+ # Use the util functions from cloudinit
+ sys.path.insert(0, find_root())
+ from cloudinit import templater
+ from cloudinit import util
+except:
+ raise
# Map python requirements to package names. If a match isn't found
# here, we assume 'python-<pypi_name>'.
@@ -43,15 +45,24 @@ PACKAGE_MAP = {
RPM_BUILD_SUBDIRS = ['BUILD', 'RPMS', 'SOURCES', 'SPECS', 'SRPMS']
+def run_helper(helper, args=None, strip=True):
+ if args is None:
+ args = []
+ cmd = [util.abs_join(find_root(), 'tools', helper)] + args
+ (stdout, _stderr) = util.subp(cmd)
+ if strip:
+ stdout = stdout.strip()
+ return stdout
+
+
def read_dependencies():
'''Returns the Python depedencies from requirements.txt. This explicitly
removes 'argparse' from the list of requirements for python >= 2.7,
because with 2.7 argparse became part of the standard library.'''
- cmd = [util.abs_join(find_root(), 'tools', 'read-dependencies')]
- (stdout, _stderr) = util.subp(cmd)
+ stdout = run_helper('read-dependencies')
return [p.lower().strip() for p in stdout.splitlines()
- if p != 'argparse' or (p == 'argparse'
- and sys.version_info[0:2] < (2, 7))]
+ if p != 'argparse' or (p == 'argparse' and
+ sys.version_info[0:2] < (2, 7))]
def translate_dependencies(deps, distro):
@@ -64,53 +75,22 @@ def translate_dependencies(deps, distro):
def read_version():
- '''Read version information. We parse the version itself from
- the changelog, and then ask git for the commit id and distance
- from the last tag.'''
- # Figure out the version and revno
- cmd = [util.abs_join(find_root(), 'tools', 'read-version')]
- (stdout, _stderr) = util.subp(cmd)
- version = stdout.strip()
+ return json.loads(run_helper('read-version', ['--json']))
- cmd = ['git', 'describe', '--tags']
- (stdout, _stderr) = util.subp(cmd)
- git_version = stdout.strip()
- try:
- _version, distance, revno = git_version.split('-')
- except ValueError:
- distance = None
- revno = None
-
- return (version, distance, revno)
-
-
-def generate_spec_contents(args, tmpl_fn, top_dir, arc_fn):
-
- # This will get us something like ('0.7.6', None, None) for a
- # tagged commit, and something like ('0.7.6', '1026', 'gd1d5796')
- # for an untagged commited.
- version, distance, revno = read_version()
+def generate_spec_contents(args, version_data, tmpl_fn, top_dir, arc_fn):
# Tmpl params
subs = {}
- subs['version'] = version
- subs['revno'] = revno
- subs['distance'] = distance
-
- if distance is not None:
- now = time.strftime('%Y%m%d', time.localtime())
- release = '.%sgit%s' % (now, revno)
- else:
- release = ''
if args.sub_release is not None:
- subs['subrelease'] = release + "." + str(args.sub_release)
+ subs['subrelease'] = str(args.sub_release)
else:
- subs['subrelease'] = release
+ subs['subrelease'] = ""
subs['archive_name'] = arc_fn
subs['source_name'] = os.path.basename(arc_fn).replace('.tar.gz', '')
+ subs.update(version_data)
# Map to known packages
python_deps = read_dependencies()
@@ -176,20 +156,19 @@ def main():
for dir in RPM_BUILD_SUBDIRS]
util.ensure_dirs(build_dirs)
+ version_data = read_version()
+
# Archive the code
- cmd = [util.abs_join(find_root(), 'tools', 'make-tarball')]
- (stdout, _stderr) = util.subp(cmd)
- archive_fn = stdout.strip()
- print "Archived source as %s" % archive_fn
- real_archive_fn = os.path.join(topdir, 'SOURCES',
- os.path.basename(archive_fn))
- shutil.move(archive_fn, real_archive_fn)
+ archive_fn = "cloud-init-%s.tar.gz" % version_data['version_long']
+ real_archive_fn = os.path.join(topdir, 'SOURCES', archive_fn)
+ archive_fn = run_helper(
+ 'make-tarball', ['--long', '--output=' + real_archive_fn])
print("Archived the code in %r" % (real_archive_fn))
# Form the spec file to be used
tmpl_fn = util.abs_join(find_root(), 'packages',
args.distro, 'cloud-init.spec.in')
- contents = generate_spec_contents(args, tmpl_fn, topdir,
+ contents = generate_spec_contents(args, version_data, tmpl_fn, topdir,
os.path.basename(archive_fn))
spec_fn = util.abs_join(topdir, 'SPECS', 'cloud-init.spec')
util.write_file(spec_fn, contents)
diff --git a/packages/debian/changelog.in b/packages/debian/changelog.in
index 544d23c..f8e9825 100644
--- a/packages/debian/changelog.in
+++ b/packages/debian/changelog.in
@@ -1,5 +1,5 @@
## template:basic
-cloud-init (${version}+${revision}~bddeb-1) UNRELEASED; urgency=low
+cloud-init (${version_long}-1~bddeb) UNRELEASED; urgency=low
* build
diff --git a/packages/debian/source/format b/packages/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/packages/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/packages/redhat/cloud-init.spec.in b/packages/redhat/cloud-init.spec.in
index c30d33c..2f02f01 100644
--- a/packages/redhat/cloud-init.spec.in
+++ b/packages/redhat/cloud-init.spec.in
@@ -6,7 +6,7 @@
# Or: http://www.rpm.org/max-rpm/ch-rpm-inside.html
Name: cloud-init
-Version: ${version}
+Version: ${version_long}
Release: 1${subrelease}%{?dist}
Summary: Cloud instance init scripts
diff --git a/tools/make-tarball b/tools/make-tarball
index 4828a62..bd7399c 100755
--- a/tools/make-tarball
+++ b/tools/make-tarball
@@ -1,16 +1,53 @@
#!/bin/sh
set -e
+TEMP_D=""
+cleanup() {
+ [ -z "$TEMP_D" ] || rm -Rf "${TEMP_D}"
+}
+trap cleanup EXIT
+
+Usage() {
+ cat <<EOF
+Usage: ${0##*/} [revision]
+ create a tarball of revision (default HEAD)
+
+ options:
+ -o | --output FILE write to file
+EOF
+}
+
+short_opts="ho:v"
+long_opts="help,output:,long,verbose"
+getopt_out=$(getopt --name "${0##*/}" \
+ --options "${short_opts}" --long "${long_opts}" -- "$@") &&
+ eval set -- "${getopt_out}" || { Usage 1>&2; exit 1; }
+
+long_opt=""
+while [ $# -ne 0 ]; do
+ cur=$1; next=$2
+ case "$cur" in
+ -o|--output) output=$next; shift;;
+ --long) long_opt="--long";;
+ --) shift; break;;
+ esac
+ shift;
+done
+
rev=${1:-HEAD}
-revname=$(git describe $rev)
+git_describe=$(git describe ${long_opt} $rev)
-# revname could be 0.7.5 or 0.7.5-NNN-gHASH
+# git_describe could be 0.7.5 or 0.7.5-NNN-gHASH
# turn that into 0.7.5 or 0.7.5+NNN.gHASH
-case "$revname" in
- *-*) revname=$(echo "$revname" | sed -e 's/-/+/' -e 's/-/./')
+case "$git_describe" in
+ *-*) version=$(echo "$git_describe" | sed -e 's/-/+/' -e 's/-/./');;
+ *) version=${git_describe};;
esac
-archive_base="cloud-init-$revname"
+archive_base="cloud-init-$version"
+if [ -z "$output" ]; then
+ output="$archive_base.tar.gz"
+fi
# when building an archiving from HEAD, ensure that there aren't any
# uncomitted changes in the working directory (because these would not
@@ -25,9 +62,11 @@ if [ "$rev" = HEAD ] && ! git diff-index --quiet HEAD --; then
fi
fi
-git archive \
- --format=tar.gz \
- --prefix="$archive_base/" "$rev" \
- "--output=$archive_base.tar.gz"
+git archive --format=tar --prefix="$archive_base/" "$rev" |
+ ( cd "$TEMP_D" && tar xpf - )
+
+sed -i "s,@@EXPORT_VERSION@@,$version," "$archive_base/cloudinit/version.py"
+
+( cd "$TEMP_D" && tar cpzf - "$archive_base/" ) > "$output"
-echo "${archive_base}.tar.gz"
+echo "$output"
diff --git a/tools/read-version b/tools/read-version
index d02651e..8c74c8f 100755
--- a/tools/read-version
+++ b/tools/read-version
@@ -1,26 +1,76 @@
#!/usr/bin/env python
import os
-import re
+import json
import sys
+try:
+ _tdir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
+ sys.path.insert(0, _tdir)
+ from cloudinit import version as ci_version
+ from cloudinit import util
+except:
+ raise
-if 'CLOUD_INIT_TOP_D' in os.environ:
- topd = os.path.realpath(os.environ.get('CLOUD_INIT_TOP_D'))
-else:
- topd = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-for fname in ("setup.py", "ChangeLog"):
- if not os.path.isfile(os.path.join(topd, fname)):
- sys.stderr.write("Unable to locate '%s' file that should "
- "exist in cloud-init root directory." % fname)
+use_long = '--long' in sys.argv or os.environ.get('CI_RV_LONG')
+use_tags = '--tags' in sys.argv or os.environ.get('CI_RV_TAGS')
+output_json = '--json' in sys.argv
+
+src_version = ci_version.version_string()
+version_long = None
+
+if os.path.isdir(os.path.join(_tdir, ".git")):
+ def fix_git_version(ver):
+ ver = ver.strip()
+ if "-" in ver:
+ # change X.Y.Z-1023-gHASH to X.Y.Z+1023.ghash
+ return "{0}+{1}.{2}".format(*ver.split("-"))
+ return ver
+
+ flags = []
+ if use_tags:
+ flags = ['--tags']
+ cmd = ['git', 'describe'] + flags
+
+ version = fix_git_version(util.subp(cmd)[0])
+
+ if not version.startswith(src_version):
+ sys.stderr.write("git describe version (%s) differs from "
+ "cloudinit.version (%s)\n" % (version, src_version))
sys.exit(1)
-vermatch = re.compile(r"^[0-9]+[.][0-9]+[.][0-9]+:$")
+ version_long = fix_git_version(util.subp(cmd + ["--long"])[0])
+else:
+ version = src_version
+ try:
+ version_long = ci_version.full_version_string()
+ except ValueError:
+ pass
+
+# version is X.Y.Z[+xxx.gHASH]
+# version_long is None or X.Y.Z+xxx.gHASH
+release = version.partition("+")[0]
+extra = None
+commit = None
+distance = None
+
+if version_long:
+ info = version_long.partition("+")[2]
+ extra = "+" + info
+ distance, commit = info.split(".")
-with open(os.path.join(topd, "ChangeLog"), "r") as fp:
- for line in fp:
- if vermatch.match(line):
- sys.stdout.write(line.strip()[:-1] + "\n")
- break
+data = {
+ 'release': release,
+ 'version': version,
+ 'version_long': version_long,
+ 'extra': extra,
+ 'commit': commit,
+ 'distance': distance,
+}
+
+if output_json:
+ sys.stdout.write(json.dumps(data, indent=1) + "\n")
+else:
+ sys.stdout.write(release + "\n")
sys.exit(0)
Follow ups