utf-queue-client 1.16.0__tar.gz → 1.17.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. utf-queue-client-1.17.2/PKG-INFO +11 -0
  2. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/setup.py +2 -3
  3. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_amqp_connections.py +1 -1
  4. utf-queue-client-1.17.2/test/test_publish_release_info.py +145 -0
  5. utf-queue-client-1.17.2/test/test_rail_data_producer_tests.py +64 -0
  6. utf-queue-client-1.17.2/utf_queue_client/clients/test_rail_data_producer.py +95 -0
  7. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/models/base_model.py +8 -4
  8. utf-queue-client-1.17.2/utf_queue_client/models/schemas/utf_queue_models/models/python/__init__.py +0 -0
  9. utf-queue-client-1.17.2/utf_queue_client/models/schemas/utf_queue_models/models/python/generated_models.py +291 -0
  10. utf-queue-client-1.17.2/utf_queue_client/models/schemas/utf_queue_models/schema/queue_message.json +662 -0
  11. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/publish_release_info_cli.py +40 -21
  12. utf-queue-client-1.17.2/utf_queue_client.egg-info/PKG-INFO +11 -0
  13. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client.egg-info/SOURCES.txt +5 -0
  14. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client.egg-info/entry_points.txt +0 -1
  15. utf-queue-client-1.16.0/PKG-INFO +0 -13
  16. utf-queue-client-1.16.0/test/test_publish_release_info.py +0 -72
  17. utf-queue-client-1.16.0/utf_queue_client.egg-info/PKG-INFO +0 -13
  18. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/README.md +0 -0
  19. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/setup.cfg +0 -0
  20. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_async_consumer.py +0 -0
  21. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_connection_retry.py +0 -0
  22. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_data_lake_data_producer.py +0 -0
  23. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_http_producer.py +0 -0
  24. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_legacy_base_model.py +0 -0
  25. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_models.py +0 -0
  26. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_opentelemetry_data_producer.py +0 -0
  27. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_publish_test_results.py +0 -0
  28. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_sqa_test_result_producer.py +0 -0
  29. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_ubai_copy.py +0 -0
  30. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_ubai_search.py +0 -0
  31. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_ubai_update_retention.py +0 -0
  32. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_ubai_upload.py +0 -0
  33. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/test/test_utils.py +0 -0
  34. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/__init__.py +0 -0
  35. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/__init__.py +0 -0
  36. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/async_consumer.py +0 -0
  37. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/base_producer.py +0 -0
  38. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/data_lake_data_producer.py +0 -0
  39. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/http_producer.py +0 -0
  40. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/opentelemetry_data_producer.py +0 -0
  41. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/sqa_test_result_producer.py +0 -0
  42. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/clients/ubai_artifact_upload_request_producer.py +0 -0
  43. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/exceptions/__init__.py +0 -0
  44. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/models/__init__.py +0 -0
  45. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/models/model_factory.py +0 -0
  46. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/models/schemas/__init__.py +0 -0
  47. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/__init__.py +0 -0
  48. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/publish_test_results_cli.py +0 -0
  49. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/ubai_copy_cli.py +0 -0
  50. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/ubai_search_cli.py +0 -0
  51. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/ubai_update_retention_cli.py +0 -0
  52. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/scripts/ubai_upload_cli.py +0 -0
  53. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/utils/__init__.py +0 -0
  54. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/utils/queue_metrics_exporter.py +0 -0
  55. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client/utils/queue_span_exporter.py +0 -0
  56. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client.egg-info/dependency_links.txt +0 -0
  57. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client.egg-info/requires.txt +0 -0
  58. {utf-queue-client-1.16.0 → utf-queue-client-1.17.2}/utf_queue_client.egg-info/top_level.txt +0 -0
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.1
2
+ Name: utf-queue-client
3
+ Version: 1.17.2
4
+ Home-page:
5
+ Author: Joe Savage
6
+ Author-email: joe.savage@silabs.com
7
+ Keywords: UTF,
8
+ Requires-Python: >=3.6
9
+
10
+ No description provided
11
+
@@ -2,11 +2,10 @@
2
2
 
