Skip to content

Commit d1fd1e1

Browse files
committed
refactor agent support and support releasing latest used agents
1 parent 5eb0310 commit d1fd1e1

File tree

6 files changed

+179
-186
lines changed

6 files changed

+179
-186
lines changed

.evergreen.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,18 @@ tasks:
397397
image_name: agent
398398
all_agents: "--all-agents"
399399

400+
- name: release_all_currently_used_agents_on_ecr
401+
# this enables us to run this manually (patch) and release all agent versions to ECR to verify
402+
# Dockerfile, script changes etc.
403+
allowed_requesters: [ "patch" ]
404+
commands:
405+
- func: clone
406+
- func: setup_building_host
407+
- func: pipeline
408+
vars:
409+
image_name: agent
410+
all_agents: "--current-agents"
411+
400412
- name: build_test_image
401413
commands:
402414
- func: clone
@@ -1927,6 +1939,16 @@ buildvariants:
19271939
tasks:
19281940
- name: release_all_agents_on_ecr
19291941

1942+
# Only called manually, It's used for testing the task release_agents_on_ecr in case the release.json
1943+
# has not changed, and you still want to push the images to ecr.
1944+
- name: manual_ecr_release_agent_currently_used
1945+
display_name: manual_ecr_release_agent_currently_used
1946+
tags: [ "release_all_agents_manually" ]
1947+
run_on:
1948+
- ubuntu2204-large
1949+
tasks:
1950+
- name: release_all_currently_used_agents_on_ecr
1951+
19301952
# These variants are used to test the code snippets and each one can be used in patches
19311953
# Prerelease is especially used when the repo is tagged
19321954
# More details in the TD: https://docs.google.com/document/d/1fuTxfRtP8QPtn7sKYxQM_AGcD6xycTZH8svngGxyKhc/edit?tab=t.0#bookmark=id.e8uva0393mbe

scripts/release/agent/__init__.py

Whitespace-only changes.

scripts/release/agent/validation.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import json
2+
from typing import List
3+
4+
import requests
5+
6+
from lib.base_logger import logger
7+
8+
9+
def load_agent_build_info():
10+
"""Load agent platform mappings from build_info_agent.json"""
11+
with open("build_info_agent.json", "r") as f:
12+
return json.load(f)
13+
14+
15+
def validate_agent_version_exists(agent_version: str, platforms: List[str]) -> bool:
16+
"""
17+
Validate that the agent version exists for all specified platforms by checking URLs.
18+
19+
Args:
20+
agent_version: MongoDB agent version to validate
21+
platforms: List of platforms to check
22+
23+
Returns:
24+
True if agent version exists for all platforms, False otherwise
25+
"""
26+
agent_info = load_agent_build_info()
27+
agent_base_url = (
28+
"https://mciuploads.s3.amazonaws.com/mms-automation/mongodb-mms-build-agent/builds/automation-agent/prod"
29+
)
30+
31+
for platform in platforms:
32+
if platform not in agent_info["platform_mappings"]:
33+
logger.warning(f"Platform {platform} not found in agent mappings, skipping validation")
34+
continue
35+
36+
mapping = agent_info["platform_mappings"][platform]
37+
agent_filename = f"{agent_info['base_names']['agent']}-{agent_version}.{mapping['agent_suffix']}"
38+
agent_url = f"{agent_base_url}/{agent_filename}"
39+
40+
try:
41+
# Use HEAD request to check if URL exists without downloading the file
42+
response = requests.head(agent_url, timeout=30)
43+
if response.status_code != 200:
44+
logger.warning(f"Agent version {agent_version} not found for platform {platform} at {agent_url} (HTTP {response.status_code})")
45+
return False
46+
logger.debug(f"Agent version {agent_version} validated for platform {platform}")
47+
except requests.RequestException as e:
48+
logger.warning(f"Failed to validate agent version {agent_version} for platform {platform}: {e}")
49+
return False
50+
51+
logger.info(f"Agent version {agent_version} validated for all platforms: {platforms}")
52+
return True
53+
54+
55+
def validate_tools_version_exists(tools_version: str, platforms: List[str]) -> bool:
56+
"""
57+
Validate that the tools version exists for all specified platforms by checking URLs.
58+
59+
Args:
60+
tools_version: MongoDB tools version to validate
61+
platforms: List of platforms to check
62+
63+
Returns:
64+
True if tools version exists for all platforms, False otherwise
65+
"""
66+
agent_info = load_agent_build_info()
67+
tools_base_url = "https://fastdl.mongodb.org/tools/db"
68+
69+
for platform in platforms:
70+
if platform not in agent_info["platform_mappings"]:
71+
logger.warning(f"Platform {platform} not found in agent mappings, skipping tools validation")
72+
continue
73+
74+
mapping = agent_info["platform_mappings"][platform]
75+
tools_suffix = mapping["tools_suffix"].replace("{TOOLS_VERSION}", tools_version)
76+
tools_filename = f"{agent_info['base_names']['tools']}-{tools_suffix}"
77+
tools_url = f"{tools_base_url}/{tools_filename}"
78+
79+
try:
80+
# Use HEAD request to check if URL exists without downloading the file
81+
response = requests.head(tools_url, timeout=30)
82+
if response.status_code != 200:
83+
logger.warning(f"Tools version {tools_version} not found for platform {platform} at {tools_url} (HTTP {response.status_code})")
84+
return False
85+
logger.debug(f"Tools version {tools_version} validated for platform {platform}")
86+
except requests.RequestException as e:
87+
logger.warning(f"Failed to validate tools version {tools_version} for platform {platform}: {e}")
88+
return False
89+
90+
logger.info(f"Tools version {tools_version} validated for all platforms: {platforms}")
91+
return True

scripts/release/atomic_pipeline.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
from opentelemetry import trace
1515

1616
from lib.base_logger import logger
17+
from scripts.release.agent.validation import validate_agent_version_exists, validate_tools_version_exists,load_agent_build_info
1718
from scripts.release.build.image_build_configuration import ImageBuildConfiguration
1819
from scripts.release.build.image_build_process import execute_docker_build
1920
from scripts.release.build.image_signing import (
2021
mongodb_artifactory_login,
2122
sign_image,
2223
verify_signature,
2324
)
24-
from scripts.release.detect_ops_manager_changes import (
25+
from scripts.release.agent.detect_ops_manager_changes import (
2526
detect_ops_manager_changes,
2627
get_currently_used_agents,
2728
get_all_agents_for_rebuild,
@@ -30,19 +31,10 @@
3031
TRACER = trace.get_tracer("evergreen-agent")
3132

3233

33-
def load_agent_build_info():
34-
"""Load agent platform mappings from build_info_agent.json"""
35-
with open("build_info_agent.json", "r") as f:
36-
return json.load(f)
37-
38-
3934
def extract_tools_version_from_release(release: Dict) -> str:
4035
"""
4136
Extract tools version from release.json mongodbToolsBundle.ubi field.
4237
43-
Args:
44-
release: Release dictionary from release.json
45-
4638
Returns:
4739
Tools version string (e.g., "100.12.2")
4840
"""
@@ -54,22 +46,6 @@ def extract_tools_version_from_release(release: Dict) -> str:
5446
return tools_version
5547

5648

57-
def get_build_arg_names(platform: str) -> Dict[str, str]:
58-
"""
59-
Generate build argument names for a platform.
60-
61-
Args:
62-
platform: Platform string (e.g., "linux/amd64")
63-
64-
Returns:
65-
Dictionary with agent_build_arg and tools_build_arg keys
66-
"""
67-
# Extract architecture from platform (e.g., "amd64" from "linux/amd64")
68-
arch = platform.split("/")[1]
69-
70-
return {"agent_build_arg": f"mongodb_agent_version_{arch}", "tools_build_arg": f"mongodb_tools_version_{arch}"}
71-
72-
7349
def generate_tools_build_args(platforms: List[str], tools_version: str) -> Dict[str, str]:
7450
"""
7551
Generate build arguments for MongoDB tools based on platform mappings.
@@ -90,12 +66,11 @@ def generate_tools_build_args(platforms: List[str], tools_version: str) -> Dict[
9066
continue
9167

9268
mapping = agent_info["platform_mappings"][platform]
93-
build_arg_names = get_build_arg_names(platform)
69+
arch = platform.split("/")[-1]
9470

95-
# Generate tools build arg only
9671
tools_suffix = mapping["tools_suffix"].replace("{TOOLS_VERSION}", tools_version)
9772
tools_filename = f"{agent_info['base_names']['tools']}-{tools_suffix}"
98-
build_args[build_arg_names["tools_build_arg"]] = tools_filename
73+
build_args[f"mongodb_tool_version_{arch}"] = tools_filename
9974

10075
return build_args
10176

@@ -121,14 +96,14 @@ def generate_agent_build_args(platforms: List[str], agent_version: str, tools_ve
12196
continue
12297

12398
mapping = agent_info["platform_mappings"][platform]
124-
build_arg_names = get_build_arg_names(platform)
99+
arch = platform.split("/")[-1]
125100

126101
agent_filename = f"{agent_info['base_names']['agent']}-{agent_version}.{mapping['agent_suffix']}"
127-
build_args[build_arg_names["agent_build_arg"]] = agent_filename
102+
build_args[f"mongodb_agent_version_{arch}"] = agent_filename
128103

129104
tools_suffix = mapping["tools_suffix"].replace("{TOOLS_VERSION}", tools_version)
130105
tools_filename = f"{agent_info['base_names']['tools']}-{tools_suffix}"
131-
build_args[build_arg_names["tools_build_arg"]] = tools_filename
106+
build_args[f"mongodb_tool_version_{arch}"] = tools_filename
132107

133108
return build_args
134109

@@ -339,6 +314,12 @@ def build_init_appdb_image(build_configuration: ImageBuildConfiguration):
339314

340315
# Extract tools version and generate platform-specific build args
341316
tools_version = extract_tools_version_from_release(release)
317+
318+
# Validate that the tools version exists before attempting to build
319+
if not validate_tools_version_exists(tools_version, build_configuration.platforms):
320+
logger.warning(f"Skipping build for init-appdb - tools version {tools_version} not found in repository")
321+
return
322+
342323
platform_build_args = generate_tools_build_args(
343324
platforms=build_configuration.platforms, tools_version=tools_version
344325
)
@@ -359,10 +340,15 @@ def build_init_appdb_image(build_configuration: ImageBuildConfiguration):
359340
def build_init_database_image(build_configuration: ImageBuildConfiguration):
360341
release = load_release_file()
361342
base_url = "https://fastdl.mongodb.org/tools/db"
362-
mongodb_tools_url_ubi = "{}{}".format(base_url, release["mongodbToolsBundle"]["ubi"])
363343

364344
# Extract tools version and generate platform-specific build args
365345
tools_version = extract_tools_version_from_release(release)
346+
347+
# Validate that the tools version exists before attempting to build
348+
if not validate_tools_version_exists(tools_version, build_configuration.platforms):
349+
logger.warning(f"Skipping build for init-database - tools version {tools_version} not found in repository")
350+
return
351+
366352
platform_build_args = generate_tools_build_args(
367353
platforms=build_configuration.platforms, tools_version=tools_version
368354
)
@@ -429,15 +415,37 @@ def build_agent(build_configuration: ImageBuildConfiguration):
429415
with ProcessPoolExecutor(max_workers=max_workers) as executor:
430416
logger.info(f"Running with factor of {max_workers}")
431417
logger.info(f"======= Agent versions to build {agent_versions_to_build} =======")
418+
419+
successful_builds = []
420+
skipped_builds = []
421+
432422
for idx, agent_tools_version in enumerate(agent_versions_to_build):
433-
logger.info(f"======= Building Agent {agent_tools_version} ({idx}/{len(agent_versions_to_build)})")
423+
agent_version = agent_tools_version[0]
424+
tools_version = agent_tools_version[1]
425+
logger.info(f"======= Building Agent {agent_tools_version} ({idx + 1}/{len(agent_versions_to_build)})")
426+
427+
if not validate_agent_version_exists(agent_version, build_configuration.platforms):
428+
logger.warning(f"Skipping agent version {agent_version} - not found in repository")
429+
skipped_builds.append(agent_tools_version)
430+
continue
431+
432+
if not validate_tools_version_exists(tools_version, build_configuration.platforms):
433+
logger.warning(f"Skipping agent version {agent_version} - tools version {tools_version} not found in repository")
434+
skipped_builds.append(agent_tools_version)
435+
continue
436+
437+
successful_builds.append(agent_tools_version)
434438
_build_agent(
435439
agent_tools_version,
436440
build_configuration,
437441
executor,
438442
tasks_queue,
439443
)
440444

445+
logger.info(f"Build summary: {len(successful_builds)} successful, {len(skipped_builds)} skipped")
446+
if skipped_builds:
447+
logger.info(f"Skipped versions: {skipped_builds}")
448+
441449
queue_exception_handling(tasks_queue)
442450

443451

@@ -464,6 +472,7 @@ def build_agent_pipeline(
464472
f"======== Building agent pipeline for version {agent_version}, build configuration version: {build_configuration.version}"
465473
)
466474

475+
# Note: Validation is now done earlier in the build_agent function
467476
# Generate platform-specific build arguments using the mapping
468477
platform_build_args = generate_agent_build_args(
469478
platforms=build_configuration.platforms, agent_version=agent_version, tools_version=tools_version

0 commit comments

Comments
 (0)