Skip to content

Commit

Permalink
Provide symlink updates in multiple files in one PR
Browse files Browse the repository at this point in the history
* Perform changes in multiple files in one PR
* Remove option symlink-conf-path
  • Loading branch information
andreas-el authored Aug 14, 2024
1 parent 7b9b35a commit dd4caf1
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 89 deletions.
81 changes: 42 additions & 39 deletions komodo/symlink/suggester/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger(__name__)

PR_TEMPLATE = """:robot: Suggesting updating {platform} {mode} to {release} in {sym_file}
PR_TEMPLATE = """:robot: Suggesting updating {mode} to {release}
---
### Description
- Release: `{release}`
- Platform: `{platform}`
- Link type: `{mode}`
- When: `{now}`
Expand All @@ -39,11 +38,6 @@ def _parse_args():
parser.add_argument("mode", help="stable,testing")
parser.add_argument("joburl", help="link to the job that triggered this")
parser.add_argument("jobname", help="name of the job")
parser.add_argument(
"--symlink-conf-path",
help="",
default="symlink_configuration/symlink_config.json",
)
parser.add_argument("--git-fork", help="git fork", default="equinor")
parser.add_argument("--git-repo", help="git repo", default="komodo-releases")
parser.add_argument("--git-ref", help="git ref", default="main")
Expand All @@ -58,6 +52,12 @@ def _parse_args():
help="Set dry-run, will do everything except making the PR",
action="store_true",
)
parser.add_argument("--python-versions", help="e.g. py38, py311", default="py311")
parser.add_argument(
"--config-files",
help="e.g. symlink_config.json, symlink_config_azure.json",
default="symlink_configuration/symlink_config.json",
)
return parser.parse_args()


