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 .evergreen-functions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ functions:
IMAGE_NAME: ${image_name}
BUILD_SCENARIO_OVERRIDE: ${build_scenario}
FLAGS: ${flags}
AGENT_VERSION_OVERRIDE: ${agent_version}

teardown_cloud_qa_all:
- command: shell.exec
Expand Down
104 changes: 27 additions & 77 deletions .evergreen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,19 +287,21 @@ tasks:
commands:
- func: lint_repo

# pct only triggers this variant once a new agent image is out
- name: release_agent
# this enables us to run this variant either manually (patch) which pct does or during an OM bump (github_pr)
allowed_requesters: [ "patch", "github_pr" ]
# Runs on every merge - detects release.json changes and releases appropriate images
- name: release_om_and_agents
allowed_requesters: [ "patch" , "commit"]
commands:
- func: clone
- func: python_venv
- func: setup_building_host
- func: quay_login
- func: setup_docker_sbom
- func: pipeline
vars:
image_name: agent
build_scenario: release
- command: subprocess.exec
params:
working_dir: src/github.com/mongodb/mongodb-kubernetes
binary: scripts/dev/run_python.sh
args:
- scripts/release/release_om_and_agents.py

- name: migrate_all_agents
# this enables us to run this variant manually to build all the agents for the new agent registry
Expand Down Expand Up @@ -343,8 +345,9 @@ tasks:
- func: quay_login
- func: pipeline
vars:
agent_version: all
image_name: agent
flags: "--parallel --all-agents --skip-if-exists=false"
flags: "--parallel --skip-if-exists=false"

- name: rebuild_currently_used_agents
# this enables us to run this manually (patch) and rebuild current agent versions to verify
Expand All @@ -356,8 +359,9 @@ tasks:
- func: quay_login
- func: pipeline
vars:
agent_version: current
image_name: agent
flags: "--parallel --current-agents --skip-if-exists=false"
flags: "--parallel --skip-if-exists=false"

- name: build_kubectl_mongodb_plugin
commands:
Expand Down Expand Up @@ -463,7 +467,8 @@ tasks:
- func: pipeline
vars:
image_name: agent
flags: "--parallel --all-agents"
agent_version: all
flags: "--parallel"

- name: build_init_database_image_ubi
commands:
Expand Down Expand Up @@ -749,7 +754,7 @@ task_groups:
- e2e_sharded_cluster_scram_sha_256_switch_project
- e2e_replica_set_scram_sha_1_switch_project
- e2e_sharded_cluster_scram_sha_1_switch_project
# TODO CLOUDP-349093 - Disabled these tests as they don't use the password secret, and project migrations aren't fully supported yet.
# TODO CLOUDP-349093 - Disabled these tests as they don't use the password secret, and project migrations aren't fully supported yet.
# e2e_sharded_cluster_x509_switch_project
# e2e_replica_set_x509_switch_project
# e2e_replica_set_ldap_switch_project
Expand Down Expand Up @@ -1893,26 +1898,6 @@ buildvariants:
tasks:
- name: build_om_images

# It will be called by pct while bumping the agent cloud manager image
- name: release_agent
display_name: release_agent
tags: [ "manual_patch", "release_agent" ]
run_on:
- release-ubuntu2404-small # This is required for CISA attestation https://jira.mongodb.org/browse/DEVPROD-17780
depends_on:
- variant: init_test_run
name: build_agent_images_ubi # this ensures the agent gets released to ECR as well
- variant: e2e_multi_cluster_kind
name: '*'
- variant: e2e_static_multi_cluster_2_clusters
name: '*'
- variant: e2e_mdb_kind_ubi_cloudqa
name: '*'
- variant: e2e_static_mdb_kind_ubi_cloudqa
name: '*'
tasks:
- name: release_agent

# Only called manually, It's used for testing the task release_agents in case the release.json
# has not changed, and you still want to push the images to registry.
- name: manual_release_all_agents
Expand Down Expand Up @@ -1946,51 +1931,6 @@ buildvariants:
- name: backup_csv_images_limit_3
- name: backup_csv_images_all

- name: publish_om60_images
display_name: publish_om60_images
tags: [ "manual_patch" ]
allowed_requesters: [ "patch", "github_pr" ]
run_on:
- release-ubuntu2404-small # This is required for CISA attestation https://jira.mongodb.org/browse/DEVPROD-17780
depends_on:
- variant: e2e_om60_kind_ubi
name: '*'
- variant: e2e_static_om60_kind_ubi
name: '*'
tasks:
- name: publish_ops_manager
- name: release_agent

- name: publish_om70_images
display_name: publish_om70_images
tags: [ "manual_patch" ]
allowed_requesters: [ "patch", "github_pr" ]
run_on:
- release-ubuntu2404-small # This is required for CISA attestation https://jira.mongodb.org/browse/DEVPROD-17780
depends_on:
- variant: e2e_om70_kind_ubi
name: '*'
- variant: e2e_static_om70_kind_ubi
name: '*'
tasks:
- name: publish_ops_manager
- name: release_agent

- name: publish_om80_images
display_name: publish_om80_images
tags: [ "manual_patch" ]
allowed_requesters: [ "patch", "github_pr" ]
run_on:
- release-ubuntu2404-small # This is required for CISA attestation https://jira.mongodb.org/browse/DEVPROD-17780
depends_on:
- variant: e2e_om80_kind_ubi
name: '*'
- variant: e2e_static_om80_kind_ubi
name: '*'
tasks:
- name: publish_ops_manager
- name: release_agent

- name: migrate_all_agents
display_name: migrate_all_agents
tags: [ "manual_patch" ]
Expand All @@ -1999,3 +1939,13 @@ buildvariants:
- ubuntu2404-large
tasks:
- name: migrate_all_agents

# Runs on every merge to master and releases images auxiliary to the operator release like OM and the Agent
- name: release_om_and_agents
display_name: release_om_and_agents
allowed_requesters: [ "patch" , "commit"]
run_on:
- release-ubuntu2404-small
patchable: false # Only run on commit builds
tasks:
- name: release_om_and_agents
Original file line number Diff line number Diff line change
Expand Up @@ -19,32 +19,6 @@
logger = logging.getLogger(__name__)


def get_content_from_git(commit: str, file_path: str) -> Optional[str]:
try:
result = subprocess.run(
["git", "show", f"{commit}:{file_path}"], capture_output=True, text=True, check=True, timeout=30
)
return result.stdout
except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
logger.error(f"Failed to get {file_path} from git commit {commit}: {e}")
return None


def load_release_json_from_master() -> Optional[Dict]:
base_revision = "origin/master"

content = get_content_from_git(base_revision, "release.json")
if not content:
logger.error(f"Could not retrieve release.json from {base_revision}")
return None

try:
return json.loads(content)
except json.JSONDecodeError as e:
logger.error(f"Invalid JSON in base release.json: {e}")
return None


def load_current_release_json() -> Optional[Dict]:
try:
with open("release.json", "r") as f:
Expand All @@ -60,28 +34,6 @@ def extract_ops_manager_mapping(release_data: Dict) -> Dict:
return release_data.get("supportedImages", {}).get("mongodb-agent", {}).get("opsManagerMapping", {})


def get_changed_agents(current_mapping: Dict, base_mapping: Dict) -> List[Tuple[str, str]]:
"""Returns list of (agent_version, tools_version) tuples for added/changed agents"""
added_agents = []

current_om_mapping = current_mapping.get("ops_manager", {})
master_om_mapping = base_mapping.get("ops_manager", {})

for om_version, agent_tools_version in current_om_mapping.items():
if om_version not in master_om_mapping or master_om_mapping[om_version] != agent_tools_version:
added_agents.append((agent_tools_version["agent_version"], agent_tools_version["tools_version"]))

current_cm = current_mapping.get("cloud_manager")
master_cm = base_mapping.get("cloud_manager")
current_cm_tools = current_mapping.get("cloud_manager_tools")
master_cm_tools = base_mapping.get("cloud_manager_tools")

if current_cm != master_cm or current_cm_tools != master_cm_tools:
added_agents.append((current_cm, current_cm_tools))

return list(set(added_agents))


def get_tools_version_for_agent(agent_version: str) -> str:
"""Get tools version for a given agent version from release.json"""
release_data = load_current_release_json()
Expand Down Expand Up @@ -206,26 +158,3 @@ def get_currently_used_agents() -> List[Tuple[str, str]]:
except Exception as e:
logger.error(f"Error getting currently used agents: {e}")
return []


def detect_ops_manager_changes() -> List[Tuple[str, str]]:
"""Returns (has_changes, changed_agents_list)"""
logger.info("=== Detecting OM Mapping Changes (Local vs Base) ===")

current_release = load_current_release_json()
if not current_release:
logger.error("Could not load current local release.json")
return []

master_release = load_release_json_from_master()
if not master_release:
logger.warning("Could not load base release.json, assuming changes exist")
return []

current_mapping = extract_ops_manager_mapping(current_release)
base_mapping = extract_ops_manager_mapping(master_release)

if current_mapping != base_mapping:
return get_changed_agents(current_mapping, base_mapping)
else:
return []
22 changes: 11 additions & 11 deletions scripts/release/atomic_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
from opentelemetry import trace

from lib.base_logger import logger
from scripts.release.agent.detect_ops_manager_changes import (
detect_ops_manager_changes,
from scripts.release.agent.agents_to_rebuild import (
get_all_agents_for_rebuild,
get_currently_used_agents,
)
Expand Down Expand Up @@ -330,22 +329,23 @@ def build_upgrade_hook_image(build_configuration: ImageBuildConfiguration):


def build_agent(build_configuration: ImageBuildConfiguration):
"""
Build the agent only for the latest operator for patches and operator releases.
"""Build the agent image(s). Validation happens in pipeline.py."""
version = build_configuration.version

"""
if build_configuration.all_agents:
if version == "all":
agent_versions_to_build = get_all_agents_for_rebuild()
logger.info("building all agents")
elif build_configuration.currently_used_agents:
elif version == "current":
agent_versions_to_build = get_currently_used_agents()
logger.info("building current used agents")
logger.info("building currently used agents")
elif version and build_configuration.agent_tools_version:
agent_versions_to_build = [(version, build_configuration.agent_tools_version)]
logger.info(f"building agent {version} with tools {build_configuration.agent_tools_version}")
else:
agent_versions_to_build = detect_ops_manager_changes()
Copy link
Collaborator Author

@nammn nammn Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to detect for changes, since we release every commit now

logger.info("building agents for changed OM versions")
raise ValueError("No agent selection provided - this should be caught by pipeline.py validation")

if not agent_versions_to_build:
logger.info("No changes detected, skipping agent build")
logger.warning("No agent versions found to build")
return

logger.info(f"Building Agent versions: {agent_versions_to_build}")
Expand Down
6 changes: 2 additions & 4 deletions scripts/release/build/image_build_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
from scripts.release.build.build_scenario import BuildScenario
from scripts.release.build.image_build_process import ImageBuilder

SUPPORTED_PLATFORMS = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm64", "linux/s390x",
"linux/ppc64le"]
SUPPORTED_PLATFORMS = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm64", "linux/s390x", "linux/ppc64le"]


@dataclass
Expand All @@ -24,9 +23,8 @@ class ImageBuildConfiguration:
# Agent specific
parallel: bool = False
parallel_factor: int = 0
all_agents: bool = False
currently_used_agents: bool = False
architecture_suffix: bool = False
agent_tools_version: Optional[str] = None # Explicit tools version for agent builds

def is_release_scenario(self) -> bool:
return self.scenario == BuildScenario.RELEASE
Expand Down
41 changes: 28 additions & 13 deletions scripts/release/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
)
from scripts.release.build.image_build_process import PodmanImageBuilder

CURRENT_AGENTS = "current"
ALL_AGENTS = "all"

"""
The goal of main.py, image_build_configuration.py and build_context.py is to provide a single source of truth for the build
configuration. All parameters that depend on the the build environment (local dev, evg, etc) should be resolved here and
Expand Down Expand Up @@ -139,9 +142,25 @@ def image_build_config_from_args(args) -> ImageBuildConfiguration:
if type(builder) is PodmanImageBuilder and len(platforms) > 1:
raise ValueError("Cannot use Podman builder with multi-platform builds")

# Validate version - only agent can have None version as the versions are managed by the agent
# which are externally retrieved from release.json
if version is None and image != "agent":
# Get agent_tools_version for agent builds (from --agent-tools-version arg)
agent_tools_version = getattr(args, "agent_tools_version", None)

# Validate version requirements
if image == "agent":
# Agent builds: version can be "all", "current", or explicit version (requires agent_tools_version)
if version is None:
raise ValueError(
"Agent build requires --version. Use one of:\n"
" --version all (for all agents in release.json)\n"
" --version current (for currently used agents)\n"
" --version <ver> --agent-tools-version <tools_ver> (for specific agent)"
)
is_special_version = version in (ALL_AGENTS, CURRENT_AGENTS)
if not is_special_version and agent_tools_version is None:
raise ValueError(
f"For agent builds with explicit version '{version}', --agent-tools-version must also be provided."
)
elif version is None:
raise ValueError(f"Version cannot be empty for {image}.")

return ImageBuildConfiguration(
Expand All @@ -157,9 +176,8 @@ def image_build_config_from_args(args) -> ImageBuildConfiguration:
skip_if_exists=skip_if_exists,
parallel=args.parallel,
parallel_factor=args.parallel_factor,
all_agents=args.all_agents,
currently_used_agents=args.current_agents,
architecture_suffix=architecture_suffix,
agent_tools_version=agent_tools_version,
)


Expand Down Expand Up @@ -274,14 +292,11 @@ def main():
help="Number of agent builds to run in parallel, defaults to number of cores",
)
parser.add_argument(
"--all-agents",
action="store_true",
help="Build all agent images.",
)
parser.add_argument(
"--current-agents",
action="store_true",
help="Build all currently used agent images.",
"--agent-tools-version",
metavar="",
action="store",
type=str,
help="Tools version to use when building agent image. Required when --version is an explicit version (not 'all' or 'current').",
)
parser.add_argument(
"--architecture-suffix",
Expand Down
Loading