Exemplo n.º 1
0
    def check(self):
        """
        checks remote api availability & version
        """

        # TODO: implement version check

        url = '{api_base_url}status/'.format(
            api_base_url=API_BASE_URL
        )

        api_version = None

        try:
            r = requests.get(url, timeout=REQUEST_TIMEOUT, headers=self.headers)

            if r.status_code == 200:
                data = r.json()
                api_version = data.get('version')

        except RequestException as e:
            log.warning('unable to call api: {}'.format(e))


        # print(api_version)
        if api_version:
            semver.parse_version_info(api_version)
Exemplo n.º 2
0
    def bump(self, major=False, minor=False, patch=False, status=None, build=None):
        # Get the current version as an instance.
        current_info = semver.parse_version_info(self.identifier)

        # Get the new version.
        if major:
            new_version = semver.bump_major(self.identifier)
        elif minor:
            new_version = semver.bump_minor(self.identifier)
        elif patch:
            new_version = semver.bump_patch(self.identifier)
        else:
            new_version = self.identifier

        # Update the status.
        if status:
            status = status
        elif current_info.prerelease:
            status = current_info.prerelease
        else:
            status = None

        if status:
            info = semver.parse_version_info(new_version)

            new_version = "%s.%s.%s-%s" % (
                info.major,
                info.minor,
                info.patch,
                status
            )

        # Update the build.
        if build:
            info = semver.parse_version_info(new_version)

            new_version = "%s.%s.%s-%s+%s" % (
                info.major,
                info.minor,
                info.patch,
                info.prerelease,
                build
            )

        # Return the new version.
        new_version = new_version.strip()
        return new_version
Exemplo n.º 3
0
    def _parse_version(self, value):
        if isinstance(value, semver.VersionInfo):
            version_info = value
        else:
            version_info = semver.parse_version_info(value)

        version = semver.format_version(*tuple(version_info))
        return version, version_info
Exemplo n.º 4
0
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.

import pkg_resources
import semver


def get_version_string():
    version = pkg_resources.get_distribution('boundary_layer').version

    # Pip seems to replace '-' with '.' in the version strings, for some reason.
    # this makes semver unhappy, so we must replace .dev0 with -dev0
    if not version.endswith('.dev0'):
        return version

    dev0_position = version.rindex('.dev0')
    return version[:dev0_position] + '-' + version[1 + dev0_position:]


VERSION_STRING = get_version_string()
VERSION = semver.parse_version_info(VERSION_STRING)
MIN_SUPPORTED_VERSION = semver.parse_version_info('0.9.9')
Exemplo n.º 5
0
def test_should_versioninfo_bump_patch_and_prerelease():
    v = parse_version_info("3.4.5-rc.1")
    expected = parse_version_info("3.4.6-rc.1")
    assert v.bump_patch().bump_prerelease() == expected
Exemplo n.º 6
0
    def install_os(self, dev, image_name):
        vendor_dir = os.path.join(self.cli_args.topdir, 'vendor_images',
                                  _OS_NAME)

        image_fpath = os.path.join(vendor_dir, image_name)
        if not os.path.exists(image_fpath):
            errmsg = 'image file does not exist: %s' % image_fpath
            self.log.error(errmsg)
            self.exit_results(dev=dev,
                              results=dict(ok=False,
                                           error_type='install',
                                           message=errmsg))

        msg = 'Installing Cumulus image=[%s] ... this can take up to 30 min.' % image_name
        self.log.info(msg)
        self.post_device_status(dev=dev, state='OS-INSTALL', message=msg)

        os_semver = semver.parse_version_info(dev.facts['os_version'])

        # Cumulus 2.x upgrade command is removed in Cumulus 3.x, so two upgrade methods are required
        # Cumulus 2.x upgrade
        if os_semver.major == 2:
            install_command = 'sudo /usr/cumulus/bin/cl-img-install -sf http://{server}/images/{os_name}/{image_name}'.format(
                server=self.cli_args.server,
                os_name=_OS_NAME,
                image_name=image_name)
            all_good, results = dev.api.execute([install_command])
            if not all_good:
                errmsg = 'Unable to run command: {}. Error message: {}'.format(
                    install_command, results)
                self.exit_results(dev=dev,
                                  results=dict(ok=False,
                                               error_type='install',
                                               message=errmsg))
        # Cumulus 3.x upgrade
        else:
            install_command = 'sudo onie-select -rf'
            all_good, results = dev.api.execute([install_command])
            if not all_good:
                errmsg = 'Unable to run command: {}. Error message: {}'.format(
                    install_command, results)
                self.exit_results(dev=dev,
                                  results=dict(ok=False,
                                               error_type='install',
                                               message=errmsg))
            dev.api.execute(['sudo reboot'])
            time.sleep(60)

            # Boot into ONIE rescue mode
            self.wait_for_onie_rescue(countdown=300,
                                      poll_delay=10,
                                      user='******')

            # Download and verify OS
            self.onie_install(dev, image_name)

            # Wait for onie-rescue shell to terminate
            time.sleep(60)

            # Wait for actual install to occur. This takes up to 30 min.
            self.wait_for_device(countdown=1800, poll_delay=30)
Exemplo n.º 7
0
def test_parse_version_info_str_hash():
    s_version = "1.2.3-alpha.1.2+build.11.e0f985a"
    v = parse_version_info(s_version)
    assert v.__str__() == s_version
    d = {}
    d[v] = ""  # to ensure that VersionInfo are hashable
Exemplo n.º 8
0
def validate_version(version):
    try:
        semver.parse_version_info(version)
    except ValueError as ex:
        print(str(ex))
        sys.exit(1)
Exemplo n.º 9
0
def create_version_branch(command_context: CommandContext,
                          operation: Callable[[VersionConfig, Optional[str], Optional[int]], Result]) -> Result:
    result = Result()
    context: Context = command_context.context

    if command_context.selected_ref.name not in [
        repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX, context.config.release_branch_base),
        repotools.create_ref_name(const.REMOTES_PREFIX,
                                  context.config.remote_name,
                                  context.config.release_branch_base)]:
        result.fail(os.EX_USAGE,
                    _("Failed to create release branch based on {branch}.")
                    .format(branch=repr(command_context.selected_ref.name)),
                    _("Release branches (major.minor) can only be created off {branch}")
                    .format(branch=repr(context.config.release_branch_base))
                    )

    existing_release_branches = list(repotools.git_list_refs(context.repo, repotools.ref_name([
        const.REMOTES_PREFIX,
        context.config.remote_name,
        'release'])))

    release_branch_merge_bases = dict()
    for release_branch in context.get_release_branches():
        merge_base = repotools.git_merge_base(context.repo, context.config.release_branch_base, release_branch)
        if merge_base is None:
            result.fail(os.EX_DATAERR,
                        "Failed to resolve merge base.",
                        None)
        branch_refs = release_branch_merge_bases.get(merge_base)
        if branch_refs is None:
            release_branch_merge_bases[merge_base] = branch_refs = list()
        branch_refs.append(release_branch)

    latest_branch = None
    branch_points_on_same_commit = list()
    subsequent_branches = list()

    for history_commit in repotools.git_list_commits(
            context=context.repo,
            start=None,
            end=command_context.selected_commit,
            options=const.BRANCH_COMMIT_SCAN_OPTIONS):
        branch_refs = release_branch_merge_bases.get(history_commit.obj_name)
        if branch_refs is not None and len(branch_refs):
            branch_refs = list(
                filter(lambda tag_ref: context.release_branch_matcher.format(tag_ref.name) is not None,
                       branch_refs))
            if not len(branch_refs):
                continue

            branch_refs.sort(
                reverse=True,
                key=utils.cmp_to_key(
                    lambda tag_ref_a, tag_ref_b: semver.compare(
                        context.release_branch_matcher.format(tag_ref_a.name),
                        context.release_branch_matcher.format(tag_ref_b.name)
                    )
                )
            )
            if latest_branch is None:
                latest_branch = branch_refs[0]
            if history_commit.obj_name == command_context.selected_commit:
                branch_points_on_same_commit.extend(branch_refs)
            # for tag_ref in tag_refs:
            #     print('<<' + tag_ref.name)
            break

    for history_commit in repotools.git_list_commits(context.repo,
                                                     command_context.selected_commit,
                                                     command_context.selected_ref):
        branch_refs = release_branch_merge_bases.get(history_commit.obj_name)
        if branch_refs is not None and len(branch_refs):
            branch_refs = list(
                filter(lambda tag_ref: context.release_branch_matcher.format(tag_ref.name) is not None,
                       branch_refs))
            if not len(branch_refs):
                continue

            branch_refs.sort(
                reverse=True,
                key=utils.cmp_to_key(
                    lambda tag_ref_a, tag_ref_b: semver.compare(
                        context.release_branch_matcher.format(tag_ref_a.name),
                        context.release_branch_matcher.format(tag_ref_b.name)
                    )
                )
            )
            # for tag_ref in tag_refs:
            #     print('>>' + tag_ref.name)
            subsequent_branches.extend(branch_refs)

    if context.verbose:
        cli.print("Branches on same commit:\n"
                  + '\n'.join(' - ' + repr(tag_ref.name) for tag_ref in branch_points_on_same_commit))

        cli.print("Subsequent branches:\n"
                  + '\n'.join(' - ' + repr(tag_ref.name) for tag_ref in subsequent_branches))

    if latest_branch is not None:
        latest_branch_version = context.release_branch_matcher.format(latest_branch.name)
        latest_branch_version_info = semver.parse_version_info(latest_branch_version)
    else:
        latest_branch_version = None
        latest_branch_version_info = None

    if latest_branch_version is not None:
        version_result = operation(context.config.version_config, latest_branch_version,
                                   get_global_sequence_number(context))
        result.add_subresult(version_result)

        new_version = version_result.value
        new_version_info = semver.parse_version_info(new_version)
    else:
        new_version_info = semver.parse_version_info(context.config.version_config.initial_version)
        new_version = version.format_version_info(new_version_info)

    scheme_procedures.get_sequence_number(context.config.version_config, new_version_info)

    if context.config.sequential_versioning:
        new_sequential_version = create_sequence_number_for_version(context, new_version)
    else:
        new_sequential_version = None

    try:
        config_in_selected_commit = read_config_in_commit(context.repo, command_context.selected_commit)
    except FileNotFoundError:
        config_in_selected_commit = dict()

    try:
        properties_in_selected_commit = read_properties_in_commit(context,
                                                                  context.repo,
                                                                  config_in_selected_commit,
                                                                  command_context.selected_commit)
    except FileNotFoundError:
        properties_in_selected_commit = dict()

    if not context.config.allow_shared_release_branch_base and len(branch_points_on_same_commit):
        result.fail(os.EX_USAGE,
                    _("Branch creation failed."),
                    _("Release branches cannot share a common ancestor commit.\n"
                      "Existing branches on commit {commit}:\n"
                      "{listing}")
                    .format(commit=command_context.selected_commit,
                            listing='\n'.join(' - ' + repr(tag_ref.name) for tag_ref in branch_points_on_same_commit)))

    if len(subsequent_branches):
        result.fail(os.EX_USAGE,
                    _("Branch creation failed."),
                    _("Subsequent release branches in history: %s\n")
                    % '\n'.join(' - ' + repr(tag_ref.name) for tag_ref in subsequent_branches))

    if context.config.tie_sequential_version_to_semantic_version \
            and len(existing_release_branches):
        prompt_result = prompt_for_confirmation(
            context=context,
            fail_title=_("Failed to create release branch based on {branch}.")
                .format(branch=repr(command_context.selected_ref.name)),
            message=_("This operation disables version increments "
                      "on all existing release branches.\n"
                      "Affected branches are:\n"
                      "{listing}")
                .format(listing=os.linesep.join(repr(branch.name) for branch in existing_release_branches))
            if not context.config.commit_version_property
            else _("This operation disables version increments on all existing branches.\n"
                   "Affected branches are:\n"
                   "{listing}")
                .format(listing=os.linesep.join(repr(branch.name) for branch in existing_release_branches)),
            prompt=_("Continue?"),
        )
        result.add_subresult(prompt_result)
        if result.has_errors() or not prompt_result.value:
            return result

    if not result.has_errors():
        if new_version is None:
            result.error(os.EX_SOFTWARE,
                         _("Internal error."),
                         _("Missing result version.")
                         )
        if latest_branch_version is not None and semver.compare(latest_branch_version, new_version) >= 0:
            result.error(os.EX_DATAERR,
                         _("Failed to increment version from {current_version} to {new_version}.")
                         .format(current_version=repr(latest_branch_version), new_version=repr(new_version)),
                         _("The new version is lower than or equal to the current version.")
                         )
        result.abort_on_error()

        branch_name = get_branch_name_for_version(context, new_version_info)
        tag_name = get_tag_name_for_version(context, new_version_info)

        clone_result = clone_repository(context, context.config.release_branch_base)
        cloned_repo: RepoContext = clone_result.value

        # run version change hooks on new release branch
        git_or_fail(cloned_repo, result, ['checkout', '--force',
                                          '-b', branch_name,
                                          command_context.selected_commit],
                    _("Failed to check out release branch."))

        clone_context: Context = create_temp_context(context, result, cloned_repo.dir)
        clone_context.config.remote_name = 'origin'

        commit_info = CommitInfo()
        commit_info.add_message("#version: " + cli.if_none(new_version))

        if (context.config.commit_version_property and new_version is not None) \
                or (context.config.commit_sequential_version_property and new_sequential_version is not None):

            update_result = update_project_property_file(clone_context,
                                                         properties_in_selected_commit,
                                                         new_version,
                                                         new_sequential_version,
                                                         commit_info)
            result.add_subresult(update_result)
            if result.has_errors():
                result.fail(os.EX_DATAERR,
                            _("Property update failed."),
                            _("An unexpected error occurred.")
                            )

        if new_version is not None:
            execute_version_change_actions(clone_context, latest_branch_version, new_version)

        if commit_info is not None:
            if command_context.selected_commit != command_context.selected_ref.target.obj_name:
                result.fail(os.EX_USAGE,
                            _("Failed to commit version update."),
                            _("The selected parent commit {commit} does not represent the tip of {branch}.")
                            .format(commit=command_context.selected_commit,
                                    branch=repr(command_context.selected_ref.name))
                            )

            # commit changes
            commit_info.add_parent(command_context.selected_commit)
            object_to_tag = create_commit(clone_context, result, commit_info)
        else:
            object_to_tag = command_context.selected_commit

        # show info and prompt for confirmation
        cli.print("ref                 : " + cli.if_none(command_context.selected_ref.name))
        cli.print("ref_" + const.DEFAULT_VERSION_VAR_NAME + "         : " + cli.if_none(latest_branch_version))
        cli.print("new_branch          : " + cli.if_none(branch_name))
        cli.print("new_" + const.DEFAULT_VERSION_VAR_NAME + "         : " + cli.if_none(new_version))
        cli.print("selected object     : " + cli.if_none(command_context.selected_commit))
        cli.print("tagged object       : " + cli.if_none(object_to_tag))

        prompt_result = prompt_for_confirmation(
            context=context,
            fail_title=_("Failed to create release branch based on {branch}.")
                .format(branch=repr(command_context.selected_ref.name)),
            message=_("The branch and tags are about to be pushed."),
            prompt=_("Continue?"),
        )
        result.add_subresult(prompt_result)
        if result.has_errors() or not prompt_result.value:
            return result

        # push atomically
        push_command = ['push', '--atomic']
        if context.dry_run:
            push_command.append('--dry-run')
        if context.verbose:
            push_command.append('--verbose')
        push_command.append(context.config.remote_name)

        # push the base branch commit
        # push_command.append(commit + ':' + const.LOCAL_BRANCH_PREFIX + selected_ref.local_branch_name)

        # push the new branch or fail if it exists
        push_command.extend(
            ['--force-with-lease=' + repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX, branch_name) + ':',
             repotools.ref_target(object_to_tag) + ':' + repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX,
                                                                                   branch_name)])
        # push the new version tag or fail if it exists
        push_command.extend(['--force-with-lease=' + repotools.create_ref_name(const.LOCAL_TAG_PREFIX, tag_name) + ':',
                             repotools.ref_target(object_to_tag) + ':' + repotools.create_ref_name(
                                 const.LOCAL_TAG_PREFIX, tag_name)])

        git_or_fail(cloned_repo, result, push_command, _("Failed to push."))

    return result
