Skip to content

Commit bec0529

Browse files
authored
Merge branch 'main' into label_asset
2 parents 3ef50a9 + abd0153 commit bec0529

File tree

5 files changed

+132
-27
lines changed

5 files changed

+132
-27
lines changed

.pre-commit-config.yaml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,6 @@ repos:
4141
- id: ruff
4242
- id: ruff-format
4343

44-
# https://github.com/renovatebot/pre-commit-hooks/issues/2621
45-
# This hook goes over the 250MiB limit that pre-commit.ci imposes
46-
# Disable unless a solution is found.
47-
# - repo: https://github.com/renovatebot/pre-commit-hooks
48-
# rev: 39.45.0
49-
# hooks:
50-
# - id: renovate-config-validator
51-
5244
- repo: https://github.com/gitleaks/gitleaks
5345
rev: v8.30.1
5446
hooks:
@@ -62,6 +54,18 @@ repos:
6254
exclude: ^(docs/|.*test.*\.py$|utilities/manifests/.*|utilities/plugins/tgis_grpc/.*)
6355

6456

57+
- repo: local
58+
hooks:
59+
- id: check-signoff
60+
name: Check Signed-off-by
61+
stages: [commit-msg]
62+
language: system
63+
entry: >
64+
bash -c 'grep -q "^Signed-off-by: .* <.*@.*>" "$1" ||
65+
{ echo "ERROR: Commit message must include a valid Signed-off-by trailer.";
66+
echo " Use: git commit -s";
67+
echo " Or add manually: Signed-off-by: Your Name <your@email.com>"; exit 1; }' --
68+
6569
- repo: https://github.com/espressif/conventional-precommit-linter
6670
rev: v1.11.0
6771
hooks:

semgrep.yaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ rules:
810810
env:
811811
TITLE: ${{ github.event.pull_request.title }}
812812
patterns:
813-
- pattern-regex: 'run:\s*(?:[|>][-+]?)?[\s\S]*?\$\{\{\s*github\.(head_ref|event\.(issue|pull_request|discussion|review|review_comment|comment)\.(title|body|head\.ref|head\.label)|event\.head_commit\.message|event\.commits\[\d+\]\.message)\s*\}\}'
813+
- pattern-regex: 'run:\s*(?:[|>][-+]?\n(?:[ \t]+[^\n]*\n)*|[^\n]*)\$\{\{\s*github\.(head_ref|event\.(issue|pull_request|discussion|review|review_comment|comment)\.(title|body|head\.ref|head\.label)|event\.head_commit\.message|event\.commits\[\d+\]\.message)\s*\}\}'
814814
paths:
815815
include:
816816
- "**/.github/workflows/*.yml"
@@ -848,7 +848,7 @@ rules:
848848
- If checkout is needed, use merge commit: refs/pull/${{ github.event.number }}/merge
849849
- Add persist-credentials: false to limit token scope
850850
patterns:
851-
- pattern-regex: 'pull_request_target[\s\S]*?uses:\s*actions/checkout@[^\n]*\n(\s+\w+:.*\n)*\s+ref:\s*\$\{\{[^\}]*pull_request\.head\.(sha|ref)\s*\}\}'
851+
- pattern-regex: 'pull_request_target[\s\S]*?uses:\s*actions/checkout@[^\n]*\n(\s+[\w-]+:.*\n)*\s+ref:\s*\$\{\{[^\}]*pull_request\.head\.(sha|ref)\s*\}\}'
852852
paths:
853853
include:
854854
- "**/.github/workflows/*.yml"
@@ -1066,8 +1066,6 @@ rules:
10661066
$VAR := os.Getenv("...")
10671067
- pattern-not: |
10681068
var $VAR = os.Getenv("...")
1069-
- pattern-not: |
1070-
const $VAR = os.Getenv("...")
10711069
- pattern-not: |
10721070
$VAR, $_ := os.LookupEnv("...")
10731071
metadata:
@@ -1869,7 +1867,7 @@ rules:
18691867
Remediation: Always quote variables in file operations:
18701868
rm "$FILE" # correct
18711869
rm $FILE # dangerous
1872-
pattern-regex: '(rm|cp|mv|eval|chmod|chown|kill|pkill)\s+[^|;]*(?<!["''\\])\$[A-Za-z_][A-Za-z0-9_]*'
1870+
pattern-regex: '(rm|cp|mv|eval|chmod|chown|kill|pkill)\s+[^|;]*(?<!["''\\])\$(?:\{[A-Za-z_][A-Za-z0-9_]*(?:[:\-\+\?=][^}]*)?\}|[A-Za-z_][A-Za-z0-9_]*)'
18731871
metadata:
18741872
cwe: "CWE-78"
18751873
category: "security"

