diff --git a/smart_tests/commands/subset.py b/smart_tests/commands/subset.py index 5beb8451c..bb8adf3da 100644 --- a/smart_tests/commands/subset.py +++ b/smart_tests/commands/subset.py @@ -27,7 +27,7 @@ from ..args4p.command import Group from ..args4p.converters import fileText, floatType, intType from ..testpath import FilePathNormalizer, TestPath -from ..utils.env_keys import REPORT_ERROR_KEY +from ..utils.env_keys import MATRIX_KEY, REPORT_ERROR_KEY from ..utils.fail_fast_mode import (FailFastModeValidateParams, fail_fast_mode_validate, set_fail_fast_mode, warn_and_exit_if_fail_fast_mode) from ..utils.input_snapshot import InputSnapshotId @@ -453,6 +453,16 @@ def warn(msg: str): self.output_handler = self._default_output_handler self.exclusion_output_handler = self._default_exclusion_output_handler + raw_matrix = os.environ.get(MATRIX_KEY) + if raw_matrix: + try: + matrix = json.loads(raw_matrix) + self.flavors = {str(k): str(v) for k, v in matrix.items()} if isinstance(matrix, dict) else {} + except (ValueError, AttributeError): + self.flavors = {} + else: + self.flavors = {} + def _default_output_handler(self, output: list[TestPath], rests: list[TestPath]): if self.rest: self.write_file(self.rest, rests) @@ -617,6 +627,9 @@ def get_payload(self) -> dict[str, Any]: if split_subset: payload['splitSubset'] = split_subset + if self.flavors: + payload['flavors'] = self.flavors + return payload def _build_split_subset_payload(self) -> dict[str, Any] | None: diff --git a/smart_tests/utils/env_keys.py b/smart_tests/utils/env_keys.py index 5d9f8e408..8540afb36 100644 --- a/smart_tests/utils/env_keys.py +++ b/smart_tests/utils/env_keys.py @@ -18,6 +18,9 @@ # Legacy token key for backward compatibility LEGACY_TOKEN_KEY = "LAUNCHABLE_TOKEN" +# GitHub Actions matrix as JSON, e.g. SMART_TESTS_MATRIX='{"shard":"1","os":"ubuntu"}' +MATRIX_KEY = "SMART_TESTS_MATRIX" + def get_token(): """Get token with backward compatibility for LAUNCHABLE_TOKEN.""" diff --git a/tests/commands/test_subset.py b/tests/commands/test_subset.py index 847b83c1d..64a9dd0d9 100644 --- a/tests/commands/test_subset.py +++ b/tests/commands/test_subset.py @@ -1249,3 +1249,36 @@ def test_subset_from_github_actions_malformed_repository_is_error(self): self.assert_exit_code(result, 1) self.assertIn("owner/repo", result.stderr) self.assertIn("no-slash", result.stderr) + + @responses.activate + @mock.patch.dict(os.environ, { + "SMART_TESTS_TOKEN": CliTestCase.smart_tests_token, + "SMART_TESTS_MATRIX": '{"shard": "1", "os": "ubuntu"}', + }) + def test_subset_sends_flavors_from_matrix_env_var(self): + pipe = "test_1.py" + result = self.cli( + "subset", "file", + "--target", "50%", + "--session", self.session, + mix_stderr=False, + input=pipe, + ) + self.assert_success(result) + payload = self.decode_request_body(self.find_request('/subset').request.body) + self.assertEqual(payload.get('flavors'), {"shard": "1", "os": "ubuntu"}) + + @responses.activate + @mock.patch.dict(os.environ, {"SMART_TESTS_TOKEN": CliTestCase.smart_tests_token}) + def test_subset_sends_no_flavors_when_matrix_env_var_absent(self): + pipe = "test_1.py" + result = self.cli( + "subset", "file", + "--target", "50%", + "--session", self.session, + mix_stderr=False, + input=pipe, + ) + self.assert_success(result) + payload = self.decode_request_body(self.find_request('/subset').request.body) + self.assertNotIn('flavors', payload)