Exemplo n.º 10
0
def release(ctx, version, skip_release_notes=False):
    """Tag a new release."""
    status = run("git status --porcelain", hide=True).stdout.strip()
    if status != "":
        raise Exit(message="git checkout not clean, cannot release")

    version = semver.parse_version_info(version)
    is_patch_release = version.patch != 0

    # Check that we have release notes for the desired version.
    run("git checkout main", echo=True)
    if not skip_release_notes:
        with open("website/content/release-notes/_index.md") as release_notes:
            if "## Version {}".format(version) not in release_notes.read():
                raise Exit(message="no release notes for v{}".format(version))

    # Move HEAD to the correct release branch - either a new one, or
    # an existing one.
    if is_patch_release:
        run("git checkout v{}.{}".format(version.major, version.minor), echo=True)
    else:
        run("git checkout -b v{}.{}".format(version.major, version.minor), echo=True)

    # Copy over release notes from main.
    if not skip_release_notes:
        run("git checkout main -- website/content/release-notes/_index.md", echo=True)

    # Update links on the website to point to files at the version
    # we're creating.
    if is_patch_release:
        previous_version = "v{}.{}.{}".format(version.major, version.minor, version.patch-1)
    else:
        previous_version = "main"
    def _replace(pattern):
        oldpat = pattern.format(previous_version)
        newpat = pattern.format("v{}").format(version)
        run("perl -pi -e 's#{}#{}#g' website/content/*.md website/content/*/*.md".format(oldpat, newpat),
            echo=True)
    _replace("/metallb/metallb/{}")
    _replace("/metallb/metallb/tree/{}")
    _replace("/metallb/metallb/blob/{}")

    # Update the version listed on the website sidebar
    run("perl -pi -e 's/MetalLB .*/MetalLB v{}/g' website/content/_header.md".format(version), echo=True)

    # Update the manifests with the new version
    run("perl -pi -e 's,image: quay.io/metallb/speaker:.*,image: quay.io/metallb/speaker:v{},g' manifests/metallb.yaml".format(version), echo=True)
    run("perl -pi -e 's,image: quay.io/metallb/controller:.*,image: quay.io/metallb/controller:v{},g' manifests/metallb.yaml".format(version), echo=True)

    # Update the versions in the helm chart (version and appVersion are always the same)
    # helm chart versions follow Semantic Versioning, and thus exclude the leading 'v'
    run("perl -pi -e 's,^version: .*,version: {},g' charts/metallb/Chart.yaml".format(version), echo=True)
    run("perl -pi -e 's,^appVersion: .*,appVersion: v{},g' charts/metallb/Chart.yaml".format(version), echo=True)
    run("perl -pi -e 's,^Current chart version is: .*,Current chart version is: `{}`,g' charts/metallb/README.md".format(version), echo=True)

    # Update the version in kustomize instructions
    #
    # TODO: Check if kustomize instructions really need the version in the
    # website or if there is a simpler way. For now, though, we just replace the
    # only page that mentions the version on release.
    run("perl -pi -e 's,github.com/metallb/metallb//manifests\?ref=.*,github.com/metallb/metallb//manifests\?ref=v{},g' website/content/installation/_index.md".format(version), echo=True)

    # Update the version embedded in the binary
    run("perl -pi -e 's/version\s+=.*/version = \"{}\"/g' internal/version/version.go".format(version), echo=True)
    run("gofmt -w internal/version/version.go", echo=True)

    run("git commit -a -m 'Automated update for release v{}'".format(version), echo=True)
    run("git tag v{} -m 'See the release notes for details:\n\nhttps://metallb.universe.tf/release-notes/#version-{}-{}-{}'".format(version, version.major, version.minor, version.patch), echo=True)
    run("git checkout main", echo=True)
Exemplo n.º 11
0
def make(ctx, check, version):
    """Perform a set of operations needed to release a single check:

        \b
        * update the version in __about__.py
        * update the changelog
        * update the requirements-agent-release.txt file
        * commit the above changes
    """
    valid_checks = get_valid_checks()
    if check != 'all' and check not in valid_checks:
        abort('Check `{}` is not an Agent-based Integration'.format(check))

    # don't run the task on the master branch
    if get_current_branch() == 'master':
        abort(
            'This task will commit, you do not want to add commits to master directly'
        )

    if check == 'all':
        if version:
            abort('You cannot bump every check to the same version')
        checks = sorted(valid_checks)
    else:
        checks = [check]

    for check in checks:
        echo_success('Check `{}`'.format(check))

        if version:
            # sanity check on the version provided
            cur_version = get_version_string(check)
            p_version = parse_version_info(version)
            p_current = parse_version_info(cur_version)
            if p_version <= p_current:
                abort('Current version is {}, cannot bump to {}'.format(
                    cur_version, version))
        else:
            cur_version, changelog_types = ctx.invoke(changes,
                                                      check=check,
                                                      dry_run=True)
            if not changelog_types:
                echo_warning('No changes for {}, skipping...'.format(check))
                continue
            bump_function = get_bump_function(changelog_types)
            version = bump_function(cur_version)

        # update the version number
        echo_info('Current version of check {}: {}, bumping to: {}'.format(
            check, cur_version, version))
        update_version_module(check, cur_version, version)

        # update the CHANGELOG
        echo_waiting('Updating the changelog...')
        # TODO: Avoid double GitHub API calls when bumping all checks at once
        ctx.invoke(changelog,
                   check=check,
                   version=version,
                   old_version=cur_version,
                   quiet=True,
                   dry_run=False)

        if check == 'datadog_checks_dev':
            commit_targets = [check]
        # update the global requirements file
        else:
            commit_targets = [check, AGENT_REQ_FILE]
            req_file = os.path.join(get_root(), AGENT_REQ_FILE)
            echo_waiting(
                'Updating the requirements file {}...'.format(req_file))
            update_agent_requirements(
                req_file, check, get_agent_requirement_line(check, version))

        # commit the changes.
        # do not use [ci skip] so releases get built https://docs.gitlab.com/ee/ci/yaml/#skipping-jobs
        msg = '[Release] Bumped {} version to {}'.format(check, version)
        git_commit(commit_targets, msg)

        # Reset version
        version = None

    # done
    echo_success(
        'All done, remember to push to origin and open a PR to merge these changes on master'
    )
Exemplo n.º 12
0
def test_should_versioninfo_bump_minor_and_patch():
    v = parse_version_info("3.4.5")
    expected = parse_version_info("3.5.1")
    assert v.bump_minor().bump_patch() == expected
Exemplo n.º 13
0
def write_version_py(filename='wradlib/version.py'):
    cnt = """
# THIS FILE IS GENERATED FROM WRADLIB SETUP.PY
short_version = '%(short_version)s'
version = '%(version)s'
full_version = '%(full_version)s'
git_revision = '%(git_revision)s'
release = %(isrelease)s
"""
    # Adding the git rev number needs to be done inside write_version_py(),
    # otherwise the import of wradlib.version messes up the build under
    # Python 3.

    SHORT_VERSION = VERSION
    FULL_VERSION = VERSION
    GIT_REVISION = VERSION + '-unknown'
    GIT_HASH = 'unknown'
    ISRELEASED = "'unknown'"

    if os.path.exists('.git'):
        GIT_REVISION, GIT_HASH = git_version()
    elif os.path.exists('wradlib/version.py'):
        # must be a source distribution, use existing version file
        try:
            from wradlib.version import full_version as GIT_REVISION
            from wradlib.version import git_revision as GIT_HASH
        except ImportError:
            raise ImportError('Unable to import git_revision. Try removing '
                              'wradlib/version.py and the build directory '
                              'before building.')

    # parse version using semver
    ver = semver.parse_version_info(GIT_REVISION)

    # get commit count, dev0 means tagged commit -> release
    try:
        ISRELEASED = ver.prerelease == 'dev0'
        if not ISRELEASED:
            if not ver.patch:
                patch = 0
                minor = 1
            else:
                patch = 1
                minor = 0

            SHORT_VERSION = semver.format_version(ver.major,
                                                  ver.minor + minor,
                                                  ver.patch + patch,
                                                  ver.prerelease)
            FULL_VERSION = GIT_REVISION

    except ValueError:
        warnings.warn("wradlib source does not contain detailed version info "
                      "via git or version.py, exact version can't be "
                      "retrieved.", UserWarning)

    print(SHORT_VERSION, FULL_VERSION, GIT_REVISION, GIT_HASH, ISRELEASED)
    a = open(filename, 'w')
    try:
        a.write(cnt % {'short_version': SHORT_VERSION,
                       'version': FULL_VERSION,
                       'full_version': GIT_REVISION,
                       'git_revision': GIT_HASH,
                       'isrelease': str(ISRELEASED)})
    finally:
        a.close()

    return SHORT_VERSION
Exemplo n.º 14
0
def test_should_versioninfo_bump_major_and_minor():
    v = parse_version_info("3.4.5")
    expected = parse_version_info("4.1.0")
    assert v.bump_major().bump_minor() == expected
Exemplo n.º 15
0
tags = {}

with Repo(join(script_dir, 'ClassicPress-nightly')) as r:
    tags.update(r.refs.as_dict('refs/tags'))

with Repo(join(script_dir, 'ClassicPress-release')) as r:
    tags.update(r.refs.as_dict('refs/tags'))

dump('tags', tags)

vers = {}

for tag in tags:
    try:
        ver = parse_version_info(tag)
        # we only care about release and nightly builds
        if not ver.build or ver.build[:7] == 'nightly':
            if ver.major in vers:
                vers[ver.major].append(ver)
            else:
                vers[ver.major] = [ver]
    except ValueError:
        # ignore non-semver tags
        pass

dump(
    'vers',
    dict((major, sorted(str(v) for v in arr))
         for (major, arr) in vers.iteritems()))
Exemplo n.º 16
0
def normalize_version(version):
    version_info = semver.parse_version_info(version)
    version_string = str(version_info)
    return version_string
Exemplo n.º 17
0
def test_semver_version():
    """Ensure the package version is semver compliant."""
    from tokendito.__version__ import __version__ as version
    assert semver.parse_version_info(version)
Exemplo n.º 18
0
def get_short_version(version):
    version = semver.parse_version_info(version)
    if version.major >= 1 and version.minor >= 1:
        return ".".join([str(version.major), str(version.minor)])
    else:
        return version
Exemplo n.º 19
0
 def __init__(self, string):
     self._current = None
     self._original = string
     self.name = None
     self.object = semver.parse_version_info(string)
Exemplo n.º 20
0
def test_should_versioninfo_bump_patch_and_prerelease_with_token():
    v = parse_version_info("3.4.5-dev.1")
    expected = parse_version_info("3.4.6-dev.1")
    assert v.bump_patch().bump_prerelease("dev") == expected
Exemplo n.º 21
0
def make(ctx, check, version, initial_release, skip_sign, sign_only):
    """Perform a set of operations needed to release a single check:

    \b
      * update the version in __about__.py
      * update the changelog
      * update the requirements-agent-release.txt file
      * update in-toto metadata
      * commit the above changes

    You can release everything at once by setting the check to `all`.

    \b
    If you run into issues signing:
    \b
      - Ensure you did `gpg --import <YOUR_KEY_ID>.gpg.pub`
    """
    # Import lazily since in-toto runs a subprocess to check for gpg2 on load
    from ..signing import update_link_metadata, YubikeyException

    root = get_root()
    releasing_all = check == 'all'

    valid_checks = get_valid_checks()
    if not releasing_all and check not in valid_checks:
        abort('Check `{}` is not an Agent-based Integration'.format(check))

    # don't run the task on the master branch
    if get_current_branch() == 'master':
        abort(
            'This task will commit, you do not want to add commits to master directly'
        )

    if releasing_all:
        if version:
            abort('You cannot bump every check to the same version')
        checks = sorted(valid_checks)
    else:
        checks = [check]

    if initial_release:
        version = '1.0.0'

    for check in checks:
        if sign_only:
            break
        elif initial_release and check in BETA_PACKAGES:
            continue

        # Initial releases will only bump if not already 1.0.0 so no need to always output
        if not initial_release:
            echo_success('Check `{}`'.format(check))

        if version:
            # sanity check on the version provided
            cur_version = get_version_string(check)

            if version == 'final':
                # Remove any pre-release metadata
                version = finalize_version(cur_version)
            else:
                # Keep track of intermediate version bumps
                prev_version = cur_version
                for method in version.split(','):
                    # Apply any supported version bumping methods. Chaining is required for going
                    # from mainline releases to development releases since e.g. x.y.z > x.y.z-rc.A.
                    # So for an initial bug fix dev release you can do `fix,rc`.
                    if method in VERSION_BUMP:
                        version = VERSION_BUMP[method](prev_version)
                        prev_version = version

            p_version = parse_version_info(version)
            p_current = parse_version_info(cur_version)
            if p_version <= p_current:
                if initial_release:
                    continue
                else:
                    abort('Current version is {}, cannot bump to {}'.format(
                        cur_version, version))
        else:
            cur_version, changelog_types = ctx.invoke(changes,
                                                      check=check,
                                                      dry_run=True)
            if not changelog_types:
                echo_warning('No changes for {}, skipping...'.format(check))
                continue
            bump_function = get_bump_function(changelog_types)
            version = bump_function(cur_version)

        if initial_release:
            echo_success('Check `{}`'.format(check))

        # update the version number
        echo_info('Current version of check {}: {}'.format(check, cur_version))
        echo_waiting('Bumping to {}... '.format(version), nl=False)
        update_version_module(check, cur_version, version)
        echo_success('success!')

        # update the CHANGELOG
        echo_waiting('Updating the changelog... ', nl=False)
        # TODO: Avoid double GitHub API calls when bumping all checks at once
        ctx.invoke(changelog,
                   check=check,
                   version=version,
                   old_version=cur_version,
                   initial=initial_release,
                   quiet=True,
                   dry_run=False)
        echo_success('success!')

        commit_targets = [check]

        # update the list of integrations to be shipped with the Agent
        if check not in NOT_CHECKS:
            commit_targets.append(AGENT_REQ_FILE)
            req_file = os.path.join(root, AGENT_REQ_FILE)
            echo_waiting('Updating the Agent requirements file... ', nl=False)
            update_agent_requirements(
                req_file, check, get_agent_requirement_line(check, version))
            echo_success('success!')

        echo_waiting('Committing files...')

        # commit the changes.
        # do not use [ci skip] so releases get built https://docs.gitlab.com/ee/ci/yaml/#skipping-jobs
        msg = '[Release] Bumped {} version to {}'.format(check, version)
        git_commit(commit_targets, msg)

        if not initial_release:
            # Reset version
            version = None

    if sign_only or not skip_sign:
        echo_waiting('Updating release metadata...')
        echo_info(
            'Please touch your Yubikey immediately after entering your PIN!')
        try:
            commit_targets = update_link_metadata(checks)
            git_commit(commit_targets, '[Release] Update metadata', force=True)
        except YubikeyException as e:
            abort('A problem occurred while signing metadata: {}'.format(e))

    # done
    echo_success(
        'All done, remember to push to origin and open a PR to merge these changes on master'
    )
Exemplo n.º 22
0
def test_should_versioninfo_bump_prerelease_and_build_with_token():
    v = parse_version_info("3.4.5-rc.1+b.1")
    expected = parse_version_info("3.4.5-rc.2+b.2")
    assert v.bump_prerelease().bump_build("b") == expected
Exemplo n.º 23
0
def changelog(ctx, check, version, old_version, quiet, dry_run):
    """Perform the operations needed to update the changelog.

    This method is supposed to be used by other tasks and not directly.
    """
    if check not in get_valid_checks():
        abort('Check `{}` is not an Agent-based Integration'.format(check))

    # sanity check on the version provided
    cur_version = old_version or get_version_string(check)
    if parse_version_info(version) <= parse_version_info(cur_version):
        abort('Current version is {}, cannot bump to {}'.format(
            cur_version, version))

    if not quiet:
        echo_info('Current version of check {}: {}, bumping to: {}'.format(
            check, cur_version, version))

    # get the name of the current release tag
    target_tag = get_release_tag_string(check, cur_version)

    # get the diff from HEAD
    diff_lines = get_diff(check, target_tag)

    # for each PR get the title, we'll use it to populate the changelog
    pr_numbers = parse_pr_numbers(diff_lines)
    if not quiet:
        echo_info('Found {} PRs merged since tag: {}'.format(
            len(pr_numbers), target_tag))

    user_config = ctx.obj
    entries = []
    for pr_num in pr_numbers:
        try:
            payload = get_pr(pr_num, user_config)
        except Exception as e:
            echo_failure('Unable to fetch info for PR #{}: {}'.format(
                pr_num, e))
            continue

        changelog_labels = get_changelog_types(payload)

        if not changelog_labels:
            abort(
                'No valid changelog labels found attached to PR #{}, please add one!'
                .format(pr_num))
        elif len(changelog_labels) > 1:
            abort(
                'Multiple changelog labels found attached to PR #{}, please only use one!'
                .format(pr_num))

        changelog_type = changelog_labels[0]
        if changelog_type == CHANGELOG_TYPE_NONE:
            if not quiet:
                # No changelog entry for this PR
                echo_info('Skipping PR #{} from changelog due to label'.format(
                    pr_num))
            continue

        author = payload.get('user', {}).get('login')
        author_url = payload.get('user', {}).get('html_url')
        title = '[{}] {}'.format(changelog_type, payload.get('title'))

        entry = ChangelogEntry(pr_num, title, payload.get('html_url'), author,
                               author_url, from_contributor(payload))

        entries.append(entry)

    # store the new changelog in memory
    new_entry = StringIO()

    # the header contains version and date
    header = '## {} / {}\n'.format(version,
                                   datetime.now().strftime('%Y-%m-%d'))
    new_entry.write(header)

    # one bullet point for each PR
    new_entry.write('\n')
    for entry in entries:
        thanks_note = ''
        if entry.from_contributor:
            thanks_note = ' Thanks [{}]({}).'.format(entry.author,
                                                     entry.author_url)
        new_entry.write('* {}. See [#{}]({}).{}\n'.format(
            entry.title, entry.number, entry.url, thanks_note))
    new_entry.write('\n')

    # read the old contents
    changelog_path = os.path.join(get_root(), check, 'CHANGELOG.md')
    old = list(stream_file_lines(changelog_path))

    # write the new changelog in memory
    changelog_buffer = StringIO()

    # preserve the title
    changelog_buffer.write(''.join(old[:2]))

    # prepend the new changelog to the old contents
    # make the command idempotent
    if header not in old:
        changelog_buffer.write(new_entry.getvalue())

    # append the rest of the old changelog
    changelog_buffer.write(''.join(old[2:]))

    # print on the standard out in case of a dry run
    if dry_run:
        echo_info(changelog_buffer.getvalue())
    else:
        # overwrite the old changelog
        write_file(changelog_path, changelog_buffer.getvalue())
Exemplo n.º 24
0
def test_parse_version_info_str_hash():
    s_version = "1.2.3-alpha.1.2+build.11.e0f985a"
    v = parse_version_info(s_version)
    assert v.__str__() == s_version
    d = {}
    d[v] = ""  # to ensure that VersionInfo are hashable
Exemplo n.º 25
0
def create_version_tag(command_context: CommandContext,
                       operation: Callable[[VersionConfig, Optional[str], Optional[int]], Result]) -> Result:
    result = Result()
    context: Context = command_context.context

    release_branches = command_context.context.get_release_branches(reverse=True)

    # TODO configuration
    allow_merge_base_tags = True  # context.config.allow_shared_release_branch_base

    selected_branch = command_context.selected_ref
    selected_branch_base_version = context.release_branch_matcher.format(command_context.selected_ref.name)
    if selected_branch_base_version is not None:
        selected_branch_base_version_info = semver.parse_version_info(selected_branch_base_version)
    else:
        selected_branch_base_version_info = None

    if selected_branch_base_version is None:
        result.fail(os.EX_USAGE,
                    _("Cannot bump version."),
                    _("{branch} is not a release branch.")
                    .format(branch=repr(command_context.selected_ref.name)))

    latest_version_tag = None
    preceding_version_tag = None
    preceding_branch_version_tag = None
    version_tags_on_same_commit = list()
    subsequent_version_tags = list()
    enclosing_versions = set()

    # abort scan, when a preceding commit for each tag type has been processed.
    # enclosing_versions now holds enough information for operation validation,
    # assuming the branch has not gone haywire in earlier commits
    # TODO evaluate upper and lower bound version for efficiency
    abort_version_scan = False

    on_selected_branch = False

    before_commit = False
    before_selected_branch = False

    for release_branch in release_branches:
        # fork_point = repotools.git_merge_base(context.repo, context.config.release_branch_base,
        #                                       command_context.selected_commit)
        # if fork_point is None:
        #     result.fail(os.EX_USAGE,
        #                 _("Cannot bump version."),
        #                 _("{branch} has no fork point on {base_branch}.")
        #                 .format(branch=repr(command_context.selected_ref.name),
        #                         base_branch=repr(context.config.release_branch_base)))
        fork_point = None

        branch_base_version = context.release_branch_matcher.format(release_branch.name)
        if branch_base_version is not None:
            branch_base_version_info = semver.parse_version_info(branch_base_version)
        else:
            branch_base_version_info = None

        on_selected_branch = not before_selected_branch and release_branch.name == selected_branch.name

        for history_commit in repotools.git_list_commits(
                context=context.repo,
                start=fork_point,
                end=release_branch.obj_name,
                options=const.BRANCH_COMMIT_SCAN_OPTIONS):
            at_commit = not before_commit and on_selected_branch and history_commit.obj_name == command_context.selected_commit

            version_tag_refs = None

            assert not at_commit if before_commit else not before_commit

            for tag_ref in repotools.git_get_tags_by_referred_object(context.repo, history_commit.obj_name):
                version_info = context.version_tag_matcher.to_version_info(tag_ref.name)
                if version_info is not None:
                    tag_matches = version_info.major == branch_base_version_info.major \
                                  and version_info.minor == branch_base_version_info.minor

                    if tag_matches:
                        if version_tag_refs is None:
                            version_tag_refs = list()
                        version_tag_refs.append(tag_ref)
                    else:
                        if fork_point is not None:
                            # fail stray tags on exclusive branch commits
                            result.fail(os.EX_DATAERR,
                                        _("Cannot bump version."),
                                        _("Found stray version tag: {version}.")
                                        .format(version=repr(version.format_version_info(version_info)))
                                        )
                        else:
                            # when no merge base is used, abort at the first mismatching tag
                            break

            if not abort_version_scan and version_tag_refs is not None and len(version_tag_refs):
                version_tag_refs.sort(
                    reverse=True,
                    key=utils.cmp_to_key(
                        lambda tag_ref_a, tag_ref_b: semver.compare(
                            context.version_tag_matcher.format(tag_ref_a.name),
                            context.version_tag_matcher.format(tag_ref_b.name)
                        )
                    )
                )
                if latest_version_tag is None:
                    latest_version_tag = version_tag_refs[0]
                if at_commit:
                    version_tags_on_same_commit.extend(version_tag_refs)
                if at_commit or before_commit:
                    if preceding_version_tag is None:
                        preceding_version_tag = version_tag_refs[0]
                    if on_selected_branch and preceding_branch_version_tag is None:
                        preceding_branch_version_tag = version_tag_refs[0]
                else:
                    subsequent_version_tags.extend(version_tag_refs)

                for tag_ref in version_tag_refs:
                    enclosing_versions.add(context.version_tag_matcher.format(tag_ref.name))

                if before_commit:
                    abort_version_scan = True

            if at_commit:
                before_commit = True

        if on_selected_branch:
            before_commit = True
            before_selected_branch = True

        if abort_version_scan:
            break

    if context.config.sequential_versioning and preceding_version_tag is not None:
        match = context.version_tag_matcher.fullmatch(preceding_version_tag.name)
        preceding_sequential_version = match.group(context.version_tag_matcher.group_unique_code)
    else:
        preceding_sequential_version = None
    if preceding_sequential_version is not None:
        preceding_sequential_version = int(preceding_sequential_version)

    if context.verbose:
        cli.print("Tags on selected commit:\n"
                  + '\n'.join(' - ' + repr(tag_ref.name) for tag_ref in version_tags_on_same_commit))

        cli.print("Tags in subsequent history:\n"
                  + '\n'.join(' - ' + repr(tag_ref.name) for tag_ref in subsequent_version_tags))

    if preceding_branch_version_tag is not None:
        latest_branch_version = context.version_tag_matcher.format(preceding_branch_version_tag.name)
    else:
        latest_branch_version = None

    global_sequence_number = get_global_sequence_number(context)
    if latest_branch_version is not None:
        version_result = operation(context.config.version_config, latest_branch_version, global_sequence_number)
        result.add_subresult(version_result)

        new_version = version_result.value
        if result.has_errors():
            return result
    else:
        template_version_info = semver.parse_version_info(context.config.version_config.initial_version)
        new_version = semver.format_version(
            major=selected_branch_base_version_info.major,
            minor=selected_branch_base_version_info.minor,

            patch=template_version_info.patch,
            prerelease=str(global_sequence_number + 1) if context.config.tie_sequential_version_to_semantic_version and global_sequence_number is not None else template_version_info.prerelease,
            build=template_version_info.build,
        )

    new_version_info = semver.parse_version_info(new_version)
    new_sequential_version = scheme_procedures.get_sequence_number(context.config.version_config, new_version_info)

    if new_version_info.major != selected_branch_base_version_info.major or new_version_info.minor != selected_branch_base_version_info.minor:
        result.fail(os.EX_USAGE,
                    _("Tag creation failed."),
                    _("The major.minor part of the new version {new_version}"
                      " does not match the branch version {branch_version}.")
                    .format(new_version=repr(new_version),
                            branch_version=repr(
                                "%d.%d" % (selected_branch_base_version_info.major, selected_branch_base_version_info.minor)))
                    )

    try:
        config_in_selected_commit = read_config_in_commit(context.repo, command_context.selected_commit)
    except FileNotFoundError:
        config_in_selected_commit = dict()

    try:
        properties_in_selected_commit = read_properties_in_commit(context,
                                                                  context.repo,
                                                                  config_in_selected_commit,
                                                                  command_context.selected_commit)
    except FileNotFoundError:
        properties_in_selected_commit = dict()

    if context.verbose:
        print("properties in selected commit:")
        print(json.dumps(obj=properties_in_selected_commit, indent=2))

    valid_tag = False

    # validate the commit
    if len(version_tags_on_same_commit):
        if config_in_selected_commit is None:
            result.fail(os.EX_DATAERR,
                        _("Tag creation failed."),
                        _("The selected commit does not contain a configuration file.")
                        )

        version_property_name = config_in_selected_commit.get(const.CONFIG_VERSION_PROPERTY)
        if version_property_name is not None \
                and properties_in_selected_commit.get(version_property_name) is None:
            result.warn(_("Missing version info."),
                        _("The selected commit does not contain a version in property '{property_name}'.")
                        .format(property_name=version_property_name)
                        )

    if len(version_tags_on_same_commit):
        if context.config.allow_qualifier_increments_within_commit:
            preceding_commit_version = context.version_tag_matcher.format(
                version_tags_on_same_commit[0].name)
            prerelease_keywords_list = [context.config.version_config.qualifiers, 1]

            preceding_commit_version_ = version.parse_version(preceding_commit_version)
            new_commit_version_ = version.parse_version(new_version)
            version_delta = version.determine_version_delta(preceding_commit_version_,
                                                            new_commit_version_,
                                                            prerelease_keywords_list
                                                            )

            version_increment_eval_result = version.evaluate_version_increment(preceding_commit_version_,
                                                                               new_commit_version_,
                                                                               context.config.strict_mode,
                                                                               prerelease_keywords_list)
            result.add_subresult(version_increment_eval_result)
            if result.has_errors():
                return result

            if not version_delta.prerelease_field_only(0, False):
                result.fail(os.EX_USAGE,
                            _("Tag creation failed."),
                            _("The selected commit already has version tags.\n"
                              "Operations on such a commit are limited to pre-release type increments.")
                            )

            valid_tag = True
        else:
            result.fail(os.EX_USAGE,
                        _("Tag creation failed."),
                        _("There are version tags pointing to the selected commit {commit}.\n"
                          "Consider reusing these versions or bumping them to stable."
                          "{listing}")
                        .format(commit=command_context.selected_commit,
                                listing='\n'.join(
                                    ' - ' + repr(tag_ref.name) for tag_ref in subsequent_version_tags))
                        )

    if not valid_tag:
        if len(subsequent_version_tags):
            result.fail(os.EX_USAGE,
                        _("Tag creation failed."),
                        _("There are version tags in branch history following the selected commit {commit}:\n"
                          "{listing}")
                        .format(commit=command_context.selected_commit,
                                listing='\n'.join(
                                    ' - ' + repr(tag_ref.name) for tag_ref in subsequent_version_tags))
                        )

    global_seq_number = global_sequence_number
    if context.config.tie_sequential_version_to_semantic_version \
            and global_seq_number is not None \
            and new_sequential_version is not None \
            and preceding_sequential_version != global_seq_number:
        result.fail(os.EX_USAGE,
                    _("Tag creation failed."),
                    _(
                        "The preceding sequential version {seq_val} "
                        "does not equal the global sequential version {global_seq_val}.")
                    .format(seq_val=preceding_sequential_version
                    if preceding_sequential_version is not None
                    else '<none>',
                            global_seq_val=global_seq_number)
                    )

    if not result.has_errors():
        if new_version is None:
            result.fail(os.EX_SOFTWARE,
                        _("Internal error."),
                        _("Missing result version.")
                        )
        if latest_branch_version is not None and semver.compare(latest_branch_version, new_version) >= 0:
            result.fail(os.EX_DATAERR,
                        _("Failed to increment version from {current} to {new}.")
                        .format(current=repr(latest_branch_version), new=repr(new_version)),
                        _("The new version is lower than or equal to the current version.")
                        )

        if context.config.push_to_local \
                and command_context.current_branch.short_name == command_context.selected_ref.short_name:
            if context.verbose:
                cli.print(
                    _('Checking out {base_branch} in order to avoid failing the push to a checked-out release branch')
                        .format(base_branch=repr(context.config.release_branch_base)))

            git_or_fail(context.repo, result, ['checkout', context.config.release_branch_base])
            original_current_branch = command_context.current_branch
        else:
            original_current_branch = None

        branch_name = get_branch_name_for_version(context, new_version_info)
        tag_name = get_tag_name_for_version(context, new_version_info)

        clone_result = clone_repository(context, context.config.release_branch_base)
        cloned_repo = clone_result.value

        commit_info = CommitInfo()
        commit_info.add_message("#version: " + cli.if_none(new_version))

        # run version change hooks on release branch
        checkout_command = ['checkout', '--force', '--track', '-b', branch_name,
                            repotools.create_ref_name(const.REMOTES_PREFIX,
                                                      context.config.remote_name,
                                                      branch_name)]
        returncode, out, err = repotools.git(cloned_repo, *checkout_command)
        if returncode != os.EX_OK:
            result.fail(os.EX_DATAERR,
                        _("Failed to check out release branch."),
                        _("An unexpected error occurred.")
                        )

        clone_context: Context = create_temp_context(context, result, cloned_repo.dir)
        clone_context.config.remote_name = 'origin'

        if (context.config.commit_version_property and new_version is not None) \
                or (context.config.commit_sequential_version_property and new_sequential_version is not None):

            update_result = update_project_property_file(clone_context,
                                                         properties_in_selected_commit,
                                                         new_version,
                                                         new_sequential_version,
                                                         commit_info)
            result.add_subresult(update_result)
            if result.has_errors():
                result.fail(os.EX_DATAERR,
                            _("Property update failed."),
                            _("An unexpected error occurred.")
                            )

        if new_version is not None:
            execute_version_change_actions(clone_context, latest_branch_version, new_version)

        if commit_info is not None:
            if command_context.selected_commit != command_context.selected_ref.target.obj_name:
                result.fail(os.EX_USAGE,
                            _("Failed to commit version update."),
                            _("The selected parent commit {commit} does not represent the tip of {branch}.")
                            .format(commit=command_context.selected_commit,
                                    branch=repr(command_context.selected_ref.name))
                            )

            # commit changes
            commit_info.add_parent(command_context.selected_commit)
            object_to_tag = create_commit(clone_context, result, commit_info)
            new_branch_ref_object = object_to_tag
        else:
            object_to_tag = command_context.selected_commit
            new_branch_ref_object = None

        # if command_context.selected_branch not in repotools.git_list_refs(context.repo,
        #                                                                   '--contains', object_to_tag,
        #                                                                   command_context.selected_branch.ref):

        # show info and prompt for confirmation
        cli.print("ref                 : " + cli.if_none(command_context.selected_ref.name))
        cli.print("ref_" + const.DEFAULT_VERSION_VAR_NAME + "         : " + cli.if_none(latest_branch_version))
        cli.print("new_tag             : " + cli.if_none(tag_name))
        cli.print("new_" + const.DEFAULT_VERSION_VAR_NAME + "         : " + cli.if_none(new_version))
        cli.print("selected object     : " + cli.if_none(command_context.selected_commit))
        cli.print("tagged object       : " + cli.if_none(object_to_tag))

        prompt_result = prompt_for_confirmation(
            context=context,
            fail_title=_("Failed to create release tag based on {branch}.")
                .format(branch=repr(command_context.selected_ref.name)),
            message=_("The tags are about to be pushed."),
            prompt=_("Continue?"),
        )
        result.add_subresult(prompt_result)
        if result.has_errors() or not prompt_result.value:
            return result

        # push atomically
        push_command = ['push', '--atomic']
        if context.dry_run:
            push_command.append('--dry-run')
        if context.verbose:
            push_command.append('--verbose')
        push_command.append(context.config.remote_name)

        # push the release branch commit or its version increment commit
        if new_branch_ref_object is not None:
            push_command.append(
                new_branch_ref_object + ':' + repotools.create_ref_name(const.LOCAL_BRANCH_PREFIX, branch_name))

        # check, if preceding tags exist on remote
        if preceding_version_tag is not None:
            push_command.append('--force-with-lease='
                                + preceding_version_tag.name + ':'
                                + preceding_version_tag.name)

        # push the new version tag or fail if it exists
        push_command.extend(['--force-with-lease=' + repotools.create_ref_name(const.LOCAL_TAG_PREFIX, tag_name) + ':',
                             repotools.ref_target(object_to_tag) + ':' + repotools.create_ref_name(
                                 const.LOCAL_TAG_PREFIX, tag_name)])

        returncode, out, err = repotools.git(clone_context.repo, *push_command)
        if returncode != os.EX_OK:
            result.fail(os.EX_DATAERR,
                        _("Failed to push."),
                        _("git push exited with " + str(returncode))
                        )

        if original_current_branch is not None:
            if context.verbose:
                cli.print(
                    _('Switching back to {original_branch} ')
                        .format(original_branch=repr(original_current_branch.name)))

            git_or_fail(context.repo, result, ['checkout', original_current_branch.short_name])

    return result
