Commit 8e12246f authored by Christos Stavrakakis's avatar Christos Stavrakakis
Browse files

Remove devtools and rename to devflow

parent 5e44a923
#!/bin/bash
REMOTEUPSTREAM=develop
REMOTEDEBIAN=debian-develop
PKGAREA=~/packages
BACKUPAREA=~/backup
BUILDAREA=$(mktemp -d --tmpdir=/tmp build-area.XXX)
PACKAGES="
snf-quotaholder-app
snf-astakos-app
snf-common
snf-webproject
snf-cyclades-app
snf-cyclades-gtools
snf-tools
snf-pithos-app
snf-pithos-backend
snf-pithos-tools"
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
import git
import os
import sys
from sh import mktemp, cd, rm, git_dch, python
from optparse import OptionParser
try:
from colors import red, green
except ImportError:
red = lambda x: x
green = lambda x: x
print_red = lambda x: sys.stdout.write(red(x) + "\n")
print_green = lambda x: sys.stdout.write(green(x) + "\n")
AVAILABLE_MODES = ["release", "snapshot"]
PACKAGES = (
"snf-astakos-app",
"snf-common",
"snf-webproject",
"snf-cyclades-app",
"snf-cyclades-gtools",
"snf-tools",
"snf-pithos-app",
"snf-pithos-backend",
"snf-pithos-tools",
)
def main():
parser = OptionParser(usage="usage: %prog [options] mode",
version="%prog 1.0")
parser.add_option("-k", "--keep-repo",
action="store_true",
dest="keep_repo",
default=False,
help="Do not delete the cloned repository")
parser.add_option("-b", "--build-dir",
dest="build_dir",
default=None,
help="Directory to store created pacakges")
parser.add_option("-r", "--repo-dir",
dest="repo_dir",
default=None,
help="Directory to clone repository")
parser.add_option("-d", "--dirty",
dest="force_dirty",
default=False,
action="store_true",
help="Do not check if working directory is dirty")
(options, args) = parser.parse_args()
mode = args[0]
if mode not in AVAILABLE_MODES:
raise ValueError(red("Invalid argument! Mode must be one: %s"
% ", ".join(AVAILABLE_MODES)))
# Do not prompt for merge message. Required for some Git versions
os.environ["GITFLOW_BUILD_MODE"] = mode
try:
original_repo = git.Repo(".")
except git.git.InvalidGitRepositoryError:
raise RuntimeError(red("Current directory is not git repository."))
if original_repo.is_dirty() and not options.force_dirty:
toplevel = original_repo.working_dir
raise RuntimeError(red("Repository %s is dirty." % toplevel))
repo_dir = options.repo_dir
if not repo_dir:
repo_dir = mktemp("-d", "/tmp/synnefo-build-repo-XXX").stdout.strip()
print_green("Created temporary directory '%s' for the cloned repo."
% repo_dir)
repo = original_repo.clone(repo_dir)
print_green("Cloned current repository to '%s'." % repo_dir)
reflog_hexsha = repo.head.log()[-1].newhexsha
print "Latest Reflog entry is %s" % reflog_hexsha
branch = repo.head.reference.name
if branch == "master":
debian_branch = "debian"
else:
debian_branch = "debian-" + branch
try:
repo.references[debian_branch]
except IndexError:
# Branch does not exist
# FIXME: remove hard-coded strings..
if branch == "debian":
repo.git.branch("--track", debian_branch, "origin/debian")
else:
repo.git.branch("--track", debian_branch, "origin/debian-develop")
repo.git.checkout(debian_branch)
print_green("Changed to branch '%s'" % debian_branch)
repo.git.merge(branch)
print_green("Merged branch '%s' into '%s'" % (branch, debian_branch))
cd(repo_dir)
version = python(repo_dir + "/devtools/version.py", "debian").strip()
print_green("The new debian version will be: '%s'" % version)
dch = git_dch("--debian-branch=%s" % debian_branch,
"--git-author",
"--ignore-regex=\".*\"",
"--multimaint-merge",
"--since=HEAD",
"--new-version=%s" % version)
print_green("Successfully ran '%s'" % " ".join(dch.cmd))
os.system("vim debian/changelog")
repo.git.add("debian/changelog")
if mode == "release":
repo.git.commit("-s", "-a", "-m", "Bump new upstream version")
if branch == "master":
repo.git.tag("debian/" + version)
for package in PACKAGES:
# python setup.py should run in its directory
cd(package)
package_dir = repo_dir + "/" + package
res = python(package_dir + "/setup.py", "sdist", _out=sys.stdout)
cd("../")
print res.stdout
# Add version.py files to repo
os.system("grep \"__version_vcs\" -r . -l -I | xargs git add -f")
build_dir = options.build_dir
if not options.build_dir:
build_dir = mktemp("-d", "/tmp/synnefo-build-XXX").stdout.strip()
print_green("Created directory '%s' to store the .deb files." %
build_dir)
os.system("git-buildpackage --git-export-dir=%s --git-upstream-branch=%s"
" --git-debian-branch=%s --git-export=INDEX --git-ignore-new -sa"
% (build_dir, branch, debian_branch))
if not options.keep_repo:
print_green("Removing cloned repo '%s'." % repo_dir)
rm("-r", repo_dir)
else:
print_green("Repository dir '%s'" % repo_dir)
print_green("Completed. Version '%s', build area: '%s'"
% (version, build_dir))
if __name__ == "__main__":
main()
#!/bin/bash
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
parse_git_branch()
{
git branch 2> /dev/null | grep '^*' | sed 's/^*\ //g'
}
die()
{
echo $* 1>&2
exit 1
}
cleanup()
{
trap - EXIT
if [ ${#CLEANUP[*]} -gt 0 ]; then
LAST_ELEMENT=$((${#CLEANUP[*]}-1))
REVERSE_INDEXES=$(seq ${LAST_ELEMENT} -1 0)
for i in $REVERSE_INDEXES; do
local cmd=${CLEANUP[$i]}
$cmd
done
fi
}
add_cleanup() {
local cmd=""
for arg; do cmd+=$(printf "%q " "$arg"); done
CLEANUP+=("$cmd")
}
add_checkpoint()
{
commit=$(git reflog | head -n1 | cut -f 1 -d " ")
add_cleanup git reset --hard $commit
LASTCHECKPOINT=$commit
}
CLEANUP=( )
source devtools/autopkg.conf
# The root of the git repository, no matter where we're called from
TOPLEVEL="$(git rev-parse --show-toplevel)"
CURRENT_BRANCH=$(parse_git_branch)
LOCALBRANCH="$CURRENT_BRANCH"
LOCALDEBIAN=$1
DEBIANBRANCH=${LOCALDEBIAN:- origin/$REMOTEDEBIAN}
MODIFIED=$(git status --short | grep -v "??")
if [[ -n $MODIFIED ]]; then
echo "error: Repository is dirty. Commit your local changes."
exit 1
fi
set -e
trap cleanup EXIT
cd "$TOPLEVEL"
# Prerequisites: Test all important directories exist
test -d "$PKGAREA" || die "Package area directory $PKGAREA missing"
test -d "$BACKUPAREA" || die "Backup area directory $BACKUPAREA missing"
# Prerequisite: Test the dialog utility is available
dialog --help &>/dev/null || die "Could not run the 'dialog' utility"
echo "##########################################################"
echo "Will build packages"
echo "under '$BUILDAREA',"
echo "from local branch '$LOCALBRANCH'"
echo "and debian branch '$DEBIANBRANCH'"
echo "##########################################################"
echo "Press Enter to continue..."
read
add_checkpoint
# Create a temporary debian branch to do everything
TMPDEBIAN=$(mktemp -u debian.XXX)
git branch --track $TMPDEBIAN $DEBIANBRANCH
#add_cleanup git branch -D $TMPDEBIAN
git checkout $TMPDEBIAN
add_cleanup git checkout $LOCALBRANCH
add_checkpoint
# Whether we are in snapshot or release mode
snap=false
mrgextra=-m
dchextra=-R
mrgmsg="Merge branch '$REMOTEUPSTREAM' into $REMOTEDEBIAN"
dialog --yesno "Create Snapshot?" 5 20 && snap=true && GITFLOW_BUILD_MODE=snapshot && dchextra=-S && mrgextra= && mrgmsg=
# merge local branch into tmp branch with a nice commit message,
# so it can be pushed as is to upstream debian
GIT_MERGE_AUTOEDIT=no
git merge $mrgextra ${mrgextra:+"$mrgmsg"} $LOCALBRANCH
# auto edit Debian changelog depending on Snapshot or Release mode
export EDITOR=/usr/bin/vim
# use the devtools to determine Debian version
export GITFLOW_BUILD_MODE
version=$(devtools/version.py debian)
git-dch --debian-branch=$TMPDEBIAN --git-author --ignore-regex=".*" --multimaint-merge --since=HEAD -N $version
git add debian/changelog
# get version from the changelog
# we add a git tag here, so setup.py sdist works as expected
# FIXME: This is a workaround for the way Synnefo packages determine
# the versions for their Python packages
version=$(IFS="()" ; read x v x < debian/changelog ; echo $v)
if ! $snap; then
git commit -s -a -m "Bump new upstream version"
TAGFILE=$(mktemp -t tag.XXX)
add_cleanup rm $TAGFILE
dialog --inputbox "New Debian Tag: " 5 30 "debian/$version" 2>$TAGFILE
git tag $(<$TAGFILE)
add_cleanup git tag -d $(<$TAGFILE)
fi
for p in $PACKAGES; do
cd $p
python setup.py sdist
grep "__version_vcs" -r . -l -I | xargs git add -f
cd -
done
# Build all packages
git-buildpackage --git-export-dir="$BUILDAREA" \
--git-upstream-branch=$LOCALBRANCH \
--git-debian-branch=$TMPDEBIAN \
--git-export=INDEX \
--git-ignore-new -sa
# do some dirty backup
# pkgarea might be needed by auto-deploy tool
rm -f "$PKGAREA"/* || true
cp -v "$BUILDAREA"/* "$PKGAREA"/ || true
cp -v "$BUILDAREA"/* "$BACKUPAREA"/ || true
echo "###############################################"
echo "#### SUCCESS ####"
echo "###############################################"
git fetch origin
#check if your local branch is up-to-date
commits_behind=$(git rev-list $LOCALBRANCH..origin/$REMOTEUPSTREAM | wc -l)
if [ $commits_behind -ne 0 ]; then
die "Your local branch is outdated!! Please run: git pull --rebase origin/$REMOTEUPSTREAM"
fi
commits_behind=$(git rev-list $DEBIANBRANCH..origin/$REMOTEDEBIAN | wc -l)
if [ $commits_behind -ne 0 ]; then
die "Your debian branch is outdated!! Please run: git pull --rebase origin/$REMOTEDEBIAN"
fi
trap - EXIT
# Remove the added versions.py files
git reset --hard HEAD
# here we can push the commits to the remote debian branch as they are
if ! $snap; then
TAGS="--tags"
fi
echo "git push $TAGS origin $TMPDEBIAN:$REMOTEDEBIAN"
echo "git checkout $LOCALBRANCH"
echo "git push $TAGS origin $LOCALBRANCH:$REMOTEUPSTREAM"
echo
exit 0
#!/usr/bin/env python
#
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
#
#
"""Unit Tests for devtools.version
Provides unit tests for module devtools.version,
for automatic generation of version strings.
"""
import os
import unittest
from pkg_resources import parse_version
from version import debian_version_from_python_version
class DebianVersionObject(object):
"""Object representing a Debian Version."""
def __init__(self, pyver):
self.version = debian_version_from_python_version(pyver)
def __str__(self):
return self.version
def debian_compare_versions(a, op, b):
i = os.system("dpkg --compare-versions %s %s %s" % (a, op, b))
return i == 0
# Set ordering between DebianVersionObject objects, by adding
# debian_compare_versions
for op in ["lt", "le", "eq", "ne", "gt", "ge"]:
def gen(op):
def operator_func(self, other):
return debian_compare_versions(self.version, op, other.version)
return operator_func
setattr(DebianVersionObject, "__%s__" % op, gen(op))
def _random_commit():
import random
import string
return "".join(random.choice(string.hexdigits) for n in xrange(8)).lower()
# Add a random commit number at the end of snapshot versions
def version_with_commit(parse_func, v):
if "_" in v:
return parse_func(v + "_" + _random_commit())
else:
return parse_func(v)
V = lambda v: version_with_commit(parse_version, v)
D = lambda v: version_with_commit(DebianVersionObject, v)
class TestVersionFunctions(unittest.TestCase):
def setUp(self):
self.version_orderings = (
("0.14next", ">", "0.14"),
("0.14next", ">", "0.14rc7"),
("0.14next", "<", "0.14.1"),
("0.14rc6", "<", "0.14"),
("0.14.2rc6", ">", "0.14.1"),
("0.14next_150", "<", "0.14next"),
("0.14.1next_150", "<", "0.14.1next"),
("0.14.1_149", "<", "0.14.1"),
("0.14.1_149", "<", "0.14.1_150"),
("0.13next_102", "<", "0.13next"),
("0.13next", "<", "0.14rc5_120"),
("0.14rc3_120", "<", "0.14rc3"),
# The following test fails, but version.python_version
# will never try to produce such a version:
# ("0.14rc3", "<", "0.14_1"),
("0.14_120", "<", "0.14"),
("0.14", "<", "0.14next_20"),
("0.14next_20", "<", "0.14next"),
)
def test_python_versions(self):
for a, op, b in self.version_orderings:
res = compare(V, a, op, b)
self.assertTrue(res, "Python version: %s %s %s"
" is not True" % (a, op, b))
def test_debian_versions(self):
for a, op, b in self.version_orderings:
res = compare(D, a, op, b)
self.assertTrue(res, "Debian version %s %s %s"
" is not True" % (a, op, b))
def compare(function, a, op, b):
import operator
str_to_op = {"<": operator.lt,
"<=": operator.le,
"==": operator.eq,
">": operator.gt,
">=": operator.ge}
try:
return str_to_op[op](function(a), function(b))
except KeyError:
raise ValueError("Unknown operator '%s'" % op)
if __name__ == '__main__':
unittest.main()
# Copyright 2011 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# 1. Redistributions of source code must retain the above
# copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials
# provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
#
import os
import sys
from contextlib import contextmanager
from fabric.api import *
from fabric.colors import *
env.project_root = "./"
env.develop = False
env.autoremove = True
env.packages = ['snf-common', 'snf-cyclades-app', 'snf-cyclades-gtools',
'snf-webproject', 'snf-pithos-backend', 'snf-pithos-app',
'snf-pithos-tools', 'snf-astakos-app']
env.capture = False
env.colors = True
env.pypi_root = 'pypi'
env.roledefs = {