0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-21 12:39:08 +01:00

SERVER-93515 Apply new VP and Overall quotas for the code lockdown (#26106)

GitOrigin-RevId: 56309603a6e1d87c9caa8b78b3208104d9e76866
This commit is contained in:
Mikhail Shchatko 2024-08-14 17:49:24 +03:00 committed by MongoDB Bot
parent db80281e66
commit cfa71f3776
11 changed files with 211 additions and 660 deletions

View File

@ -1,5 +1,6 @@
from __future__ import annotations
from datetime import datetime, timezone
from enum import Enum
from typing import Dict, List, NamedTuple, Optional, Set
@ -14,9 +15,9 @@ class BfCategory(str, Enum):
class CategorizedBFs(NamedTuple):
hot_bfs: Set[str]
cold_bfs: Set[str]
perf_bfs: Set[str]
hot_bfs: Set[BfIssue]
cold_bfs: Set[BfIssue]
perf_bfs: Set[BfIssue]
@classmethod
def empty(cls) -> CategorizedBFs:
@ -36,13 +37,13 @@ class CategorizedBFs(NamedTuple):
test_type = TestType.from_evg_project_name(evg_project)
if test_type == TestType.PERFORMANCE:
self.perf_bfs.add(bf.key)
self.perf_bfs.add(bf)
if test_type == TestType.CORRECTNESS:
if bf.temperature == BfTemperature.HOT:
self.hot_bfs.add(bf.key)
self.hot_bfs.add(bf)
if bf.temperature in [BfTemperature.COLD, BfTemperature.NONE]:
self.cold_bfs.add(bf.key)
self.cold_bfs.add(bf)
def add(self, more_bfs: CategorizedBFs) -> None:
"""
@ -76,43 +77,38 @@ class BFsReport(NamedTuple):
def get_bf_count(
self,
bf_category: BfCategory,
assigned_team: Optional[str] = None,
include_bfs_older_than_time: Optional[datetime] = None,
assigned_teams: Optional[List[str]] = None,
) -> int:
"""
Calculate BFs count for a given criteria.
:param bf_category: BF category (hot, cold, perf).
:param assigned_team: Assigned team criterion, all teams if None.
:param include_bfs_older_than_time: Count BFs that have created date older than provided time.
:param assigned_teams: List of Assigned teams criterion, all teams if None.
:return: BFs count.
"""
total_bf_count = 0
if include_bfs_older_than_time is None:
include_bfs_older_than_time = datetime.utcnow().replace(tzinfo=timezone.utc)
team_reports = self.team_reports.values()
if assigned_team is not None:
team_reports = [self.team_reports[assigned_team]]
if assigned_teams is not None:
team_reports = [
self.team_reports.get(team, CategorizedBFs.empty()) for team in assigned_teams
]
for team_report in team_reports:
bfs = set()
if bf_category == BfCategory.HOT:
total_bf_count += len(team_report.hot_bfs)
bfs = team_report.hot_bfs
if bf_category == BfCategory.COLD:
total_bf_count += len(team_report.cold_bfs)
bfs = team_report.cold_bfs
if bf_category == BfCategory.PERF:
total_bf_count += len(team_report.perf_bfs)
bfs = team_report.perf_bfs
total_bf_count += len(
[bf for bf in bfs if bf.created_time < include_bfs_older_than_time]
)
return total_bf_count
def combine_teams(self, team_names: List[str], group_name: str) -> None:
"""
Mutate `self.team_reports` by removing `team_names` entries and combining their BFs under `group_name`.
:param team_names: Names of teams to combine BFs.
:param group_name: Group name to combine BFs under.
"""
group_bfs = CategorizedBFs.empty()
for team in team_names:
team_bfs = self.team_reports.pop(team, None)
if team_bfs is not None:
group_bfs.add(team_bfs)
self.team_reports[group_name] = group_bfs

View File

@ -43,12 +43,8 @@ JIRA_SERVER = "https://jira.mongodb.org"
DEFAULT_REPO = "10gen/mongo"
DEFAULT_BRANCH = "master"
SLACK_CHANNEL = "#10gen-mongo-code-lockdown"
FRIDAY_INDEX = 4 # datetime.weekday() returns Monday as 0 and Sunday as 6
EVERGREEN_LOOKBACK_DAYS = 14
GREEN_THRESHOLD_PERCENTS = 100
RED_THRESHOLD_PERCENTS = 200
def iterable_to_jql(entries: Iterable[str]) -> str:
return ", ".join(f'"{entry}"' for entry in entries)
@ -66,57 +62,25 @@ ACTIVE_BFS_QUERY = (
)
class ExitCode(Enum):
SUCCESS = 0
PREVIOUS_BUILD_STATUS_UNKNOWN = 1
class BuildStatus(Enum):
class CodeMergeStatus(Enum):
RED = "RED"
YELLOW = "YELLOW"
GREEN = "GREEN"
UNKNOWN = "UNKNOWN"
@classmethod
def from_str(cls, status: Optional[str]) -> BuildStatus:
try:
return cls[status]
except KeyError:
return cls.UNKNOWN
@classmethod
def from_threshold_percentages(cls, threshold_percentages: List[float]) -> BuildStatus:
if any(percentage > RED_THRESHOLD_PERCENTS for percentage in threshold_percentages):
def from_threshold_percentages(cls, threshold_percentages: List[float]) -> CodeMergeStatus:
if any(percentage > 100 for percentage in threshold_percentages):
return cls.RED
if all(percentage < GREEN_THRESHOLD_PERCENTS for percentage in threshold_percentages):
return cls.GREEN
return cls.YELLOW
return cls.GREEN
class SummaryMsg(Enum):
TITLE = "`[SUMMARY]`"
PREFIX = "`[SUMMARY]`"
BELOW_THRESHOLDS = f"All metrics are within {GREEN_THRESHOLD_PERCENTS}% of their thresholds."
BELOW_THRESHOLDS = "All metrics are within 100% of their thresholds.\nAll merges are allowed."
THRESHOLD_EXCEEDED = (
f"At least one metric exceeds {GREEN_THRESHOLD_PERCENTS}% of its threshold."
"At least one metric exceeds 100% of its threshold.\n"
"Approve only changes that fix BFs, Bugs, and Performance Regressions in the following scopes:"
)
THRESHOLD_EXCEEDED_X2 = (
f"At least one metric exceeds {RED_THRESHOLD_PERCENTS}% of its threshold."
)
STATUS_CHANGED = "<!here> Build status has changed to `{status}`."
STATUS_IS = "Build status is `{status}`."
ENTER_RED = "We are entering the code block state."
STILL_RED = "We are still in the code block state."
EXIT_RED = "We are exiting the code block state."
ACTION_ON_RED = "Approve only changes that fix BFs, Bugs, and Performance Regressions."
ACTION_ON_YELLOW = (
"Warning: all merges are still allowed, but now is a good time to get BFs, Bugs, and"
" Performance Regressions under control to avoid a blocking state."
)
ACTION_ON_GREEN = "All merges are allowed."
PLAYBOOK_REFERENCE = f"Refer to our playbook at <{BLOCK_ON_RED_PLAYBOOK_URL}> for details."
@ -132,13 +96,9 @@ class MonitorBuildStatusOrchestrator:
self.evg_service = evg_service
self.code_lockdown_config = code_lockdown_config
def evaluate_build_redness(
self, repo: str, branch: str, notify: bool, input_status_file: str, output_status_file: str
) -> ExitCode:
exit_code = ExitCode.SUCCESS
def evaluate_build_redness(self, repo: str, branch: str, notify: bool) -> None:
status_message = f"\n`[STATUS]` '{repo}' repo '{branch}' branch"
threshold_percentages = []
scope_percentages: Dict[str, List[float]] = {}
LOGGER.info("Getting Evergreen projects data")
evg_projects_info = self.evg_service.get_evg_project_info(repo, branch)
@ -150,7 +110,7 @@ class MonitorBuildStatusOrchestrator:
bfs_report, self.code_lockdown_config
)
status_message = f"{status_message}\n{bf_count_status_msg}\n"
threshold_percentages.extend(bf_count_percentages)
scope_percentages.update(bf_count_percentages)
# We are looking for Evergreen versions that started before the beginning of yesterday
# to give them time to complete
@ -167,48 +127,7 @@ class MonitorBuildStatusOrchestrator:
)
status_message = f"{status_message}\n{waterfall_failure_rate_status_msg}\n"
previous_build_status = BuildStatus.UNKNOWN
if os.path.exists(input_status_file):
with open(input_status_file, "r") as input_file:
input_file_content = input_file.read().strip()
LOGGER.info(
"Input status file content",
file=input_status_file,
content=input_file_content,
)
previous_build_status = BuildStatus.from_str(input_file_content)
if previous_build_status == BuildStatus.UNKNOWN:
LOGGER.error(
"Could not parse previous build status from the input build status file,"
" the file was corrupted or contained unexpected string"
)
else:
LOGGER.warning("Input status file is absent", file=input_status_file)
LOGGER.warning(
"The absence of input build status file is expected if the task is running for"
" the first time or for the first time after the file storage location is changed"
)
if previous_build_status == BuildStatus.UNKNOWN:
LOGGER.warning(
"We were not able to get the previous build status, which could lead to build status"
" being changed from RED to YELLOW, which should not happen, and/or summary messages"
" could be somewhat off"
)
LOGGER.warning(
"If we are in a YELLOW condition, there's different behavior to communicate if that"
" was previously GREEN (things are worse, but not RED yet), YELLOW (no change), or"
" RED (still RED but improving)"
)
LOGGER.warning(
"The state will still be reported, but may lose accuracy on specific actions to take"
)
exit_code = ExitCode.PREVIOUS_BUILD_STATUS_UNKNOWN
current_build_status = BuildStatus.from_threshold_percentages(threshold_percentages)
resulting_build_status, summary = self._summarize(
previous_build_status, current_build_status, self._today_is_friday()
)
summary = self._summarize(scope_percentages)
status_message = f"{status_message}\n{summary}"
for line in status_message.split("\n"):
@ -221,11 +140,6 @@ class MonitorBuildStatusOrchestrator:
msg=status_message.strip(),
)
with open(output_status_file, "w") as output_file:
output_file.write(resulting_build_status.value)
return exit_code
def _make_bfs_report(self, evg_projects_info: EvgProjectsInfo) -> BFsReport:
query = (
f'{ACTIVE_BFS_QUERY} AND "{JiraCustomFieldNames.EVERGREEN_PROJECT}" in'
@ -245,17 +159,16 @@ class MonitorBuildStatusOrchestrator:
@staticmethod
def _get_bf_counts_status(
bfs_report: BFsReport, code_lockdown_config: CodeLockdownConfig
) -> Tuple[str, List[float]]:
for group in code_lockdown_config.team_groups or []:
bfs_report.combine_teams(group.teams, group.name)
) -> Tuple[str, Dict[str, List[float]]]:
now = datetime.utcnow().replace(tzinfo=timezone.utc)
scope_percentages: Dict[str, List[float]] = {}
percentages = []
status_message = "`[STATUS]` The current BF count"
headers = ["Assigned Team/Group", "Hot BFs", "Cold BFs", "Perf BFs"]
headers = ["Scope", "Hot BFs", "Cold BFs", "Perf BFs"]
table_data = []
def _process_thresholds(
label: str,
scope: str,
hot_bf_count: int,
cold_bf_count: int,
perf_bf_count: int,
@ -268,40 +181,60 @@ class MonitorBuildStatusOrchestrator:
cold_bf_percentage = cold_bf_count / thresholds.cold_bf_count * 100
perf_bf_percentage = perf_bf_count / thresholds.perf_bf_count * 100
percentages.extend([hot_bf_percentage, cold_bf_percentage, perf_bf_percentage])
scope_percentages[scope] = [hot_bf_percentage, cold_bf_percentage, perf_bf_percentage]
table_data.append(
[
label,
scope,
f"{hot_bf_percentage:.0f}% ({hot_bf_count} / {thresholds.hot_bf_count})",
f"{cold_bf_percentage:.0f}% ({cold_bf_count} / {thresholds.cold_bf_count})",
f"{perf_bf_percentage:.0f}% ({perf_bf_count} / {thresholds.perf_bf_count})",
]
)
for assigned_team in sorted(list(bfs_report.team_reports.keys())):
_process_thresholds(
assigned_team,
bfs_report.get_bf_count(BfCategory.HOT, assigned_team),
bfs_report.get_bf_count(BfCategory.COLD, assigned_team),
bfs_report.get_bf_count(BfCategory.PERF, assigned_team),
code_lockdown_config.get_thresholds(assigned_team),
)
overall_older_than_time = now - timedelta(
hours=code_lockdown_config.overall_thresholds.include_bfs_older_than_hours
)
_process_thresholds(
"Overall",
bfs_report.get_bf_count(BfCategory.HOT),
bfs_report.get_bf_count(BfCategory.COLD),
bfs_report.get_bf_count(BfCategory.PERF),
"[Org] Overall",
bfs_report.get_bf_count(BfCategory.HOT, overall_older_than_time),
bfs_report.get_bf_count(BfCategory.COLD, overall_older_than_time),
bfs_report.get_bf_count(BfCategory.PERF, overall_older_than_time),
code_lockdown_config.overall_thresholds,
)
for group in code_lockdown_config.team_groups or []:
group_thresholds = code_lockdown_config.get_thresholds(group.name)
group_older_than_time = now - timedelta(
hours=group_thresholds.include_bfs_older_than_hours
)
_process_thresholds(
f"[Group] {group.name}",
bfs_report.get_bf_count(BfCategory.HOT, group_older_than_time, group.teams),
bfs_report.get_bf_count(BfCategory.COLD, group_older_than_time, group.teams),
bfs_report.get_bf_count(BfCategory.PERF, group_older_than_time, group.teams),
group_thresholds,
)
for assigned_team in sorted(list(bfs_report.team_reports.keys())):
team_thresholds = code_lockdown_config.get_thresholds(assigned_team)
team_older_than_time = now - timedelta(
hours=team_thresholds.include_bfs_older_than_hours
)
_process_thresholds(
f"[Team] {assigned_team}",
bfs_report.get_bf_count(BfCategory.HOT, team_older_than_time, [assigned_team]),
bfs_report.get_bf_count(BfCategory.COLD, team_older_than_time, [assigned_team]),
bfs_report.get_bf_count(BfCategory.PERF, team_older_than_time, [assigned_team]),
team_thresholds,
)
table_str = tabulate(
table_data, headers, tablefmt="outline", colalign=("left", "right", "right", "right")
)
status_message = f"{status_message}\n```\n{table_str}\n```"
return status_message, percentages
return status_message, scope_percentages
def _make_waterfall_report(
self, evg_project_names: List[str], window_end: datetime
@ -376,64 +309,25 @@ class MonitorBuildStatusOrchestrator:
return status_message
@staticmethod
def _summarize(
previous_status: BuildStatus, current_status: BuildStatus, today_is_friday: bool
) -> Tuple[BuildStatus, str]:
resulting_status = previous_status
if current_status == BuildStatus.RED and previous_status != BuildStatus.RED:
if today_is_friday:
resulting_status = BuildStatus.RED
else:
resulting_status = BuildStatus.YELLOW
if current_status == BuildStatus.YELLOW and previous_status != BuildStatus.RED:
resulting_status = BuildStatus.YELLOW
if current_status == BuildStatus.GREEN:
resulting_status = BuildStatus.GREEN
def _summarize(scope_percentages: Dict[str, List[float]]) -> str:
summary = SummaryMsg.PREFIX.value
summary = SummaryMsg.TITLE.value
red_scopes = []
for scope, percentages in scope_percentages.items():
status = CodeMergeStatus.from_threshold_percentages(percentages)
if status == CodeMergeStatus.RED:
red_scopes.append(scope)
if resulting_status != previous_status:
status_msg = SummaryMsg.STATUS_CHANGED.value.format(status=resulting_status.value)
if len(red_scopes) == 0:
summary = f"{summary} {SummaryMsg.BELOW_THRESHOLDS.value}"
else:
status_msg = SummaryMsg.STATUS_IS.value.format(status=resulting_status.value)
summary = f"{summary}\n{status_msg}"
if current_status == BuildStatus.RED:
summary = f"{summary}\n{SummaryMsg.THRESHOLD_EXCEEDED_X2.value}"
if current_status == BuildStatus.YELLOW:
summary = f"{summary}\n{SummaryMsg.THRESHOLD_EXCEEDED.value}"
if current_status == BuildStatus.GREEN:
summary = f"{summary}\n{SummaryMsg.BELOW_THRESHOLDS.value}"
if previous_status != BuildStatus.RED and resulting_status == BuildStatus.RED:
summary = f"{summary}\n{SummaryMsg.ENTER_RED.value}"
if previous_status == BuildStatus.RED and resulting_status == BuildStatus.RED:
summary = f"{summary}\n{SummaryMsg.STILL_RED.value}"
if previous_status == BuildStatus.RED and resulting_status != BuildStatus.RED:
summary = f"{summary}\n{SummaryMsg.EXIT_RED.value}"
if resulting_status == BuildStatus.RED:
summary = f"{summary}\n{SummaryMsg.ACTION_ON_RED.value}"
if resulting_status == BuildStatus.YELLOW:
summary = f"{summary}\n{SummaryMsg.ACTION_ON_YELLOW.value}"
if resulting_status == BuildStatus.GREEN:
summary = f"{summary}\n{SummaryMsg.ACTION_ON_GREEN.value}"
summary = f"{summary} {SummaryMsg.THRESHOLD_EXCEEDED.value}"
for scope in red_scopes:
summary = f"{summary}\n\t- {scope}"
summary = f"{summary}\n\n{SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
LOGGER.info(
"Got build statuses",
previous_build_status=previous_status.value,
current_build_status=current_status.value,
resulting_build_status=resulting_status.value,
today_is_friday=today_is_friday,
)
return resulting_status, summary
@staticmethod
def _today_is_friday() -> bool:
return datetime.utcnow().weekday() == FRIDAY_INDEX
return summary
def main(
@ -446,12 +340,6 @@ def main(
notify: Annotated[
bool, typer.Option(help="Whether to send slack notification with the results")
] = False, # default to the more "quiet" setting
input_status_file: Annotated[
str, typer.Option(help="The file that contains a previous build status")
] = "input_build_status_file.txt",
output_status_file: Annotated[
str, typer.Option(help="The file that contains the current build status")
] = "output_build_status_file.txt",
) -> None:
"""
Analyze Jira BFs count and Evergreen redness data.
@ -484,10 +372,7 @@ def main(
code_lockdown_config=code_lockdown_config,
)
exit_code = orchestrator.evaluate_build_redness(
github_repo, branch, notify, input_status_file, output_status_file
)
sys.exit(exit_code.value)
orchestrator.evaluate_build_redness(github_repo, branch, notify)
if __name__ == "__main__":

View File

@ -10,6 +10,7 @@ class BfCountThresholds(BaseModel):
hot_bf_count: int
cold_bf_count: int
perf_bf_count: int
include_bfs_older_than_hours: int
class TeamGroupConfig(BaseModel):
@ -38,8 +39,8 @@ class CodeLockdownConfig(BaseModel):
"""
Get group or default team thresholds.
:param group_name: The name of the group or team.
:return: Group or default team thresholds.
:param group_name: The name of the group.
:return: Group thresholds or default team thresholds.
"""
for group in self.team_groups or []:
if group.name == group_name:

View File

@ -1,9 +1,11 @@
from __future__ import annotations
import re
from datetime import datetime
from enum import Enum
from typing import List, NamedTuple, Optional
from typing import Any, List, NamedTuple, Optional
import dateutil.parser
from jira import Issue
from buildscripts.client.jiraclient import JiraClient
@ -58,6 +60,7 @@ class BfIssue(NamedTuple):
assigned_team: str
evergreen_projects: List[str]
temperature: BfTemperature
created_time: datetime
@classmethod
def from_jira_issue(cls, issue: Issue) -> BfIssue:
@ -88,8 +91,15 @@ class BfIssue(NamedTuple):
assigned_team=assigned_team,
evergreen_projects=evergreen_projects,
temperature=temperature,
created_time=dateutil.parser.parse(issue.fields.created),
)
def __eq__(self, other: Any) -> bool:
return isinstance(other, self.__class__) and self.key == other.key
def __hash__(self) -> int:
return hash(self.key)
class JiraService:
def __init__(self, jira_client: JiraClient) -> None:

