Skip to content

fix(login): preserve runpodctl credentials in ~/.runpod/config.toml#333

Open
vaskoz wants to merge 1 commit intomainfrom
fix/login-preserve-runpodctl-credentials
Open

fix(login): preserve runpodctl credentials in ~/.runpod/config.toml#333
vaskoz wants to merge 1 commit intomainfrom
fix/login-preserve-runpodctl-credentials

Conversation

@vaskoz
Copy link
Copy Markdown

@vaskoz vaskoz commented May 6, 2026

Summary

  • flash login was clobbering the top-level apikey/apiurl values that runpodctl writes to ~/.runpod/config.toml. The cause: save_api_key() delegated to runpod-python's set_credentials(overwrite=True), which opens the file in "w" mode and rewrites it with only a [default] section.
  • save_api_key() now does a line-based merge that updates only the [default].api_key field and preserves everything else — runpodctl's top-level keys, other profile sections, and any unrelated fields within [default].

Test plan

  • New unit tests cover: preserving runpodctl top-level keys, adding [default] when missing, preserving other profile sections, fresh-file creation
  • Existing test_credentials.py and test_login.py still pass (26/26)
  • Smoke-tested merger against real-world TOML shapes (file with both formats coexisting, only top-level keys, empty file, [default] without api_key, blank lines between sections)

🤖 Generated with Claude Code

flash login was clobbering the top-level apikey/apiurl values that
runpodctl writes to ~/.runpod/config.toml, because it delegated to
runpod-python's set_credentials() which opens the file in "w" mode.
save_api_key() now does a line-based merge that updates only the
[default].api_key field and preserves all other content.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

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.

Pull request overview

This PR updates flash login credential persistence to avoid clobbering runpodctl’s top-level apikey/apiurl keys in ~/.runpod/config.toml by performing a targeted text merge that updates only [default].api_key.

Changes:

  • Replace runpod-python’s set_credentials(overwrite=True) usage with a line-based upsert that preserves unrelated TOML content.
  • Add unit tests covering mixed runpodctl + [default] formats, missing [default], preserving other profiles, and fresh-file creation.

Reviewed changes

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

File Description
src/runpod_flash/core/credentials.py Implements _upsert_default_api_key() and updates save_api_key() to preserve non-flash TOML content.
tests/unit/test_credentials.py Adds unit tests to validate config preservation behavior when saving API keys.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +27 to +28
_DEFAULT_HEADER_RE = re.compile(r"^\s*\[default\]\s*$")
_SECTION_HEADER_RE = re.compile(r"^\s*\[[^\]]+\]\s*$")
Comment on lines +79 to +107
def test_preserves_runpodctl_top_level_keys(self, isolate_credentials_file):
isolate_credentials_file.parent.mkdir(parents=True, exist_ok=True)
isolate_credentials_file.write_text(
"apikey = 'rpa_runpodctl_key'\n"
"apiurl = 'https://api.runpod.io/graphql'\n"
"\n"
"[default]\n"
'api_key = "old-flash-key"\n'
)
save_api_key("new-flash-key")
text = isolate_credentials_file.read_text()
assert "apikey = 'rpa_runpodctl_key'" in text
assert "apiurl = 'https://api.runpod.io/graphql'" in text
parsed = tomllib.loads(text)
assert parsed["apikey"] == "rpa_runpodctl_key"
assert parsed["apiurl"] == "https://api.runpod.io/graphql"
assert parsed["default"]["api_key"] == "new-flash-key"

def test_adds_default_section_when_missing(self, isolate_credentials_file):
isolate_credentials_file.parent.mkdir(parents=True, exist_ok=True)
isolate_credentials_file.write_text(
"apikey = 'rpa_runpodctl_key'\napiurl = 'https://api.runpod.io/graphql'\n"
)
save_api_key("flash-key")
text = isolate_credentials_file.read_text()
parsed = tomllib.loads(text)
assert parsed["apikey"] == "rpa_runpodctl_key"
assert parsed["apiurl"] == "https://api.runpod.io/graphql"
assert parsed["default"]["api_key"] == "flash-key"
Comment on lines +123 to +127
insert_idx = default_end
while insert_idx > default_start + 1 and lines[insert_idx - 1].strip() == "":
insert_idx -= 1
lines.insert(insert_idx, new_line + "\n")
return "".join(lines)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants