diff --git a/release/release_bob.py b/release/release_bob.py index 56068bd3c51e93d811a3a0d2016a2bed7e819afb..2e3414fb548de59b878f9b25fb6e52a5f5183e1c 100755 --- a/release/release_bob.py +++ b/release/release_bob.py @@ -3,9 +3,52 @@ """ By using changelog file as an input (can be generated with 'generate_changelog.py' script), this script goes through all packages in changelog file (in order listed), tags them correctly -as per the file, and releases them one by one. A script can also be used to release a single package. +as per the file, and releases them one by one. This script uses python-gitlab package for accessing GitLab's API. +This script uses the provided changelog file to release a package. +The changelog is expected to have the following structure: + + * package name + * tag1 name (date of the tag). + * tag description. Each line of the tag description starts with `*` character. + - commits (from earliest to latest). Each line of the commit starts with `-` character. + * tag2 name (date of the tag). + * tag description. Each line of the tag description starts with `*` character. + - commits (from earliest to latest). Each line of the commit starts with `-` character. + * patch + - leftover not-tagged commits (from earliest to latest) + +This script can also be used to release a single package. +`IMPORTANT`: there are some considerations that needs to be taken +into account **before** you release a new version of a package: + + * In the changelog file, write the name of this package and write the last tag. + For the tag name, you can either indicate `patch` to `minor` or `major`, + and the package will be then released with either patch, minor, or major version bump. + Alternatively, you can specify the version name directly but be careful that it is higher + than the last release tag of this package. + Then, under the desired new tag version of the package, please write down the changes that are applied + to the package between the last released version and this version. This + changes are written to release tags of packages in the Gitlab interface. + For an example look at: https://gitlab.idiap.ch/bob/bob.extension/tags + * Make sure all the tests for the package are passing. + * Make sure the documentation is building with the following command: + ``sphinx-build -aEWn doc sphinx`` + * Make sure the documentation badges in README.rst are pointing to: + https://www.idiap.ch/software/bob/docs/bob/... + * Make sure all changes are committed to the git repository and pushed. + * For database packages, make sure that the '.sql3' file or other + metadata files have been generated (if any). + * Make sure bob.nightlies is green after the changes are submitted if the + package is a part of the nightlies. + * Make sure you follow semantic versions: http://semver.org + * Make sure that the `stable` version that you are trying to release is not + already released. + * If your package depends on an unreleased version of another Bob package, + you need to release that package first. + + Usage: {0} [-v...] [options] [--] <private_token> {0} -h | --help @@ -72,6 +115,20 @@ def _update_readme(readme, version=None): return '\n'.join(new_readme) +def get_latest_tag(gitpkg): + # get 50 latest tags as a list + latest_tags = gitpkg.tags.list(per_page=50, page=1) + if not latest_tags: + return None + # create list of tags' names but ignore the first 'v' character in each name + tag_names = [tag.name[1:] for tag in latest_tags] + # sort them correctly according to each subversion number + tag_names.sort(key=lambda s: [int(u) for u in s.split('.')]) + # take the last one, as it is the latest tag in the sorted tags + latest_tag_name = tag_names[-1] + return latest_tag_name + + def get_parsed_tag(gitpkg, tag): """ An older tag is formatted as 'v2.1.3 (Sep 22, 2017 10:37)', from which we need only v2.1.3 @@ -84,25 +141,25 @@ def get_parsed_tag(gitpkg, tag): # if we bump the version, we need to find the latest released version for this package if 'patch' == tag or 'minor' == tag or 'major' == tag: - latest_tag = gitpkg.tags.list(per_page=1, page=1) - # if there were no tags yet, assume the first version - if not latest_tag: - return 'v1.0.0' - latest_tag = latest_tag[0] - latest_tag_name = latest_tag.name - # check that it has expected format v#.#.# + # find the correct latest tag of this package (without 'v' in front), + # None if there are no tags yet + latest_tag_name = get_latest_tag(gitpkg) + # if there were no tags yet, assume the very first version + if not latest_tag_name: + return 'v0.0.1' + # check that it has expected format #.#.# # latest_tag_name = Version(latest_tag_name) - m = re.match(r"(v\d.\d.\d)", latest_tag_name) + m = re.match(r"(\d.\d.\d)", latest_tag_name) if not m: raise ValueError( - 'The latest tag name {0} in package {1} has unknown format'.format(latest_tag_name, gitpkg.name)) + 'The latest tag name {0} in package {1} has unknown format'.format('v' + latest_tag_name, gitpkg.name)) # increase the version accordingly - if 'major' == tag: # increment the first number in 'v#.#.#' - return latest_tag_name[0] + str(int(latest_tag_name[1]) + 1) + latest_tag_name[2:] - if 'minor' == tag: # increment the second number in 'v#.#.#' - return latest_tag_name[:3] + str(int(latest_tag_name[3]) + 1) + latest_tag_name[4:] + if 'major' == tag: # increment the first number in 'v#.#.#' but make minor and patch to be 0 + return 'v' + str(int(latest_tag_name[0]) + 1) + '.0.0' + if 'minor' == tag: # increment the second number in 'v#.#.#' but make patch to be 0 + return 'v' + latest_tag_name[:2] + str(int(latest_tag_name[3]) + 1) + '.0' if 'patch' == tag: # increment the last number in 'v#.#.#' - return latest_tag_name[:-1] + str(int(latest_tag_name[-1]) + 1) + return 'v' + latest_tag_name[:-1] + str(int(latest_tag_name[-1]) + 1) if 'none' == tag: # we do nothing in this case return tag