-
Notifications
You must be signed in to change notification settings - Fork 9
PYTHON-5389: Add Tags to each buildvariant and augment test skipping/tracking policy. #82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
7a03b0e
f045cda
28e4f7d
fabe044
088abf7
3d467f3
69b644a
df7a55c
2d2f67c
7889fcc
bc1f49e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
Pre-commit hook to check if buildvariant tasks contain required language tags. | ||
""" | ||
|
||
import logging | ||
import sys | ||
import yaml | ||
from pathlib import Path | ||
from typing import List, Dict, Any | ||
|
||
logging.basicConfig() | ||
logger = logging.getLogger(__file__) | ||
logger.setLevel(logging.DEBUG) | ||
|
||
|
||
CURRENT_DIR = Path(__file__).parent.resolve() | ||
CONFIG_YML = CURRENT_DIR / "config.yml" | ||
VALID_LANGUAGES = {"python", "golang", "javascript", "csharp"} | ||
|
||
|
||
def load_yaml_file(file_path: str) -> Dict[Any, Any]: | ||
"""Load and parse a YAML file.""" | ||
with open(file_path, "r", encoding="utf-8") as file: | ||
return yaml.safe_load(file) or {} | ||
|
||
|
||
def check_buildvariants(data: Dict[Any, Any]) -> List[str]: | ||
""" | ||
Check if buildvariant tasks contain at least one required language tag | ||
as well as the language within the buildvariant name. | ||
|
||
Example Buildvariant structure in YAML: | ||
buildvariants: | ||
- name: test-semantic-kernel-python-rhel | ||
display_name: Semantic-Kernel RHEL Python | ||
tags: [python] | ||
expansions: | ||
DIR: semantic-kernel-python | ||
run_on: | ||
- rhel87-small | ||
tasks: | ||
- name: test-semantic-kernel-python-local | ||
- name: test-semantic-kernel-python-remote | ||
batchtime: 10080 # 1 week | ||
|
||
Args: | ||
data: Parsed YAML data | ||
|
||
Returns: | ||
List of error messages for tasks missing required tags | ||
""" | ||
errors = [] | ||
|
||
buildvariants = data.get("buildvariants", []) | ||
if not isinstance(buildvariants, list): | ||
return ["'buildvariants' should be a list"] | ||
|
||
for i, buildvariant in enumerate(buildvariants): | ||
if not isinstance(buildvariant, dict): | ||
errors.append(f"buildvariants[{i}] should contain sub-fields") | ||
continue | ||
|
||
buildvariant_name = buildvariant.get("name", "") | ||
if not buildvariant_name: | ||
errors.append(f"buildvariants[{i}] is missing 'name'") | ||
continue | ||
else: | ||
if all([f"-{lang}-" not in buildvariant_name for lang in VALID_LANGUAGES]): | ||
errors.append( | ||
f"buildvariant '{buildvariant_name}' should contain one" | ||
f" '-[{', '.join(VALID_LANGUAGES)}]-' in its name" | ||
f"got: {buildvariant_name}", | ||
) | ||
|
||
buildvariant_display_name = buildvariant.get("display_name", buildvariant_name) | ||
|
||
tags = buildvariant.get("tags", []) | ||
|
||
if not isinstance(tags, list) or len(tags) != 1: | ||
errors.append( | ||
f"'tags' in buildvariant '{buildvariant_display_name}' should be a list of size 1" | ||
) | ||
continue | ||
|
||
if tags[0] not in VALID_LANGUAGES: | ||
errors.append( | ||
f"buildvariant '{buildvariant_display_name}' has invalid tag '{tags[0]}'. " | ||
f"Valid tags are: {', '.join(VALID_LANGUAGES)}" | ||
) | ||
return errors | ||
|
||
|
||
def main(): | ||
"""Main function for the pre-commit hook.""" | ||
total_errors = 0 | ||
|
||
data = load_yaml_file(CONFIG_YML) | ||
if not data: | ||
raise FileNotFoundError(f"Failed to load or parse {CONFIG_YML}") | ||
|
||
errors = check_buildvariants(data) | ||
|
||
if errors: | ||
logger.error("❌ Errors found in %s:", CONFIG_YML) | ||
for error in errors: | ||
logger.error(" - %s", error) | ||
total_errors += len(errors) | ||
|
||
if total_errors > 0: | ||
logger.error("❌ Total errors found: %s", total_errors) | ||
return 1 | ||
else: | ||
logger.info("✅ %s passed AI/ML testing pipeline validation", CONFIG_YML) | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,6 +110,8 @@ Test execution flow is defined in `.evergreen/config.yml`. The test pipeline's c | |
- `run_on` -- Specified platform to run on. `rhel87-small` or `ubuntu2204-small` should be used by default. Any other distro may fail Atlas CLI setup. | ||
- `tasks` -- Tasks to run. See below for more details | ||
- `cron` -- The tests are run via a cron job on a nightly cadence. This can be modified by setting a different cadence. Cron jobs can be scheduled using [cron syntax](https://crontab.guru/#0_0_*_*_*) | ||
- `tags` -- This should include the language where the AI/ML is run. i.e. `[python, csharp, golang, javascript]` Any tagged language will populate the | ||
appropriate language-specific slack channel. | ||
|
||
**[Tasks](https://docs.devprod.prod.corp.mongodb.com/evergreen/Project-Configuration/Project-Configuration-Files#tasks)** -- These are the "building blocks" of our runs. Here is where we consolidate the specific set of functions. The basic parameters to add are shown below | ||
|
||
|
@@ -185,8 +187,10 @@ evergreen patch -p ai-ml-pipeline-testing --param REPO_ORG=caseyclements --param | |
|
||
### Handling Failing Tests | ||
|
||
If tests are found to be failing, and cannot be addressed quickly, the responsible team MUST create a JIRA ticket, and disable the relevant tests | ||
Tests are run periodically (nightly) and any failures will propagate into both the `dbx-ai-ml-testing-pipline-notifications` and `dbx-ai-ml-testing-pipeline-notifications-{language}` channel. Repo owners of this `ai-ml-testing-pipeline` library are required to join the `dbx-ai-ml-testing-pipeline-notifications`. Pipeline specific implementers must **at least** join `dbx-ai-ml-testing-pipline-notifications-{language}` (e.g. whomever implemented `langchain-js` must at least be a member of `dbx-ai-ml-testing-pipeline-notifications-js`). | ||
|
||
If tests are found to be failing, and cannot be addressed quickly, the responsible team MUST create a JIRA ticket within their team's project (e.g. a python failure should generate an `INTPYTHON` ticket), and disable the relevant tests | ||
in the `config.yml` file, with a comment about the JIRA ticket that will address it. | ||
|
||
This policy will help ensure that a single failing integration does not cause noise in the `dbx-ai-ml-testing-pipeline-notifications` that would mask other | ||
This policy will help ensure that a single failing integration does not cause noise in the `dbx-ai-ml-testing-pipeline-notifications` or `dbx-ai-ml-testing-pipeline-notifications-{language}` that would mask other | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Won't there still be noise in the shared channel because failures are propagated to both slack channels? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the shared channel then becomes an opt-in. If there are several failures in one day across multiple drivers, it's difficult to parse. With individual channels it's easier to pay attention to only the relevant driver team notifications. The only users required to stay within that larger channel are those with a vested interest across driver implementations or the repo owners. |
||
failures. |
Uh oh!
There was an error while loading. Please reload this page.