diff --git a/codecov_cli/helpers/logging_utils.py b/codecov_cli/helpers/logging_utils.py index 658c8d43..0155dd41 100644 --- a/codecov_cli/helpers/logging_utils.py +++ b/codecov_cli/helpers/logging_utils.py @@ -42,11 +42,12 @@ def format(self, record): f"{prefix} - {asctime} -- {x}" for x in msg.splitlines() ) if hasattr(record, "extra_log_attributes"): - token = record.extra_log_attributes.get("token") - if token: - record.extra_log_attributes["token"] = ( - "NOTOKEN" if not token else (str(token)[:1] + 18 * "*") - ) + passed_token_attribute = record.extra_log_attributes.get("token") + record.extra_log_attributes["token"] = ( + "NOTOKEN" + if passed_token_attribute is None + else (str(passed_token_attribute)[:1] + 18 * "*") + ) msg += " --- " + json.dumps( record.extra_log_attributes, cls=JsonEncoder ) diff --git a/tests/commands/test_upload_token_discovery.py b/tests/commands/test_upload_token_discovery.py new file mode 100644 index 00000000..af15a960 --- /dev/null +++ b/tests/commands/test_upload_token_discovery.py @@ -0,0 +1,93 @@ +"""Tests ensuring that an env-provided token can be found.""" + +from pathlib import Path + +from click.testing import CliRunner +from pytest import MonkeyPatch +from pytest_mock import MockerFixture + +from codecov_cli.commands import upload +from codecov_cli.main import cli + + +def test_no_token_anywhere( + mocker: MockerFixture, + monkeypatch: MonkeyPatch, + tmp_path: Path, +) -> None: + """Test that a missing token produces `NOTOKEN` in logs.""" + # NOTE: The pytest's `caplog` fixture is not used in this test as it + # NOTE: doesn't play well with Click's testing CLI runner, and does + # NOTE: not capture any log entries for mysterious reasons. + # + # Refs: + # * https://github.com/pallets/click/issues/2573#issuecomment-1649773563 + # * https://github.com/pallets/click/issues/1763#issuecomment-767687608 + monkeypatch.chdir(tmp_path) + + mocker.patch.object(upload, "do_upload_logic") + do_upload_cmd_spy = mocker.spy(upload, "do_upload_logic") + debug_log_spy = mocker.spy(upload.logger, "debug") + + cov_upload_cmd_output = ( + CliRunner() + .invoke( + cli, + [ + "-v", # <- NOTE: this is the only way to turn on debug logger + "do-upload", + "--commit-sha=deadbeef", + ], + obj={}, + ) + .output + ) + + assert ( + debug_log_spy.call_args[1]["extra"]["extra_log_attributes"]["token"] + == "NOTOKEN" + ) + assert '"token": "NOTOKEN"' in cov_upload_cmd_output + assert do_upload_cmd_spy.call_args[-1]["token"] is None + + +def test_cli_token_masked_in_logs( + mocker: MockerFixture, + monkeypatch: MonkeyPatch, + tmp_path: Path, +) -> None: + """Test that a present token is masked in logs.""" + # NOTE: The pytest's `caplog` fixture is not used in this test as it + # NOTE: doesn't play well with Click's testing CLI runner, and does + # NOTE: not capture any log entries for mysterious reasons. + # + # Refs: + # * https://github.com/pallets/click/issues/2573#issuecomment-1649773563 + # * https://github.com/pallets/click/issues/1763#issuecomment-767687608 + monkeypatch.chdir(tmp_path) + + mocker.patch.object(upload, "do_upload_logic") + do_upload_cmd_spy = mocker.spy(upload, "do_upload_logic") + debug_log_spy = mocker.spy(upload.logger, "debug") + + cov_upload_cmd_output = ( + CliRunner() + .invoke( + cli, + [ + "-v", # <- NOTE: this is the only way to turn on debug logger + "do-upload", + "--commit-sha=deadbeef", + "--token=sentinel-value", + ], + obj={}, + ) + .output + ) + + assert ( + debug_log_spy.call_args[1]["extra"]["extra_log_attributes"]["token"] + == "s" + "*" * 18 + ) + assert f'"token": "s{"*" * 18}"' in cov_upload_cmd_output + assert do_upload_cmd_spy.call_args[-1]["token"] == "sentinel-value"