diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 41a3374bb6..806d264a88 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -7039,6 +7039,8 @@ components: description: The programming language of the source code. example: python type: string + options: + $ref: "#/components/schemas/AnalysisRequestOptions" rules: description: The list of static analysis rules to apply during analysis. items: @@ -7060,6 +7062,20 @@ components: type: string x-enum-varnames: - ANALYSIS_REQUEST + AnalysisRequestOptions: + description: |- + Analyzer options sent by browser-based clients. Accepted but ignored: the API always runs + the analysis with tree-sitter enabled and rule output logged. + properties: + log_output: + description: Whether to capture the output logged by rules during execution. Ignored by this operation. + example: true + type: boolean + use_tree_sitter: + description: Whether to use tree-sitter to parse the source code. Ignored by this operation. + example: true + type: boolean + type: object AnalysisRequestRule: additionalProperties: {} description: |- @@ -29880,9 +29896,7 @@ components: example: foobarbaz type: string last_revision: - $ref: "#/components/schemas/CustomRuleRevisionEmbedded" - description: Most recent revision of the rule, or null when the rule has no revisions. - nullable: true + $ref: "#/components/schemas/CustomRuleNullableRevisionEmbedded" name: description: Rule name example: my-rule @@ -29907,6 +29921,125 @@ components: type: string x-enum-varnames: - CUSTOM_RULE + CustomRuleNullableRevisionEmbedded: + description: The most recent revision of the rule, or null when the rule has no revisions. + nullable: true + properties: + arguments: + description: Rule arguments + items: + $ref: "#/components/schemas/Argument" + nullable: true + type: array + category: + $ref: "#/components/schemas/CustomRuleRevisionAttributesCategory" + checksum: + description: Code checksum + example: 8a66c4e4e631099ad71be3c1ea3ea8fc2d57193e56db2c296e2dd8a508b26b99 + type: string + code: + description: Rule code + example: Y29uZHVjdG9yOgogICAgLSBkZXBsb3lfb25seTogdHJ1ZQ== + type: string + created_at: + description: Creation timestamp + example: "2026-01-09T13:00:57.473141Z" + format: date-time + type: string + created_by: + description: Creator identifier + example: foobarbaz + type: string + creation_message: + description: Revision creation message + example: Initial revision + type: string + cve: + description: Associated CVE. Omitted when the revision has no associated CVE. + example: CVE-2024-1234 + type: string + cwe: + description: Associated CWE. Omitted when the revision has no associated CWE. + example: CWE-79 + type: string + description: + description: Full description + example: bG9uZyBkZXNjcmlwdGlvbg== + type: string + documentation_url: + description: Documentation URL. Omitted when the revision has no documentation URL. + example: https://docs.example.com/rules/my-rule + type: string + id: + description: Revision identifier + example: revision-123 + type: string + is_published: + description: Whether the revision is published + example: false + type: boolean + is_testing: + description: Whether this is a testing revision + example: false + type: boolean + language: + $ref: "#/components/schemas/Language" + severity: + $ref: "#/components/schemas/CustomRuleRevisionAttributesSeverity" + short_description: + description: Short description + example: c2hvcnQgZGVzY3JpcHRpb24= + type: string + should_use_ai_fix: + description: Whether to use AI for fixes + example: false + type: boolean + tags: + description: Rule tags + example: + - security + - custom + items: + description: A tag attached to the rule. + type: string + nullable: true + type: array + tests: + description: Rule tests + items: + $ref: "#/components/schemas/CustomRuleRevisionTest" + nullable: true + type: array + tree_sitter_query: + description: Tree-sitter query + example: Y29uZHVjdG9yOgogICAgLSBkZXBsb3lfb25seTogdHJ1ZQ== + type: string + version_id: + description: Monotonically increasing version number of the revision. + example: 1 + format: int64 + type: integer + required: + - id + - version_id + - creation_message + - short_description + - description + - code + - checksum + - language + - tree_sitter_query + - created_at + - created_by + - severity + - category + - arguments + - tests + - tags + - is_published + - should_use_ai_fix + - is_testing + type: object CustomRuleRequest: description: Request body for creating or updating a custom rule. properties: @@ -30673,9 +30806,7 @@ components: example: my-rule type: string last_revision: - $ref: "#/components/schemas/CustomRuleRevisionEmbedded" - description: Most recent revision of the rule, or null when the rule has no revisions. - nullable: true + $ref: "#/components/schemas/CustomRuleNullableRevisionEmbedded" name: description: Rule name example: my-rule diff --git a/examples/v2/security-monitoring/CreateStaticAnalysisServerAnalysis.py b/examples/v2/security-monitoring/CreateStaticAnalysisServerAnalysis.py index 16f467a73a..45d2099ab0 100644 --- a/examples/v2/security-monitoring/CreateStaticAnalysisServerAnalysis.py +++ b/examples/v2/security-monitoring/CreateStaticAnalysisServerAnalysis.py @@ -9,6 +9,7 @@ from datadog_api_client.v2.model.analysis_request_data import AnalysisRequestData from datadog_api_client.v2.model.analysis_request_data_attributes import AnalysisRequestDataAttributes from datadog_api_client.v2.model.analysis_request_data_type import AnalysisRequestDataType +from datadog_api_client.v2.model.analysis_request_options import AnalysisRequestOptions from datadog_api_client.v2.model.analysis_request_rule import AnalysisRequestRule from datadog_api_client.v2.model.analysis_request_rule_argument import AnalysisRequestRuleArgument from datadog_api_client.v2.model.analysis_request_rule_test import AnalysisRequestRuleTest @@ -20,6 +21,10 @@ file_encoding="utf-8", filename="test.py", language="python", + options=AnalysisRequestOptions( + log_output=True, + use_tree_sitter=True, + ), rules=[ AnalysisRequestRule( arguments=[ diff --git a/src/datadog_api_client/v2/model/analysis_request_data_attributes.py b/src/datadog_api_client/v2/model/analysis_request_data_attributes.py index 15ab84d30c..38576eecfc 100644 --- a/src/datadog_api_client/v2/model/analysis_request_data_attributes.py +++ b/src/datadog_api_client/v2/model/analysis_request_data_attributes.py @@ -3,21 +3,25 @@ # Copyright 2019-Present Datadog, Inc. from __future__ import annotations -from typing import List, TYPE_CHECKING +from typing import List, Union, TYPE_CHECKING from datadog_api_client.model_utils import ( ModelNormal, cached_property, + unset, + UnsetType, ) if TYPE_CHECKING: + from datadog_api_client.v2.model.analysis_request_options import AnalysisRequestOptions from datadog_api_client.v2.model.analysis_request_rule import AnalysisRequestRule class AnalysisRequestDataAttributes(ModelNormal): @cached_property def openapi_types(_): + from datadog_api_client.v2.model.analysis_request_options import AnalysisRequestOptions from datadog_api_client.v2.model.analysis_request_rule import AnalysisRequestRule return { @@ -25,6 +29,7 @@ def openapi_types(_): "file_encoding": (str,), "filename": (str,), "language": (str,), + "options": (AnalysisRequestOptions,), "rules": ([AnalysisRequestRule],), } @@ -33,11 +38,19 @@ def openapi_types(_): "file_encoding": "file_encoding", "filename": "filename", "language": "language", + "options": "options", "rules": "rules", } def __init__( - self_, code: str, file_encoding: str, filename: str, language: str, rules: List[AnalysisRequestRule], **kwargs + self_, + code: str, + file_encoding: str, + filename: str, + language: str, + rules: List[AnalysisRequestRule], + options: Union[AnalysisRequestOptions, UnsetType] = unset, + **kwargs, ): """ The attributes of the analysis request, containing the source code and rules to apply. @@ -54,9 +67,15 @@ def __init__( :param language: The programming language of the source code. :type language: str + :param options: Analyzer options sent by browser-based clients. Accepted but ignored: the API always runs + the analysis with tree-sitter enabled and rule output logged. + :type options: AnalysisRequestOptions, optional + :param rules: The list of static analysis rules to apply during analysis. :type rules: [AnalysisRequestRule] """ + if options is not unset: + kwargs["options"] = options super().__init__(kwargs) self_.code = code diff --git a/src/datadog_api_client/v2/model/analysis_request_options.py b/src/datadog_api_client/v2/model/analysis_request_options.py new file mode 100644 index 0000000000..9acb4d4165 --- /dev/null +++ b/src/datadog_api_client/v2/model/analysis_request_options.py @@ -0,0 +1,46 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + unset, + UnsetType, +) + + +class AnalysisRequestOptions(ModelNormal): + @cached_property + def openapi_types(_): + return { + "log_output": (bool,), + "use_tree_sitter": (bool,), + } + + attribute_map = { + "log_output": "log_output", + "use_tree_sitter": "use_tree_sitter", + } + + def __init__( + self_, log_output: Union[bool, UnsetType] = unset, use_tree_sitter: Union[bool, UnsetType] = unset, **kwargs + ): + """ + Analyzer options sent by browser-based clients. Accepted but ignored: the API always runs + the analysis with tree-sitter enabled and rule output logged. + + :param log_output: Whether to capture the output logged by rules during execution. Ignored by this operation. + :type log_output: bool, optional + + :param use_tree_sitter: Whether to use tree-sitter to parse the source code. Ignored by this operation. + :type use_tree_sitter: bool, optional + """ + if log_output is not unset: + kwargs["log_output"] = log_output + if use_tree_sitter is not unset: + kwargs["use_tree_sitter"] = use_tree_sitter + super().__init__(kwargs) diff --git a/src/datadog_api_client/v2/model/custom_rule_attributes.py b/src/datadog_api_client/v2/model/custom_rule_attributes.py index 0af1800ef3..70228d7edc 100644 --- a/src/datadog_api_client/v2/model/custom_rule_attributes.py +++ b/src/datadog_api_client/v2/model/custom_rule_attributes.py @@ -14,18 +14,22 @@ if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_rule_nullable_revision_embedded import CustomRuleNullableRevisionEmbedded from datadog_api_client.v2.model.custom_rule_revision_embedded import CustomRuleRevisionEmbedded class CustomRuleAttributes(ModelNormal): @cached_property def openapi_types(_): + from datadog_api_client.v2.model.custom_rule_nullable_revision_embedded import ( + CustomRuleNullableRevisionEmbedded, + ) from datadog_api_client.v2.model.custom_rule_revision_embedded import CustomRuleRevisionEmbedded return { "created_at": (datetime,), "created_by": (str,), - "last_revision": (CustomRuleRevisionEmbedded,), + "last_revision": (CustomRuleNullableRevisionEmbedded,), "name": (str,), "revisions": ([CustomRuleRevisionEmbedded], none_type), } @@ -42,7 +46,7 @@ def __init__( self_, created_at: datetime, created_by: str, - last_revision: CustomRuleRevisionEmbedded, + last_revision: Union[CustomRuleNullableRevisionEmbedded, none_type], name: str, revisions: Union[List[CustomRuleRevisionEmbedded], none_type], **kwargs, @@ -56,8 +60,8 @@ def __init__( :param created_by: Creator identifier :type created_by: str - :param last_revision: A revision of a custom static analysis rule as embedded in a rule or ruleset response. - :type last_revision: CustomRuleRevisionEmbedded + :param last_revision: The most recent revision of the rule, or null when the rule has no revisions. + :type last_revision: CustomRuleNullableRevisionEmbedded, none_type :param name: Rule name :type name: str diff --git a/src/datadog_api_client/v2/model/custom_rule_nullable_revision_embedded.py b/src/datadog_api_client/v2/model/custom_rule_nullable_revision_embedded.py new file mode 100644 index 0000000000..06a9ceafe9 --- /dev/null +++ b/src/datadog_api_client/v2/model/custom_rule_nullable_revision_embedded.py @@ -0,0 +1,216 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + none_type, + unset, + UnsetType, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.argument import Argument + from datadog_api_client.v2.model.custom_rule_revision_attributes_category import ( + CustomRuleRevisionAttributesCategory, + ) + from datadog_api_client.v2.model.language import Language + from datadog_api_client.v2.model.custom_rule_revision_attributes_severity import ( + CustomRuleRevisionAttributesSeverity, + ) + from datadog_api_client.v2.model.custom_rule_revision_test import CustomRuleRevisionTest + + +class CustomRuleNullableRevisionEmbedded(ModelNormal): + _nullable = True + + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.argument import Argument + from datadog_api_client.v2.model.custom_rule_revision_attributes_category import ( + CustomRuleRevisionAttributesCategory, + ) + from datadog_api_client.v2.model.language import Language + from datadog_api_client.v2.model.custom_rule_revision_attributes_severity import ( + CustomRuleRevisionAttributesSeverity, + ) + from datadog_api_client.v2.model.custom_rule_revision_test import CustomRuleRevisionTest + + return { + "arguments": ([Argument], none_type), + "category": (CustomRuleRevisionAttributesCategory,), + "checksum": (str,), + "code": (str,), + "created_at": (datetime,), + "created_by": (str,), + "creation_message": (str,), + "cve": (str,), + "cwe": (str,), + "description": (str,), + "documentation_url": (str,), + "id": (str,), + "is_published": (bool,), + "is_testing": (bool,), + "language": (Language,), + "severity": (CustomRuleRevisionAttributesSeverity,), + "short_description": (str,), + "should_use_ai_fix": (bool,), + "tags": ([str], none_type), + "tests": ([CustomRuleRevisionTest], none_type), + "tree_sitter_query": (str,), + "version_id": (int,), + } + + attribute_map = { + "arguments": "arguments", + "category": "category", + "checksum": "checksum", + "code": "code", + "created_at": "created_at", + "created_by": "created_by", + "creation_message": "creation_message", + "cve": "cve", + "cwe": "cwe", + "description": "description", + "documentation_url": "documentation_url", + "id": "id", + "is_published": "is_published", + "is_testing": "is_testing", + "language": "language", + "severity": "severity", + "short_description": "short_description", + "should_use_ai_fix": "should_use_ai_fix", + "tags": "tags", + "tests": "tests", + "tree_sitter_query": "tree_sitter_query", + "version_id": "version_id", + } + + def __init__( + self_, + arguments: Union[List[Argument], none_type], + category: CustomRuleRevisionAttributesCategory, + checksum: str, + code: str, + created_at: datetime, + created_by: str, + creation_message: str, + description: str, + id: str, + is_published: bool, + is_testing: bool, + language: Language, + severity: CustomRuleRevisionAttributesSeverity, + short_description: str, + should_use_ai_fix: bool, + tags: Union[List[str], none_type], + tests: Union[List[CustomRuleRevisionTest], none_type], + tree_sitter_query: str, + version_id: int, + cve: Union[str, UnsetType] = unset, + cwe: Union[str, UnsetType] = unset, + documentation_url: Union[str, UnsetType] = unset, + **kwargs, + ): + """ + The most recent revision of the rule, or null when the rule has no revisions. + + :param arguments: Rule arguments + :type arguments: [Argument], none_type + + :param category: Rule category + :type category: CustomRuleRevisionAttributesCategory + + :param checksum: Code checksum + :type checksum: str + + :param code: Rule code + :type code: str + + :param created_at: Creation timestamp + :type created_at: datetime + + :param created_by: Creator identifier + :type created_by: str + + :param creation_message: Revision creation message + :type creation_message: str + + :param cve: Associated CVE. Omitted when the revision has no associated CVE. + :type cve: str, optional + + :param cwe: Associated CWE. Omitted when the revision has no associated CWE. + :type cwe: str, optional + + :param description: Full description + :type description: str + + :param documentation_url: Documentation URL. Omitted when the revision has no documentation URL. + :type documentation_url: str, optional + + :param id: Revision identifier + :type id: str + + :param is_published: Whether the revision is published + :type is_published: bool + + :param is_testing: Whether this is a testing revision + :type is_testing: bool + + :param language: Programming language + :type language: Language + + :param severity: Rule severity + :type severity: CustomRuleRevisionAttributesSeverity + + :param short_description: Short description + :type short_description: str + + :param should_use_ai_fix: Whether to use AI for fixes + :type should_use_ai_fix: bool + + :param tags: Rule tags + :type tags: [str], none_type + + :param tests: Rule tests + :type tests: [CustomRuleRevisionTest], none_type + + :param tree_sitter_query: Tree-sitter query + :type tree_sitter_query: str + + :param version_id: Monotonically increasing version number of the revision. + :type version_id: int + """ + if cve is not unset: + kwargs["cve"] = cve + if cwe is not unset: + kwargs["cwe"] = cwe + if documentation_url is not unset: + kwargs["documentation_url"] = documentation_url + super().__init__(kwargs) + + self_.arguments = arguments + self_.category = category + self_.checksum = checksum + self_.code = code + self_.created_at = created_at + self_.created_by = created_by + self_.creation_message = creation_message + self_.description = description + self_.id = id + self_.is_published = is_published + self_.is_testing = is_testing + self_.language = language + self_.severity = severity + self_.short_description = short_description + self_.should_use_ai_fix = should_use_ai_fix + self_.tags = tags + self_.tests = tests + self_.tree_sitter_query = tree_sitter_query + self_.version_id = version_id diff --git a/src/datadog_api_client/v2/model/custom_ruleset_rule_embedded.py b/src/datadog_api_client/v2/model/custom_ruleset_rule_embedded.py index c68c9472e4..9d72b43fa7 100644 --- a/src/datadog_api_client/v2/model/custom_ruleset_rule_embedded.py +++ b/src/datadog_api_client/v2/model/custom_ruleset_rule_embedded.py @@ -14,19 +14,23 @@ if TYPE_CHECKING: + from datadog_api_client.v2.model.custom_rule_nullable_revision_embedded import CustomRuleNullableRevisionEmbedded from datadog_api_client.v2.model.custom_rule_revision_embedded import CustomRuleRevisionEmbedded class CustomRulesetRuleEmbedded(ModelNormal): @cached_property def openapi_types(_): + from datadog_api_client.v2.model.custom_rule_nullable_revision_embedded import ( + CustomRuleNullableRevisionEmbedded, + ) from datadog_api_client.v2.model.custom_rule_revision_embedded import CustomRuleRevisionEmbedded return { "created_at": (datetime,), "created_by": (str,), "id": (str,), - "last_revision": (CustomRuleRevisionEmbedded,), + "last_revision": (CustomRuleNullableRevisionEmbedded,), "name": (str,), "revisions": ([CustomRuleRevisionEmbedded], none_type), } @@ -45,7 +49,7 @@ def __init__( created_at: datetime, created_by: str, id: str, - last_revision: CustomRuleRevisionEmbedded, + last_revision: Union[CustomRuleNullableRevisionEmbedded, none_type], name: str, revisions: Union[List[CustomRuleRevisionEmbedded], none_type], **kwargs, @@ -62,8 +66,8 @@ def __init__( :param id: Rule identifier, which is the same as the rule name. :type id: str - :param last_revision: A revision of a custom static analysis rule as embedded in a rule or ruleset response. - :type last_revision: CustomRuleRevisionEmbedded + :param last_revision: The most recent revision of the rule, or null when the rule has no revisions. + :type last_revision: CustomRuleNullableRevisionEmbedded, none_type :param name: Rule name :type name: str diff --git a/src/datadog_api_client/v2/models/__init__.py b/src/datadog_api_client/v2/models/__init__.py index 00201895f8..ae75152957 100644 --- a/src/datadog_api_client/v2/models/__init__.py +++ b/src/datadog_api_client/v2/models/__init__.py @@ -324,6 +324,7 @@ from datadog_api_client.v2.model.analysis_request_data import AnalysisRequestData from datadog_api_client.v2.model.analysis_request_data_attributes import AnalysisRequestDataAttributes from datadog_api_client.v2.model.analysis_request_data_type import AnalysisRequestDataType +from datadog_api_client.v2.model.analysis_request_options import AnalysisRequestOptions from datadog_api_client.v2.model.analysis_request_rule import AnalysisRequestRule from datadog_api_client.v2.model.analysis_request_rule_argument import AnalysisRequestRuleArgument from datadog_api_client.v2.model.analysis_request_rule_test import AnalysisRequestRuleTest @@ -2234,6 +2235,7 @@ from datadog_api_client.v2.model.custom_rule import CustomRule from datadog_api_client.v2.model.custom_rule_attributes import CustomRuleAttributes from datadog_api_client.v2.model.custom_rule_data_type import CustomRuleDataType +from datadog_api_client.v2.model.custom_rule_nullable_revision_embedded import CustomRuleNullableRevisionEmbedded from datadog_api_client.v2.model.custom_rule_request import CustomRuleRequest from datadog_api_client.v2.model.custom_rule_request_data import CustomRuleRequestData from datadog_api_client.v2.model.custom_rule_request_data_attributes import CustomRuleRequestDataAttributes @@ -13250,6 +13252,7 @@ "AnalysisRequestData", "AnalysisRequestDataAttributes", "AnalysisRequestDataType", + "AnalysisRequestOptions", "AnalysisRequestRule", "AnalysisRequestRuleArgument", "AnalysisRequestRuleTest", @@ -14622,6 +14625,7 @@ "CustomRule", "CustomRuleAttributes", "CustomRuleDataType", + "CustomRuleNullableRevisionEmbedded", "CustomRuleRequest", "CustomRuleRequestData", "CustomRuleRequestDataAttributes", diff --git a/tests/v2/features/security_monitoring.feature b/tests/v2/features/security_monitoring.feature index 49b1f7aeec..76da45be8a 100644 --- a/tests/v2/features/security_monitoring.feature +++ b/tests/v2/features/security_monitoring.feature @@ -96,7 +96,7 @@ Feature: Security Monitoring Scenario: Analyze code returns "Bad Request" response Given operation "CreateStaticAnalysisServerAnalysis" enabled And new "CreateStaticAnalysisServerAnalysis" request - And body with value {"data": {"attributes": {"code": "aW1wb3J0IHN5cw==", "file_encoding": "utf-8", "filename": "test.py", "language": "python", "rules": [{"arguments": [{}], "category": "BEST_PRACTICES", "checksum": "abc123def456", "code": "ZnVuY3Rpb24gdmlzaXQobm9kZSkge30=", "entity_checked": null, "id": "python-best-practices/no-exit", "language": "python", "name": "no-exit", "regex": null, "severity": "WARNING", "tags": [], "tests": [{}], "tree_sitter_query": "KGNhbGwgbmFtZTogKGF0dHJpYnV0ZSkpQHZhbA==", "type": "TREE_SITTER_QUERY"}]}, "type": "analysis_request"}} + And body with value {"data": {"attributes": {"code": "aW1wb3J0IHN5cw==", "file_encoding": "utf-8", "filename": "test.py", "language": "python", "options": {"log_output": true, "use_tree_sitter": true}, "rules": [{"arguments": [{}], "category": "BEST_PRACTICES", "checksum": "abc123def456", "code": "ZnVuY3Rpb24gdmlzaXQobm9kZSkge30=", "entity_checked": null, "id": "python-best-practices/no-exit", "language": "python", "name": "no-exit", "regex": null, "severity": "WARNING", "tags": [], "tests": [{}], "tree_sitter_query": "KGNhbGwgbmFtZTogKGF0dHJpYnV0ZSkpQHZhbA==", "type": "TREE_SITTER_QUERY"}]}, "type": "analysis_request"}} When the request is sent Then the response status is 400 Bad Request @@ -104,7 +104,7 @@ Feature: Security Monitoring Scenario: Analyze code returns "OK" response Given operation "CreateStaticAnalysisServerAnalysis" enabled And new "CreateStaticAnalysisServerAnalysis" request - And body with value {"data": {"attributes": {"code": "aW1wb3J0IHN5cw==", "file_encoding": "utf-8", "filename": "test.py", "language": "python", "rules": [{"arguments": [{}], "category": "BEST_PRACTICES", "checksum": "abc123def456", "code": "ZnVuY3Rpb24gdmlzaXQobm9kZSkge30=", "entity_checked": null, "id": "python-best-practices/no-exit", "language": "python", "name": "no-exit", "regex": null, "severity": "WARNING", "tags": [], "tests": [{}], "tree_sitter_query": "KGNhbGwgbmFtZTogKGF0dHJpYnV0ZSkpQHZhbA==", "type": "TREE_SITTER_QUERY"}]}, "type": "analysis_request"}} + And body with value {"data": {"attributes": {"code": "aW1wb3J0IHN5cw==", "file_encoding": "utf-8", "filename": "test.py", "language": "python", "options": {"log_output": true, "use_tree_sitter": true}, "rules": [{"arguments": [{}], "category": "BEST_PRACTICES", "checksum": "abc123def456", "code": "ZnVuY3Rpb24gdmlzaXQobm9kZSkge30=", "entity_checked": null, "id": "python-best-practices/no-exit", "language": "python", "name": "no-exit", "regex": null, "severity": "WARNING", "tags": [], "tests": [{}], "tree_sitter_query": "KGNhbGwgbmFtZTogKGF0dHJpYnV0ZSkpQHZhbA==", "type": "TREE_SITTER_QUERY"}]}, "type": "analysis_request"}} When the request is sent Then the response status is 200 OK