View File

@ -1,4 +1,5 @@
import unittest
from datetime import datetime
import buildscripts.monitor_build_status.bfs_report as under_test
@ -24,12 +25,13 @@ class TestBFsReport(unittest.TestCase):
assigned_team="team-1",
evergreen_projects=["mongodb-mongo-master", "mongodb-mongo-master-nightly"],
temperature=under_test.BfTemperature.HOT,
created_time=datetime.now(),
)
bfs_report = under_test.BFsReport.empty()
bfs_report.add_bf_data(bf_1, evg_projects_info)
self.assertEqual(bfs_report.team_reports["team-1"].hot_bfs, {"BF-1"})
self.assertEqual(bfs_report.team_reports["team-1"].hot_bfs, {bf_1})
self.assertEqual(len(bfs_report.team_reports["team-1"].cold_bfs), 0)
self.assertEqual(len(bfs_report.team_reports["team-1"].perf_bfs), 0)
self.assertEqual(len(bfs_report.team_reports.keys()), 1)
@ -40,12 +42,13 @@ class TestBFsReport(unittest.TestCase):
assigned_team="team-1",
evergreen_projects=["mongodb-mongo-master"],
temperature=under_test.BfTemperature.HOT,
created_time=datetime.now(),
)
bfs_report = under_test.BFsReport.empty()
bfs_report.add_bf_data(bf_1, evg_projects_info)
self.assertEqual(bfs_report.team_reports["team-1"].hot_bfs, {"BF-1"})
self.assertEqual(bfs_report.team_reports["team-1"].hot_bfs, {bf_1})
self.assertEqual(len(bfs_report.team_reports["team-1"].cold_bfs), 0)
self.assertEqual(len(bfs_report.team_reports["team-1"].perf_bfs), 0)
self.assertEqual(len(bfs_report.team_reports.keys()), 1)
@ -56,13 +59,14 @@ class TestBFsReport(unittest.TestCase):
assigned_team="team-1",
evergreen_projects=["mongodb-mongo-master"],
temperature=under_test.BfTemperature.COLD,
created_time=datetime.now(),
)
bfs_report = under_test.BFsReport.empty()
bfs_report.add_bf_data(bf_1, evg_projects_info)
self.assertEqual(len(bfs_report.team_reports["team-1"].hot_bfs), 0)
self.assertEqual(bfs_report.team_reports["team-1"].cold_bfs, {"BF-1"})
self.assertEqual(bfs_report.team_reports["team-1"].cold_bfs, {bf_1})
self.assertEqual(len(bfs_report.team_reports["team-1"].perf_bfs), 0)
self.assertEqual(len(bfs_report.team_reports.keys()), 1)
@ -72,6 +76,7 @@ class TestBFsReport(unittest.TestCase):
assigned_team="team-1",
evergreen_projects=["sys-perf"],
temperature=under_test.BfTemperature.HOT,
created_time=datetime.now(),
)
bfs_report = under_test.BFsReport.empty()
@ -79,7 +84,7 @@ class TestBFsReport(unittest.TestCase):
self.assertEqual(len(bfs_report.team_reports["team-1"].hot_bfs), 0)
self.assertEqual(len(bfs_report.team_reports["team-1"].cold_bfs), 0)
self.assertEqual(bfs_report.team_reports["team-1"].perf_bfs, {"BF-1"})
self.assertEqual(bfs_report.team_reports["team-1"].perf_bfs, {bf_1})
self.assertEqual(len(bfs_report.team_reports.keys()), 1)
def test_add_cold_perf_bf(self):
@ -88,6 +93,7 @@ class TestBFsReport(unittest.TestCase):
assigned_team="team-1",
evergreen_projects=["sys-perf"],
temperature=under_test.BfTemperature.COLD,
created_time=datetime.now(),
)
bfs_report = under_test.BFsReport.empty()
@ -95,37 +101,5 @@ class TestBFsReport(unittest.TestCase):
self.assertEqual(len(bfs_report.team_reports["team-1"].hot_bfs), 0)
self.assertEqual(len(bfs_report.team_reports["team-1"].cold_bfs), 0)
self.assertEqual(bfs_report.team_reports["team-1"].perf_bfs, {"BF-1"})
self.assertEqual(len(bfs_report.team_reports.keys()), 1)
def test_combine_teams(self):
bfs_report = under_test.BFsReport(
team_reports={
"Team 1": under_test.CategorizedBFs(
hot_bfs={"HOT-BF-1", "HOT-BF-2"},
cold_bfs={"COLD-BF-1", "COLD-BF-2"},
perf_bfs={"PERF-BF-1", "PERF-BF-2"},
),
"Team 2": under_test.CategorizedBFs(
hot_bfs={"HOT-BF-3", "HOT-BF-4"},
cold_bfs={"COLD-BF-3", "COLD-BF-4"},
perf_bfs={"PERF-BF-3", "PERF-BF-4"},
),
}
)
bfs_report.combine_teams(["Team 1", "Team 2"], "Group 1")
self.assertEqual(
bfs_report.team_reports["Group 1"].hot_bfs,
{"HOT-BF-1", "HOT-BF-2", "HOT-BF-3", "HOT-BF-4"},
)
self.assertEqual(
bfs_report.team_reports["Group 1"].cold_bfs,
{"COLD-BF-1", "COLD-BF-2", "COLD-BF-3", "COLD-BF-4"},
)
self.assertEqual(
bfs_report.team_reports["Group 1"].perf_bfs,
{"PERF-BF-1", "PERF-BF-2", "PERF-BF-3", "PERF-BF-4"},
)
self.assertEqual(bfs_report.team_reports["team-1"].perf_bfs, {bf_1})
self.assertEqual(len(bfs_report.team_reports.keys()), 1)

View File

@ -4,345 +4,57 @@ import buildscripts.monitor_build_status.cli as under_test
class TestSummarize(unittest.TestCase):
def test_previous_unknown_current_red_not_friday(self):
previous_build_status = under_test.BuildStatus.UNKNOWN
current_build_status = under_test.BuildStatus.RED
today_is_friday = False
def test_all_thresholds_below_100(self):
scope_percentages = {
"Scope 1": [0.0, 0.0, 0.0],
"Scope 2": [0.0, 0.0, 0.0],
"Scope 3": [0.0, 0.0, 0.0],
"Scope 4": [0.0, 0.0, 0.0],
}
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
summary = under_test.MonitorBuildStatusOrchestrator._summarize(scope_percentages)
expected_status = under_test.BuildStatus.YELLOW
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_YELLOW.value}\n\n"
f"{under_test.SummaryMsg.PREFIX.value} "
f"{under_test.SummaryMsg.BELOW_THRESHOLDS.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_green_current_red_not_friday(self):
previous_build_status = under_test.BuildStatus.GREEN
current_build_status = under_test.BuildStatus.RED
today_is_friday = False
def test_all_thresholds_are_100(self):
scope_percentages = {
"Scope 1": [100.0, 100.0, 100.0],
"Scope 2": [100.0, 100.0, 100.0],
"Scope 3": [100.0, 100.0, 100.0],
"Scope 4": [100.0, 100.0, 100.0],
}
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
summary = under_test.MonitorBuildStatusOrchestrator._summarize(scope_percentages)
expected_status = under_test.BuildStatus.YELLOW
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_YELLOW.value}\n\n"
f"{under_test.SummaryMsg.PREFIX.value} "
f"{under_test.SummaryMsg.BELOW_THRESHOLDS.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_yellow_current_red_not_friday(self):
previous_build_status = under_test.BuildStatus.YELLOW
current_build_status = under_test.BuildStatus.RED
today_is_friday = False
def test_some_threshold_exceeded_100(self):
scope_percentages = {
"Scope 1": [101.0, 0.0, 0.0],
"Scope 2": [0.0, 101.0, 0.0],
"Scope 3": [0.0, 0.0, 101.0],
"Scope 4": [0.0, 0.0, 0.0],
}
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
summary = under_test.MonitorBuildStatusOrchestrator._summarize(scope_percentages)
expected_status = under_test.BuildStatus.YELLOW
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_IS.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_YELLOW.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_red_current_red_not_friday(self):
previous_build_status = under_test.BuildStatus.RED
current_build_status = under_test.BuildStatus.RED
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.RED
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_IS.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.STILL_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_RED.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_unknown_current_red_on_friday(self):
previous_build_status = under_test.BuildStatus.UNKNOWN
current_build_status = under_test.BuildStatus.RED
today_is_friday = True
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.RED
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.ENTER_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_RED.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_green_current_red_on_friday(self):
previous_build_status = under_test.BuildStatus.GREEN
current_build_status = under_test.BuildStatus.RED
today_is_friday = True
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.RED
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.ENTER_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_RED.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_yellow_current_red_on_friday(self):
previous_build_status = under_test.BuildStatus.YELLOW
current_build_status = under_test.BuildStatus.RED
today_is_friday = True
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.RED
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.ENTER_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_RED.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_red_current_red_on_friday(self):
previous_build_status = under_test.BuildStatus.RED
current_build_status = under_test.BuildStatus.RED
today_is_friday = True
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.RED
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_IS.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED_X2.value}\n"
f"{under_test.SummaryMsg.STILL_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_RED.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_unknown_current_yellow(self):
previous_build_status = under_test.BuildStatus.UNKNOWN
current_build_status = under_test.BuildStatus.YELLOW
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.YELLOW
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.PREFIX.value} "
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_YELLOW.value}\n\n"
f"\t- Scope 1\n\t- Scope 2\n\t- Scope 3\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_green_current_yellow(self):
previous_build_status = under_test.BuildStatus.GREEN
current_build_status = under_test.BuildStatus.YELLOW
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.YELLOW
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_YELLOW.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_yellow_current_yellow(self):
previous_build_status = under_test.BuildStatus.YELLOW
current_build_status = under_test.BuildStatus.YELLOW
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.YELLOW
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_IS.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_YELLOW.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_red_current_yellow(self):
previous_build_status = under_test.BuildStatus.RED
current_build_status = under_test.BuildStatus.YELLOW
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.RED
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_IS.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.THRESHOLD_EXCEEDED.value}\n"
f"{under_test.SummaryMsg.STILL_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_RED.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_unknown_current_green(self):
previous_build_status = under_test.BuildStatus.UNKNOWN
current_build_status = under_test.BuildStatus.GREEN
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.GREEN
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.BELOW_THRESHOLDS.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_GREEN.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_green_current_green(self):
previous_build_status = under_test.BuildStatus.GREEN
current_build_status = under_test.BuildStatus.GREEN
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.GREEN
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_IS.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.BELOW_THRESHOLDS.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_GREEN.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_yellow_current_green(self):
previous_build_status = under_test.BuildStatus.YELLOW
current_build_status = under_test.BuildStatus.GREEN
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.GREEN
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.BELOW_THRESHOLDS.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_GREEN.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)
def test_previous_red_current_green(self):
previous_build_status = under_test.BuildStatus.RED
current_build_status = under_test.BuildStatus.GREEN
today_is_friday = False
resulting_build_status, summary = under_test.MonitorBuildStatusOrchestrator._summarize(
previous_build_status, current_build_status, today_is_friday
)
expected_status = under_test.BuildStatus.GREEN
expected_summary = (
f"{under_test.SummaryMsg.TITLE.value}\n"
f"{under_test.SummaryMsg.STATUS_CHANGED.value.format(status=expected_status.value)}\n"
f"{under_test.SummaryMsg.BELOW_THRESHOLDS.value}\n"
f"{under_test.SummaryMsg.EXIT_RED.value}\n"
f"{under_test.SummaryMsg.ACTION_ON_GREEN.value}\n\n"
f"{under_test.SummaryMsg.PLAYBOOK_REFERENCE.value}\n"
)
self.assertEqual(resulting_build_status, expected_status)
self.assertEqual(summary, expected_summary)

