Skip to content

Commit

Permalink
Merge c42e205 into 8bbd737
Browse files Browse the repository at this point in the history
  • Loading branch information
mvidalgarcia committed Aug 7, 2020
2 parents 8bbd737 + c42e205 commit f5177c2
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 36 deletions.
133 changes: 97 additions & 36 deletions reana/reana_dev/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
)
from reana.reana_dev.utils import (
display_message,
fetch_latest_pypi_version,
get_srcdir,
run_command,
select_components,
update_module_in_cluster_components,
)


Expand Down Expand Up @@ -676,7 +678,7 @@ def git_push(component): # noqa: D301
run_command(cmd, component)


@git_commands.command(name="git-shared-modules-upgrade")
@git_commands.command(name="git-upgrade-all-shared-modules")
@click.option(
"--commit-and-publish",
is_flag=True,
Expand All @@ -686,33 +688,11 @@ def git_push(component): # noqa: D301
' "installation: shared packages version bump" message will'
" be created for all affected CLUSTER components.",
)
def git_shared_modules_upgrade(commit_and_publish):
"""Upgrade all cluster components to latest REANA-Commons version."""
def git_upgrade_all_shared_modules(commit_and_publish):
"""Upgrade all cluster components to latest REANA-Commons/DB version.
def _fetch_latest_pypi_version(package):
"""Fetch latest released version of a package."""
import requests

pypi_rc_info = requests.get(
"https://pypi.python.org/pypi/{}/json".format(package)
)
return sorted(pypi_rc_info.json()["releases"].keys())[-1]

def _update_module_in_cluster_components(module, new_version):
"""Update the specified module version in all affected components."""
components_to_update = {
"reana-commons": COMPONENTS_USING_SHARED_MODULE_COMMONS,
"reana-db": COMPONENTS_USING_SHARED_MODULE_DB,
}
for component in components_to_update[module]:
update_setup_py_dep_cmd = (
'LN=`cat setup.py | grep -n -e "{module}.*>=" | cut -f1 -d: `'
'&& sed -i.bk "`echo $LN`s/>=.*,</>={new_version},</" '
"setup.py && rm setup.py.bk".format(
module=module, new_version=new_version
)
)
run_command(update_setup_py_dep_cmd, component)
Optionally create commits and PRs in all components bumping version.
"""

def _commit_and_publish_version_bumps(components):
"""Create commit and version bump PRs for all specified components."""
Expand Down Expand Up @@ -743,15 +723,8 @@ def _commit_and_publish_version_bumps(components):
).union(set(COMPONENTS_USING_SHARED_MODULE_COMMONS))

for module in REPO_LIST_SHARED:
last_version = _fetch_latest_pypi_version(module)
_update_module_in_cluster_components(module, last_version)
click.secho(
"✅ {module} updated to: {last_version}".format(
module=module, last_version=last_version
),
bold=True,
fg="green",
)
last_version = fetch_latest_pypi_version(module)
update_module_in_cluster_components(module, last_version)

if commit_and_publish:
click.secho("Creating version bump commits and pull requests...")
Expand All @@ -767,4 +740,92 @@ def _commit_and_publish_version_bumps(components):
)


@git_commands.command(name="git-upgrade-shared-modules")
@click.option(
"--component",
"-c",
multiple=True,
default=["CLUSTER", "CLIENT"],
help="Which components? [shortname|name|.|CLUSTER|ALL]",
)
@click.option(
"--use-latest-known-tag",
is_flag=True,
default=False,
help="Should the upgrade use the latest known tag of the shared modules?"
" If so, the latest known tag of the shared modules will be used to upgrade the"
" provided components. Else, the upgrade will only occur if the latest commit of the"
" shared modules points at a tag, in other case, the command will be aborted.",
)
@click.option(
"--create-new-version-bump-commit",
is_flag=True,
default=False,
help="Should version bump changes be included in a separate commit?"
' If so, a new commit with "installation: bump shared modules" message will'
" be created for the provided components. Else, changes will be integrated"
" in the latest commit of each component.",
)
@click.pass_context
def git_upgrade_shared_modules(
ctx, component, use_latest_known_tag, create_new_version_bump_commit
): # noqa: D301
"""Upgrade selected components to latest REANA-Commons/DB version.
\b
:param components: The option ``component`` can be repeated. The value may
consist of:
* (1) standard component name such as
'reana-workflow-controller';
* (2) short component name such as 'r-w-controller';
* (3) special value '.' indicating component of the
current working directory;
* (4) special value 'CLUSTER' that will expand to
cover all REANA cluster components [default];
* (5) special value 'CLIENT' that will expand to
cover all REANA client components;
* (6) special value 'DEMO' that will expand
to include several runable REANA demo examples;
* (7) special value 'ALL' that will expand to include
all REANA repositories.
:type component: str
"""

def _create_commit_or_amend(components):
for component in components:
commit_cmd = "git commit --amend --no-edit"
if create_new_version_bump_commit:
commit_cmd = 'git commit -m "installation: bump shared modules"'

run_command(
f"git add setup.py requirements.txt && {commit_cmd}", component,
)

def _push_to_origin(components):
for component in components:
branch = run_command(
"git branch --show-current", component, return_output=True
)
run_command(
f"git push --force origin {branch}", component,
)

components = select_components(component)

for module in REPO_LIST_SHARED:
last_version = fetch_latest_pypi_version(module)
update_module_in_cluster_components(
module,
last_version,
components_to_update=components,
use_latest_known_tag=use_latest_known_tag,
force_feature_branch=True,
)

_create_commit_or_amend(components)
ctx.invoke(git_diff, component=component)
if click.confirm("Do you want to push your feature branches?"):
_push_to_origin(components)


git_commands_list = list(git_commands.commands.values())
122 changes: 122 additions & 0 deletions reana/reana_dev/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import click

from reana.config import (
COMPONENTS_USING_SHARED_MODULE_COMMONS,
COMPONENTS_USING_SHARED_MODULE_DB,
REPO_LIST_ALL,
REPO_LIST_CLIENT,
REPO_LIST_CLUSTER,
Expand Down Expand Up @@ -335,3 +337,123 @@ def get_prefixed_component_name(component):
:return: Prefixed name.
"""
return "-".join([INSTANCE_NAME, component])


def fetch_latest_pypi_version(package):
"""Fetch latest released version of a package."""
import requests

pypi_rc_info = requests.get("https://pypi.python.org/pypi/{}/json".format(package))
return sorted(pypi_rc_info.json()["releases"].keys())[-1]


def is_last_commit_tagged(package):
"""Check whether the last commit of the module points at a tag."""
tag = run_command("git tag --points-at", package, return_output=True)
return bool(tag)


def is_feature_branch(component):
"""Check whether component current branch is different from master."""
return get_current_branch(get_srcdir(component)) != "master"


def replace_string(
file_=None, find=None, replace=None, line_selector_regex=None, component=None
):
"""Replace the old string with the new one in the specified file.
:param file_: filename where the replacement takes place
(e.g. 'setup.py', 'requirements.txt')
:param find: current string regex
:param replace: new string regex
:param line_selector_regex: grep expression to identify file line of the replacement
:param component: standard component name where to run the command
:type file_: str
:type find: str
:type replace: str
:type line_selector_regex: str
:type component: str
"""
line = ""
if line_selector_regex:
line = run_command(
f'cat {file_} | grep -n -e "{line_selector_regex}" | cut -f1 -d: ',
return_output=True,
)

cmd = (
f"sed -i.bk '{line}s/{find}/{replace}/' {file_} && [ -e {file_}.bk ]"
f" && rm {file_}.bk" # Compatibility with BSD sed
)

run_command(cmd, component)


def update_module_in_cluster_components(
module,
new_version,
components_to_update=None,
use_latest_known_tag=True,
force_feature_branch=False,
):
"""Update the specified module version in all affected components."""
updatable_components = {
"reana-commons": COMPONENTS_USING_SHARED_MODULE_COMMONS + ["reana-client"],
"reana-db": COMPONENTS_USING_SHARED_MODULE_DB,
}[module]

if components_to_update:
components_to_update = set(components_to_update).intersection(
set(updatable_components)
)
else:
components_to_update = updatable_components

if (
components_to_update
and not use_latest_known_tag
and not is_last_commit_tagged(module)
):
click.secho(
f"[ERROR] Last commit of {module} does not point to a tag."
" Use `--use-latest-known-tag` if you want to proceed using the latest"
" known tag.",
err=True,
fg="red",
),
sys.exit(1)

for component in components_to_update:
if force_feature_branch and not is_feature_branch(component):
click.secho(
f"[ERROR] Component {component} current branch is master."
" Must be a feature branch.",
err=True,
fg="red",
),
sys.exit(1)

replace_version_string(
file_="setup.py",
find=">=.*,<",
replace=f">={new_version},<",
line_selector_regex=f"{module}.*>=",
component=component,
)
replace_version_string(
file_="requirements.txt",
find="==.*#",
replace=f"=={new_version}\t#",
line_selector_regex=f"{module}.*==",
component=component,
)

if components_to_update:
click.secho(
"✅ {module} updated to: {last_version}".format(
module=module, last_version=new_version
),
bold=True,
fg="green",
)

0 comments on commit f5177c2

Please sign in to comment.