Skip to content

feat(7983): improving warnings on incorrect or absent configuration #193

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

kieranmanning
Copy link

@kieranmanning kieranmanning commented Apr 12, 2025

What?

Improve Cloudsmith CLI user experience when encountering configuration issues or uncertainties. Can be disabled with a --no-warn flag

Why?

Currently, there are a number of potential pitfalls around config management for the Cloudsmith CLI. These include:

  1. No warnings when commands are passed non-existent profiles
  2. No warnings when commands are run with zero discovered configuration
  3. Normally remote commands appear to complete successfully despite not authenticating against, or reaching, any Cloudsmith instance

Acceptance Criteria (Is It Done?)

  1. Incorrect --profile values result in warnings to users
  2. The CLI expects to find some kind of accurate configuration and warns if not
  3. Commands which expect API responses warn when none are returned, indicating likely authentication failure

Screenshots

image

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • .envrc: Language not supported

@kieranmanning kieranmanning force-pushed the ENG-7893/improve-first-cli-use-behaviour branch 2 times, most recently from b7a3909 to 08876e1 Compare May 20, 2025 20:32
@kieranmanning kieranmanning force-pushed the ENG-7893/improve-first-cli-use-behaviour branch from 26b75af to e08e621 Compare May 27, 2025 19:19
@kieranmanning kieranmanning changed the title chore: improving warnings on incorrect or absent configuration feat(7983): improving warnings on incorrect or absent configuration May 28, 2025
@kieranmanning kieranmanning force-pushed the ENG-7893/improve-first-cli-use-behaviour branch from e08e621 to 84e4286 Compare June 4, 2025 09:58
Copy link

@greener2 greener2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM Kieran, I haven't touched the CLI before but your changes are concise, well-documented and make sense.

It might still be best to get a review from someone with more CLI experience than me.

Comment on lines +21 to +36
if [ ! -d ".venv" ]
then
# System python doesn't like us installing packages into it
# Test if uv is already installed (via brew or other package manager etc.)
# and use that if available. Otherwise fall back to previous behvaiour
if command -v uv
then
uv venv .venv --python $PYTHON_VERSION
uv pip install -U pip uv
uv pip install -e .
else
python -m uv venv .venv --python $PYTHON_VERSION
python -m uv pip install -U pip uv
python -m uv pip install -e .
fi
fi
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't see this mentioned in the PR description.

There is probably something to be done here. You're right to question the awkward combination of tooling, but I think it's better to omit this from the PR and raise it separately.

return f"{self.__class__.__name__} - {self.cloudsmith_host}"


class CliWarnings(list):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why inherit from list here? Can't we just use composition rather than inheritance?

Comment on lines +86 to +87
def __dedupe__(self) -> List[CliWarning]:
return list(set(self.warnings))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid user-defined dunders.

I don't see this used anywhere except in the test... what do we need it for?

Comment on lines +93 to +97
def __repr__(self) -> str:
return self.__str__()

def __str__(self) -> str:
return ",".join([str(x) for x in self.warnings])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: __str__ implicitly returns __repr__. You only need to define __repr__.


def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return False
return NotImplemented

Comment on lines +5 to +8
class CliWarning(ABC):
"""
Abstract base class for all Cloudsmith CLI warnings.
"""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the benefit of using an abstract base class for this purpose?

Comment on lines +179 to +183
if not any(list(existing_config_paths.values())):
config_load_warning = ConfigLoadWarning(
paths=existing_config_paths,
)
warnings.append(config_load_warning)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to warn if no config file was found?

The user might have provided the CLOUDSMITH_API_KEY environment variable for example, such as we do in the pytest suite.

opts = config.get_or_create_options(ctx)

if warnings and not opts.no_warn:
click_warn_partial = partial(click.secho, fg="yellow")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't write warnings to stdout.

(Question: Is writing to stdout why a bunch of pre-existing tests now need the pytest fixture to suppress these warnings? If we write warnings to stderr instead, do those tests pass without that fixture?)

Suggested change
click_warn_partial = partial(click.secho, fg="yellow")
click_warn_partial = partial(click.secho, fg="yellow", err=True)

)


class TestWarnings:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WLTS tests that replicate the scenarios mentioned in the PR description.

Comment on lines +76 to +81


@pytest.fixture()
def set_no_warn_env_var():
"""Set the CLOUDSMITH_API_KEY environment variable."""
os.environ["CLOUDSMITH_CLI_NO_WARN"] = "True"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The need to add this fixture to so many pre-existing tests is a bit of a smell.

No, I'm not advocating for autouse=True :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants