Skip to content

Commit 7d1360e

Browse files
SCANPY-115 Parse the scanner properties from the generic environnement variables (#164)
1 parent ca88ec5 commit 7d1360e

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

src/pysonar_scanner/configuration/environment_variables.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919
#
2020
import os
21+
import json
2122
from typing import Dict
2223

2324
from pysonar_scanner.configuration.properties import Key, PROPERTIES
@@ -30,11 +31,34 @@ def load() -> Dict[Key, str]:
3031
Returns:
3132
Dictionary of property keys and their values extracted from environment variables.
3233
"""
33-
properties = {}
3434
# Extract properties from environment variables using the env_variable_name() method
35+
36+
# First check for JSON params environment variable
37+
properties = load_json_env_variables()
38+
# Extract properties from environment variables using the mapping in Property objects
39+
properties.update(load_properties_env_variables())
40+
41+
return properties
42+
43+
44+
def load_json_env_variables():
45+
properties = {}
46+
if "SONAR_SCANNER_JSON_PARAMS" in os.environ:
47+
try:
48+
json_params = os.environ["SONAR_SCANNER_JSON_PARAMS"]
49+
json_properties = json.loads(json_params)
50+
properties.update(json_properties)
51+
except json.JSONDecodeError:
52+
# If JSON is invalid, continue with regular environment variables
53+
# SCANPY-135 should log the error
54+
pass
55+
return properties
56+
57+
58+
def load_properties_env_variables():
59+
properties = {}
3560
for prop in PROPERTIES:
3661
env_var_name = prop.env_variable_name()
3762
if env_var_name in os.environ:
3863
properties[prop.name] = os.environ[env_var_name]
39-
4064
return properties

tests/test_configuration_loader.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ def test_load_from_env_variables_only(self):
299299
"SONAR_HOST_URL": "https://sonar.env.example.com", # Not set elsewhere, should be used
300300
"SONAR_USER_HOME": "/env/sonar/home", # Should be used (overriding sonar-project.properties)
301301
"SONAR_SCANNER_JAVA_OPTS": "-Xmx2048m", # Unique to env vars
302+
"SONAR_SCANNER_JSON_PARAMS": '{"sonar.exclusions": "json-exclusions/**/*", "SONAR_HOST_URL": "https://sonar.env.example.com"}', # JSON params
302303
},
303304
clear=True,
304305
)
@@ -361,10 +362,12 @@ def test_properties_priority(self):
361362

362363
# pyproject.toml [tool.sonar] section overrides sonar-project.properties
363364
self.assertEqual(configuration[SONAR_SOURCES], "src/toml")
364-
self.assertEqual(configuration[SONAR_EXCLUSIONS], "toml-exclusions/**/*")
365365
self.assertEqual(configuration[SONAR_PROJECT_NAME], "TOML Project") # Overrides sonar-project.properties
366366

367-
# Environment variables override pyproject.toml [tool.sonar]
367+
# JSON params from environment variable should override toml but be overridden by regular env vars
368+
self.assertEqual(configuration[SONAR_EXCLUSIONS], "json-exclusions/**/*") # JSON overrides toml
369+
370+
# Environment variables override pyproject.toml [tool.sonar] and JSON params
368371
self.assertEqual(configuration[SONAR_HOST_URL], "https://sonar.env.example.com")
369372
self.assertEqual(configuration[SONAR_SCANNER_JAVA_OPTS], "-Xmx2048m")
370373
self.assertEqual(configuration[SONAR_USER_HOME], "/env/sonar/home") # Env var overrides [sonar] toml

tests/test_environment_variables.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,39 @@ def test_mixed_environment_variables(self):
9191
}
9292
self.assertEqual(len(properties), 5)
9393
self.assertDictEqual(properties, expected_properties)
94+
95+
def test_environment_variables_from_json_params(self):
96+
env = {
97+
"SONAR_SCANNER_JSON_PARAMS": '{"sonar.token": "json-token", "sonar.host.url": "https://json.example.com"}'
98+
}
99+
with patch.dict("os.environ", env, clear=True):
100+
properties = environment_variables.load()
101+
expected_properties = {
102+
SONAR_TOKEN: "json-token",
103+
SONAR_HOST_URL: "https://json.example.com",
104+
}
105+
self.assertEqual(len(properties), 2)
106+
self.assertDictEqual(properties, expected_properties)
107+
108+
def test_invalid_json_params(self):
109+
env = {"SONAR_SCANNER_JSON_PARAMS": '{"sonar.token": "json-token"'}
110+
with patch.dict("os.environ", env, clear=True):
111+
properties = environment_variables.load()
112+
self.assertEqual(len(properties), 0)
113+
self.assertDictEqual(properties, {})
114+
115+
def test_environment_variables_priority_over_json_params(self):
116+
env = {
117+
"SONAR_TOKEN": "regular-token", # This should take priority
118+
"SONAR_HOST_URL": "https://regular.example.com", # This should take priority
119+
"SONAR_SCANNER_JSON_PARAMS": '{"sonar.token": "json-token", "sonar.host.url": "https://json.example.com", "sonar.region": "eu"}',
120+
}
121+
with patch.dict("os.environ", env, clear=True):
122+
properties = environment_variables.load()
123+
expected_properties = {
124+
SONAR_TOKEN: "regular-token", # Regular env var takes priority
125+
SONAR_HOST_URL: "https://regular.example.com", # Regular env var takes priority
126+
SONAR_REGION: "eu", # Only in JSON, so this value is used
127+
}
128+
self.assertEqual(len(properties), 3)
129+
self.assertDictEqual(properties, expected_properties)

0 commit comments

Comments
 (0)