def get_latest_release_version(finder: PackageFinder,
                               package: str) -> VersionInfo:
    results = finder.find_all_candidates(package)
    versions = sorted(set([p.version for p in results]), reverse=True)
    return semver.parse_version_info(str(versions[0]).replace('rc', '-rc'))
Exemplo n.º 27
0
def call(context: Context, operation: Callable[[VersionConfig, Optional[str], Optional[int]], Result]) -> Result:
    command_context = get_command_context(
        context=context,
        object_arg=context.args['<object>']
    )

    check_in_repo(command_context)

    # determine the type of operation to be performed and run according subroutines
    if operation == scheme_procedures.version_bump_major \
            or operation == scheme_procedures.version_bump_minor:

        check_requirements(command_context=command_context,
                           ref=command_context.selected_ref,
                           branch_classes=[BranchClass.DEVELOPMENT_BASE],
                           modifiable=True,
                           with_upstream=True,  # not context.config.push_to_local
                           in_sync_with_upstream=True,
                           fail_message=_("Version creation failed.")
                           )

        tag_result = create_version_branch(command_context, operation)
        command_context.add_subresult(tag_result)

    elif operation == scheme_procedures.version_bump_patch \
            or operation == scheme_procedures.version_bump_qualifier \
            or operation == scheme_procedures.version_bump_prerelease \
            or operation == scheme_procedures.version_bump_to_release:

        check_requirements(command_context=command_context,
                           ref=command_context.selected_ref,
                           branch_classes=[BranchClass.RELEASE],
                           modifiable=True,
                           with_upstream=True,  # not context.config.push_to_local
                           in_sync_with_upstream=True,
                           fail_message=_("Version creation failed.")
                           )

        tag_result = create_version_tag(command_context, operation)
        command_context.add_subresult(tag_result)

    elif isinstance(operation, scheme_procedures.VersionSet):
        check_requirements(command_context=command_context,
                           ref=command_context.selected_ref,
                           branch_classes=None,
                           modifiable=True,
                           with_upstream=True,  # not context.config.push_to_local
                           in_sync_with_upstream=True,
                           fail_message=_("Version creation failed.")
                           )

        version_result = operation(context.config.version_config, None, get_global_sequence_number(context))
        command_context.add_subresult(version_result)
        new_version = version_result.value
        if new_version is None:
            command_context.fail(os.EX_USAGE,
                                 _("Illegal argument."),
                                 _("Failed to parse version.")
                                 )
        new_version_info = semver.parse_version_info(new_version)

        branch_name = get_branch_name_for_version(context, new_version_info)

        release_branch = repotools.get_branch_by_name(context.repo, {context.config.remote_name}, branch_name,
                                                      BranchSelection.BRANCH_PREFER_LOCAL)
        if release_branch is None:
            tag_result = create_version_branch(command_context, operation)
            command_context.add_subresult(tag_result)
        else:
            selected_ref = release_branch
            tag_result = create_version_tag(command_context, operation)
            command_context.add_subresult(tag_result)

    if not command_context.has_errors() \
            and context.config.pull_after_bump \
            and not context.config.push_to_local:
        fetch_all_and_ff(context.repo, command_context.result, context.config.remote_name)

    return context.result
