Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ packages:
repo: redis/redis-rpm
build_workflow: release_build_and_test.yml
build_inputs: {}
build_timeout_minutes: 45
publish_internal_release: yes
publish_workflow: release_publish.yml
publish_timeout_minutes: 10
Expand Down
8 changes: 2 additions & 6 deletions src/redis_release/bht/behaviours.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from redis_release.bht.state import reset_model_to_defaults

from ..github_client_async import GitHubClientAsync
from ..logging_config import log_once
from ..models import RedisVersion, ReleaseType, WorkflowConclusion, WorkflowStatus
from .logging_wrapper import PyTreesLoggerWrapper
from .state import Package, PackageMeta, ReleaseMeta, Workflow
Expand Down Expand Up @@ -53,10 +54,7 @@ def log_exception_and_return_failure(self, e: Exception) -> Status:
return Status.FAILURE

def log_once(self, key: str, container: Dict[str, bool]) -> bool:
if key not in container:
container[key] = True
return True
return False
return log_once(key, container)


class ReleaseAction(LoggingAction):
Expand Down Expand Up @@ -109,7 +107,6 @@ def initialise(self) -> None:
f"Parsed release version: {self.release_version.major}.{self.release_version.minor}"
)
except ValueError as e:
self.logger.error(f"Failed to parse release tag: {e}")
return

# List remote branches matching release pattern with major version
Expand Down Expand Up @@ -257,7 +254,6 @@ def initialise(self) -> None:
)
self.feedback_message = "failed to trigger workflow"
return
self.workflow.inputs["release_tag"] = self.release_meta.tag
ref = self.package_meta.ref if self.package_meta.ref is not None else "main"
if self.log_once(
"workflow_trigger_start", self.workflow.ephemeral.log_once_flags
Expand Down
133 changes: 116 additions & 17 deletions src/redis_release/bht/behaviours_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,100 @@

from py_trees.common import Status

from redis_release.bht.behaviours import LoggingAction, ReleaseAction
from redis_release.bht.state import PackageMeta, ReleaseMeta, Workflow
from redis_release.models import RedisVersion, ReleaseType
from ..models import RedisVersion, ReleaseType
from .behaviours import IdentifyTargetRef, LoggingAction, ReleaseAction
from .state import DockerMeta, ReleaseMeta, Workflow


class DockerWorkflowInputs(ReleaseAction):
"""
Docker uses only release_tag input which is set automatically in TriggerWorkflow
"""
class DockerBuildWorkflowInputs(ReleaseAction):
def __init__(
self,
name: str,
workflow: Workflow,
package_meta: DockerMeta,
release_meta: ReleaseMeta,
log_prefix: str = "",
) -> None:
self.workflow = workflow
self.package_meta = package_meta
self.release_meta = release_meta
self.release_version: Optional[RedisVersion] = None
super().__init__(name=name, log_prefix=log_prefix)

def initialise(self) -> None:
if self.release_meta.tag is None:
self.logger.error("Release tag is not set")
return
try:
self.release_version = RedisVersion.parse(self.release_meta.tag)
except ValueError as e:
self.logger.debug(f"Failed to parse release tag: {e}")
return

def update(self) -> Status:
# If version is not determined, assume we do want to build from tag
if self.release_version is not None:
self.workflow.inputs["run_type"] = "release"
else:
self.workflow.inputs["run_type"] = "custom"
if self.package_meta.module_versions:
self.workflow.inputs["run_type"] = "custom"
for module, version in self.package_meta.module_versions.items():
self.workflow.inputs[f"{module.value}_version"] = version

if self.release_meta.ephemeral.slack_channel_id is not None:
self.workflow.inputs["slack_channel_id"] = (
self.release_meta.ephemeral.slack_channel_id
)

if self.release_meta.ephemeral.slack_thread_ts is not None:
self.workflow.inputs["slack_thread_ts"] = (
self.release_meta.ephemeral.slack_thread_ts
)

if self.release_meta.tag is not None:
self.workflow.inputs["release_tag"] = self.release_meta.tag
if self.package_meta.release_type is not None:
self.workflow.inputs["release_type"] = self.package_meta.release_type.value

if self.log_once("workflow_inputs_set", self.workflow.ephemeral.log_once_flags):
self.logger.info(f"Workflow inputs set: {self.workflow.inputs}")

return Status.SUCCESS


class DockerPublishWorkflowInputs(ReleaseAction):
def __init__(
self,
name: str,
workflow: Workflow,
package_meta: PackageMeta,
package_meta: DockerMeta,
release_meta: ReleaseMeta,
log_prefix: str = "",
) -> None:
self.workflow = workflow
self.package_meta = package_meta
self.release_meta = release_meta
self.release_version: Optional[RedisVersion] = None
super().__init__(name=name, log_prefix=log_prefix)

def initialise(self) -> None:
pass

def update(self) -> Status:
if self.release_meta.ephemeral.slack_channel_id is not None:
self.workflow.inputs["slack_channel_id"] = (
self.release_meta.ephemeral.slack_channel_id
)

if self.release_meta.ephemeral.slack_thread_ts is not None:
self.workflow.inputs["slack_thread_ts"] = (
self.release_meta.ephemeral.slack_thread_ts
)

if self.log_once("workflow_inputs_set", self.workflow.ephemeral.log_once_flags):
self.logger.info(f"Workflow inputs set: {self.workflow.inputs}")

return Status.SUCCESS


Expand All @@ -35,7 +105,7 @@ class DetectReleaseTypeDocker(LoggingAction):
def __init__(
self,
name: str,
package_meta: PackageMeta,
package_meta: DockerMeta,
release_meta: ReleaseMeta,
log_prefix: str = "",
) -> None:
Expand All @@ -52,7 +122,14 @@ def initialise(self) -> None:
return
if self.release_meta.tag == "unstable":
return
self.release_version = RedisVersion.parse(self.release_meta.tag)
try:
self.release_version = RedisVersion.parse(self.release_meta.tag)
except ValueError as e:
if self.release_meta.tag != "":
self.logger.info(
f"Failed to parse release tag: {e}, assuming custom release with tag {self.release_meta.tag}"
)
return

def update(self) -> Status:
result: Status = Status.FAILURE
Expand All @@ -70,8 +147,9 @@ def update(self) -> Status:
f"Detected release type for docker: {self.package_meta.release_type}"
)
else:
self.feedback_message = "Failed to detect release type"
result = Status.FAILURE
self.package_meta.release_type = ReleaseType.INTERNAL
self.feedback_message = "Set release type to internal for custom build"
result = Status.SUCCESS