View File

@ -5,45 +5,56 @@ import buildscripts.monitor_build_status.jira_service as under_test
class TestBfIssue(unittest.TestCase):
def setUp(self):
self.created = "Mon, 5 Aug 2024 15:05:10 +0000"
def test_parse_assigned_team_from_jira_issue(self):
team_name = "Team Name"
jira_issue_1 = MagicMock(fields=MagicMock(customfield_12751=[MagicMock(value=team_name)]))
jira_issue_1 = MagicMock(
fields=MagicMock(customfield_12751=[MagicMock(value=team_name)], created=self.created)
)
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_1)
self.assertEqual(bf_issue.assigned_team, team_name)
jira_issue_2 = MagicMock(fields=MagicMock(customfield_12751=[]))
jira_issue_2 = MagicMock(fields=MagicMock(customfield_12751=[], created=self.created))
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_2)
self.assertEqual(bf_issue.assigned_team, under_test.UNASSIGNED_LABEL)
jira_issue_3 = MagicMock(fields=MagicMock())
jira_issue_3 = MagicMock(fields=MagicMock(created=self.created))
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_3)
self.assertEqual(bf_issue.assigned_team, under_test.UNASSIGNED_LABEL)
def test_parse_evergreen_projects_from_jira_issue(self):
evergreen_projects = ["evg-project"]
jira_issue_1 = MagicMock(fields=MagicMock(customfield_14278=evergreen_projects))
jira_issue_1 = MagicMock(
fields=MagicMock(customfield_14278=evergreen_projects, created=self.created)
)
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_1)
self.assertEqual(bf_issue.evergreen_projects, evergreen_projects)
jira_issue_2 = MagicMock(fields=MagicMock(customfield_14278=[]))
jira_issue_2 = MagicMock(fields=MagicMock(customfield_14278=[], created=self.created))
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_2)
self.assertEqual(bf_issue.evergreen_projects, [])
jira_issue_3 = MagicMock(fields=MagicMock())
jira_issue_3 = MagicMock(fields=MagicMock(created=self.created))
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_3)
self.assertEqual(bf_issue.evergreen_projects, [])
def test_parse_bf_temperature_from_jira_issue(self):
bf_temperature = "hot"
jira_issue_1 = MagicMock(fields=MagicMock(customfield_24859=bf_temperature))
jira_issue_1 = MagicMock(
fields=MagicMock(customfield_24859=bf_temperature, created=self.created)
)
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_1)
self.assertEqual(bf_issue.temperature, under_test.BfTemperature.HOT)
bf_temperature = "cold"
jira_issue_2 = MagicMock(fields=MagicMock(customfield_24859=bf_temperature))
jira_issue_2 = MagicMock(
fields=MagicMock(customfield_24859=bf_temperature, created=self.created)
)
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_2)
self.assertEqual(bf_issue.temperature, under_test.BfTemperature.COLD)
jira_issue_3 = MagicMock(fields=MagicMock())
jira_issue_3 = MagicMock(fields=MagicMock(created=self.created))
bf_issue = under_test.BfIssue.from_jira_issue(jira_issue_3)
self.assertEqual(bf_issue.temperature, under_test.BfTemperature.NONE)

