Skip to content

Commit

Permalink
Merge pull request #313 from camptocamp/fix
Browse files Browse the repository at this point in the history
Versions: fixies, see commits
  • Loading branch information
sbrunner authored Jun 4, 2024
2 parents 543b10f + 616f051 commit d2d2bcd
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 50 deletions.
1 change: 1 addition & 0 deletions VERSIONS-CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Properties

- **`additional-packages`** _(object)_: The additional packages to be added to the versions.
- **`external-packages`** _(array)_

- **Items** _(object)_: Cannot contain additional properties.
Expand Down
33 changes: 21 additions & 12 deletions github_app_geo_project/module/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,6 @@ def git_clone(github_project: configuration.GithubProject, branch: str) -> bool:

def get_stabilization_branch(security: c2cciutils.security.Security) -> list[str]:
"""Get the stabilization versions."""
alternate_index = security.headers.index("Alternate Tag") if "Alternate Tag" in security.headers else -1
version_index = security.headers.index("Version") if "Version" in security.headers else -1
supported_until_index = (
security.headers.index("Supported Until") if "Supported Until" in security.headers else -1
Expand All @@ -632,23 +631,33 @@ def get_stabilization_branch(security: c2cciutils.security.Security) -> list[str
_LOGGER.warning("No Supported Until column in the SECURITY.md")
return []

alternate = []
if alternate_index >= 0:
for row in security.data:
if row[alternate_index]:
alternate.append(row[alternate_index])

versions = []
for row in security.data:
if row[supported_until_index] != "Unsupported":
if alternate:
if row[alternate_index] not in alternate:
versions.append(row[version_index])
else:
versions.append(row[version_index])
versions.append(row[version_index])
return versions


def get_alternate_versions(security: c2cciutils.security.Security, branch: str) -> list[str]:
"""Get the stabilization versions."""
alternate_index = security.headers.index("Alternate Tag") if "Alternate Tag" in security.headers else -1
version_index = security.headers.index("Version") if "Version" in security.headers else -1

if alternate_index < 0:
return []

if version_index < 0:
_LOGGER.warning("No Version column in the SECURITY.md")
return []

for row in security.data:
if row[version_index] == branch:
return [v.strip() for v in row[alternate_index].split(",") if v.strip()]

_LOGGER.warning("Branch %s not found in the SECURITY.md", branch)
return []


def manage_updated(status: dict[str, Any], key: str, days_old: int = 2) -> None:
"""
Manage the updated status.
Expand Down
95 changes: 59 additions & 36 deletions github_app_geo_project/module/versions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ class _DependenciesBranches(BaseModel):
class _EventData(BaseModel):
step: int
branch: str | None = None
alternate_versions: list[str] | None = None


class VersionException(Exception):
Expand Down Expand Up @@ -159,6 +160,7 @@ async def process(
key = f"{context.github_project.owner}/{context.github_project.repository}"
status = context.transversal_status.repositories.setdefault(key, _TransversalStatusRepo())
if context.module_event_data.step == 1:
_apply_additional_packages(context)
status.url = (
f"https://github.com/{context.github_project.owner}/{context.github_project.repository}"
)
Expand Down Expand Up @@ -196,11 +198,11 @@ async def process(

else:
_LOGGER.debug("No SECURITY.md file in the repository, apply on default branch")
stabilization_branch = [repo.default_branch]
status.versions.setdefault(
repo.default_branch,
_TransversalStatusVersion(support="Best effort"),
).support = "Best effort"
stabilization_branch.append(repo.default_branch)
status.versions.setdefault(
repo.default_branch,
_TransversalStatusVersion(support="Best effort"),
).support = "Best effort"
_LOGGER.debug("Versions: %s", ", ".join(stabilization_branch))

versions = status.versions
Expand All @@ -210,7 +212,16 @@ async def process(

actions = []
for branch in stabilization_branch:
actions.append(module.Action(data=_EventData(step=2, branch=branch), title=branch))
actions.append(
module.Action(
data=_EventData(
step=2,
branch=branch,
alternate_versions=module_utils.get_alternate_versions(security, branch),
),
title=branch,
)
)
return ProcessOutput(actions=actions, transversal_status=context.transversal_status)
if context.module_event_data.step == 2:
assert context.module_event_data.branch is not None
Expand All @@ -222,6 +233,10 @@ async def process(
raise VersionException("Failed to clone the repository")

version_status = status.versions[context.module_event_data.branch]
for alternate in context.module_event_data.alternate_versions or []:
status.versions[alternate] = version_status
for datasource_data in version_status.names_by_datasource.values():
datasource_data.names = list(set(datasource_data.names))
transversal_status = context.transversal_status

_get_names(context, version_status.names_by_datasource, context.module_event_data.branch)
Expand Down Expand Up @@ -430,32 +445,30 @@ def _get_names(
if match.group(1) not in names:
names.append(match.group(1))

if os.path.exists("ci/config.yaml"):
with open("ci/config.yaml", encoding="utf-8") as file:
data = yaml.load(file, Loader=yaml.SafeLoader)
docker_config = data.get("publish", {}).get("docker", {})
if docker_config:
names = names_by_datasource.setdefault("docker", _TransversalStatusNameByDatasource()).names
for conf in docker_config.get("images", []):
for tag in conf.get("tags", ["{version}"]):
for repository_conf in docker_config.get(
"repository", c2cciutils.configuration.DOCKER_REPOSITORY_DEFAULT
).values():
repository_server = repository_conf.get("server", False)
add_names = []
if repository_server:
add_names.append(
f"{repository_server}/{conf.get('name')}:{tag.format(version=branch)}"
)
data = c2cciutils.get_config()
docker_config = data.get("publish", {}).get("docker", {})
if docker_config:
names = names_by_datasource.setdefault("docker", _TransversalStatusNameByDatasource()).names
for conf in docker_config.get("images", []):
for tag in conf.get("tags", ["{version}"]):
for repository_conf in docker_config.get(
"repository", c2cciutils.configuration.DOCKER_REPOSITORY_DEFAULT
).values():
repository_server = repository_conf.get("server", False)
add_names = []
if repository_server:
add_names.append(
f"{repository_server}/{conf.get('name')}:{tag.format(version=branch)}"
)

else:
add_names = [
f"{conf.get('name')}:{tag.format(version=branch)}",
f"docker.io/{conf.get('name')}:{tag.format(version=branch)}",
]
for add_name in add_names:
if add_name not in names:
names.append(add_name)
else:
add_names = [
f"{conf.get('name')}:{tag.format(version=branch)}",
f"docker.io/{conf.get('name')}:{tag.format(version=branch)}",
]
for add_name in add_names:
if add_name not in names:
names.append(add_name)

for filename in subprocess.run( # nosec
["git", "ls-files", "package.json", "*/package.json"],
Expand Down Expand Up @@ -695,15 +708,17 @@ def _build_internal_dependencies(
)
for datasource_name, dependencies_data in version_data.dependencies_by_datasource.items():
for dependency_name, dependency_versions in dependencies_data.versions_by_names.items():
if datasource_name not in names.by_datasources:
continue
for dependency_version in dependency_versions.versions:
if datasource_name not in names.by_datasources:
continue
dependency_data = names.by_datasources[datasource_name]
if datasource_name == "docker":
dependency_name = f"{dependency_name}:{dependency_version}"
if dependency_name not in dependency_data.by_package:
full_dependency_name = f"{dependency_name}:{dependency_version}"
else:
full_dependency_name = dependency_name
if full_dependency_name not in dependency_data.by_package:
continue
dependency_package_data = dependency_data.by_package[dependency_name]
dependency_package_data = dependency_data.by_package[full_dependency_name]
dependency_minor = _canonical_minor_version(datasource_name, dependency_version)
support = dependency_package_data.status_by_version.get(
dependency_minor,
Expand Down Expand Up @@ -790,3 +805,11 @@ def _build_reverse_dependency(
repo=other_repo,
)
)


def _apply_additional_packages(
context: module.ProcessContext[configuration.VersionsConfiguration, _EventData, _TransversalStatus],
) -> None:
for repo, data in context.module_config.get("additional-packages", {}).items():
pydentic_data = _TransversalStatusRepo(**data)
context.transversal_status.repositories[repo] = pydentic_data
4 changes: 3 additions & 1 deletion github_app_geo_project/module/versions/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
Automatically generated file from a JSON schema.
"""

from typing import TypedDict
from typing import Any, TypedDict

from typing_extensions import Required

# Versions configuration.
VersionsConfiguration = TypedDict(
"VersionsConfiguration",
{
# The additional packages to be added to the versions
"additional-packages": dict[str, Any],
# examples:
# - datasource: pypi
# package: python
Expand Down
4 changes: 4 additions & 0 deletions github_app_geo_project/module/versions/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
"additionalProperties": false,

"properties": {
"additional-packages": {
"type": "object",
"description": "The additional packages to be added to the versions"
},
"external-packages": {
"type": "array",
"examples": [
Expand Down
69 changes: 68 additions & 1 deletion tests/test_module_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def test_get_transversal_dashboard_repo_forward_docker() -> None:
support="Best effort",
forward=[
_Dependency(
name="camptocamp/other:2.0",
name="camptocamp/other",
datasource="docker",
version="2.0",
support="Best effort",
Expand All @@ -273,6 +273,73 @@ def test_get_transversal_dashboard_repo_forward_docker() -> None:
)


def test_get_transversal_dashboard_repo_forward_docker_double() -> None:
versions = Versions()
context = Mock()
context.status = _TransversalStatus(
repositories={
"camptocamp/test": _TransversalStatusRepo(
versions={
"1.0": _TransversalStatusVersion(
support="Best effort",
dependencies_by_datasource={
"docker": _TransversalStatusNameInDatasource(
versions_by_names={
"camptocamp/other": _TransversalStatusVersions(versions=["1.0", "2.0"]),
}
)
},
)
},
),
"camptocamp/other": _TransversalStatusRepo(
versions={
"1.0": _TransversalStatusVersion(
support="Best effort",
names_by_datasource={
"docker": _TransversalStatusNameByDatasource(names=["camptocamp/other:1.0"])
},
),
"2.0": _TransversalStatusVersion(
support="Best effort",
names_by_datasource={
"docker": _TransversalStatusNameByDatasource(names=["camptocamp/other:2.0"])
},
),
},
),
}
)
context.params = {"repository": "camptocamp/test"}
output = versions.get_transversal_dashboard(context)
assert output.data["dependencies_branches"] == _DependenciesBranches(
by_branch={
"1.0": _Dependencies(
support="Best effort",
forward=[
_Dependency(
name="camptocamp/other",
datasource="docker",
version="1.0",
support="Best effort",
color="--bs-body-bg",
repo="camptocamp/other",
),
_Dependency(
name="camptocamp/other",
datasource="docker",
version="2.0",
support="Best effort",
color="--bs-body-bg",
repo="camptocamp/other",
),
],
reverse=[],
)
}
)


def test_get_transversal_dashboard_repo_forward_inexisting() -> None:
versions = Versions()
context = Mock()
Expand Down

0 comments on commit d2d2bcd

Please sign in to comment.