if self.log_once(
"release_type_detected", self.package_meta.ephemeral.log_once_flags
Expand All @@ -83,6 +161,27 @@ def update(self) -> Status:
return result


class IdentifyTargetRefDocker(IdentifyTargetRef):
def update(self) -> Status:
# If ref is already set, we're done
if self.package_meta.ref is not None:
self.logger.debug(f"Ref already set: {self.package_meta.ref}")
return Status.SUCCESS

if self.release_version is None:
self.package_meta.ref = "unstable"
if self.log_once(
"target_ref_identified", self.package_meta.ephemeral.log_once_flags
):
self.logger.info(
f"Version not parsed, assuming custom release, using {self.package_meta.ref} branch"
)
self.feedback_message = f"Target ref set to {self.package_meta.ref}"
return Status.SUCCESS

return super().update()


# Conditions


Expand All @@ -92,7 +191,7 @@ class NeedToReleaseDocker(LoggingAction):
def __init__(
self,
name: str,
package_meta: PackageMeta,
package_meta: DockerMeta,
release_meta: ReleaseMeta,
log_prefix: str = "",
) -> None:
Expand All @@ -114,7 +213,7 @@ def initialise(self) -> None:
try:
self.release_version = RedisVersion.parse(self.release_meta.tag)
except ValueError as e:
self.logger.error(f"Failed to parse release tag: {e}")
self.logger.debug(f"Failed to parse release tag: {e}")
return
pass

Expand All @@ -123,9 +222,6 @@ def update(self) -> Status:
if self.release_meta.tag is None:
self.feedback_message = "Release tag is not set"
result = Status.FAILURE
if self.release_meta.tag == "unstable":
self.feedback_message = "Skip unstable release for docker"
result = Status.FAILURE

if self.release_version is not None:
if self.release_version.major < 8:
Expand All @@ -138,6 +234,9 @@ def update(self) -> Status:
f"Need to release docker version {str(self.release_version)}"
)
result = Status.SUCCESS
else:
self.feedback_message = "Custom build, need to release"
result = Status.SUCCESS

