Skip to content

Commit ccbceda

Browse files
[YOLO] create a new pipeline to run functional tests per framework (#1451)
1 parent 2da0de1 commit ccbceda

File tree

4 files changed

+218
-0
lines changed

4 files changed

+218
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
inputSet:
2+
name: default_on_pr_input
3+
identifier: default_on_pr_input
4+
orgIdentifier: Custom_Models
5+
projectIdentifier: datarobotusermodels
6+
pipeline:
7+
identifier: Test_functional_by_framework_multisteps
8+
properties:
9+
ci:
10+
codebase:
11+
repoName: datarobot-user-models
12+
build:
13+
type: PR
14+
spec:
15+
number: <+trigger.prNumber>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
pipeline:
2+
projectIdentifier: datarobotusermodels
3+
orgIdentifier: Custom_Models
4+
tags: {}
5+
properties:
6+
ci:
7+
codebase:
8+
connectorRef: account.svc_harness_git1
9+
repoName: <+input>
10+
build: <+input>
11+
sparseCheckout: []
12+
stages:
13+
- stage:
14+
name: Build list of envs to test
15+
identifier: build_list_of_envs_to_test
16+
description: ""
17+
type: CI
18+
spec:
19+
cloneCodebase: true
20+
execution:
21+
steps:
22+
- step:
23+
type: Run
24+
name: build_list_of_environments_to_test_on
25+
identifier: build_list_of_environments_to_test_on
26+
spec:
27+
connectorRef: account.dockerhub_datarobot_read
28+
shell: Sh
29+
command: |-
30+
matrix_values=$(python3 ./harness_scripts/functional_by_framework_multistep/generate_testlist.py ./tests/functional/test_per_framework.json ./)
31+
echo ${matrix_values}
32+
outputVariables:
33+
- name: matrix_values
34+
caching:
35+
enabled: true
36+
paths: []
37+
platform:
38+
os: Linux
39+
arch: Amd64
40+
runtime:
41+
type: Cloud
42+
spec: {}
43+
buildIntelligence:
44+
enabled: true
45+
- stage:
46+
name: Test functional by framework
47+
identifier: check_by_framework
48+
description: ""
49+
type: CI
50+
spec:
51+
cloneCodebase: true
52+
execution:
53+
steps:
54+
- step:
55+
type: Run
56+
name: Run functional test in provided framework
57+
identifier: Run_1
58+
spec:
59+
connectorRef: datarobot_user_models_read_write
60+
image: datarobotdev/<+matrix.env.repo>:<+matrix.env.tag>
61+
shell: Sh
62+
command: |-
63+
./harness_scripts/functional_by_framework/check_by_framework_run1_step_entrypoint.sh \
64+
<+matrix.env.framework> <+matrix.env.env_folder>
65+
resources:
66+
limits:
67+
memory: 3G
68+
when:
69+
stageStatus: Success
70+
caching:
71+
enabled: true
72+
paths: []
73+
platform:
74+
os: Linux
75+
arch: Amd64
76+
runtime:
77+
type: Cloud
78+
spec: {}
79+
buildIntelligence:
80+
enabled: true
81+
when:
82+
pipelineStatus: Success
83+
strategy:
84+
matrix:
85+
env: <+json.list("environments", <+pipeline.stages.build_list_of_envs_to_test.spec.execution.steps.build_list_of_environments_to_test_on.output.outputVariables.matrix_values>)>
86+
nodeName: <+matrix.env.env_folder>/<+matrix.env.framework> - <+matrix.env.tag>
87+
identifier: Test_functional_by_framework_multisteps
88+
description: |-
89+
Runs functional tests for each framework in a corresponding image.
90+
If only DRUM changed in the PR, latest image is taken for every framework, DRUM installed and tests run.
91+
If environment itself has changed, temporary image is built.
92+
name: Test functional by framework - multisteps
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import json
2+
import os
3+
import sys
4+
import logging
5+
6+
# Configure logging
7+
logging.basicConfig(
8+
level=logging.INFO,
9+
format="[%(levelname)s] %(asctime)s - %(message)s",
10+
datefmt="%Y-%m-%d %H:%M:%S",
11+
)
12+
13+
logger = logging.getLogger(__name__)
14+
15+
16+
def load_tests_list(tests_list_path):
17+
try:
18+
logger.info(f"Loading tests list from {tests_list_path}")
19+
with open(tests_list_path, "r") as f:
20+
data = json.load(f)
21+
return data.get("environments", [])
22+
except FileNotFoundError:
23+
logger.error(f"Tests list file not found: {tests_list_path}")
24+
sys.exit(1)
25+
except json.JSONDecodeError:
26+
logger.error("Invalid JSON in tests list.")
27+
sys.exit(1)
28+
29+
30+
def load_env_info(env_info_path):
31+
try:
32+
logger.info(f"Reading env_info from {env_info_path}")
33+
with open(env_info_path, "r") as f:
34+
data = json.load(f)
35+
return {"repo": data["imageRepository"], "tag": data["environmentVersionId"]}
36+
except FileNotFoundError:
37+
logger.error(f"env_info.json not found at path: {env_info_path}")
38+
return None
39+
except KeyError as e:
40+
logger.error(f"Missing key in env_info.json: {e}")
41+
return None
42+
except json.JSONDecodeError:
43+
logger.error("Invalid JSON in env_info.json.")
44+
return None
45+
46+
47+
def build_environments(env_list, root_path):
48+
output_envs = []
49+
50+
for env in env_list:
51+
env_folder = env["env_folder"]
52+
framework = env["framework"]
53+
with_local = env.get("with_local", False)
54+
55+
env_info_path = os.path.join(root_path, env_folder, framework, "env_info.json")
56+
env_info = load_env_info(env_info_path)
57+
58+
if not env_info:
59+
logger.warning(f"Skipping environment due to invalid env_info: {env}")
60+
continue
61+
62+
base_record = {
63+
"env_folder": env_folder,
64+
"framework": framework,
65+
"repo": env_info["repo"],
66+
"tag": env_info["tag"],
67+
}
68+
69+
output_envs.append(base_record)
70+
71+
if with_local:
72+
local_record = base_record.copy()
73+
local_record["tag"] = f"{env_info['tag']}.local"
74+
output_envs.append(local_record)
75+
logger.info(f"Added local version for environment: {env_folder}/{framework}")
76+
77+
return output_envs
78+
79+
80+
def main():
81+
if len(sys.argv) != 3:
82+
logger.error("Usage: python build_env_output.py <tests-list.json> <root-path>")
83+
sys.exit(1)
84+
85+
tests_list_path = sys.argv[1]
86+
root_path = sys.argv[2]
87+
88+
env_list = load_tests_list(tests_list_path)
89+
final_envs = build_environments(env_list, root_path)
90+
91+
output = {"environments": final_envs}
92+
print(json.dumps(output, separators=(",", ":"))) # Minified JSON
93+
94+
95+
if __name__ == "__main__":
96+
main()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"environments" : [
3+
{"env_folder": "public_dropin_environments", "framework": "java_codegen", "with_local": true},
4+
{"env_folder": "public_dropin_environments", "framework": "python3_keras", "with_local": true},
5+
{"env_folder": "public_dropin_environments", "framework": "python3_onnx", "with_local": true},
6+
{"env_folder": "public_dropin_environments", "framework": "python3_pmml", "with_local": true},
7+
{"env_folder": "public_dropin_environments", "framework": "python3_pytorch", "with_local": true},
8+
{"env_folder": "public_dropin_environments", "framework": "python3_sklearn", "with_local": true},
9+
{"env_folder": "public_dropin_environments", "framework": "python3_xgboost", "with_local": true},
10+
{"env_folder": "public_dropin_environments", "framework": "python311", "with_local": true},
11+
{"env_folder": "public_dropin_environments", "framework": "python311_genai", "with_local": true},
12+
{"env_folder": "public_dropin_environments", "framework": "r_lang", "with_local": true},
13+
{"env_folder": "public_dropin_gpu_environments", "framework": "vllm"}
14+
]
15+
}

0 commit comments

Comments
 (0)