cloudsmith-cli 1.19.0__tar.gz → 1.20.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cloudsmith_cli-1.19.0/cloudsmith_cli.egg-info → cloudsmith_cli-1.20.0}/PKG-INFO +29 -21
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/README.md +24 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/mcp.py +4 -1
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/whoami.py +3 -1
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/config.py +24 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/decorators.py +50 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/utils.py +20 -1
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/validators.py +44 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/docker/installer.py +19 -1
- cloudsmith_cli-1.20.0/cloudsmith_cli/data/VERSION +1 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0/cloudsmith_cli.egg-info}/PKG-INFO +29 -21
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli.egg-info/SOURCES.txt +1 -56
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli.egg-info/requires.txt +1 -1
- cloudsmith_cli-1.20.0/pyproject.toml +138 -0
- cloudsmith_cli-1.20.0/setup.cfg +4 -0
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/conftest.py +0 -27
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/policy/__init__.py +0 -0
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/policy/test_deny.py +0 -175
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/policy/test_licence.py +0 -200
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py +0 -204
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_auth.py +0 -283
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_check.py +0 -73
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_credential_helper.py +0 -564
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_credential_helper_install.py +0 -718
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_download.py +0 -555
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_entitlements.py +0 -20
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_login.py +0 -30
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_logout.py +0 -147
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_main.py +0 -54
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_mcp.py +0 -581
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_metadata.py +0 -699
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_package_commands.py +0 -172
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_repos.py +0 -201
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_tokens.py +0 -187
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_upstream.py +0 -161
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands/test_vulnerabilities.py +0 -112
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/conftest.py +0 -78
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/test_metadata_common.py +0 -123
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/test_oidc_detector_config.py +0 -77
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/test_push.py +0 -1466
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/test_saml.py +0 -164
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/test_utils.py +0 -35
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/test_webserver.py +0 -159
- cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/utils.py +0 -12
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/credentials/__init__.py +0 -0
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/mcp/__init__.py +0 -0
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/__init__.py +0 -0
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_azure_devops_detector.py +0 -125
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_bitbucket_pipelines_detector.py +0 -55
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_cache_utils.py +0 -375
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_circleci_detector.py +0 -76
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_cli_flag_provider.py +0 -46
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_credential_chain_priority.py +0 -135
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_credential_context.py +0 -30
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_credential_provider_chain.py +0 -80
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_credentials_file_provider.py +0 -47
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_detector_controls.py +0 -153
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_download.py +0 -708
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_env_var_provider.py +0 -45
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_generic_detector.py +0 -72
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_github_actions_detector.py +0 -116
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_gitlab_ci_detector.py +0 -74
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_init.py +0 -120
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_keyring.py +0 -296
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_keyring_provider.py +0 -81
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_metadata.py +0 -605
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_rest.py +0 -67
- cloudsmith_cli-1.19.0/cloudsmith_cli/core/tests/test_version.py +0 -18
- cloudsmith_cli-1.19.0/cloudsmith_cli/data/VERSION +0 -1
- cloudsmith_cli-1.19.0/cloudsmith_cli.egg-info/not-zip-safe +0 -1
- cloudsmith_cli-1.19.0/setup.cfg +0 -40
- cloudsmith_cli-1.19.0/setup.py +0 -109
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/LICENSE +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/MANIFEST.in +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/__main__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/command.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/auth.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/check.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/copy.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/credential_helper/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/credential_helper/docker.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/credential_helper/manage.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/delete.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/dependencies.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/docs.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/download.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/entitlements.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/help_.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/list_.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/login.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/logout.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/main.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/metadata.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/metrics/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/metrics/command.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/metrics/entitlements.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/metrics/packages.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/move.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/policy/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/policy/command.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/policy/deny.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/policy/license.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/policy/vulnerability.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/push.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/quarantine.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/quota/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/quota/command.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/quota/history.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/quota/quota.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/repos.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/resync.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/status.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/tags.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/tokens.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/upstream.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/commands/vulnerabilities.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/exceptions.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/metadata_common.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/saml.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/table.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/types.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/cli/webserver.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/distros.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/entitlements.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/exceptions.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/files.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/init.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/metadata.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/metrics.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/orgs.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/packages.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/quota.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/rates.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/repos.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/status.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/upstreams.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/user.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/version.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/api/vulnerabilities.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/cache_utils.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/config.py +0 -0
- {cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests → cloudsmith_cli-1.20.0/cloudsmith_cli/core/credentials}/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/chain.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/models.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/cache.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/aws.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/azure_devops.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/base.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/bitbucket_pipelines.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/circleci.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/generic.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/github_actions.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/detectors/gitlab_ci.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/oidc/exchange.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/provider.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/providers/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/providers/cli_flag.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/providers/credentials_file.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/providers/env_var.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/providers/keyring_provider.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/credentials/providers/oidc_provider.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/download.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/keyring.py +0 -0
- {cloudsmith_cli-1.19.0/cloudsmith_cli/cli/tests/commands → cloudsmith_cli-1.20.0/cloudsmith_cli/core/mcp}/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/mcp/data.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/mcp/server.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/pagination.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/ratelimits.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/rest.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/utils.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/core/version.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/backends.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/common.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/custom_domains.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/docker/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/docker/runtime.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/credential_helpers/launchers.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/data/config.ini +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/data/credentials.ini +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/templates/__init__.py +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/templates/auth_error.html +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli/templates/auth_success.html +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli.egg-info/dependency_links.txt +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli.egg-info/entry_points.txt +0 -0
- {cloudsmith_cli-1.19.0 → cloudsmith_cli-1.20.0}/cloudsmith_cli.egg-info/top_level.txt +0 -0
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudsmith-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.20.0
|
|
4
4
|
Summary: Cloudsmith Command-Line Interface (CLI)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
License: Apache License 2.0
|
|
5
|
+
Author-email: Cloudsmith Ltd <support@cloudsmith.io>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudsmith-io/cloudsmith-cli
|
|
9
8
|
Keywords: cloudsmith,cli,devops
|
|
10
|
-
Platform: any
|
|
11
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
10
|
Classifier: Environment :: Console
|
|
13
11
|
Classifier: Intended Audience :: Developers
|
|
14
12
|
Classifier: Intended Audience :: System Administrators
|
|
15
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
13
|
Classifier: Operating System :: POSIX :: Linux
|
|
17
14
|
Classifier: Programming Language :: Python
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -31,7 +28,7 @@ Requires-Dist: click-configfile>=0.2.3
|
|
|
31
28
|
Requires-Dist: click-didyoumean>=0.0.3
|
|
32
29
|
Requires-Dist: click-spinner>=0.1.7
|
|
33
30
|
Requires-Dist: json5>=0.9.0
|
|
34
|
-
Requires-Dist: cloudsmith-api<3.0,>=2.0.
|
|
31
|
+
Requires-Dist: cloudsmith-api<3.0,>=2.0.29
|
|
35
32
|
Requires-Dist: keyring>=25.4.1
|
|
36
33
|
Requires-Dist: mcp==1.27.2
|
|
37
34
|
Requires-Dist: PyJWT[crypto]>=2.0.0
|
|
@@ -45,20 +42,7 @@ Provides-Extra: aws
|
|
|
45
42
|
Requires-Dist: boto3[crt]>=1.26.0; extra == "aws"
|
|
46
43
|
Provides-Extra: all
|
|
47
44
|
Requires-Dist: boto3[crt]>=1.26.0; extra == "all"
|
|
48
|
-
Dynamic: author
|
|
49
|
-
Dynamic: author-email
|
|
50
|
-
Dynamic: classifier
|
|
51
|
-
Dynamic: description
|
|
52
|
-
Dynamic: description-content-type
|
|
53
|
-
Dynamic: home-page
|
|
54
|
-
Dynamic: keywords
|
|
55
|
-
Dynamic: license
|
|
56
45
|
Dynamic: license-file
|
|
57
|
-
Dynamic: platform
|
|
58
|
-
Dynamic: provides-extra
|
|
59
|
-
Dynamic: requires-dist
|
|
60
|
-
Dynamic: requires-python
|
|
61
|
-
Dynamic: summary
|
|
62
46
|
|
|
63
47
|
# Cloudsmith Command Line Interface (CLI)
|
|
64
48
|
|
|
@@ -203,6 +187,30 @@ Or you can get the latest pre-release version from Cloudsmith:
|
|
|
203
187
|
pip install --upgrade cloudsmith-cli --extra-index-url=https://dl.cloudsmith.io/public/cloudsmith/cli/python/index/
|
|
204
188
|
```
|
|
205
189
|
|
|
190
|
+
### Standalone Binaries
|
|
191
|
+
|
|
192
|
+
Each release also ships self-contained binaries that bundle Python and all dependencies — no Python installation required. Download the archive for your platform from the [GitHub releases page](https://github.com/cloudsmith-io/cloudsmith-cli/releases) (or the [Cloudsmith CLI repository](https://cloudsmith.io/~cloudsmith/repos/cli/packages/)), verify it against the accompanying `.sha256` file, extract it, and add the extracted `cloudsmith` directory to your `PATH`:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
tar -xzf cloudsmith-<version>-<target>.tar.gz
|
|
196
|
+
./cloudsmith/cloudsmith --version
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Available targets: `linux-x86_64-gnu`, `linux-x86_64-musl`, `linux-aarch64-gnu`, `linux-aarch64-musl`, `macos-arm64`, `macos-x86_64`, and `windows-x86_64` (as a `.zip`).
|
|
200
|
+
|
|
201
|
+
Standalone binaries include all optional features, including AWS OIDC support.
|
|
202
|
+
|
|
203
|
+
#### Verifying Linux binaries
|
|
204
|
+
|
|
205
|
+
The four Linux archives (`linux-x86_64-gnu`, `linux-x86_64-musl`, `linux-aarch64-gnu`, `linux-aarch64-musl`) are GPG-signed with a detached binary signature published alongside each archive as `<archive>.sig`. To verify, import the Cloudsmith CLI release public key (`cloudsmith-cli-release-key.asc`, attached to each GitHub release) and check the signature:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
gpg --import cloudsmith-cli-release-key.asc
|
|
209
|
+
gpg --verify cloudsmith-<version>-linux-x86_64-gnu.tar.gz.sig cloudsmith-<version>-linux-x86_64-gnu.tar.gz
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A successful verification reports a good signature from the Cloudsmith CLI release key. (The macOS and Windows binaries are not GPG-signed; native signing for those platforms is tracked separately.)
|
|
213
|
+
|
|
206
214
|
### Optional Dependencies
|
|
207
215
|
|
|
208
216
|
The CLI supports optional extras for additional functionality:
|
|
@@ -141,6 +141,30 @@ Or you can get the latest pre-release version from Cloudsmith:
|
|
|
141
141
|
pip install --upgrade cloudsmith-cli --extra-index-url=https://dl.cloudsmith.io/public/cloudsmith/cli/python/index/
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
### Standalone Binaries
|
|
145
|
+
|
|
146
|
+
Each release also ships self-contained binaries that bundle Python and all dependencies — no Python installation required. Download the archive for your platform from the [GitHub releases page](https://github.com/cloudsmith-io/cloudsmith-cli/releases) (or the [Cloudsmith CLI repository](https://cloudsmith.io/~cloudsmith/repos/cli/packages/)), verify it against the accompanying `.sha256` file, extract it, and add the extracted `cloudsmith` directory to your `PATH`:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
tar -xzf cloudsmith-<version>-<target>.tar.gz
|
|
150
|
+
./cloudsmith/cloudsmith --version
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Available targets: `linux-x86_64-gnu`, `linux-x86_64-musl`, `linux-aarch64-gnu`, `linux-aarch64-musl`, `macos-arm64`, `macos-x86_64`, and `windows-x86_64` (as a `.zip`).
|
|
154
|
+
|
|
155
|
+
Standalone binaries include all optional features, including AWS OIDC support.
|
|
156
|
+
|
|
157
|
+
#### Verifying Linux binaries
|
|
158
|
+
|
|
159
|
+
The four Linux archives (`linux-x86_64-gnu`, `linux-x86_64-musl`, `linux-aarch64-gnu`, `linux-aarch64-musl`) are GPG-signed with a detached binary signature published alongside each archive as `<archive>.sig`. To verify, import the Cloudsmith CLI release public key (`cloudsmith-cli-release-key.asc`, attached to each GitHub release) and check the signature:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
gpg --import cloudsmith-cli-release-key.asc
|
|
163
|
+
gpg --verify cloudsmith-<version>-linux-x86_64-gnu.tar.gz.sig cloudsmith-<version>-linux-x86_64-gnu.tar.gz
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A successful verification reports a good signature from the Cloudsmith CLI release key. (The macOS and Windows binaries are not GPG-signed; native signing for those platforms is tracked separately.)
|
|
167
|
+
|
|
144
168
|
### Optional Dependencies
|
|
145
169
|
|
|
146
170
|
The CLI supports optional extras for additional functionality:
|
|
@@ -291,7 +291,7 @@ def configure(ctx, opts, client, is_global): # pylint: disable=unused-argument
|
|
|
291
291
|
|
|
292
292
|
def _get_server_config(profile=None):
|
|
293
293
|
"""Determine the first available command configuration to run the MCP server."""
|
|
294
|
-
|
|
294
|
+
is_frozen = getattr(sys, "frozen", False)
|
|
295
295
|
in_venv = hasattr(sys, "real_prefix") or (
|
|
296
296
|
hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix
|
|
297
297
|
)
|
|
@@ -301,6 +301,9 @@ def _get_server_config(profile=None):
|
|
|
301
301
|
if profile:
|
|
302
302
|
base_args.extend(["-P", profile])
|
|
303
303
|
|
|
304
|
+
if is_frozen:
|
|
305
|
+
return {"command": sys.executable, "args": base_args + ["mcp", "start"]}
|
|
306
|
+
|
|
304
307
|
# In a venv, always use python -m to ensure we use the venv's packages
|
|
305
308
|
if in_venv:
|
|
306
309
|
return {
|
|
@@ -172,12 +172,14 @@ def whoami(ctx, opts):
|
|
|
172
172
|
data["auth"] = _get_verbose_auth_data(opts, api_host)
|
|
173
173
|
|
|
174
174
|
if utils.maybe_print_as_json(opts, data):
|
|
175
|
+
if not is_auth:
|
|
176
|
+
ctx.exit(1)
|
|
175
177
|
return
|
|
176
178
|
|
|
177
179
|
if not is_auth:
|
|
178
180
|
click.echo("You are authenticated as:")
|
|
179
181
|
click.secho("Nobody (i.e. anonymous user)", fg="yellow")
|
|
180
|
-
|
|
182
|
+
ctx.exit(1)
|
|
181
183
|
|
|
182
184
|
if opts.verbose:
|
|
183
185
|
_print_verbose_text(data)
|
|
@@ -155,6 +155,30 @@ class ConfigReader(ConfigFileReader):
|
|
|
155
155
|
|
|
156
156
|
return False
|
|
157
157
|
|
|
158
|
+
@classmethod
|
|
159
|
+
def read_relative_config_value(cls, key, profile=None):
|
|
160
|
+
"""Read `key` as loaded from directory-relative (untrusted) configs only.
|
|
161
|
+
|
|
162
|
+
Loads via the normal machinery but through a reader narrowed to the
|
|
163
|
+
relative search paths/files (e.g. the current working directory);
|
|
164
|
+
absolute/user-level paths and any explicit ``--config-file`` are
|
|
165
|
+
excluded. The value is parsed and quote-stripped exactly as a real run
|
|
166
|
+
would. Returns None when the key is absent or empty.
|
|
167
|
+
"""
|
|
168
|
+
relative_searchpath = [p for p in cls.config_searchpath if not os.path.isabs(p)]
|
|
169
|
+
relative_files = [f for f in cls.config_files if not os.path.isabs(f)]
|
|
170
|
+
if not relative_searchpath or not relative_files:
|
|
171
|
+
return None
|
|
172
|
+
|
|
173
|
+
relative_reader = type(
|
|
174
|
+
"RelativeConfigReader",
|
|
175
|
+
(cls,),
|
|
176
|
+
{"config_searchpath": relative_searchpath, "config_files": relative_files},
|
|
177
|
+
)
|
|
178
|
+
probe = Options()
|
|
179
|
+
relative_reader.load_config(probe, profile=profile)
|
|
180
|
+
return probe.opts.get(key)
|
|
181
|
+
|
|
158
182
|
@classmethod
|
|
159
183
|
def load_config(cls, opts, path=None, profile=None):
|
|
160
184
|
"""Load a configuration file into an options object."""
|
|
@@ -255,6 +255,40 @@ def common_api_auth_options(f):
|
|
|
255
255
|
return wrapper
|
|
256
256
|
|
|
257
257
|
|
|
258
|
+
def _parse_suffixes(value):
|
|
259
|
+
"""Split a CSV of trusted host suffixes into a normalised tuple."""
|
|
260
|
+
return tuple(
|
|
261
|
+
token.strip().lstrip(".") for token in (value or "").split(",") if token.strip()
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _guard_untrusted_endpoints(ctx, opts, host_suffixes, proxy_suffixes):
|
|
266
|
+
"""Reject api_host/api_proxy redirections from directory-relative config.
|
|
267
|
+
|
|
268
|
+
Enforcement applies only when the effective value originated from an
|
|
269
|
+
untrusted (relative) config file and was not supplied via a CLI flag or
|
|
270
|
+
environment variable. Both must match their allow-listed host suffixes;
|
|
271
|
+
api_proxy has no public default suffixes, so it is rejected unless one is
|
|
272
|
+
supplied via the environment.
|
|
273
|
+
"""
|
|
274
|
+
trusted_sources = (ParameterSource.COMMANDLINE, ParameterSource.ENVIRONMENT)
|
|
275
|
+
profile = ctx.meta.get("profile")
|
|
276
|
+
|
|
277
|
+
if ctx.get_parameter_source("api_host") not in trusted_sources:
|
|
278
|
+
relative_host = config.ConfigReader.read_relative_config_value(
|
|
279
|
+
"api_host", profile=profile
|
|
280
|
+
)
|
|
281
|
+
if relative_host and opts.api_host == relative_host:
|
|
282
|
+
validators.validate_untrusted_api_host(opts.api_host, host_suffixes)
|
|
283
|
+
|
|
284
|
+
if ctx.get_parameter_source("api_proxy") not in trusted_sources:
|
|
285
|
+
relative_proxy = config.ConfigReader.read_relative_config_value(
|
|
286
|
+
"api_proxy", profile=profile
|
|
287
|
+
)
|
|
288
|
+
if relative_proxy and opts.api_proxy == relative_proxy:
|
|
289
|
+
validators.validate_untrusted_api_proxy(opts.api_proxy, proxy_suffixes)
|
|
290
|
+
|
|
291
|
+
|
|
258
292
|
def initialise_session(f):
|
|
259
293
|
"""Create a shared HTTP session with proxy/SSL/user-agent settings."""
|
|
260
294
|
|
|
@@ -286,11 +320,25 @@ def initialise_session(f):
|
|
|
286
320
|
envvar="CLOUDSMITH_API_HEADERS",
|
|
287
321
|
help="A CSV list of extra headers (key=value) to send to the API.",
|
|
288
322
|
)
|
|
323
|
+
@click.option(
|
|
324
|
+
"--allowed-api-host-suffixes",
|
|
325
|
+
envvar="CLOUDSMITH_ALLOWED_API_HOST_SUFFIXES",
|
|
326
|
+
hidden=True,
|
|
327
|
+
help="Comma-separated extra trusted api_host suffixes (internal use).",
|
|
328
|
+
)
|
|
329
|
+
@click.option(
|
|
330
|
+
"--allowed-api-proxy-suffixes",
|
|
331
|
+
envvar="CLOUDSMITH_ALLOWED_API_PROXY_SUFFIXES",
|
|
332
|
+
hidden=True,
|
|
333
|
+
help="Comma-separated trusted api_proxy host suffixes (internal use).",
|
|
334
|
+
)
|
|
289
335
|
@click.pass_context
|
|
290
336
|
@functools.wraps(f)
|
|
291
337
|
def wrapper(ctx, *args, **kwargs):
|
|
292
338
|
# pylint: disable=missing-docstring
|
|
293
339
|
opts = config.get_or_create_options(ctx)
|
|
340
|
+
host_suffixes = _parse_suffixes(kwargs.pop("allowed_api_host_suffixes"))
|
|
341
|
+
proxy_suffixes = _parse_suffixes(kwargs.pop("allowed_api_proxy_suffixes"))
|
|
294
342
|
opts.api_host = kwargs.pop("api_host")
|
|
295
343
|
opts.api_proxy = kwargs.pop("api_proxy")
|
|
296
344
|
opts.api_ssl_verify = _pop_boolean_flag(
|
|
@@ -299,6 +347,8 @@ def initialise_session(f):
|
|
|
299
347
|
opts.api_user_agent = kwargs.pop("api_user_agent")
|
|
300
348
|
opts.api_headers = kwargs.pop("api_headers")
|
|
301
349
|
|
|
350
|
+
_guard_untrusted_endpoints(ctx, opts, host_suffixes, proxy_suffixes)
|
|
351
|
+
|
|
302
352
|
opts.session = _create_session(
|
|
303
353
|
proxy=opts.api_proxy,
|
|
304
354
|
ssl_verify=opts.api_ssl_verify,
|
|
@@ -194,6 +194,25 @@ def maybe_truncate_list(data, max_len=5):
|
|
|
194
194
|
return data
|
|
195
195
|
|
|
196
196
|
|
|
197
|
+
def maybe_unstyle_prompt(prompt, err=False):
|
|
198
|
+
"""Strip ANSI styling from a prompt when the target stream is not a TTY.
|
|
199
|
+
|
|
200
|
+
As of click 8.4, ``click.prompt``/``click.confirm`` pass the prompt text
|
|
201
|
+
straight to the (readline-backed) prompt function instead of routing it
|
|
202
|
+
through ``echo()``. This means click's ``should_strip_ansi`` logic no
|
|
203
|
+
longer fires for prompt text, so any ANSI codes baked into the prompt via
|
|
204
|
+
``click.style(..., bold=True)`` leak raw into non-TTY output (piped
|
|
205
|
+
output, CI logs, captured streams). Restore the pre-8.4 behaviour by
|
|
206
|
+
unstyling the prompt ourselves when the destination stream isn't a TTY.
|
|
207
|
+
|
|
208
|
+
Applying ``click.unstyle`` to plain text is a harmless no-op.
|
|
209
|
+
"""
|
|
210
|
+
stream = click.get_text_stream("stderr" if err else "stdout")
|
|
211
|
+
if not stream.isatty():
|
|
212
|
+
prompt = click.unstyle(prompt)
|
|
213
|
+
return prompt
|
|
214
|
+
|
|
215
|
+
|
|
197
216
|
def confirm_operation(prompt, prefix=None, assume_yes=False, err=False):
|
|
198
217
|
"""Prompt the user for confirmation for dangerous actions."""
|
|
199
218
|
if assume_yes:
|
|
@@ -203,7 +222,7 @@ def confirm_operation(prompt, prefix=None, assume_yes=False, err=False):
|
|
|
203
222
|
"Are you %s certain you want to" % (click.style("absolutely", bold=True))
|
|
204
223
|
)
|
|
205
224
|
|
|
206
|
-
prompt = f"{prefix} {prompt}?"
|
|
225
|
+
prompt = maybe_unstyle_prompt(f"{prefix} {prompt}?", err=err)
|
|
207
226
|
|
|
208
227
|
answered = click.confirm(prompt, err=err)
|
|
209
228
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import base64
|
|
4
4
|
from datetime import datetime
|
|
5
|
+
from urllib.parse import urlsplit
|
|
5
6
|
|
|
6
7
|
import click
|
|
7
8
|
from click.core import ParameterSource
|
|
@@ -11,6 +12,7 @@ from .types import ExpandPath
|
|
|
11
12
|
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
|
12
13
|
BAD_API_HEADERS = ("user-agent", "host")
|
|
13
14
|
API_HEADER_TRANSFORMS = {}
|
|
15
|
+
PUBLIC_API_HOST_SUFFIXES = ("cloudsmith.io", "cloudsmith.com")
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class IntOrWildcard(click.ParamType):
|
|
@@ -84,6 +86,48 @@ def validate_api_headers(param, value):
|
|
|
84
86
|
return headers
|
|
85
87
|
|
|
86
88
|
|
|
89
|
+
def host_matches_suffixes(url, suffixes):
|
|
90
|
+
"""True if url's hostname equals or is a subdomain of one of the suffixes.
|
|
91
|
+
|
|
92
|
+
Parsing the hostname (rather than substring-matching the URL) ensures
|
|
93
|
+
userinfo, port, and path components cannot smuggle a host past the check.
|
|
94
|
+
"""
|
|
95
|
+
hostname = (urlsplit(url).hostname or "").lower()
|
|
96
|
+
return bool(hostname) and any(
|
|
97
|
+
hostname == suffix or hostname.endswith(f".{suffix}") for suffix in suffixes
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def is_trusted_api_host(host, extra_suffixes=()):
|
|
102
|
+
"""True if host is an allowed Cloudsmith host (or matches an extra suffix)."""
|
|
103
|
+
return host_matches_suffixes(host, PUBLIC_API_HOST_SUFFIXES + tuple(extra_suffixes))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def validate_untrusted_api_host(host, extra_suffixes=()):
|
|
107
|
+
"""Raise if an api_host from an untrusted config is not an allowed host."""
|
|
108
|
+
if is_trusted_api_host(host, extra_suffixes):
|
|
109
|
+
return
|
|
110
|
+
raise click.UsageError(
|
|
111
|
+
f'api_host "{host}" is set by a config file in the current directory '
|
|
112
|
+
"and is not an allowed Cloudsmith host. Allowed hosts must be under "
|
|
113
|
+
"*.cloudsmith.io or *.cloudsmith.com. To use a custom host, set it via "
|
|
114
|
+
"--api-host, the CLOUDSMITH_API_HOST environment variable, an explicit "
|
|
115
|
+
"--config-file, or your user-level config."
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def validate_untrusted_api_proxy(proxy, allowed_suffixes=()):
|
|
120
|
+
"""Raise if an api_proxy from an untrusted config is not an allowed proxy."""
|
|
121
|
+
if host_matches_suffixes(proxy, allowed_suffixes):
|
|
122
|
+
return
|
|
123
|
+
raise click.UsageError(
|
|
124
|
+
f'api_proxy "{proxy}" is set by a config file in the current directory '
|
|
125
|
+
"and is not an allowed proxy. To use a proxy, set it via --api-proxy, "
|
|
126
|
+
"the CLOUDSMITH_API_PROXY environment variable, an explicit "
|
|
127
|
+
"--config-file, or your user-level config."
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
87
131
|
def validate_slashes(
|
|
88
132
|
param, value, minimum=2, maximum=None, form=None, allow_blank=False
|
|
89
133
|
):
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
import json
|
|
12
12
|
import logging
|
|
13
13
|
import os
|
|
14
|
+
import sys
|
|
14
15
|
from pathlib import Path
|
|
15
16
|
|
|
16
17
|
from ...core.cache_utils import merge_json_file
|
|
@@ -56,6 +57,21 @@ class DockerInstaller:
|
|
|
56
57
|
name = "docker"
|
|
57
58
|
summary = "Docker credential helper for Cloudsmith registries"
|
|
58
59
|
|
|
60
|
+
@classmethod
|
|
61
|
+
def _resolve_target_cmd(cls) -> str:
|
|
62
|
+
"""Return the command the launcher forwards to.
|
|
63
|
+
|
|
64
|
+
A pip/source install resolves the bare ``cloudsmith`` command via
|
|
65
|
+
``PATH``. A frozen standalone binary (PyInstaller) is not guaranteed
|
|
66
|
+
to be on ``PATH`` under that name, so point the launcher at the
|
|
67
|
+
absolute executable instead — mirroring the frozen handling in
|
|
68
|
+
:func:`cloudsmith_cli.cli.commands.mcp._get_server_config`. The path
|
|
69
|
+
is quoted so a directory containing spaces still execs correctly.
|
|
70
|
+
"""
|
|
71
|
+
if getattr(sys, "frozen", False):
|
|
72
|
+
return f'"{sys.executable}" credential-helper docker'
|
|
73
|
+
return cls.TARGET_CMD
|
|
74
|
+
|
|
59
75
|
def install(
|
|
60
76
|
self,
|
|
61
77
|
*,
|
|
@@ -190,7 +206,9 @@ class DockerInstaller:
|
|
|
190
206
|
return actions
|
|
191
207
|
|
|
192
208
|
# Real install
|
|
193
|
-
launcher_path = write_launcher(
|
|
209
|
+
launcher_path = write_launcher(
|
|
210
|
+
target_dir, self.LAUNCHER_NAME, self._resolve_target_cmd()
|
|
211
|
+
)
|
|
194
212
|
actions.append(f"wrote launcher {launcher_path}")
|
|
195
213
|
|
|
196
214
|
changed = merge_json_file(config_path, mutate)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.20.0
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cloudsmith-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.20.0
|
|
4
4
|
Summary: Cloudsmith Command-Line Interface (CLI)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
License: Apache License 2.0
|
|
5
|
+
Author-email: Cloudsmith Ltd <support@cloudsmith.io>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/cloudsmith-io/cloudsmith-cli
|
|
9
8
|
Keywords: cloudsmith,cli,devops
|
|
10
|
-
Platform: any
|
|
11
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
10
|
Classifier: Environment :: Console
|
|
13
11
|
Classifier: Intended Audience :: Developers
|
|
14
12
|
Classifier: Intended Audience :: System Administrators
|
|
15
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
13
|
Classifier: Operating System :: POSIX :: Linux
|
|
17
14
|
Classifier: Programming Language :: Python
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -31,7 +28,7 @@ Requires-Dist: click-configfile>=0.2.3
|
|
|
31
28
|
Requires-Dist: click-didyoumean>=0.0.3
|
|
32
29
|
Requires-Dist: click-spinner>=0.1.7
|
|
33
30
|
Requires-Dist: json5>=0.9.0
|
|
34
|
-
Requires-Dist: cloudsmith-api<3.0,>=2.0.
|
|
31
|
+
Requires-Dist: cloudsmith-api<3.0,>=2.0.29
|
|
35
32
|
Requires-Dist: keyring>=25.4.1
|
|
36
33
|
Requires-Dist: mcp==1.27.2
|
|
37
34
|
Requires-Dist: PyJWT[crypto]>=2.0.0
|
|
@@ -45,20 +42,7 @@ Provides-Extra: aws
|
|
|
45
42
|
Requires-Dist: boto3[crt]>=1.26.0; extra == "aws"
|
|
46
43
|
Provides-Extra: all
|
|
47
44
|
Requires-Dist: boto3[crt]>=1.26.0; extra == "all"
|
|
48
|
-
Dynamic: author
|
|
49
|
-
Dynamic: author-email
|
|
50
|
-
Dynamic: classifier
|
|
51
|
-
Dynamic: description
|
|
52
|
-
Dynamic: description-content-type
|
|
53
|
-
Dynamic: home-page
|
|
54
|
-
Dynamic: keywords
|
|
55
|
-
Dynamic: license
|
|
56
45
|
Dynamic: license-file
|
|
57
|
-
Dynamic: platform
|
|
58
|
-
Dynamic: provides-extra
|
|
59
|
-
Dynamic: requires-dist
|
|
60
|
-
Dynamic: requires-python
|
|
61
|
-
Dynamic: summary
|
|
62
46
|
|
|
63
47
|
# Cloudsmith Command Line Interface (CLI)
|
|
64
48
|
|
|
@@ -203,6 +187,30 @@ Or you can get the latest pre-release version from Cloudsmith:
|
|
|
203
187
|
pip install --upgrade cloudsmith-cli --extra-index-url=https://dl.cloudsmith.io/public/cloudsmith/cli/python/index/
|
|
204
188
|
```
|
|
205
189
|
|
|
190
|
+
### Standalone Binaries
|
|
191
|
+
|
|
192
|
+
Each release also ships self-contained binaries that bundle Python and all dependencies — no Python installation required. Download the archive for your platform from the [GitHub releases page](https://github.com/cloudsmith-io/cloudsmith-cli/releases) (or the [Cloudsmith CLI repository](https://cloudsmith.io/~cloudsmith/repos/cli/packages/)), verify it against the accompanying `.sha256` file, extract it, and add the extracted `cloudsmith` directory to your `PATH`:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
tar -xzf cloudsmith-<version>-<target>.tar.gz
|
|
196
|
+
./cloudsmith/cloudsmith --version
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Available targets: `linux-x86_64-gnu`, `linux-x86_64-musl`, `linux-aarch64-gnu`, `linux-aarch64-musl`, `macos-arm64`, `macos-x86_64`, and `windows-x86_64` (as a `.zip`).
|
|
200
|
+
|
|
201
|
+
Standalone binaries include all optional features, including AWS OIDC support.
|
|
202
|
+
|
|
203
|
+
#### Verifying Linux binaries
|
|
204
|
+
|
|
205
|
+
The four Linux archives (`linux-x86_64-gnu`, `linux-x86_64-musl`, `linux-aarch64-gnu`, `linux-aarch64-musl`) are GPG-signed with a detached binary signature published alongside each archive as `<archive>.sig`. To verify, import the Cloudsmith CLI release public key (`cloudsmith-cli-release-key.asc`, attached to each GitHub release) and check the signature:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
gpg --import cloudsmith-cli-release-key.asc
|
|
209
|
+
gpg --verify cloudsmith-<version>-linux-x86_64-gnu.tar.gz.sig cloudsmith-<version>-linux-x86_64-gnu.tar.gz
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
A successful verification reports a good signature from the Cloudsmith CLI release key. (The macOS and Windows binaries are not GPG-signed; native signing for those platforms is tracked separately.)
|
|
213
|
+
|
|
206
214
|
### Optional Dependencies
|
|
207
215
|
|
|
208
216
|
The CLI supports optional extras for additional functionality:
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
MANIFEST.in
|
|
3
3
|
README.md
|
|
4
|
-
|
|
5
|
-
setup.py
|
|
4
|
+
pyproject.toml
|
|
6
5
|
cloudsmith_cli/__init__.py
|
|
7
6
|
cloudsmith_cli/__main__.py
|
|
8
7
|
cloudsmith_cli.egg-info/PKG-INFO
|
|
9
8
|
cloudsmith_cli.egg-info/SOURCES.txt
|
|
10
9
|
cloudsmith_cli.egg-info/dependency_links.txt
|
|
11
10
|
cloudsmith_cli.egg-info/entry_points.txt
|
|
12
|
-
cloudsmith_cli.egg-info/not-zip-safe
|
|
13
11
|
cloudsmith_cli.egg-info/requires.txt
|
|
14
12
|
cloudsmith_cli.egg-info/top_level.txt
|
|
15
13
|
cloudsmith_cli/cli/__init__.py
|
|
@@ -67,37 +65,6 @@ cloudsmith_cli/cli/commands/quota/__init__.py
|
|
|
67
65
|
cloudsmith_cli/cli/commands/quota/command.py
|
|
68
66
|
cloudsmith_cli/cli/commands/quota/history.py
|
|
69
67
|
cloudsmith_cli/cli/commands/quota/quota.py
|
|
70
|
-
cloudsmith_cli/cli/tests/__init__.py
|
|
71
|
-
cloudsmith_cli/cli/tests/conftest.py
|
|
72
|
-
cloudsmith_cli/cli/tests/test_metadata_common.py
|
|
73
|
-
cloudsmith_cli/cli/tests/test_oidc_detector_config.py
|
|
74
|
-
cloudsmith_cli/cli/tests/test_push.py
|
|
75
|
-
cloudsmith_cli/cli/tests/test_saml.py
|
|
76
|
-
cloudsmith_cli/cli/tests/test_utils.py
|
|
77
|
-
cloudsmith_cli/cli/tests/test_webserver.py
|
|
78
|
-
cloudsmith_cli/cli/tests/utils.py
|
|
79
|
-
cloudsmith_cli/cli/tests/commands/__init__.py
|
|
80
|
-
cloudsmith_cli/cli/tests/commands/conftest.py
|
|
81
|
-
cloudsmith_cli/cli/tests/commands/test_auth.py
|
|
82
|
-
cloudsmith_cli/cli/tests/commands/test_check.py
|
|
83
|
-
cloudsmith_cli/cli/tests/commands/test_credential_helper.py
|
|
84
|
-
cloudsmith_cli/cli/tests/commands/test_credential_helper_install.py
|
|
85
|
-
cloudsmith_cli/cli/tests/commands/test_download.py
|
|
86
|
-
cloudsmith_cli/cli/tests/commands/test_entitlements.py
|
|
87
|
-
cloudsmith_cli/cli/tests/commands/test_login.py
|
|
88
|
-
cloudsmith_cli/cli/tests/commands/test_logout.py
|
|
89
|
-
cloudsmith_cli/cli/tests/commands/test_main.py
|
|
90
|
-
cloudsmith_cli/cli/tests/commands/test_mcp.py
|
|
91
|
-
cloudsmith_cli/cli/tests/commands/test_metadata.py
|
|
92
|
-
cloudsmith_cli/cli/tests/commands/test_package_commands.py
|
|
93
|
-
cloudsmith_cli/cli/tests/commands/test_repos.py
|
|
94
|
-
cloudsmith_cli/cli/tests/commands/test_tokens.py
|
|
95
|
-
cloudsmith_cli/cli/tests/commands/test_upstream.py
|
|
96
|
-
cloudsmith_cli/cli/tests/commands/test_vulnerabilities.py
|
|
97
|
-
cloudsmith_cli/cli/tests/commands/policy/__init__.py
|
|
98
|
-
cloudsmith_cli/cli/tests/commands/policy/test_deny.py
|
|
99
|
-
cloudsmith_cli/cli/tests/commands/policy/test_licence.py
|
|
100
|
-
cloudsmith_cli/cli/tests/commands/policy/test_vulnerability.py
|
|
101
68
|
cloudsmith_cli/core/__init__.py
|
|
102
69
|
cloudsmith_cli/core/cache_utils.py
|
|
103
70
|
cloudsmith_cli/core/config.py
|
|
@@ -151,28 +118,6 @@ cloudsmith_cli/core/credentials/providers/oidc_provider.py
|
|
|
151
118
|
cloudsmith_cli/core/mcp/__init__.py
|
|
152
119
|
cloudsmith_cli/core/mcp/data.py
|
|
153
120
|
cloudsmith_cli/core/mcp/server.py
|
|
154
|
-
cloudsmith_cli/core/tests/__init__.py
|
|
155
|
-
cloudsmith_cli/core/tests/test_azure_devops_detector.py
|
|
156
|
-
cloudsmith_cli/core/tests/test_bitbucket_pipelines_detector.py
|
|
157
|
-
cloudsmith_cli/core/tests/test_cache_utils.py
|
|
158
|
-
cloudsmith_cli/core/tests/test_circleci_detector.py
|
|
159
|
-
cloudsmith_cli/core/tests/test_cli_flag_provider.py
|
|
160
|
-
cloudsmith_cli/core/tests/test_credential_chain_priority.py
|
|
161
|
-
cloudsmith_cli/core/tests/test_credential_context.py
|
|
162
|
-
cloudsmith_cli/core/tests/test_credential_provider_chain.py
|
|
163
|
-
cloudsmith_cli/core/tests/test_credentials_file_provider.py
|
|
164
|
-
cloudsmith_cli/core/tests/test_detector_controls.py
|
|
165
|
-
cloudsmith_cli/core/tests/test_download.py
|
|
166
|
-
cloudsmith_cli/core/tests/test_env_var_provider.py
|
|
167
|
-
cloudsmith_cli/core/tests/test_generic_detector.py
|
|
168
|
-
cloudsmith_cli/core/tests/test_github_actions_detector.py
|
|
169
|
-
cloudsmith_cli/core/tests/test_gitlab_ci_detector.py
|
|
170
|
-
cloudsmith_cli/core/tests/test_init.py
|
|
171
|
-
cloudsmith_cli/core/tests/test_keyring.py
|
|
172
|
-
cloudsmith_cli/core/tests/test_keyring_provider.py
|
|
173
|
-
cloudsmith_cli/core/tests/test_metadata.py
|
|
174
|
-
cloudsmith_cli/core/tests/test_rest.py
|
|
175
|
-
cloudsmith_cli/core/tests/test_version.py
|
|
176
121
|
cloudsmith_cli/credential_helpers/__init__.py
|
|
177
122
|
cloudsmith_cli/credential_helpers/backends.py
|
|
178
123
|
cloudsmith_cli/credential_helpers/common.py
|