Expand All @@ -78,55 +78,58 @@ def suggest_symlink_configuration(
"""Returns a pull request if the symlink configuration could be updated,
or None if no update was possible.
"""
try:
sym_conf_content = repo.get_contents(args.symlink_conf_path, ref=args.git_ref)
except UnknownObjectException:
sys.exit(f"Filename {args.symlink_conf_path} is not in repo {repo.full_name}")
config_files = args.config_files.split(",")
python_versions = args.python_versions.split(",")

if args.release.startswith("bleeding"):
logger.warning("Symlink to bleeding is not allowed")
return None

try:
new_symlink_content, updated = configuration.update(
b64decode(sym_conf_content.content),
args.release,
args.mode,
)
except ValueError as exc:
logger.critical(exc)
sys.exit(1)

if not updated:
logger.info("Nothing to update")
return None

platform = "azure" if "azure" in args.symlink_conf_path else "onprem"

target_branch = f"{args.release}/{platform}-{args.mode}"

target_branch = f"{args.release}/{args.mode}"
from_sha = repo.get_branch(args.git_ref).commit.sha
msg = f"Update {args.mode} symlinks for {args.release}"

msg = f"Update {platform} {args.mode} symlinks for {args.release}"
if not dry_run:
repo.create_git_ref(ref=f"refs/heads/{target_branch}", sha=from_sha)
repo.update_file(
args.symlink_conf_path,
msg,
new_symlink_content,
sym_conf_content.sha,
branch=target_branch,
)

for symlink_config_file in config_files:
symlink_config_file = symlink_config_file.strip()
try:
sym_conf_content = repo.get_contents(symlink_config_file, ref=args.git_ref)
except UnknownObjectException:
sys.exit(f"Filename {symlink_config_file} is not in repo {repo.full_name}")

try:
new_symlink_content, updated = configuration.update(
b64decode(sym_conf_content.content),
args.release,
args.mode,
python_versions,
)
except ValueError as exc:
logger.critical(exc)
sys.exit(1)

if not updated:
logger.info("Nothing to update")
return None

if not dry_run:
repo.update_file(
symlink_config_file,
msg,
new_symlink_content,
sym_conf_content.sha,
branch=target_branch,
)

body = PR_TEMPLATE.format(
sym_file=args.symlink_conf_path,
change=target_branch,
release=args.release,
mode=args.mode,
now=datetime.now(),
job_url=args.joburl,
job_name=args.jobname,
platform=platform,
)

if dry_run:
Expand Down
89 changes: 50 additions & 39 deletions komodo/symlink/suggester/configuration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from typing import Tuple
from typing import List, Tuple

from komodo.symlink.suggester.release import Release

Expand All @@ -18,38 +18,42 @@ def _get_concrete_release(self, link):
release = Release(self.links[repr(release)])
return release

def update(self, release, mode):
link = f"{mode}-{release.py_ver()}"
link_exists = link in self.links
linked_release = self._get_concrete_release(link) if link_exists else None

if mode == "testing":
stable_link = f"stable-{release.py_ver()}"
stable = (
self._get_concrete_release(stable_link)
if stable_link in self.links
else None
)
linked = self.links.get(link, None)

# ripe is when stable is -1 month ago, ours is that the handle
# already points to a release in the same month
# if no stable, then it is ripe
handle_ripe = stable.monthly_diff(release) <= -1 if stable else True
handle_ours = link_exists and linked_release.monthly_diff(release) == 0
if handle_ripe or handle_ours:
# i.e. if the linked release is a month alias
if linked and not Release(linked).is_concrete():
self.links[release.month_alias()] = repr(release)
self.links[link] = release.month_alias()
else:
self.links[link] = repr(release)
elif mode == "stable":
self.links[release.month_alias()] = repr(release)
self.links[link] = release.month_alias()
else:
msg = f"Mode {mode} was not recognized"
raise ValueError(msg)
def update(self, release, mode, python_versions: List[str]):
for python_version in python_versions:
python_version = python_version.strip()
release.set_python_version(python_version)

link = f"{mode}-{python_version}"
link_exists = link in self.links
linked_release = self._get_concrete_release(link) if link_exists else None

if mode == "testing":
stable_link = f"stable-{python_version}"
stable = (
self._get_concrete_release(stable_link)
if stable_link in self.links
else None
)
linked = self.links.get(link, None)

# ripe is when stable is -1 month ago, ours is that the handle
# already points to a release in the same month
# if no stable, then it is ripe
handle_ripe = stable.monthly_diff(release) <= -1 if stable else True
handle_ours = link_exists and linked_release.monthly_diff(release) == 0
if handle_ripe or handle_ours:
# i.e. if the linked release is a month alias
if linked and not Release(linked).is_concrete():
self.links[release.month_alias()] = repr(release)
self.links[link] = release.month_alias()
else:
self.links[link] = repr(release)
elif mode == "stable":
self.links[release.month_alias()] = repr(release)
self.links[link] = release.month_alias()
else:
msg = f"Mode {mode} was not recognized"
raise ValueError(msg)

def to_json(self, json_kwargs):
return json.dumps(self.conf, **json_kwargs)
Expand All @@ -59,17 +63,24 @@ def from_json(conf_json_str):
return Configuration(json.loads(conf_json_str))


def update(symlink_configuration, release_id, mode) -> Tuple[str, bool]:
def update(
symlink_configuration, release_id, mode, python_versions: List[str] = None
) -> Tuple[str, bool]:
"""Return a tuple of a string representing the new symlink config json,
and whether or not an update was made. This function assumes the release_id
is in the yyyy.mm.[part ...]-py[\\d+] format and that symlink_configuration
is a string representing the current symlink config json.
and whether an update was made. This function assumes the release_id
is in the yyyy.mm.[part ...] format and will look for python suffix (-py38, -py311)
if no python_versions are passed. Symlink_configuration shall be a string
representing the current symlink config json.
"""
json_kwargs = {"sort_keys": True, "indent": 4, "separators": (",", ": ")}
release = Release(release_id)

id_parts = release_id.split("-")
release = Release(id_parts[0])
if not python_versions:
python_versions = [part for part in id_parts[1:] if "py" in part][:1]

configuration = Configuration.from_json(symlink_configuration)
configuration.update(release, mode)
configuration.update(release, mode, python_versions)

new_json_str = configuration.to_json(json_kwargs)
old_json_str = json.dumps(json.loads(symlink_configuration), **json_kwargs)
Expand Down
3 changes: 3 additions & 0 deletions komodo/symlink/suggester/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def __init__(self, release_id: str) -> None:
def __repr__(self) -> str:
return self.release_id

def set_python_version(self, python_version: str) -> None:
self.release_id = self.release_id.split("-")[0] + "-" + python_version

def month(self) -> str:
return self.release_id[0:7]

Expand Down
Loading

0 comments on commit dd4caf1

Please sign in to comment.