if self.log_once("need_to_release", self.package_meta.ephemeral.log_once_flags):
color_open = "" if result == Status.SUCCESS else "[yellow]"
Expand Down
12 changes: 12 additions & 0 deletions src/redis_release/bht/behaviours_homebrew.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ def update(self) -> Status:
self.logger.info(self.feedback_message)
return Status.SUCCESS

if self.release_version is None and self.release_meta.tag != "":
self.logger.info(
f"Release version is not set, skipping probably custom release {self.release_meta.tag}"
)
return Status.SUCCESS

assert self.release_version is not None
if self.package_meta.release_type is None:
if self.release_version.is_internal:
Expand Down Expand Up @@ -147,6 +153,12 @@ def initialise(self) -> None:
self.package_meta.remote_version = "unstable"
return

if self.release_meta.tag != "":
self.package_meta.ephemeral.is_version_acceptable = False
# we need to set remote version to not None as it is a sign of successful classify step
self.package_meta.remote_version = "custom"
return

self.feedback_message = ""
# Validate homebrew_channel is set
if self.package_meta.homebrew_channel is None:
Expand Down
17 changes: 17 additions & 0 deletions src/redis_release/bht/behaviours_snap.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ def update(self) -> Status:
self.package_meta.release_type = ReleaseType.PUBLIC
self.package_meta.snap_risk_level = SnapRiskLevel.EDGE
else:
if self.release_version is None and self.release_meta.tag != "":
self.logger.info(
f"Release version is not set, skipping probably custom release: {self.release_meta.tag}"
)
return Status.SUCCESS
assert self.release_version is not None
if self.package_meta.release_type is None:
if self.release_version.is_internal:
Expand Down Expand Up @@ -144,6 +149,18 @@ def initialise(self) -> None:
if self.package_meta.ephemeral.is_version_acceptable is not None:
return

# TODO: don't like this expresion, should be better way to handle custom releases skipping
if (
self.release_meta.tag is not None
and self.release_meta.tag != ""
and self.release_meta.tag != "unstable"
and self.package_meta.snap_risk_level is None
):
self.package_meta.ephemeral.is_version_acceptable = False
# we need to set remote version to not None as it is a sign of successful classify step
self.package_meta.remote_version = "custom"
return

self.feedback_message = ""
# Validate snap_risk_level is set
if self.package_meta.snap_risk_level is None:
Expand Down
11 changes: 7 additions & 4 deletions src/redis_release/bht/composites.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,19 @@ def __init__(
release_meta: ReleaseMeta,
github_client: GitHubClientAsync,
log_prefix: str = "",
behaviour: Optional[Behaviour] = None,
) -> None:
super().__init__(
None if name == "" else name,
IdentifyTargetRef(
if behaviour is None:
behaviour = IdentifyTargetRef(
"Identify Target Ref",
package_meta,
release_meta,
github_client,
log_prefix=log_prefix,
),
)
super().__init__(
None if name == "" else name,
behaviour,
package_meta.ephemeral,
"identify_ref",
log_prefix=log_prefix,
Expand Down
23 changes: 2 additions & 21 deletions src/redis_release/bht/ppas.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

Chains are formed and latched in `tree_factory.py`

Note: functions from here are gradually migrating to respective tree factory files

"""

from typing import Union
Expand Down Expand Up @@ -116,27 +118,6 @@ def create_trigger_workflow_ppa(
)


def create_identify_target_ref_ppa(
package_meta: PackageMeta,
release_meta: ReleaseMeta,
github_client: GitHubClientAsync,
log_prefix: str,
) -> Union[Selector, Sequence]:
return create_PPA(
"Identify Target Ref",
IdentifyTargetRefGuarded(
"",
package_meta,
release_meta,
github_client,
log_prefix=log_prefix,
),
IsTargetRefIdentified(
"Is Target Ref Identified?", package_meta, log_prefix=log_prefix
),
)


def create_download_artifacts_ppa(
workflow: Workflow,
package_meta: PackageMeta,
Expand Down
Loading