From b01b6a477ef281fb43634fc7165fad681d3d7173 Mon Sep 17 00:00:00 2001 From: Ian Duffy Date: Wed, 26 Aug 2026 16:59:30 +0100 Subject: [PATCH 1/2] release: cloudsmith-cli v1.26.0 Co-Authored-By: Claude Fable 5 --- .bumpversion.cfg | 2 +- CHANGELOG.md | 17 ++++++++++++++--- cloudsmith_cli/data/VERSION | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 77db4d41..eb2bd0cf 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.25.0 +current_version = 1.26.0 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b87e660..a49b1b4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,20 +7,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [1.26.0] - 2026-08-26 + ### Added -- Added `cloudsmith repos gpg` for managing the GPG key a repository signs its package indexes with. `get` shows the active key and its armored public block, `upload` installs a key you supply, and `regenerate` replaces the current key with a freshly generated Cloudsmith one. Key material and passphrases are only ever read from a file, stdin, or a hidden prompt, never from a command-line value, and `--debug` is refused on `upload` so the request body can't be logged. Both mutating subcommands accept `-n/--dry-run`, which checks the inputs and the key currently in place - naming the fingerprint that would be replaced - then stops before the request, so a mistyped repository or a stale credential fails there rather than on the real attempt. `regenerate` asks you to type `regenerate` to confirm - with no terminal attached it fails instead of blocking, so pass `-y/--yes` for unattended runs. There's no `delete` subcommand because the API has no way to remove a repository's key. -- Added `cloudsmith repos privileges` for managing explicit repository access from the terminal. `list` shows the teams, users and service accounts that were granted access explicitly; `set` grants access to any number of them and leaves everyone else untouched, asking first if it would lower access someone already has; `revoke` takes access away from the ones named, skipping any that had none; and `replace` makes a JSON file (or stdin) the complete truth for the repository. `revoke` and `replace` ask for confirmation first unless `-y` is passed. +- Added `cloudsmith repos gpg` to manage the GPG key that a repository signs its package indexes with. `get` shows the active key and its armored public block. `upload` installs a key you supply. `regenerate` replaces the current key with a new key that Cloudsmith generates. The CLI reads key material and passphrases from a file, stdin, or a hidden prompt, never from a command-line value, and it refuses `--debug` on `upload` so the request body cannot reach the logs. Both `upload` and `regenerate` accept `-n/--dry-run`, which checks your inputs and the key currently in place, names the fingerprint it would replace, and stops before the request. A mistyped repository or a stale credential fails in the dry run instead of the real attempt. `regenerate` asks you to type `regenerate` to confirm. Without a terminal it fails instead of blocking, so pass `-y/--yes` for unattended runs. There is no `delete` subcommand because the API has no way to remove a repository's key. +- Added `cloudsmith repos privileges` to manage explicit repository access from the terminal. `list` shows the teams, users and service accounts with explicit access. `set` grants access to any number of them and leaves everyone else untouched; it asks first if it would lower access someone already has. `revoke` removes access from the ones you name and skips any that had none. `replace` makes a JSON file (or stdin) the complete truth for the repository. `revoke` and `replace` ask for confirmation unless you pass `-y`. +- Added a Cargo credential provider for Cloudsmith registries. `cloudsmith credential-helper install cargo` installs a `cargo-credential-cloudsmith` launcher binary and registers it in `$CARGO_HOME/config.toml`. Cargo then authenticates to Cloudsmith registries with your existing CLI credentials, without `cargo login` and without a token stored in `credentials.toml`. The provider speaks Cargo's [credential provider protocol](https://doc.rust-lang.org/cargo/reference/credential-provider-protocol.html), a newline-delimited JSON exchange. It answers `get` with the resolved token, and answers a registry that is not a Cloudsmith one with `url-not-supported`, so Cargo falls through to the next configured provider and authentication to crates.io keeps working. The installer appends the provider to `registry.global-credential-providers`, keeps `cargo:token` as the fallback, and pins it on any `[registries.*]` entry whose index points at a known Cloudsmith Cargo host. The CLI discovers custom Cloudsmith registry domains through the API and caches them locally. Add extra hostnames with `--domain` (repeatable), disable discovery with `--no-discover`, or preview changes with `--dry-run`. Manage installed helpers with `cloudsmith credential-helper uninstall cargo` and `cloudsmith credential-helper list`. ### Changed - `cloudsmith copy` now prints `Copied: owner/repo/slug (slug_perm)` after a successful copy and includes `slug_perm` in `-F json` output, matching `push`. +- The CLI starts faster. It imports command modules only when their command runs, and it imports the Cloudsmith SDK, `requests`, `rich`, `urllib3` and `semver` only when the code path needs them. A custom-domain cache hit no longer imports the SDK at all. + +### Fixed + +- On macOS, the keychain no longer asks for permission again after you click "Always Allow". The `keyring` library implements every write as a delete followed by a re-create, which resets the item's access control list. The CLI now updates the stored secret in place with `SecItemUpdate`, so the item and its grants survive every token refresh. This also holds when you run the CLI from more than one install, such as the standalone binary and a Python environment. +- SSO tokens in the keyring are now scoped per profile. Profiles that target the same API host used to share one set of entries and clobber each other's sessions. The default profile keeps the existing entry names. An existing non-default profile's session moves to its own scoped entries on its first token refresh, without a re-login. +- When the server definitively rejects an SSO token refresh (HTTP 400, 401, 403 or 422), the CLI now removes the dead tokens and returns the profile to a clean logged-out state with a "run `cloudsmith auth`" message. It used to keep the dead tokens, warn on every refresh attempt, and serve a stale bearer token in between. Transient failures (network errors, 5xx) still retry as before. +- Retry notices for throttled requests now go to stderr. This keeps stdout clean for machine-readable output. +- The pnpm credential helper now always prefixes the returned token with `Bearer`. pnpm's own scheme detection failed to add the prefix in some environments, for example Docker containers, and authentication failed there. ## [1.25.0] - 2026-08-24 ### Added -- Added a Cargo credential provider for Cloudsmith registries. `cloudsmith credential-helper install cargo` installs a `cargo-credential-cloudsmith` launcher binary and registers it in `$CARGO_HOME/config.toml`, so Cargo authenticates to Cloudsmith registries automatically using your existing CLI credentials — no `cargo login` and no token in `credentials.toml`. `cloudsmith credential-helper cargo` speaks Cargo's [credential provider protocol](https://doc.rust-lang.org/cargo/reference/credential-provider-protocol.html): a newline-delimited JSON exchange that answers `get` with the resolved token, and answers a registry that is not a Cloudsmith one with `url-not-supported` so Cargo falls through to the next configured provider — registering globally cannot break authentication to crates.io. The provider is appended to `registry.global-credential-providers` (keeping `cargo:token` as the fallback) and pinned on any `[registries.*]` entry whose index points at a known Cloudsmith Cargo host. Custom Cloudsmith registry domains are discovered via the API and cached locally; add extra hostnames with `--domain` (repeatable), disable discovery with `--no-discover`, or preview changes with `--dry-run`. Manage installed helpers with `cloudsmith credential-helper uninstall cargo` and `cloudsmith credential-helper list`. - Added Nix package and upstream support. Use `cloudsmith push nix` to upload Nix packages and `cloudsmith upstream nix` to manage Nix channel upstreams. - Added a pnpm credential helper. `cloudsmith credential-helper install pnpm` registers `pnpm-credential-cloudsmith` in the user-level `.npmrc`, using existing CLI credentials for Cloudsmith registries. It supports custom-domain discovery, additional `--domain` values, `--no-discover`, `--dry-run`, listing, and uninstalling. - Added `CLOUDSMITH_KEYRING_FILE_PATH` and `CLOUDSMITH_KEYRING_DIR` to relocate tokens stored by the bundled file-based keyring backends. An explicit file path takes precedence over the directory, and `KEYRING_PROPERTY_FILE_PATH` takes precedence over its Cloudsmith alias. diff --git a/cloudsmith_cli/data/VERSION b/cloudsmith_cli/data/VERSION index ad219194..5ff8c4f5 100644 --- a/cloudsmith_cli/data/VERSION +++ b/cloudsmith_cli/data/VERSION @@ -1 +1 @@ -1.25.0 +1.26.0 From 5abeeae48768ef85914fceeffefc205a52ebfb68 Mon Sep 17 00:00:00 2001 From: Ian Duffy Date: Wed, 26 Aug 2026 17:04:30 +0100 Subject: [PATCH 2/2] docs: tighten the 1.26.0 changelog entries Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a49b1b4b..d80fa2ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,22 +11,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added -- Added `cloudsmith repos gpg` to manage the GPG key that a repository signs its package indexes with. `get` shows the active key and its armored public block. `upload` installs a key you supply. `regenerate` replaces the current key with a new key that Cloudsmith generates. The CLI reads key material and passphrases from a file, stdin, or a hidden prompt, never from a command-line value, and it refuses `--debug` on `upload` so the request body cannot reach the logs. Both `upload` and `regenerate` accept `-n/--dry-run`, which checks your inputs and the key currently in place, names the fingerprint it would replace, and stops before the request. A mistyped repository or a stale credential fails in the dry run instead of the real attempt. `regenerate` asks you to type `regenerate` to confirm. Without a terminal it fails instead of blocking, so pass `-y/--yes` for unattended runs. There is no `delete` subcommand because the API has no way to remove a repository's key. -- Added `cloudsmith repos privileges` to manage explicit repository access from the terminal. `list` shows the teams, users and service accounts with explicit access. `set` grants access to any number of them and leaves everyone else untouched; it asks first if it would lower access someone already has. `revoke` removes access from the ones you name and skips any that had none. `replace` makes a JSON file (or stdin) the complete truth for the repository. `revoke` and `replace` ask for confirmation unless you pass `-y`. -- Added a Cargo credential provider for Cloudsmith registries. `cloudsmith credential-helper install cargo` installs a `cargo-credential-cloudsmith` launcher binary and registers it in `$CARGO_HOME/config.toml`. Cargo then authenticates to Cloudsmith registries with your existing CLI credentials, without `cargo login` and without a token stored in `credentials.toml`. The provider speaks Cargo's [credential provider protocol](https://doc.rust-lang.org/cargo/reference/credential-provider-protocol.html), a newline-delimited JSON exchange. It answers `get` with the resolved token, and answers a registry that is not a Cloudsmith one with `url-not-supported`, so Cargo falls through to the next configured provider and authentication to crates.io keeps working. The installer appends the provider to `registry.global-credential-providers`, keeps `cargo:token` as the fallback, and pins it on any `[registries.*]` entry whose index points at a known Cloudsmith Cargo host. The CLI discovers custom Cloudsmith registry domains through the API and caches them locally. Add extra hostnames with `--domain` (repeatable), disable discovery with `--no-discover`, or preview changes with `--dry-run`. Manage installed helpers with `cloudsmith credential-helper uninstall cargo` and `cloudsmith credential-helper list`. +- `cloudsmith repos gpg`: view, upload, or regenerate the GPG key your repository signs its package indexes with. No more trips to the web app. +- `cloudsmith repos privileges`: see who has explicit access to a repository, then grant, revoke, or replace it wholesale, all from the terminal. +- A Cargo credential provider. Run `cloudsmith credential-helper install cargo` once and Cargo authenticates to your Cloudsmith registries with your existing CLI credentials. No `cargo login`, no token on disk, and crates.io is left untouched. ### Changed -- `cloudsmith copy` now prints `Copied: owner/repo/slug (slug_perm)` after a successful copy and includes `slug_perm` in `-F json` output, matching `push`. -- The CLI starts faster. It imports command modules only when their command runs, and it imports the Cloudsmith SDK, `requests`, `rich`, `urllib3` and `semver` only when the code path needs them. A custom-domain cache hit no longer imports the SDK at all. +- The CLI starts noticeably faster. Heavy dependencies now load only when a command needs them. +- `cloudsmith copy` now tells you exactly what it copied, including the `slug_perm`, just like `push`. ### Fixed -- On macOS, the keychain no longer asks for permission again after you click "Always Allow". The `keyring` library implements every write as a delete followed by a re-create, which resets the item's access control list. The CLI now updates the stored secret in place with `SecItemUpdate`, so the item and its grants survive every token refresh. This also holds when you run the CLI from more than one install, such as the standalone binary and a Python environment. -- SSO tokens in the keyring are now scoped per profile. Profiles that target the same API host used to share one set of entries and clobber each other's sessions. The default profile keeps the existing entry names. An existing non-default profile's session moves to its own scoped entries on its first token refresh, without a re-login. -- When the server definitively rejects an SSO token refresh (HTTP 400, 401, 403 or 422), the CLI now removes the dead tokens and returns the profile to a clean logged-out state with a "run `cloudsmith auth`" message. It used to keep the dead tokens, warn on every refresh attempt, and serve a stale bearer token in between. Transient failures (network errors, 5xx) still retry as before. -- Retry notices for throttled requests now go to stderr. This keeps stdout clean for machine-readable output. -- The pnpm credential helper now always prefixes the returned token with `Bearer`. pnpm's own scheme detection failed to add the prefix in some environments, for example Docker containers, and authentication failed there. +- macOS finally remembers "Always Allow". The CLI now updates keychain items in place instead of recreating them, so the recurring permission prompts stop for good. +- Every profile now keeps its own SSO session. Profiles that point at the same API host no longer clobber each other. +- A dead SSO session now cleans itself up and asks you to log in again, instead of nagging you every half hour. +- Retry notices for throttled requests go to stderr, keeping stdout clean for scripts. +- The pnpm credential helper now always sends `Bearer`, fixing authentication in Docker containers and other places pnpm's own detection missed. ## [1.25.0] - 2026-08-24