View File

@ -1,12 +1,14 @@
overall_thresholds:
hot_bf_count: 15
cold_bf_count: 50
perf_bf_count: 15
hot_bf_count: 30
cold_bf_count: 100
perf_bf_count: 30
include_bfs_older_than_hours: 168 # 7 days
team_default_thresholds:
hot_bf_count: 3
cold_bf_count: 10
perf_bf_count: 5
include_bfs_older_than_hours: 48
team_groups:
######################################################################
@ -14,11 +16,48 @@ team_groups:
######################################################################
# - name: Group Name
# teams:
# - Team Name 1 # Should exactly match "Assigned Teams" field value
# - Team Name 1 # Should exactly match "Assigned Teams" Jira BF field value
# - Team Name 2
# - Team Name 3
# thresholds:
# hot_bf_count: 3
# cold_bf_count: 10
# perf_bf_count: 5
# include_bfs_older_than_hours: 168 # 7 days
######################################################################
# Core Server Team VP orgs as described in https://wiki.corp.mongodb.com/pages/viewpage.action?spaceKey=KERNEL&title=Server+Home
- name: "Clusters & Integrations"
teams:
- Server Security
- Networking & Observability
- Workload Scheduling
- Server Programmability
- Cluster Scalability
- Catalog and Routing
thresholds:
hot_bf_count: 15
cold_bf_count: 50
perf_bf_count: 15
include_bfs_older_than_hours: 168 # 7 days
- name: "Durable Transactions & Availability"
teams:
- Replication
- Storage Execution
- RSS Sydney
- Storage Engines
thresholds:
hot_bf_count: 15
cold_bf_count: 50
perf_bf_count: 15
include_bfs_older_than_hours: 168 # 7 days
- name: "Query"
teams:
- Query Execution
- Query Optimization
- Query Integration
thresholds:
hot_bf_count: 15
cold_bf_count: 50
perf_bf_count: 15
include_bfs_older_than_hours: 168 # 7 days