Exemplo n.º 28
0
def app_version():
    if _STUB_FOR_TEST:
        return parse_version_info('0.0.0-local+0')
    return _VERSION_INFO
Exemplo n.º 29
0
branch = os.environ.get('READTHEDOCS_VERSION')
if not branch or branch == 'latest':
    branch = 'HEAD'
    archive_name = 'master'
    chart_release = './cilium'
    image_tag = 'latest'
elif branch == 'stable':
    branch = release
    archive_name = release
    chart_release = 'cilium/cilium --version ' + release
    tags.add('stable')
else:
    archive_name = branch
    chart_release = 'cilium/cilium --version ' + release
    tags.add('stable')
relinfo = semver.parse_version_info(release)
current_release = '%d.%d' % (relinfo.major, relinfo.minor)
if relinfo.patch == 90:
    next_release = '%d.%d' % (relinfo.major, relinfo.minor + 1)
else:
    next_release = current_release
githubusercontent = 'https://raw.githubusercontent.com/cilium/cilium/'
scm_web = githubusercontent + branch
jenkins_branch = 'https://jenkins.cilium.io/view/Cilium-v' + current_release
archive_filename = archive_name + '.tar.gz'
archive_link = 'https://github.com/cilium/cilium/archive/' + archive_filename
archive_name = 'cilium-' + archive_name.strip('v')
project_link = 'https://github.com/cilium/cilium/projects?query=is:open+' + next_release
backport_format = 'https://github.com/cilium/cilium/pulls?q=is:open+is:pr+label:%s/' + current_release

# Store variables in the epilogue so they are globally available.
Exemplo n.º 30
0
def parse_version(version: str) -> semver.VersionInfo:
    try:
        return semver.parse_version_info(
            version[1:] if version.startswith("v") else version)
    except ValueError:
        pass
Exemplo n.º 31
0
# -*- coding: utf-8 -*-
# @author: vuolter

from pkg_resources import get_distribution
from semver import parse_version_info

__package__ = 'pyload'
__package_name__ = 'pyload-ng'
__version__ = get_distribution(__package_name__).version
__version_info__ = parse_version_info(__version__)
__credits__ = (('Walter Purcaro', '*****@*****.**', '2015-2017'),
               ('pyLoad Team', '*****@*****.**', '2009-2015'))

del get_distribution, parse_version_info
Exemplo n.º 32
0
 def from_db_value(self, value, expression, connection, context):
     if value is None:
         return value
     return semver.parse_version_info(value)
Exemplo n.º 33
0
APPID = "pyload"
PKGNAME = "pyload-ng"
PKGDIR = pkg_resources.resource_filename(__name__, None)
USERHOMEDIR = os.path.expanduser("~")
DATADIR = os.path.join(
    os.getenv("APPDATA") if os.name == "nt" else USERHOMEDIR, "pyLoad"
)
TMPDIR = os.path.join(tempfile.gettempdir(), "pyLoad")

os.makedirs(DATADIR, exist_ok=True)
os.makedirs(TMPDIR, exist_ok=True)

os.chdir(USERHOMEDIR)

__version__ = pkg_resources.get_distribution(PKGNAME).parsed_version.base_version
__version_info__ = semver.parse_version_info(__version__)


### Locale ############################################################################

locale.setlocale(locale.LC_ALL, "")
if os.name == "nt":
    _locale._getdefaultlocale = lambda *args: ["en_US", "utf_8_sig"]


### Exception logger ##################################################################

exc_logger = logging.getLogger("exception")


def excepthook(exc_type, exc_value, exc_traceback):
Exemplo n.º 34
0
 def to_python(self, value):
     if isinstance(value, semver.VersionInfo):
         return value
     if value is None:
         return value
     return semver.parse_version_info(value)
Exemplo n.º 35
0
def bump_version_command():
    """Increment the version number immediately after checking out a release branch."""

    __author__ = "Shawn Davis <*****@*****.**>"
    __date__ = "2018-01-29"
    __help__ = """NOTES

This command is based upon [Semantic Versioning](http://semver.org)

If you omit the ``project_name`` then ``bumpversion`` will attempt to locate the ``VERSION.txt`` file to determine the
current project name.

The ``version.py`` file will also be updated if you specify the ``--path``. Or you may configure this by adding a 
``.bumpversion.cfg`` file to project root:

    version_path = source/main/version.py

This would cause version info to be written to the given path without using the ``--path`` switch.

When ``--path`` or ``.bumpversion.cfg``, the file is created if it does not exist. However, the full path to the file
must be present; it is not created for you.

    """
    __version__ = "0.17.0-d"

    # Define options and arguments.
    parser = ArgumentParser(description=__doc__, epilog=__help__, formatter_class=RawDescriptionHelpFormatter)

    parser.add_argument(
        "-b=",
        "--build=",
        dest="build_name",
        help="An optional build name."
    )

    parser.add_argument(
        "-M",
        "--major",
        action="store_true",
        dest="major_version",
        help="Bumping the major version resets the minor and patch level."
    )

    parser.add_argument(
        "-m",
        "--minor",
        action="store_true",
        dest="minor_version",
        help="Bumping the minor version resets the patch level."
    )

    parser.add_argument(
        "-p",
        "--patch",
        action="store_true",
        dest="patch_level",
        help="Bump the patch level."
    )

    parser.add_argument(
        "--path=",
        dest="version_path",
        help="Path to version.py file. See NOTES."
    )

    parser.add_argument(
        "--preview",
        action="store_true",
        dest="preview",
        help="Preview the changes."
    )

    parser.add_argument(
        "-s=",
        "--status=",
        dest="status",
        help="Set the status."
    )

    # Access to the version number requires special consideration, especially
    # when using sub parsers. The Python 3.3 behavior is different. See this
    # answer: http://stackoverflow.com/questions/8521612/argparse-optional-subparser-for-version
    # parser.add_argument('--version', action='version', version='%(prog)s 2.0')
    parser.add_argument(
        "-v",
        action="version",
        help="Show version number and exit.",
        version=__version__
    )
    parser.add_argument(
        "--version",
        action="version",
        help="Show verbose version information and exit.",
        version="%(prog)s" + " %s %s by %s" % (__version__, __date__, __author__)
    )

    # This will display help or input errors as needed.
    args = parser.parse_args()
    # print args

    # Load the current version.
    try:
        with open("VERSION.txt", "rb") as f:
            current_version = f.read()
            current_version = current_version.strip()
            f.close()
    except IOError:
        current_version = "0.1.0-d"

    # Just display the current version if no changes are requested.
    actions = [args.build_name or False, args.major_version, args.minor_version, args.patch_level, args.status or False]
    count = 0
    for a in actions:
        if a:
            count += 1

    if count == 0:
        print("Current Version: %s" % current_version)
        sys.exit(EXIT_OK)

    # Get the version instance.
    version = Version(current_version)

    # Use args to update the version.
    new_version = version.bump(
        major=args.major_version,
        minor=args.minor_version,
        patch=args.patch_level,
        status=args.status,
        build=args.build_name
    )

    # Preview and write out the new version.
    print("%-30s %-30s" % ("Bump", "To"))
    print("%-30s %-30s" % (current_version, new_version))

    if not args.preview:
        with open("VERSION.txt", "wb") as f:
            f.write(new_version)
            f.close()

        if args.version_path:
            version_py = args.version_path
        elif os.path.exists(".bumpversion.cfg"):
            config = load_simple_config(".bumpversion.cfg")
            version_py = config.get("version_path")
        else:
            version_py = None

        if version_py is not None:
            info = semver.parse_version_info(new_version)

            try:
                with open(version_py, "wb") as f:
                    f.write("# created by bumpversion from python-projectutils\n")

                    if info.build:
                        f.write('build = "%s"\n' % info.build)
                    else:
                        f.write('build = None\n')

                    f.write('major = %s\n' % info.major)
                    f.write('minor = %s\n' % info.minor)
                    f.write('patch = %s\n' % info.patch)

                    if info.prerelease:
                        f.write('status = "%s"\n' % info.prerelease)
                    else:
                        f.write('status = None\n')

                    f.write('version = "%s"\n' % new_version)

                    f.close()
            except IOError as e:
                print(e.message)

    # Quit.
    sys.exit(EXIT_OK)
