Skip to content

Commit 0089223

Browse files
[CLOUDP-352383] Add a build variant to release chart to OCI registry (#542)
1 parent 61dfb1e commit 0089223

File tree

4 files changed

+85
-11
lines changed

4 files changed

+85
-11
lines changed

.evergreen-functions.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ functions:
227227
type: setup
228228
params:
229229
working_dir: src/github.com/mongodb/mongodb-kubernetes
230+
include_expansions_in_env:
231+
- quay_prod_username
232+
- quay_prod_robot_token
230233
add_to_path:
231234
- ${workdir}/bin
232235
- ${PROJECT_DIR}/bin

.evergreen-release.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ tasks:
134134
- func: clone
135135
- func: python_venv
136136
- func: create_chart_release_pr
137+
138+
- name: release_chart_to_oci_registry
139+
tags: [ "release_chart_to_oci_registry" ]
140+
commands:
141+
- func: clone
142+
- func: python_venv
143+
- func: setup_kubectl
144+
- func: setup_aws
145+
- func: helm_registry_login
146+
- func: publish_helm_chart
137147

138148
### Release build variants
139149
buildvariants:
@@ -260,3 +270,12 @@ buildvariants:
260270
allowed_requesters: [ "patch", "github_tag" ]
261271
tasks:
262272
- name: create_chart_release_pr
273+
274+
- name: release_chart_to_oci_registry
275+
display_name: release_chart_to_oci_registry
276+
tags: [ "release" ]
277+
run_on:
278+
- release-ubuntu2404-small # This is required for CISA attestation https://jira.mongodb.org/browse/DEVPROD-17780
279+
allowed_requesters: [ "patch", "github_tag" ]
280+
tasks:
281+
- name: release_chart_to_oci_registry

scripts/release/helm_registry_login.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
import os
33
import subprocess
44
import sys
5+
from shlex import quote
56

67
from lib.base_logger import logger
78
from scripts.release.build.build_info import load_build_info
89

10+
BUILD_SCENARIO_RELEASE = "release"
11+
QUAY_USERNAME_ENV_VAR = "quay_prod_username"
12+
QUAY_PASSWORD_ENV_VAR = "quay_prod_robot_token"
13+
QUAY_REGISTRY = "quay.io"
914

10-
def helm_registry_login(helm_registry: str, region: str):
15+
16+
def helm_registry_login_to_ecr(helm_registry: str, region: str):
1117
logger.info(f"Attempting to log into ECR registry: {helm_registry}, using helm registry login.")
1218

1319
aws_command = ["aws", "ecr", "get-login-password", "--region", region]
@@ -67,7 +73,45 @@ def main():
6773

6874
registry = build_info.helm_charts["mongodb-kubernetes"].registry
6975
region = build_info.helm_charts["mongodb-kubernetes"].region
70-
return helm_registry_login(registry, region)
76+
77+
if registry == QUAY_REGISTRY:
78+
return helm_registry_login_to_quay(registry)
79+
80+
return helm_registry_login_to_ecr(registry, region)
81+
82+
83+
def helm_registry_login_to_quay(registry):
84+
username = os.environ.get(QUAY_USERNAME_ENV_VAR)
85+
password = os.environ.get(QUAY_PASSWORD_ENV_VAR)
86+
87+
if not username:
88+
raise Exception(f"Env var {QUAY_USERNAME_ENV_VAR} must be set with the quay username.")
89+
if not password:
90+
raise Exception(f"Env var {QUAY_PASSWORD_ENV_VAR} must be set with the quay password.")
91+
92+
# using quote will help us avoid command injectin issues, was reported by semggrep in PR
93+
command = ["helm", "registry", "login", "--username", quote(username), "--password-stdin", quote(registry)]
94+
95+
try:
96+
result = subprocess.run(
97+
command,
98+
input=quote(password), # Pass the password as input bytes
99+
capture_output=True,
100+
text=True,
101+
check=False, # Do not raise an exception on non-zero exit code
102+
)
103+
104+
if result.returncode == 0:
105+
logger.info(f"Successfully logged into helm continer registry {registry}.")
106+
else:
107+
raise Exception(
108+
f"Helm registry login failed to {registry}. Stdout: {result.stderr.strip()}, Stderr: {result.stderr.strip()}"
109+
)
110+
111+
except FileNotFoundError:
112+
raise Exception("Error: 'helm' command not found. Ensure Helm CLI is installed and in your PATH.")
113+
except Exception as e:
114+
raise Exception(f"An unexpected error occurred during execution: {e}")
71115

72116

73117
if __name__ == "__main__":

scripts/release/publish_helm_chart.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from lib.base_logger import logger
99
from scripts.release.build.build_info import *
10+
from scripts.release.helm_registry_login import BUILD_SCENARIO_RELEASE
1011

1112
CHART_DIR = "helm_chart"
1213

@@ -28,17 +29,14 @@ def run_command(command: list[str]):
2829

2930
# update_chart_and_get_metadata updates the helm chart's Chart.yaml and sets the version
3031
# to either evg patch id or commit which is set in OPERATOR_VERSION.
31-
def update_chart_and_get_metadata(chart_dir: str) -> tuple[str, str]:
32+
def update_chart_and_get_metadata(chart_dir: str, build_scenario) -> tuple[str, str]:
3233
chart_path = os.path.join(chart_dir, "Chart.yaml")
33-
version_id = os.environ.get("OPERATOR_VERSION")
34-
if not version_id:
34+
version = os.environ.get("OPERATOR_VERSION")
35+
if not version:
3536
raise ValueError(
3637
"Error: Environment variable 'OPERATOR_VERSION' must be set to determine the chart version to publish."
3738
)
3839

39-
new_version = f"0.0.0+{version_id}"
40-
logger.info(f"New helm chart version will be: {new_version}")
41-
4240
if not os.path.exists(chart_path):
4341
raise FileNotFoundError(
4442
f"Error: Chart.yaml not found in directory '{chart_dir}'. "
@@ -52,7 +50,17 @@ def update_chart_and_get_metadata(chart_dir: str) -> tuple[str, str]:
5250
chart_name = data.get("name")
5351
if not chart_name:
5452
raise ValueError("Chart.yaml is missing required 'name' field.")
53+
except Exception as e:
54+
raise Exception(f"Unable to load Chart.yaml from dir {chart_path}")
55+
56+
# if build_scenario is release, the chart.yaml would already have correct chart version
57+
if build_scenario == BUILD_SCENARIO_RELEASE:
58+
return chart_name, version
5559

60+
new_version = f"0.0.0+{version}"
61+
logger.info(f"New helm chart version will be: {new_version}")
62+
63+
try:
5664
data["version"] = new_version
5765

5866
with open(chart_path, "w") as f:
@@ -79,10 +87,10 @@ def get_oci_registry(chart_info: HelmChartInfo) -> str:
7987
return oci_registry
8088

8189

82-
def publish_helm_chart(chart_info: HelmChartInfo):
90+
def publish_helm_chart(chart_info: HelmChartInfo, build_scenario):
8391
try:
8492
oci_registry = get_oci_registry(chart_info)
85-
chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR)
93+
chart_name, chart_version = update_chart_and_get_metadata(CHART_DIR, build_scenario)
8694
tgz_filename = f"{chart_name}-{chart_version}.tgz"
8795

8896
logger.info(f"Packaging chart: {chart_name} with Version: {chart_version}")
@@ -108,7 +116,7 @@ def main():
108116
build_scenario = args.build_scenario
109117
build_info = load_build_info(build_scenario)
110118

111-
return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"])
119+
return publish_helm_chart(build_info.helm_charts["mongodb-kubernetes"], build_scenario)
112120

113121

114122
if __name__ == "__main__":

0 commit comments

Comments
 (0)