Repository navigation
fix(no-ticket): keep credentials.ini sections and save missing API keys - #533
Merged
cloudsmith-iduffy merged 6 commits intoNov 2, 2026
Merged
Conversation
The api_key pattern used "\s*" after "=". "\s" also matches a newline, so an empty api_key consumed the next line that is not blank. On the second logout, this removed the next section header, and each later command failed with DuplicateOptionError. Match only spaces and tabs, accept ":" as configparser does, and give re.sub a callable so the key is never read as a template. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused fix preserves existing behavior, covers the reported corruption paths with regression tests, and has no unresolved findings.
No open issues 🎉
What changed in this PR
Fixes credentials-file corruption when logout clears an already-empty API key or login updates one, preserving section headers and the existing all-section behavior.
Changes:
- Restricts API-key replacement to one line, supports
:separators, and preserves literal backslashes. - Adds regression tests for repeated clears, updates after empty keys, and LF/CRLF input.
- Documents the fix and registers the Windows test marker.
| File | Description |
|---|---|
pyproject.toml |
Registers the Windows test marker. |
cloudsmith_cli/cli/tests/test_config.py |
Tests section preservation during credential edits. |
cloudsmith_cli/cli/config.py |
Fixes API-key replacement and adds type hints. |
CHANGELOG.md |
Documents the corruption fix and affected commands. |
Review effort: Balanced
This was referenced Oct 24, 2026
cloudsmith-iduffy
marked this pull request as ready for review
October 24, 2026 17:43
cloudsmith-iduffy
requested review from
a team and
cloudsmith-bot
as code owners
October 24, 2026 17:43
cloudsmith-iduffy
enabled auto-merge (squash)
October 24, 2026 17:43
When the [default] section had no api_key line, update_api_key changed nothing, but login and --save-config showed UPDATED. Add the key to [default], and create the section when it does not exist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tigh-latte
approved these changes
Oct 29, 2026
Collaborator
Author
|
@copilot resolve the merge conflicts on this branch. |
…redentials-corruption # Conflicts: # CHANGELOG.md # cloudsmith_cli/cli/config.py Co-authored-by: cloudsmith-iduffy <178375997+cloudsmith-iduffy@users.noreply.github.com>
auto-merge was automatically disabled
October 30, 2026 10:39
Head branch was pushed to by a user without write access
Contributor
Resolved the conflicts and merged |
* origin/master: fix(no-ticket): set a default timeout on each API request (#538) fix(no-ticket): print the result count when a list is empty (#545) fix(no-ticket): escape the args in the terraformrc block (#543) fix(no-ticket): show the dependencies help for list deps (#546) # Conflicts: # CHANGELOG.md
cloudsmith-iduffy
enabled auto-merge (squash)
November 2, 2026 00:22
cloudsmith-iduffy
deleted the
iduffy/fix-logout-credentials-corruption
branch
November 2, 2026 00:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR fixes two bugs in
CredentialsReader._set_api_key. The first breakscredentials.inion logout. The second loses a new API key without an error.cloudsmith logoutcan breakcredentials.iniso badly that no later command runs. The pattern inCredentialsReader._set_api_keyused\s*after the=.\salso matches a newline, so an emptyapi_key =line swallowed the blank line and the next section header.The common way to hit it is to run
logouttwice. Start with:The first
logoutis fine and leaves both keys empty. The secondlogoutturns the file into:After that, every command fails with
DuplicateOptionError: ... option 'api_key' in section 'default' already exists, includinglogoutitself, so the user has to fix the file by hand.loginand the--save-configoptions (tokens create,tokens refresh,auth --request-api-key) go through the same function throughupdate_api_key, so they did the same damage when they wrote a key after an empty one.With this change, the second
logoutleaves the file as:The change is in
_set_api_keyonly:^api_key[ \t]*[=:].*$, so it cannot cross a line. It also accepts:, which configparser reads as a separator. Before,logoutsaid it removed the credentials but left anapi_key: ...line in place. This is the same entry pattern that_set_section_valuein the same file uses.re.subgets a callable instead of a template string, so a backslash in a key is written as it is._set_section_valueis not a drop-in replacement for the clear. It edits one section and adds the key when the section has none, which would change whatlogoutwrites.Second fix: a missing key was never saved
When
credentials.inihas noapi_keyline in[default],update_api_keychanged nothing.create_config_filesstill printedCredentials config file: ... UPDATED, sologinand the--save-configoptions lost the new key without telling you. For example, a file with only:[default]stayed like that. Now it becomes:
When a key is written,
_set_api_keynow also calls_set_section_valuefor[default]. That replaces the key there, or adds it when it is missing. When the file has no[default]section, it creates one. The clear path does not call it, sologoutnever adds a key line.Type of Change
Additional Notes
cloudsmith_cli/cli/tests/test_config.py. They callCredentialsReaderon a file intmp_path, because the logout command tests mock the reader. One test clears a two-key file twice: the first call makes the file that has the empty key, and the second call is the call that broke it. The second test covers theupdate_api_keypath after an empty key. The third test covers a[default]section that has no key. Each test failed before its fix.\r\nbecomes\nbefore the pattern runs and no\ris left behind. The file is written back with the platform line ending. The CRLF case of the clear test compares bytes and has thewindowsmarker. It runs on every platform.windowsmarker line inpyproject.tomlis the same as the one iniduffy/fix-non-ascii-output-crash, which adds the marker and awindows-latestCI job. Whichever PR merges second keeps the line with no conflict. pytest runs with--strict-markers, so this PR has to register the marker itself.update_api_keywrites the new key into every section, not only the active profile. Sotokens create --save-configfor the default profile also replaces the key in each[profile:NAME]section, andlogoutclears every section. Logout scopes the keyring step to the active profile but not the file step, andcreate_config_fileshas no profile to pass. The intended behaviour is not clear from the code, tests, or docs, so I left it for a separate change.🤖 Generated with Claude Code