View File

@ -1103,26 +1103,6 @@ tasks:
- func: "set up venv"
- func: "upload pip requirements"
- func: "configure evergreen api credentials"
# Attempting to download build status file that was uploaded by previous run of this task
# `remote_file` location should match uploading file location in steps below
# `optional: true` is to pass this step when this task is running for the first time
- command: s3.get
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
remote_file: ${project}/monitor_build_status/${branch_name}/build_status_latest_file.txt
bucket: mciuploads
local_file: src/input_build_status_file.txt
optional: true
# The same as above but for patches for testing purposes
- command: s3.get
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
remote_file: ${project}/monitor_build_status_testing/${branch_name}/build_status_latest_file_testing.txt
bucket: mciuploads
local_file: src/input_build_status_file_testing.txt
optional: true
- command: subprocess.exec
type: test
params:
@ -1134,41 +1114,6 @@ tasks:
JIRA_AUTH_ACCESS_TOKEN_SECRET: ${jira_auth_access_token_secret}
JIRA_AUTH_CONSUMER_KEY: ${jira_auth_consumer_key}
JIRA_AUTH_KEY_CERT: ${jira_auth_key_cert}
# Uploading build status file after each run of this task to be consumed by the next run
# `remote_file` location should match downloading file location in steps above
- command: s3.put
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
local_file: src/output_build_status_file.txt
remote_file: ${project}/monitor_build_status/${branch_name}/build_status_latest_file.txt
bucket: mciuploads
permissions: public-read
content_type: text/plain
display_name: Build Status Latest
patchable: false
# The same as above but for patches for testing purposes to avoid overriding the file
# that is used on the waterfall runs
# However `remote_file` location could be changed here to intentionally override the file
# that is used on the waterfall from the patch in case of emergency, e.g. build status was
# evaluated incorrectly on the waterfall and incorrect status was uploaded on S3
- command: s3.put
params:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
local_file: src/output_build_status_file_testing.txt
remote_file: ${project}/monitor_build_status_testing/${branch_name}/build_status_latest_file_testing.txt
bucket: mciuploads
permissions: public-read
content_type: text/plain
display_name: Build Status Latest Patch Testing
patch_only: true
- command: subprocess.exec
type: test
params:
binary: bash
args:
- "src/evergreen/monitor_build_status_exit.sh"
- name: monitor_mongo_fork_10gen
tags: ["assigned_to_jira_team_devprod_correctness", "auxiliary"]

View File

@ -1,16 +0,0 @@
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 2>&1 && pwd)"
. "$DIR/prelude.sh"
set -o errexit
set -o verbose
cd src
if [ -f monitor_build_status_command_exit_code.txt ]; then
exit_code=$(cat monitor_build_status_command_exit_code.txt)
else
exit_code=0
fi
echo "Exiting monitor_build_status with code $exit_code"
exit "$exit_code"

View File

@ -8,15 +8,9 @@ cd src
activate_venv
command_invocation="$python buildscripts/monitor_build_status/cli.py"
if [ "${is_patch}" = "true" ]; then
command_invocation="$command_invocation --input-status-file input_build_status_file_testing.txt"
command_invocation="$command_invocation --output-status-file output_build_status_file_testing.txt"
else
if [ "${is_patch}" != "true" ]; then
command_invocation="$command_invocation --notify"
fi
echo "Verbatim monitor_build_status invocation: ${command_invocation}"
set +o errexit
eval "${command_invocation}"
echo "$?" > monitor_build_status_command_exit_code.txt
set -o errexit