tests/model_registry/mcp_servers/config/conftest.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
MCP_CATALOG_INVALID_SOURCE,
1313
MCP_CATALOG_SOURCE,
1414
MCP_CATALOG_SOURCE2,
15+
MCP_CATALOG_SOURCE_ID,
16+
MCP_CATALOG_SOURCE_NAME,
1517
MCP_SERVERS_YAML,
1618
MCP_SERVERS_YAML2,
19+
MCP_SERVERS_YAML_CATALOG_PATH,
1720
)
1821
from tests.model_registry.utils import (
1922
wait_for_mcp_catalog_api,
@@ -106,3 +109,64 @@ def mcp_invalid_yaml_configmap_patch(
106109
wait_for_model_catalog_pod_ready_after_deletion(
107110
client=admin_client, model_registry_namespace=model_registry_namespace
108111
)
112+
113+
114+
@pytest.fixture(scope="class")
115+
def mcp_included_excluded_configmap_patch(
116+
request: pytest.FixtureRequest,
117+
admin_client: DynamicClient,
118+
model_registry_namespace: str,
119+
mcp_catalog_rest_urls: list[str],
120+
model_registry_rest_headers: dict[str, str],
121+
) -> Generator[None]:
122+
"""
123+
Class-scoped fixture that patches the ConfigMap with an MCP source
124+
including includedServers/excludedServers filters.
125+
126+
Parametrized via request.param with a dict containing:
127+
- "includedServers": list[str] (optional)
128+
- "excludedServers": list[str] (optional)
129+
"""
130+
filter_params = request.param
131+
132+
source_config: dict = {
133+
"name": MCP_CATALOG_SOURCE_NAME,
134+
"id": MCP_CATALOG_SOURCE_ID,
135+
"type": "yaml",
136+
"enabled": True,
137+
"properties": {"yamlCatalogPath": MCP_SERVERS_YAML_CATALOG_PATH},
138+
"labels": [MCP_CATALOG_SOURCE_NAME],
139+
}
140+
if "includedServers" in filter_params:
141+
source_config["includedServers"] = filter_params["includedServers"]
142+
if "excludedServers" in filter_params:
143+
source_config["excludedServers"] = filter_params["excludedServers"]
144+
145+
catalog_config_map = ConfigMap(
146+
name=DEFAULT_CUSTOM_MODEL_CATALOG,
147+
client=admin_client,
148+
namespace=model_registry_namespace,
149+
)
150+
151+
current_data = yaml.safe_load(catalog_config_map.instance.data.get("sources.yaml", "{}") or "{}")
152+
if "mcp_catalogs" not in current_data:
153+
current_data["mcp_catalogs"] = []
154+
current_data["mcp_catalogs"].append(source_config)
155+
156+
patches = {
157+
"data": {
158+
"sources.yaml": yaml.dump(current_data, default_flow_style=False),
159+
"mcp-servers.yaml": MCP_SERVERS_YAML,
160+
}
161+
}
162+
163+
with ResourceEditor(patches={catalog_config_map: patches}):
164+
wait_for_model_catalog_pod_ready_after_deletion(
165+
client=admin_client, model_registry_namespace=model_registry_namespace
166+
)
167+
wait_for_mcp_catalog_api(url=mcp_catalog_rest_urls[0], headers=model_registry_rest_headers)
168+
yield
169+
170+
wait_for_model_catalog_pod_ready_after_deletion(
171+
client=admin_client, model_registry_namespace=model_registry_namespace
172+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from typing import Self
2+
3+
import pytest
4+
from simple_logger.logger import get_logger
5+
6+
from tests.model_registry.utils import execute_get_command
7+
8+
LOGGER = get_logger(name=__name__)
9+
10+
11+
@pytest.mark.tier2
12+
@pytest.mark.parametrize(
13+
"mcp_included_excluded_configmap_patch",
14+
[
15+
pytest.param(
16+
{"includedServers": ["weather-*", "file-*"], "excludedServers": ["file-*"]},
17+
id="combined_include_exclude",
18+
),
19+
],
20+
indirect=True,
21+
)
22+
@pytest.mark.usefixtures("mcp_included_excluded_configmap_patch")
23+
class TestMCPServerIncludedExcludedFiltering:
24+
"""Tests for includedServers/excludedServers glob pattern filtering (TC-LOAD-003, TC-LOAD-004, TC-LOAD-005)."""
25+
26+
def test_included_and_excluded_servers(
27+
self: Self,
28+
mcp_catalog_rest_urls: list[str],
29+
model_registry_rest_headers: dict[str, str],
30+
):
31+
"""Verify includedServers are loaded and excludedServers are not (TC-LOAD-003, TC-LOAD-004, TC-LOAD-005)."""
32+
response = execute_get_command(
33+
url=f"{mcp_catalog_rest_urls[0]}mcp_servers",
34+
headers=model_registry_rest_headers,
35+
)
36+
server_names = {server["name"] for server in response.get("items", [])}
37+
assert "weather-api" in server_names, f"Expected 'weather-api' in {server_names}"
38+
assert "file-manager" not in server_names, f"Expected 'file-manager' not in {server_names}"

uv.lock

Lines changed: 15 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)