def next_version(ctx, bump): """ Returns incremented version number by looking at git tags """ # Get latest git tag: try: latest_tag = latest_version(ctx) except ReleaseError: latest_tag = '0.0.0' increment = { 'build': semver.bump_build, 'patch': semver.bump_patch, 'minor': semver.bump_minor, 'major': semver.bump_major } if bump in ['pre-patch', 'pre-minor', 'pre-major']: incremented = increment[bump[4:]](latest_tag) try: #Check incremented = semver.bump_prerelease( latest_prerelease(ctx, incremented) ) # Try to increment the pre-release if there are existing pre-releases except: # No existing pre-release, so create one incremented = semver.bump_prerelease(incremented) else: incremented = increment[bump](latest_tag) return incremented
def test_should_bump_prerelease(self): self.assertEqual(bump_prerelease('3.4.5-rc.9'), '3.4.5-rc.10') self.assertEqual(bump_prerelease('3.4.5-0009.dev'), '3.4.5-0010.dev') self.assertEqual(bump_prerelease('3.4.5'), '3.4.5-rc.1')
def bump(latest): merge_request_id = extract_merge_request_id_from_commit() labels = retrieve_labels_from_merge_request(merge_request_id) new_version = None print('MR Labels', labels) if "bump-major" in labels: print('Bump major') new_version = semver.bump_major(latest) elif "bump-minor" in labels: print('Bump minor') new_version = semver.bump_minor(latest) elif "bump-patch" in labels: print('Bump patch') new_version = semver.bump_patch(latest) elif "finalize-rc" in labels: print('Finalize rc') new_version = semver.finalize_version(latest) elif "bump-build": print('Bump build') new_version = semver.bump_build(new_version if new_version else latest) if "bump-rc" in labels and not "finalize-rc" in labels: print('Bump rc') new_version = semver.bump_prerelease( new_version if new_version else latest) new_version = semver.bump_build(new_version) return new_version if new_version else latest
def update_version() -> str: """ Retrieves the current version from github, bumps the version, and updates the values in service_config.json before committing to the dst branch :return: The new version. """ cur_version = get_current_version(args.stage) if args.stage == "prod": prv_version = get_current_version(stage='staging') new_version = semver.finalize_version(prv_version) elif args.stage == "staging": prv_version = get_current_version(stage='integration') assert '-integration' in prv_version new_version = prv_version.replace( '-integration', '-rc') # don't bump the version number else: new_version = getattr(semver, f'bump_{args.release}')(str(cur_version)) new_version = new_version if semver.parse_version_info(new_version).prerelease \ else semver.bump_prerelease(new_version, token='integration') if cur_version == new_version: print("Nothing to promote") exit(0) else: print(f"Upgrading: {cur_version} -> {new_version}") return new_version
def version_bump_prerelease(version_config: VersionConfig, version: Optional[str], global_seq: Optional[int]): result = Result() version_info = semver.parse_version_info( version) if version is not None else semver.parse_version_info("0.0.0") if version_info.prerelease: prerelease_version_elements = version_info.prerelease.split(".") if len(prerelease_version_elements ) > 0 and prerelease_version_elements[0].upper() == "SNAPSHOT": if len(prerelease_version_elements) == 1: result.error( os.EX_DATAERR, _("The pre-release increment has been skipped."), _("In order to retain Maven compatibility, " "the pre-release component of snapshot versions must not be versioned." )) else: result.error( os.EX_DATAERR, _("Failed to increment the pre-release component of version {version}." ).format(version=repr(version)), _("Snapshot versions must not have a pre-release version.") ) result.value = version elif len(prerelease_version_elements) == 1: if version_config.versioning_scheme != VersioningScheme.SEMVER_WITH_SEQ: result.error( os.EX_DATAERR, _("Failed to increment the pre-release component of version {version}." ).format(version=repr(version)), _("The qualifier {qualifier} must already be versioned."). format(qualifier=repr(prerelease_version_elements[0]))) result.value = semver.bump_prerelease(version) else: result.error( os.EX_DATAERR, _("Failed to increment the pre-release component of version {version}." ).format(version=repr(version)), _("Pre-release increments cannot be performed on release versions." )) if result.has_errors(): result.value = None elif result.value is not None and not semver.compare( result.value, version) > 0: result.value = None if not result.value: result.error( os.EX_SOFTWARE, _("Failed to increment the pre-release of version {version} for unknown reasons." ).format(version=repr(version)), None) return result
def semver_command(bump, prerelease_name, path, version_file, version_initial, **options): """ Bump version to specified level [init, major, minor, patch] Other keyword will create pre-release version :param options: :return: """ ctx = click.get_current_context() # Check version file exists current_version = ctx.invoke(current, path=path, version_file=version_file, quiet=True) version = current_version or version_initial if bump == "major": version = semver.bump_major(version) elif bump == "minor": version = semver.bump_minor(version) elif bump == "patch": version = semver.bump_patch(version) elif bump == "pre": version = semver.bump_prerelease(version, prerelease_name) # Handle pre-release with other than pre bump if bump != "pre" and prerelease_name: version = semver.bump_prerelease(version, prerelease_name) click.confirm(f"You are going to bump version \"{version}\", proceed?", default=True, abort=True) # Write version with open(version_file, "w+") as h: h.write(version)
def make_new_semver(current_semver, last_release_semver, all_triggers, **overrides): """Defines how to increment semver based on which significant figure is triggered :param current_semver: the version to increment :param last_release_semver: the previous release version, if available :param all_triggers: list of major/minor/patch/prerelease :param overrides: explicit values for some or all of the sigfigs :return: """ version_string = str(current_semver) # if the current version isn't a full release if not is_release(current_semver) and last_release_semver: # we check to see how important the changes are # in the triggers, compared to the changes made between the current version and previous release if sigfig_gt(max_sigfig(all_triggers), semver_diff(current_semver, last_release_semver)): # here, the changes are more significant than the original RC bump, so we re-bump pass else: # here the changes are same or lesser than the original RC bump, so we only bump prerelease all_triggers = {SemVerSigFig.prerelease} if is_release(current_semver): # if the current semver is a release, we can't just do a prerelease or build increment # there *must* be a minimum patch increment, otherwise you could get 2.0.0 -> 2.0.0-RC.1 all_triggers.add(SemVerSigFig.patch) bump_sigfig = max_sigfig(all_triggers) if bump_sigfig: # perform an increment using the most-significant trigger version_string = getattr(semver, "bump_" + bump_sigfig)( str(current_semver), **get_token_args(bump_sigfig)) if sigfig_gt(bump_sigfig, SemVerSigFig.prerelease): # if we *didnt* increment sub-patch already, then we should do so # this provides the "devmode template" as previously # and ensures a simple 'bump' doesn't look like a full release version_string = semver.bump_prerelease( version_string, token=config.PRERELEASE_TOKEN) # perform any explicit setting of sigfigs version_info = semver.parse_version_info(version_string) for k, v in overrides.items(): token_args = get_token_args(k) prefix = list(token_args.values()).pop() + "." if token_args else "" setattr(version_info, "_" + k, prefix + str(v)) return version_info
def update_version(ctx): """Update version number in Podspec and Frameworks.""" if _git_modified_files(): _logger.error('Branch must be clean before updating version spec. ' 'Clean up modified files and try again.') return current_version = _get_current_version('Fritz.podspec') new_version = semver.bump_prerelease(current_version, token='beta') _update_changelog(new_version) _update_podspec('Fritz.podspec', current_version, new_version) _update_info_plists(new_version) os.system('git commit -am "Bump to version {}"'.format(new_version))
def next_semver(major, minor, prerelease=None, versions=None): # type: (int, int, str, list) -> str major = int(major) minor = int(minor) def stuff_we_care_about(v): """ we only care about stuff that: - has our same major+minor version - is a release OR has our same prerelease token """ if v.major != major: return False if v.minor != minor: return False if not prerelease: return True if v.prerelease is None: return True prefix = prerelease + "." if v.prerelease.startswith(prefix): # also needs to end in an int for us to care about it return bool(re.match("^\d+$", v.prerelease[len(prefix):])) return False semvers = [ VersionInfo.parse(v[1:] if v.startswith("v") else v) for v in versions or [] ] semvers = filter(stuff_we_care_about, semvers) if semvers: latest = sorted(semvers)[-1] version = str(latest) # do we bump patch? if not latest.prerelease: version = semver.bump_patch(version) # is this a final version? if prerelease: version = semver.bump_prerelease(version, prerelease) else: version = semver.finalize_version(version) else: # nothing exists on the current minor version so create a new one version = "%s.%s.0" % (major, minor) if prerelease: version += "-%s.1" % prerelease return "v" + version
def bump(self, what): if self.bumped: debug('version already bumped, don\'t do it twice') return if '=' in what: what, what_name = what.split('=') else: what, what_name = what, None old = semver.format_version(*self.version) types = ['major', 'minor', 'patch', 'prerelease', 'build'] if what == "last": # count how many non None parts there are parts = len([k for k in self.version if k is not None]) new = semver_bump[parts - 1](old) elif what == 'finalize': new = semver.finalize_version(old) elif what in types: if what_name: if what == 'prerelease': # to enable x.y.z-beta.1 -> x.y.z->rc.0 old_final = semver.finalize_version(old) new = semver_bump[types.index(what)](old_final, what_name) elif what in ['major', 'minor', 'patch']: # to go from 0.1.0 -> 0.2.0-beta1 new = semver_bump[types.index(what)](old) new = semver.bump_prerelease(new, what_name) else: new = semver_bump[types.index(what)](old, what_name) else: new = semver_bump[types.index(what)](old) else: error("unknown what: {}", what) info("version was {}, is now {}", old, new) self.version = [ k for k in semver.parse_version_info(new) if k is not None ] self.bumped = True
def update_version(repo, src, dst) -> str: """ Retrieves the current version from github, bumps the version, and updates the values in service_config.json before committing to the dst branch :return: The new version. """ cur_version = get_current_version(repo, cmd_args.stage) if src == "prod": prv_version = get_current_version(repo, _stage=dst) _new_version = semver.finalize_version(prv_version) else: _new_version = getattr(semver, f"bump_{cmd_args.release}")(str(cur_version)) _new_version = (_new_version if semver.parse_version_info(_new_version).prerelease else semver.bump_prerelease(_new_version, token="rc")) if cur_version == _new_version: print("Nothing to promote") exit(0) else: print(f"Upgrading: {cur_version} -> {_new_version}") return _new_version
def make_new_semver(version_string, all_triggers, **overrides): """Defines how to increment semver based on which significant figure is triggered (most significant takes precendence) :param version_string: the version to increment :param all_triggers: major/minor/patch/prerelease :param overrides: explicit values for some or all of the sigfigs :return: """ # perform an increment using the most-significant trigger also_prerelease = True for sig_fig in SemVerSigFig: # iterate sig figs in order of significance if sig_fig in all_triggers: if sig_fig in (SemVerSigFig.prerelease, SemVerSigFig.build): also_prerelease = False version_string = getattr(semver, "bump_" + sig_fig)( version_string, **get_token_args(sig_fig)) break if also_prerelease: # if we *didnt* increment sub-patch, then we should do so # this provides the "devmode template" as previously # and ensures a simple 'bump' doesn't look like a full release version_string = semver.bump_prerelease(version_string, token=config.PRERELEASE_TOKEN) # perform any explicit setting of parts version_info = semver.parse_version_info(version_string) for k, v in overrides.items(): token_args = get_token_args(k) prefix = list(token_args.values()).pop() + "." if token_args else "" setattr(version_info, "_" + k, prefix + str(v)) version_string = str(version_info) return version_string
def test_should_ignore_build_on_prerelease_bump(): assert bump_prerelease('3.4.5-rc.1+build.4') == '3.4.5-rc.2'
"The rpc_release value of %s does not comply with the release naming" " standard. Please correct it!" % rpc_release) # Extract the SemVer-compliant portion of the version (no 'r' prefix) rpc_release_semver = re.sub('^r', '', rpc_release) # If the rpc_rc_release and rpc_release versions match, # then we need to increment the value of rpc_release. if rpc_rc_release == rpc_release: # If the current version is a prerelease version, # then increment the prerelease. if rpc_release != "master": rpc_release_parts = semver.parse(rpc_release_semver) if rpc_release_parts['prerelease'] is not None: rpc_release_semver_new = semver.bump_prerelease(rpc_release_semver) # Otherwise, this is a standard release and we # just need to do a patch version increment. else: rpc_release_semver_new = semver.bump_patch(rpc_release_semver) # Now add the 'r' prefix back on for the final version rpc_release = "r" + rpc_release_semver_new if rpc_release == 'master': release_data['maas_release'] = 'master' release_data['osa_release'] = 'master' release_data['rpc_release'] = 'master' else: # Adjust the maas release release_data['maas_release'] = maas_release
def test_should_bump_prerelease(): assert bump_prerelease('3.4.5-rc.9') == '3.4.5-rc.10' assert bump_prerelease('3.4.5-0009.dev') == '3.4.5-0010.dev' assert bump_prerelease('3.4.5') == '3.4.5-rc.1'
def test_should_ignore_build_on_prerelease_bump(self): self.assertEqual(bump_prerelease('3.4.5-rc.1+build.4'), '3.4.5-rc.2')
def test_should_bump_prerelease(version, token, expected): token = "rc" if not token else token assert bump_prerelease(version, token) == expected
def bump_pre(self, token=None): v = semver.bump_prerelease(str(self), token=self.pre_token) self.parse_version(v) return v
def test_should_ignore_build_on_prerelease_bump(): assert bump_prerelease("3.4.5-rc.1+build.4") == "3.4.5-rc.2"
def test_should_bump_prerelease(): assert bump_prerelease('3.4.5-rc.9') == '3.4.5-rc.10' assert bump_prerelease('3.4.5') == '3.4.5-rc.1'
assert release_naming_standard.match(rpc_release), ( "The rpc_release value of %s does not comply with the release naming" " standard. Please correct it!" % rpc_release) # Extract the SemVer-compliant portion of the version (no 'r' prefix) rpc_release_semver = re.sub('^r', '', rpc_release) # If the rpc_rc_release and rpc_release versions match, # then we need to increment the value of rpc_release. if rpc_rc_release == rpc_release: # If the current version is a prerelease version, # then increment the prerelease. rpc_release_parts = semver.parse(rpc_release_semver) if rpc_release_parts['prerelease'] is not None: rpc_release_semver_new = semver.bump_prerelease(rpc_release_semver) # Otherwise, this is a standard release and we # just need to do a minor version increment. else: rpc_release_semver_new = semver.bump_minor(rpc_release_semver) # Now add the 'r' prefix back on for the final version rpc_release = "r" + rpc_release_semver_new # Adjust the maas release release_data['maas_release'] = maas_release # Adjust the OSA SHA release_data['osa_release'] = osa_release
exit(1) else: print "Error: No file extension found in the artifact_name (%s)" % args.artifact_name exit(1) # Go find what versions already exist artifact_prefix = args.bucket_dir + "/" + file_name bucket = s3.Bucket(args.bucket_name) obj_iterator = bucket.objects.filter(Prefix=artifact_prefix) item_names = sorted([x.key for x in obj_iterator]) if not len(item_names): # New file to begin versioning new_ver = semver.format_version(0, 0, 1) new_ver = semver.bump_prerelease(new_ver) print new_ver exit(0) ver_index = item_names[-1].rfind("_") highest_existing_ver = item_names[-1][ver_index:] if item_names[-1][:ver_index] != artifact_prefix: print "Error: Found no versioned files based on %s" % artifact_prefix exit(1) if highest_existing_ver.startswith("_"): highest_existing_ver = highest_existing_ver[1:] else: print "Have highest_existing_ver=%s" % highest_existing_ver print "Error: the highest existing version number doesn't start with \"_\" (%s)" % item_names[
def _get_version(cls, release_version, bump_and_set_dev): if not bump_and_set_dev: return release_version bumped = semver.bump_patch(release_version) return semver.bump_prerelease(bumped, token='dev')
'internal': 'integrations-internal', 'agent': 'datadog-agent', } VERSION_BUMP = { 'Added': semver.bump_minor, 'Changed': semver.bump_major, 'Deprecated': semver.bump_minor, 'Fixed': semver.bump_patch, 'Removed': semver.bump_major, 'Security': semver.bump_minor, 'major': semver.bump_major, 'minor': semver.bump_minor, 'patch': semver.bump_patch, 'fix': semver.bump_patch, 'rc': lambda v: semver.bump_prerelease(v, 'rc'), 'alpha': lambda v: semver.bump_prerelease(v, 'alpha'), 'beta': lambda v: semver.bump_prerelease(v, 'beta'), } CHANGELOG_TYPES_ORDERED = [ 'Added', 'Fixed', 'Security', 'Changed', 'Deprecated', 'Removed' ] AGENT_V5_ONLY = { 'agent_metrics', 'docker_daemon', 'go-metro', 'kubernetes', 'ntp' } BETA_PACKAGES = {'datadog_checks_dev', 'datadog_checks_downloader'} NOT_CHECKS = {'datadog_checks_dev'}
CHANGELOG_LABEL_PREFIX = 'changelog/' CHANGELOG_TYPE_NONE = 'no-changelog' VERSION_BUMP = OrderedDict( [ ('Added', semver.bump_minor), ('Changed', semver.bump_major), ('Deprecated', semver.bump_minor), ('Fixed', semver.bump_patch), ('Removed', semver.bump_major), ('Security', semver.bump_minor), ('major', semver.bump_major), ('minor', semver.bump_minor), ('patch', semver.bump_patch), ('fix', semver.bump_patch), ('rc', lambda v: semver.bump_prerelease(v, 'rc')), ('alpha', lambda v: semver.bump_prerelease(v, 'alpha')), ('beta', lambda v: semver.bump_prerelease(v, 'beta')), ] ) AGENT_V5_ONLY = {'agent_metrics', 'docker_daemon', 'go-metro', 'kubernetes', 'ntp'} BETA_PACKAGES = {'datadog_checks_dev', 'datadog_checks_downloader'} NOT_CHECKS = {'datadog_checks_dev'} # Some integrations do not have an associated tile, mostly system integrations NOT_TILES = [ 'agent_metrics', 'directory',
def release_local(url, version='patch', base='master', integration=None, default_version='0.0.1', use_prefix=None): # type: (str, str, str, str, str, str) -> str """ Tag given repository with a new semver tag (bump version), optionally merging a integration branch. This will: - clone the repository to temporary directory - checkout branch indicated via base argument - retrieve all the tags, sort them in natural order - retrieve the last tag and bump it to given version - merge integration branch, if defined - tag and push base branch back to origin If no tag is present and version argument is any of the bump arguments, default_version will be used :rtype: str :param url: URL of the repository :param version: specific version or one of: build, prerelease, patch, minor, major :param base: base branch to use, by default master :param integration: integration branch to use, by default none :param default_version: default version used for when there are no tags and no specific version, default 0.0.1 :param use_prefix: use prefix for tags - sometimes, 'v', :return: newly released version string or None if can not tag """ workspace = mkdtemp() repo = Repo.clone_from(url, workspace, progress=SimpleProgressPrinter()) if repo.bare: print_err('Cloned a bare repository, can not release [???]') origin = repo.remote('origin') if repo.active_branch.name != base: origin.fetch('refs/heads/{0}:refs/heads/{0}'.format(base), progress=SimpleProgressPrinter()) repo.heads[base].checkout() if integration is not None and integration in repo.heads: print_info('Found integration branch "{0}", fetching'.format(integration)) origin.fetch('refs/heads/{0}:refs/heads/{0}'.format(integration), progress=SimpleProgressPrinter()) print_info('Will now attempt fast-forward {0} to include {1}'.format(base, integration)) print_git_output(repo.git.merge('--commit', '--no-edit', '--stat', '--ff-only', '-v', integration)) head_tags = (tag for tag in repo.tags if tag.commit == repo.head.commit) sorted_head_tags = natsorted(head_tags, key=lambda t: t.path) if 0 != len(sorted_head_tags): print_info( 'Not going to auto-tag already tagged HEAD, tagged with {0}' .format( str.join(', ', (t.path[10:] for t in sorted_head_tags)) ) ) return None last_tag = None if repo.tags: sorted_tags = natsorted(repo.tags, key=lambda t: t.path) current_tag = sorted_tags[-1].path[10:] print_info('Current tag is {0}'.format(current_tag)) if use_prefix is not None and current_tag.startswith(use_prefix): last_tag = current_tag[len(use_prefix):] else: last_tag = current_tag print_info('Last known version: {0}'.format(last_tag)) if last_tag is None: print('Unknown last version, using default version {0}'.format(default_version)) last_tag = default_version if 'build' == version: next_version = bump_build(last_tag) elif 'prerelease' == version: next_version = bump_prerelease(last_tag) elif 'patch' == version: next_version = bump_patch(last_tag) elif 'minor' == version: next_version = bump_minor(last_tag) elif 'major' == version: next_version = bump_major(last_tag) else: next_version = version print_info('Next version: {0}'.format(next_version)) next_tag = next_version.strip() if use_prefix is not None: next_tag = use_prefix + next_version print_info('Next tag: {0}'.format(next_tag)) print_info('Tagging and pushing version') release_tag = repo.create_tag( path=next_tag, ref=repo.heads[base], message='Release tag of {0}'.format(next_version) ) origin.push([release_tag, repo.heads[base]], progress=SimpleProgressPrinter()) print_info('Done, clearing workspace') rmtree(workspace) return next_version