From 3a6d1b7ba7206ade9bbdceef63ba6736205adbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D0=BA=D0=BE?= =?UTF-8?q?=D1=81?= Date: Thu, 25 Jun 2026 21:06:19 +0700 Subject: [PATCH] Fix .env override priority and password whitespace stripping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change load_dotenv() to load_dotenv(override=False) so real environment variables always take priority over stale .env files. This prevents a hardcoded or outdated REDMINE_API_KEY in .env from silently overriding a fresh token exported in the shell (#15). Add .strip() to get_redmine_password() for consistency with all other config getters — trailing whitespace in .env no longer causes silent auth failures (#35). Closes #15, closes #35 --- redmine_reporter/config.py | 4 ++-- tests/test_config.py | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/redmine_reporter/config.py b/redmine_reporter/config.py index cada757..d156ace 100644 --- a/redmine_reporter/config.py +++ b/redmine_reporter/config.py @@ -3,7 +3,7 @@ from typing import Union from dotenv import load_dotenv -load_dotenv() +load_dotenv(override=False) DEFAULT_REDMINE_VERIFY = "/etc/ssl/certs/ca-certificates.crt" FALSE_VALUES = {"0", "false", "no", "off"} @@ -25,7 +25,7 @@ class Config: @classmethod def get_redmine_password(cls) -> str: - return os.getenv("REDMINE_PASSWORD", "") + return os.getenv("REDMINE_PASSWORD", "").strip() @classmethod def get_redmine_verify(cls) -> Union[bool, str]: diff --git a/tests/test_config.py b/tests/test_config.py index 46b767f..b7a54ca 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -99,3 +99,27 @@ def test_get_redmine_verify_true_values(value): @mock.patch.dict(os.environ, {"REDMINE_VERIFY": "/tmp/redmine-ca.pem"}, clear=True) def test_get_redmine_verify_custom_path(): assert Config.get_redmine_verify() == "/tmp/redmine-ca.pem" + + +# -- #15: .env не должен переопределять переменные окружения -- + + +@mock.patch("dotenv.load_dotenv") +def test_env_var_takes_priority_over_dotenv(mock_load): + """load_dotenv вызывается с override=False — env vars не перебиваются .env.""" + import importlib + + from redmine_reporter import config as cfg_mod + + importlib.reload(cfg_mod) + + mock_load.assert_called_once_with(override=False) + + +# -- #35: get_redmine_password должен делать .strip() -- + + +@mock.patch.dict(os.environ, {"REDMINE_PASSWORD": " secret123 "}, clear=True) +def test_get_redmine_password_strips_whitespace(): + """Пароль обрезается от whitespace, как и все остальные геттеры.""" + assert Config.get_redmine_password() == "secret123"