3
3
  """
4
4
 
5
-
6
5
  from setuptools import setup, find_packages # noqa: H301
7
6
 
8
7
  NAME = "utf-queue-client"
9
- VERSION = "1.16.0"
8
+ VERSION = "1.17.2"
10
9
  # To install the library, run the following
11
10
  #
12
11
  # python setup.py install
@@ -54,7 +53,7 @@ setup(
54
53
  "publish_test_results_cli = utf_queue_client.scripts.publish_test_results_cli:cli_entrypoint",
55
54
  "ubai_update_retention_cli = utf_queue_client.scripts.ubai_update_retention_cli:cli_entrypoint",
56
55
  "publish_release_info_cli = utf_queue_client.scripts.publish_release_info_cli:cli_entrypoint",
57
- "ubai_copy_cli = utf_queue_client.scripts.ubai_copy_cli:cli_entrypoint"
56
+ "ubai_copy_cli = utf_queue_client.scripts.ubai_copy_cli:cli_entrypoint",
58
57
  ],
59
58
  },
60
59
  include_package_data=True,
@@ -25,7 +25,7 @@ def queue_server(request):
25
25
  ],
26
26
  )
27
27
  def test_producer(queue_server, username, password):
28
- suffix = ".dev.silabs.net"
28
+ suffix = ".silabs.net"
29
29
  queue_server = f"{queue_server}{suffix}"
30
30
  l = logging.getLogger("test_producer")
31
31
  l.info("Creating producer...")
@@ -0,0 +1,145 @@
1
+ import pytest
2
+ from otel_extensions import inject_context_to_env, instrumented
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ from utf_queue_client.scripts.publish_release_info_cli import publish_release_information, \
7
+ update_artifacts_retention_days_to_keep_forever, cli
8
+ import requests
9
+ from unittest import mock
10
+ from unittest.mock import MagicMock, patch
11
+
12
+
13
+ @pytest.fixture
14
+ def publish_release_info():
15
+ yield [
16
+ ("releaseDate", "2023-06-16"),
17
+ ("branchName", "release/gecko_sdk_3.2"),
18
+ ("releaseType", "GA"),
19
+ ("releaseName", "23Q2-GA"),
20
+ ("SDKBuildNum", "407"),
21
+ ("installerURLSDK", "https://jenkins-cbs-gecko-sdk.silabs.net/job/Gecko_SDK_Suite_super/job/release%252F21q4/284/"),
22
+ ("IARVersionNum", "9.20.4"),
23
+ ("GCCVersionNum", "10.3.1"),
24
+ ("CommanderVersionNum", "v1.8.1"),
25
+ ("SEVersionNum", "1.2.4"),
26
+ ("WSTKFirmwareVersionNum", "v1.4.4")
27
+ ]
28
+
29
+
30
+ @instrumented
31
+ def test_publish_release_info(request, publish_release_info):
32
+ args = ["--username", "svc_sqabot", "--password", "password"]
33
+ for k, v in publish_release_info:
34
+ args += ["--data", k, v]
35
+
36
+ base_dir = os.path.dirname(os.path.dirname(__file__))
37
+ @inject_context_to_env
38
+ def call_cli_script():
39
+ assert "TRACEPARENT" in os.environ
40
+ process = subprocess.Popen(
41
+ [
42
+ sys.executable,
43
+ os.path.join(
44
+ base_dir, "utf_queue_client", "scripts", "publish_release_info_cli.py"
45
+ ),
46
+ ]
47
+ + args,
48
+ )
49
+ process.communicate()
50
+ assert process.poll() == 0
51
+
52
+ call_cli_script()
53
+
54
+
55
+ def test_publish_release_information():
56
+ requests_post = requests.post
57
+ requests.post = MagicMock()
58
+ publish_release_information("", "", {})
59
+ assert requests.post.call_count == 2
60
+ requests.post = requests_post
61
+
62
+
63
+ def test_publish_release_cli_insufficient_params():
64
+ requests_post = requests.post
65
+ requests_post_mock = MagicMock()
66
+ requests.post = requests_post_mock
67
+ cli("", "", {})
68
+ assert requests.post.call_count == 0
69
+ requests.post = requests_post
70
+
71
+
72
+ def test_publish_release_cli():
73
+ requests_post = requests.post
74
+ requests_post_mock = MagicMock()
75
+ requests.post = requests_post_mock
76
+ cli("", "", {("branchName", "test"), ("releaseData", "")})
77
+ assert requests_post_mock.call_count == 2
78
+ post_params = requests_post_mock.call_args.kwargs.get('json')
79
+ assert post_params.get("branchName") == "test"
80
+ assert post_params.get("releaseData") is None
81
+ requests.post = requests_post
82
+
83
+
84
+ def test_update_artifacts_retention_days_to_keep_forever():
85
+ requests_patch = requests.patch
86
+ requests.patch = MagicMock()
87
+ data_dict = {"branchName": "release/gec", "SDKBuildNum": "407"}
88
+ update_artifacts_retention_days_to_keep_forever(data_dict)
89
+ assert requests.patch.call_count == 1
90
+ requests.patch = requests_patch
91
+ patch_response = MagicMock()
92
+ mocked_patch =mock.patch.object(requests, "patch", return_value=patch_response)
93
+ patch_response.status_code = 200
94
+ update_artifacts_retention_days_to_keep_forever(data_dict)
95
+
96
+
97
+ @patch('requests.post')
98
+ def test_publish_release_information_success(mock_post):
99
+ mock_response_auth = MagicMock()
100
+ mock_response_auth.json.return_value = {"access_token": "test_token"}
101
+ mock_response_auth.raise_for_status.return_value = None
102
+
103
+ mock_response_release = MagicMock()
104
+ mock_response_release.status_code = 201
105
+ mock_response_release.json.return_value = {"message": "success"}
106
+
107
+ mock_post.side_effect = [mock_response_auth, mock_response_release]
108
+
109
+ result = publish_release_information("test_username", "test_password", {"test_key": "test_value"})
110
+ assert mock_response_release.json.called
111
+ assert result
112
+
113
+ @patch('requests.post')
114
+ def test_publish_release_information_release_fail(mock_post):
115
+ # Mock the responses
116
+ mock_response_auth = MagicMock()
117
+ mock_response_auth.json.return_value = {"access_token": "test_token"}
118
+ mock_response_auth.raise_for_status.return_value = None
119
+
120
+ mock_response_release = MagicMock()
121
+ mock_response_release.status_code = 400
122
+ mock_response_release.text = "Release failed"
123
+
124
+ mock_post.side_effect = [mock_response_auth, mock_response_release]
125
+
126
+ result = publish_release_information("test_username", "test_password", {"test_key": "test_value"})
127
+ assert result is None
128
+
129
+ @patch('requests.post')
130
+ def test_publish_release_information_release_fail_422(mock_post):
131
+ # Mock the responses
132
+ mock_response_auth = MagicMock()
133
+ mock_response_auth.json.return_value = {"access_token": "test_token"}
134
+ mock_response_auth.raise_for_status.return_value = None
135
+
136
+ mock_response_release = MagicMock()
137
+ mock_response_release.status_code = 422
138
+ mock_response_release.json.return_value = {"detail": [{"loc": ["", "test_field"], "msg": "test_error"}]}
139
+
140
+ mock_post.side_effect = [mock_response_auth, mock_response_release]
141
+
142
+ # Call the function
143
+ result = publish_release_information("test_username", "test_password", {"test_key": "test_value"})
144
+ assert mock_response_release.json.called
145
+ assert result is None
@@ -0,0 +1,64 @@
1
+ from unittest.mock import MagicMock
2
+
3
+ from utf_queue_client.clients.test_rail_data_producer import (
4
+ TestRailDataProducer,
5
+ TestRailDataProducerFactory,
6
+ DummyTestRailDataProducer,
7
+ LocalTestRailDataProducer,
8
+ )
9
+ import pytest
10
+ import os
11
+
12
+
13
+ def test_result_producer_empty_url():
14
+ with pytest.raises(RuntimeError):
15
+ _ = TestRailDataProducer()
16
+
17
+
18
+ @pytest.mark.parametrize("queue_consumer", [60, 120], indirect=True)
19
+ def test_result_producer_central_queue(
20
+ request,
21
+ test_rail_add_test_result,
22
+ amqp_url,
23
+ queue_consumer,
24
+ ):
25
+ os.environ["UTF_PRODUCER_APP_ID"] = request.node.name
26
+ producer = TestRailDataProducerFactory.create_producer()
27
+ producer.publish_add_test_result(test_rail_add_test_result)
28
+ queue_consumer.expect_messages(1)
29
+
30
+
31
+ def test_dummy_producer(test_rail_add_test_result):
32
+ producer = DummyTestRailDataProducer()
33
+ producer.publish_add_test_result(test_rail_add_test_result)
34
+
35
+
36
+ def test_local_test_rail_producer(test_rail_add_test_result, mocker):
37
+ mocker.patch(
38
+ "utf_queue_client.clients.base_producer.BlockingProducer.__init__",
39
+ return_value=None,
40
+ )
41
+ mocker.patch(
42
+ "utf_queue_client.clients.base_producer.BlockingProducer.queue_declare"
43
+ )
44
+ mock_producer_publish = mocker.patch(
45
+ "utf_queue_client.clients.base_producer.BlockingProducer.publish"
46
+ )
47
+ producer = LocalTestRailDataProducer()
48
+ producer.producer_app_id = "DUMMY"
49
+ producer.publish_add_test_result(test_rail_add_test_result)
50
+ assert mock_producer_publish.called
51
+ kwargs = mock_producer_publish.call_args.kwargs
52
+ payload = kwargs.get("payload")
53
+ assert payload.get("recordType") == "TEST_RAIL_EVENT"
54
+ assert payload.get("recordSubType") == "TEST_RESULT"
55
+ assert payload.get("tenantKey") == "DUMMY"
56
+ payload_data = payload.get("payload")
57
+ assert payload_data.get("version") == "v1"
58
+ assert payload_data.get("comment") == "testing"
59
+ assert payload_data.get("status") == "pass"
60
+ assert payload_data.get("run_id") == 1234
61
+ assert payload_data.get("id") == "C123"
62
+ custom_props = payload_data.get("custom_props")
63
+ assert custom_props.get("custom_interface_type") == "gcc"
64
+ assert custom_props.get("custom_evk_version") == "v2"
@@ -0,0 +1,95 @@
1
+ import os
2
+ from .base_producer import BlockingProducer as AMQPBlockingProducer, ConnectionError
3
+ from .http_producer import CompositeHTTPProducer
4
+ from ..models import TestRailResult
5
+ from ..models import QueueMessage
6
+ from . import Loggable
7
+ from socket import gethostname
8
+ from datetime import datetime
9
+ from abc import ABC, abstractmethod
10
+ from otel_extensions import instrumented
11
+ from typing import Optional
12
+
13
+
14
+ __all__ = [
15
+ "TestRailDataProducer",
16
+ "DummyTestRailDataProducer",
17
+ "ConnectionError",
18
+ "TestRailDataProducerFactory",
19
+ ]
20
+
21
+
22
+ class BaseTestRailDataProducer(ABC):
23
+ @abstractmethod
24
+ def publish_add_test_result(self, test_result: TestRailResult):
25
+ """publish a test result object"""
26
+
27
+
28
+ class TestRailDataProducer(BaseTestRailDataProducer):
29
+ RECORD_TYPE = "TEST_RAIL_EVENT"
30
+
31
+ def __init__(
32
+ self,
33
+ url=None,
34
+ producer_app_id: str = None,
35
+ producer_class: Optional[type] = None,
36
+ ):
37
+ if producer_class is None:
38
+ producer_class = AMQPBlockingProducer
39
+ self.queue_name = "default"
40
+ self.__producer_client = producer_class(url, producer_app_id)
41
+ self.__producer_client.queue_declare(queue=self.queue_name, durable=True)
42
+ self.producer_app_id = producer_app_id
43
+
44
+ @instrumented
45
+ def publish_add_test_result(self, test_result: TestRailResult):
46
+ queue_message = QueueMessage(
47
+ payload=test_result,
48
+ recordType=self.RECORD_TYPE,
49
+ recordSubType="TEST_RESULT",
50
+ tenantKey=self.producer_app_id,
51
+ recordTimestamp=datetime.now().isoformat(),
52
+ )
53
+ queue_message.validate_schema()
54
+ self.__producer_client.publish(
55
+ exchange="",
56
+ routing_key=self.queue_name,
57
+ payload=queue_message.as_dict(),
58
+ persistent=True,
59
+ )
60
+
61
+
62
+ class LocalTestRailDataProducer(TestRailDataProducer):
63
+ def __init__(self):
64
+ super().__init__(
65
+ "amqp://guest:guest@localhost:5672/%2f",
66
+ os.environ.get(
67
+ "UTF_PRODUCER_APP_ID", f"LocalTestRailDataProducer at {gethostname()}"
68
+ ),
69
+ )
70
+
71
+
72
+ class DummyTestRailDataProducer(BaseTestRailDataProducer):
73
+ def publish_add_test_result(self, test_result: TestRailResult):
74
+ # noqa
75
+ pass
76
+
77
+
78
+ class TestRailDataProducerFactory(Loggable):
79
+ @classmethod
80
+ def create_producer(cls, raise_on_connection_error=False):
81
+ try:
82
+ queue_server_url = os.environ.get("UTF_QUEUE_SERVER_URL")
83
+ if queue_server_url is not None:
84
+ return TestRailDataProducer(
85
+ url=queue_server_url,
86
+ producer_app_id=os.environ.get("UTF_PRODUCER_APP_ID"),
87
+ producer_class=CompositeHTTPProducer,
88
+ )
89
+ else:
90
+ return LocalTestRailDataProducer()
91
+ except ConnectionError as e:
92
+ cls.logger.warning(f"Unable to connect to queue server: {repr(e)}")
93
+ if raise_on_connection_error:
94
+ raise
95
+ return DummyTestRailDataProducer()
@@ -1,4 +1,6 @@
1
1
  from typing import Optional, List, Any
2
+ from warnings import catch_warnings, filterwarnings
3
+
2
4
  import jsonschema
3
5
  from ..exceptions import SchemaValidationError, ValidationError
4
6
  from pydantic import (
@@ -26,10 +28,12 @@ class BaseModelWithValidation(PydanticBaseModel):
26
28
  def _set_schema(self, schema: dict, class_name: str):
27
29
  validator_class = jsonschema.validators.validator_for(schema)
28
30
  validator_class.check_schema(schema)
29
- self.__validator = validator_class(
30
- schema["definitions"][class_name],
31
- resolver=jsonschema.RefResolver.from_schema(schema),
32
- )
31
+ with catch_warnings():
32
+ filterwarnings("ignore", category=DeprecationWarning)
33
+ self.__validator = validator_class(
34
+ schema["definitions"][class_name],
35
+ resolver=jsonschema.RefResolver.from_schema(schema),
36
+ )
33
37
 
34
38
  def as_dict(self) -> dict:
35
39
  return self.dict()
@@ -0,0 +1,291 @@
1
+ # generated by datamodel-codegen:
2
+ # filename: queue_message.json
3
+ # timestamp: 2024-03-25T08:36:22+00:00
4
+
5
+ from typing import Any, Dict, List, Optional, Union
6
+
7
+ from pydantic import Extra, Field, constr
8
+ from typing_extensions import Literal
9
+ from utf_queue_client.models.base_model import BaseModelWithValidation
10
+
11
+
12
+ class Model(BaseModelWithValidation):
13
+ __root__: Any
14
+
15
+
16
+ class QueueRecord(BaseModelWithValidation):
17
+ pass
18
+
19
+ class Config:
20
+ extra = Extra.allow
21
+
22
+
23
+ class DataLakeData(BaseModelWithValidation):
24
+ dataFormat: Literal['CSV', 'JSON', 'JSONSTR', 'NDJSON', 'PARQUET']
25
+ object_id: Optional[str] = None
26
+ data: Union[Dict[str, Any], List[Dict[str, Any]], str]
27
+ compression: Optional[Literal['GZIP', 'NONE', 'SNAPPY']] = None
28
+
29
+
30
+ class TelemetryData(BaseModelWithValidation):
31
+ dataType: Literal['LOGS', 'METRICS', 'TRACES']
32
+ base64ProtobufData: str
33
+ compression: Optional[str] = None
34
+
35
+
36
+ class ArtifactMetadata(BaseModelWithValidation):
37
+ pass
38
+
39
+ class Config:
40
+ extra = Extra.allow
41
+
42
+
43
+ class ArtifactBuildMetadata(BaseModelWithValidation):
44
+ branch: Optional[str] = None
45
+ stack: Optional[str] = None
46
+ build_number: Optional[str] = None
47
+ target: Optional[str] = None
48
+ studio: Optional[str] = None
49
+ compiler: Optional[str] = None
50
+ app_name: Optional[str] = None
51
+ test_suite: Optional[str] = None
52
+ chip_id: Optional[str] = None
53
+ studio_build_version: Optional[str] = None
54
+ compiler_build_version: Optional[str] = None
55
+
56
+
57
+ class SqaAppBuildResult(BaseModelWithValidation):
58
+ session_pk_id: str = Field(
59
+ ...,
60
+ description='Logical FK to dbo.jobStatusTable.\nNot creating the constraint in case this comes in before the session record.',
61
+ )
62
+ app_name: constr(max_length=512) = Field(..., description='Name of the application')
63
+ app_description: Optional[constr(max_length=1024)] = Field(
64
+ None, description='Description of what the application does'
65
+ )
66
+ test_suite_name: Optional[constr(max_length=512)] = Field(
67
+ None, description='Description of the grouping of applications'
68
+ )
69
+ test_result_type: constr(max_length=256) = Field(
70
+ ..., description='Need table for validation created from the existing java enum'
71
+ )
72
+ executor_name: Optional[constr(max_length=256)] = Field(
73
+ None, description='Where the application was built'
74
+ )
75
+ feature_name: Optional[constr(max_length=256)] = Field(
76
+ None, description='Feature being tested by this test'
77
+ )
78
+ module_name: Optional[constr(max_length=256)] = Field(
79
+ None, description='Description of the device type that the application runs on'
80
+ )
81
+ phy_name: Optional[constr(max_length=256)] = Field(
82
+ None, description='Radio configuration used by the device'
83
+ )
84
+ test_result: Literal['FAIL', 'PASS', 'block', 'fail', 'pass', 'skip'] = Field(
85
+ ..., description='Did the application build'
86
+ )
87
+ engineer_name: Optional[constr(max_length=256)] = Field(
88
+ None, description='Name of the engineer who created the test'
89
+ )
90
+ exception_msg: Optional[str] = Field(
91
+ None, description='Stack dump exception message from build'
92
+ )
93
+ iot_req_id: Optional[constr(max_length=256)] = Field(
94
+ None, description='JIRA IOT Req Number'
95
+ )
96
+ tool_chain: Optional[constr(max_length=256)] = Field(
97
+ None,
98
+ description='Need table for validation.\nThis is the tool and version used to build the application with colon separation\niar:7.80.1',
99
+ )
100
+ notes: Optional[constr(max_length=256)] = None
101
+ test_duration_sec: float = Field(
102
+ ..., description='Length of time to build the application'
103
+ )
104
+
105
+
106
+ class SqaTestResult(BaseModelWithValidation):
107
+ session_pk_id: str = Field(
108
+ ...,
109
+ description='Logical FK to dbo.jobStatusTable.\nNot creating the constraint in case this comes in before the session record.',
110
+ )
111
+ test_case_id: constr(max_length=512) = Field(
112
+ ...,
113
+ description='Passed in from the test executor.\nFrom the test management system or git.',
114
+ )
115
+ test_case_version_num: int
116
+ test_suite_name: Optional[constr(max_length=512)] = Field(
117
+ None, description='Named group of tests'
118
+ )
119
+ test_description: Optional[constr(max_length=1024)] = Field(
120
+ None, description='What does the test case actually do'
121
+ )
122
+ test_result_type: constr(max_length=256) = Field(
123
+ ..., description='Need to create a table for verification of this field'
124
+ )
125
+ test_parametric_data: Optional[str] = Field(
126
+ None, description='Test Parametric Data'
127
+ )
128
+ test_case_name: constr(max_length=512) = Field(
129
+ ...,
130
+ description='Human readable version of the test case ID\nShort summary/description',
131
+ )
132
+ executor_name: constr(max_length=256) = Field(
133
+ ..., description='Where the test actually ran'
134
+ )
135
+ feature_name: constr(max_length=256) = Field(
136
+ ..., description='Feature being tested by this test'
137
+ )
138
+ test_creation_date: str = Field(
139
+ ..., description='Date the test was created\nISO-8601 format'
140
+ )
141
+ testbed_name: constr(max_length=256) = Field(
142
+ ..., description='Grouping of all of the hardware used to execute the test'
143
+ )
144
+ module_name: constr(max_length=256) = Field(
145
+ ..., description='Testbed component list'
146
+ )
147
+ phy_name: Optional[constr(max_length=256)] = Field(
148
+ None, description='Radio configuration used by the device'
149
+ )
150
+ test_result: Literal['block', 'fail', 'metrics', 'pass', 'skip']
151
+ engineer_name: Optional[constr(max_length=256)] = Field(
152
+ None, description='Name of the engineer who created the test'
153
+ )
154
+ exception_msg: Optional[str] = Field(
155
+ None, description='If an error occurs, this is the message returned.'
156
+ )
157
+ iot_req_id: constr(max_length=256)
158
+ tool_chain: constr(max_length=256) = Field(
159
+ ...,
160
+ description='Need table for validation.\nThis is the tool and version used to build the application with colon separation\niar:7.80.1',
161
+ )
162
+ vendor_name: Optional[constr(max_length=256)] = None
163
+ vendor_build: Optional[constr(max_length=256)] = None
164
+ vendor_result: Optional[constr(max_length=256)] = None
165
+ notes: Optional[constr(max_length=1024)] = None
166
+ portal_watch: Optional[str] = Field(
167
+ None, description='Change this to boolean - default false'
168
+ )
169
+ test_duration_sec: float = Field(..., description='Test duration in seconds')
170
+ test_bed_label: Optional[constr(max_length=256)] = None
171
+ req_id: Optional[constr(max_length=256)] = None
172
+ product_line: Optional[constr(max_length=256)] = None
173
+ product_type: Optional[constr(max_length=256)] = None
174
+ customer_type: Optional[constr(max_length=256)] = None
175
+ jenkins_test_case_results_url: Optional[constr(max_length=1500)] = None
176
+ test_case_uuid: Optional[str] = Field(
177
+ None, description='UUID generated by the client software'
178
+ )
179
+
180
+
181
+ class SqaTestSession(BaseModelWithValidation):
182
+ PK_ID: str = Field(..., description='UUID generated by the Jenkins client software')
183
+ startTime: str = Field(..., description='ISO-8601 Datetime')
184
+ stopTime: Optional[str] = Field(None, description='ISO-8601 datetime')
185
+ jenkinsJobStatus: Literal['COMPLETE', 'FAIL', 'IN PROGRESS'] = Field(
186
+ ..., description='Status of the Jenkins job'
187
+ )
188
+ duration: Optional[int] = Field(
189
+ None,
190
+ description='Elapsed number of seconds for the Jenkins job.\nShould be close to stop time - start time.\nChange the data type in the DB to integer.',
191
+ )
192
+ jobType: Optional[constr(max_length=256)] = Field(
193
+ None, description='Type of Jenkins job'
194
+ )
195
+ releaseName: constr(max_length=256)
196
+ branchName: constr(max_length=256)
197
+ stackName: constr(max_length=256)
198
+ SDKBuildNum: int
199
+ SDKUrl: Optional[constr(max_length=1500)] = None
200
+ studioUrl: Optional[constr(max_length=1500)] = None
201
+ totalTests: Optional[int] = None
202
+ PASS_cnt: Optional[int] = None
203
+ FAIL_cnt: Optional[int] = None
204
+ SKIP_cnt: Optional[int] = None
205
+ BLOCK_cnt: Optional[int] = None
206
+ jenkinsServerName: constr(max_length=256)
207
+ jenkinRunNum: int
208
+ jenkinsJobName: constr(max_length=1500)
209
+ jenkinsTestResultsUrl: constr(max_length=1500)
210
+ traceId: Optional[constr(max_length=500)] = None
211
+ testFramework: Optional[constr(max_length=256)] = None
212
+ SDKVersion: Optional[constr(max_length=256)] = None
213
+ test_run_by: Optional[constr(max_length=256)] = None
214
+
215
+
216
+ class LogEvent(BaseModelWithValidation):
217
+ pass
218
+
219
+
220
+ class ExceptionEvent(BaseModelWithValidation):
221
+ pass
222
+
223
+
224
+ class TestResultCustomProps(BaseModelWithValidation):
225
+ pass
226
+
227
+ class Config:
228
+ extra = Extra.allow
229
+
230
+
231
+ class QueueMessage(BaseModelWithValidation):
232
+ recordType: Literal[
233
+ 'ARTIFACT_UPLOAD_REQUEST',
234
+ 'DATALAKE_DATA',
235
+ 'EXCEPTION_EVENT',
236
+ 'LOG_EVENT',
237
+ 'OPENTELEMETRY_DATA',
238
+ 'TEST_RAIL_EVENT',
239
+ 'UTF_TEST_EVENT',
240
+ ] = Field(..., description='Type of record')
241
+ recordSubType: Optional[
242
+ Literal['BUILD_RESULT', 'SESSION_START', 'SESSION_STOP', 'TEST_RESULT']
243
+ ] = Field(
244
+ None,
245
+ description='Subtype of record. Not all types have a subtype, but it is required when they have one.',
246
+ )
247
+ tenantKey: str = Field(
248
+ ...,
249
+ description='Unique string that identifies the app/group sending the message.\nForward looking to match the data lake infrastructure.',
250
+ )
251
+ recordTimestamp: str = Field(
252
+ ...,
253
+ description='UTC datetime.\nUse ISO-8601 format with time zone\n2022-03-10T18:50:05Z',
254
+ )
255
+ payload: 'QueueRecord' = Field(
256
+ ...,
257
+ description='Record Payload.\nThis is flexible to allow different fields for different record types and DB tables',
258
+ )
259
+
260
+
261
+ class QueueMessageV1(BaseModelWithValidation):
262
+ recordType: Literal[
263
+ 'ARTIFACT_UPLOAD_REQUEST',
264
+ 'EXCEPTION_EVENT',
265
+ 'LOG_EVENT',
266
+ 'TEST_EVENT',
267
+ 'UTF_TEST_EVENT',
268
+ ] = Field(..., description='Type of record')
269
+ payload: 'QueueRecord' = Field(..., description='Record Payload')
270
+ timestamp: float = Field(
271
+ ..., description='UTC Timestamp\nGiven in seconds since epoch (unix time)'
272
+ )
273
+
274
+
275
+ class ArtifactUploadRequest(BaseModelWithValidation):
276
+ name: str
277
+ extension: str
278
+ metadata: Union['ArtifactMetadata', 'ArtifactBuildMetadata']
279
+ base64Content: str
280
+ validateMetadata: bool
281
+
282
+
283
+ class TestRailResult(BaseModelWithValidation):
284
+ id: str
285
+ run_id: int
286
+ status: str
287
+ comment: Optional[str] = None
288
+ version: Optional[str] = None
289
+ defects: Optional[str] = None
290
+ assigned_to_id: Optional[int] = None
291
+ custom_props: Optional['TestResultCustomProps'] = None