Exemplo n.º 36
0
    def _get_expected_versions(self, components):
        """
        This method assigns a version to each component. That version can be used later to construct URIs for
        containers in GCR, locations of cloud function code, etc.

        If a released version is specified (e.g. 0.0.1) that is validated in github and, if present, used. If not
        found in github, it will not be used.

        If "latest" is specified then github is interrogated and the tag with the highest version number is extracted
        and used.

        If a prerelease version string (as defined by semver) is used, that is allowed through without github validation

        :param components: The list of components to assign versions to
        :return: A list of (component, version) tuples. version will None if none could be retrieved or validated
                """
        result = []

        available_versions = self._get_available_versions(components)
        for component in components:
            if not component.has_code_version:
                result.append((component, constants.NO_CODE_VERSION))
                continue

            tag_name = component.git_tag_name

            if tag_name not in available_versions:
                logging.warn(
                    'Component type %s (tag name %s) not found in %s/%s/%s!',
                    component.type, tag_name, git.ETSY_GITHUB_HOST,
                    component.code_repo_owner, component.code_repo)
                result.append((component, None))
                continue

            component_versions = available_versions[tag_name]

            if component.code_version in component_versions:
                result.append((component, component.code_version))
                continue

            if component.code_version_is_latest:
                result.append((component, component_versions[-1]))
                continue

            try:
                if semver.parse_version_info(
                        component.code_version).prerelease:
                    result.append((component, component.code_version))
                    continue
            except ValueError:
                # Just warn here to let the deploy process continue. The component won't have a version and therefore
                # won't be deployable, but other components can continue. This check must be after the check for
                # `latest` because that is a valid, non-semver identifier.
                logging.warn('Component %s has an invalid version', component)

            logging.warn(
                'Component %s (tag name %s) not available in %s/%s/%s!',
                component, tag_name, git.ETSY_GITHUB_HOST,
                component.code_repo_owner, component.code_repo)
            result.append((component, None))

        return result
Exemplo n.º 37
0
    def parse(self, folder, pattern=False, home={}):
        """
        returns dict with information
        home contains parsed plugins from pyload.

        {
        name : {path, version, config, (pattern, re), (plugin, class)}
        }

        """
        plugins = {}
        if home:
            pfolder = os.path.join(self.pyload.userdir, "plugins", folder)
            os.makedirs(pfolder, exist_ok=True)
            try:
                file = open(os.path.join(pfolder, "__init__.py"), mode="wb")
                file.close()
            except Exception:
                pass
        else:
            pfolder = os.path.join(PKGDIR, "plugins", folder)

        configs = {}
        for entry in os.listdir(pfolder):
            if (
                os.path.isfile(os.path.join(pfolder, entry)) and entry.endswith(".py")
            ) and not entry.startswith("_"):

                with open(os.path.join(pfolder, entry)) as data:
                    content = data.read()

                name = entry[:-3]
                if name[-1] == ".":
                    name = name[:-4]

                m_pyver = self._PYLOAD_VERSION.search(content)
                if m_pyver is None:
                    self.pyload.log.debug(
                        f"__pyload_version__ not found in plugin {name}"
                    )
                else:
                    pyload_version = m_pyver.group(1)

                    requires_version = f"{pyload_version}.0"
                    requires_version_info = semver.parse_version_info(requires_version)

                    if self.pyload.version_info.major:
                        core_version = self.pyload.version_info.major
                        plugin_version = requires_version_info.major
                    else:
                        core_version = self.pyload.version_info.minor
                        plugin_version = requires_version_info.minor

                    if core_version > plugin_version:
                        self.pyload.log.warning(
                            self._(
                                "Plugin {} not compatible with current pyLoad version"
                            ).format(name)
                        )
                        continue

                m_ver = self._VERSION.search(content)
                if m_ver is None:
                    self.pyload.log.debug(f"__version__ not found in plugin {name}")
                    version = 0
                else:
                    version = float(m_ver.group(1))

                # home contains plugins from pyload root
                if isinstance(home, dict) and name in home:
                    if home[name]["v"] >= version:
                        continue

                plugins[name] = {}
                plugins[name]["v"] = version

                module = entry.replace(".pyc", "").replace(".py", "")

                # the plugin is loaded from user directory
                plugins[name]["user"] = True if home else False
                plugins[name]["name"] = module
                plugins[name]["folder"] = folder

                if pattern:
                    m_pat = self._PATTERN.search(content)
                    pattern = r"^unmachtable$" if m_pat is None else m_pat.group(1)

                    plugins[name]["pattern"] = pattern

                    try:
                        plugins[name]["re"] = re.compile(pattern)
                    except Exception:
                        self.pyload.log.error(
                            self._("{} has a invalid pattern").format(name)
                        )

                # internals have no config
                if folder == "base":
                    self.pyload.config.delete_config(name)
                    continue

                m_desc = self._DESC.search(content)
                desc = "" if m_desc is None else m_desc.group(1)

                config = self._CONFIG.findall(content)
                if not config:
                    new_config = {"enabled": ["bool", "Activated", False], "desc": desc}
                    configs[name] = new_config
                    continue

                config = literal_eval(
                    config[0].strip().replace("\n", "").replace("\r", "")
                )

                if isinstance(config, list) and all(
                    isinstance(c, tuple) for c in config
                ):
                    config = {x[0]: x[1:] for x in config}
                else:
                    self.pyload.log.error(
                        self._("Invalid config in {}: {}").format(name, config)
                    )
                    continue

                if folder == "addons" and "enabled" not in config:
                    config["enabled"] = ["bool", "Activated", False]

                config["desc"] = desc
                configs[name] = config

        if not home:
            temp_plugins, temp_configs = self.parse(folder, pattern, plugins or True)
            plugins.update(temp_plugins)
            configs.update(temp_configs)

        return plugins, configs
Exemplo n.º 38
0
def changelog(ctx, check, version, old_version, initial, quiet, dry_run,
              output_file, tag_prefix):
    """Perform the operations needed to update the changelog.

    This method is supposed to be used by other tasks and not directly.
    """
    if check and check not in get_valid_checks():
        abort(f'Check `{check}` is not an Agent-based Integration')

    # sanity check on the version provided
    cur_version = old_version or get_version_string(check,
                                                    tag_prefix=tag_prefix)
    if parse_version_info(version.replace(
            tag_prefix, '', 1)) <= parse_version_info(
                cur_version.replace(tag_prefix, '', 1)):
        abort(f'Current version is {cur_version}, cannot bump to {version}')

    if not quiet:
        echo_info(
            f'Current version of check {check}: {cur_version}, bumping to: {version}'
        )

    # get the name of the current release tag
    target_tag = get_release_tag_string(check, cur_version)

    # get the diff from HEAD
    diff_lines = get_commits_since(check, None if initial else target_tag)

    # for each PR get the title, we'll use it to populate the changelog
    pr_numbers = parse_pr_numbers(diff_lines)
    if not quiet:
        echo_info(
            f'Found {len(pr_numbers)} PRs merged since tag: {target_tag}')

    if initial:
        # Only use the first one
        del pr_numbers[:-1]

    user_config = ctx.obj
    entries = []
    for pr_num in pr_numbers:
        try:
            payload = get_pr(pr_num, user_config)
        except Exception as e:
            echo_failure(f'Unable to fetch info for PR #{pr_num}: {e}')
            continue

        changelog_labels = get_changelog_types(payload)

        if not changelog_labels:
            abort(
                f'No valid changelog labels found attached to PR #{pr_num}, please add one!'
            )
        elif len(changelog_labels) > 1:
            abort(
                f'Multiple changelog labels found attached to PR #{pr_num}, please only use one!'
            )

        changelog_type = changelog_labels[0]
        if changelog_type == CHANGELOG_TYPE_NONE:
            if not quiet:
                # No changelog entry for this PR
                echo_info(f'Skipping PR #{pr_num} from changelog due to label')
            continue

        author = payload.get('user', {}).get('login')
        author_url = payload.get('user', {}).get('html_url')
        title = f"[{changelog_type}] {payload.get('title')}"

        entry = ChangelogEntry(pr_num, title, payload.get('html_url'), author,
                               author_url, from_contributor(payload))

        entries.append(entry)

    # store the new changelog in memory
    new_entry = StringIO()

    # the header contains version and date
    header = f"## {version} / {datetime.utcnow().strftime('%Y-%m-%d')}\n"
    new_entry.write(header)

    # one bullet point for each PR
    new_entry.write('\n')
    for entry in entries:
        thanks_note = ''
        if entry.from_contributor:
            thanks_note = f' Thanks [{entry.author}]({entry.author_url}).'
        new_entry.write(
            f'* {entry.title}. See [#{entry.number}]({entry.url}).{thanks_note}\n'
        )
    new_entry.write('\n')

    # read the old contents
    if check:
        changelog_path = os.path.join(get_root(), check, output_file)
    else:
        changelog_path = os.path.join(get_root(), output_file)
    old = list(stream_file_lines(changelog_path))

    # write the new changelog in memory
    changelog_buffer = StringIO()

    # preserve the title
    changelog_buffer.write(''.join(old[:2]))

    # prepend the new changelog to the old contents
    # make the command idempotent
    if header not in old:
        changelog_buffer.write(new_entry.getvalue())

    # append the rest of the old changelog
    changelog_buffer.write(''.join(old[2:]))

    # print on the standard out in case of a dry run
    if dry_run:
        echo_info(changelog_buffer.getvalue())
    else:
        # overwrite the old changelog
        write_file(changelog_path, changelog_buffer.getvalue())