feat(ENG-13679): NPM Credential Helper - #367
Conversation
There was a problem hiding this comment.
Pull request overview
Adds an NPM credential-helper integration to Cloudsmith CLI so pnpm/npm can authenticate to Cloudsmith registries without hard-coded tokens, plus installer/uninstaller support and tests.
Changes:
- Introduces an NPM credential helper runtime and Click command (
cloudsmith credential-helper npm). - Adds an NPM installer that writes a launcher and configures
.npmrctokenHelperentries (with best-effort custom-domain discovery). - Extends the credential-helper management CLI, launcher utilities, and test suite to cover NPM flows.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| cloudsmith_cli/credential_helpers/npm/runtime.py | New NPM helper runtime that returns a token for Cloudsmith registries. |
| cloudsmith_cli/credential_helpers/npm/rc.py | New .npmrc parser/mutator for //host/:key=value entries. |
| cloudsmith_cli/credential_helpers/npm/installer.py | New install/uninstall/status implementation for NPM .npmrc + launcher wiring. |
| cloudsmith_cli/credential_helpers/npm/init.py | Exports NPM helper runtime API. |
| cloudsmith_cli/credential_helpers/launchers.py | Adds dry_run support to launcher write/remove helpers. |
| cloudsmith_cli/credential_helpers/generic.py | Adds PartialInstallError for partial-install reporting/exit handling. |
| cloudsmith_cli/credential_helpers/docker/installer.py | Adjusts PATH warning text (but currently incorrect). |
| cloudsmith_cli/cli/commands/credential_helper/npm.py | New Click command entry point for the NPM helper protocol. |
| cloudsmith_cli/cli/commands/credential_helper/manage.py | Registers NPM installer and adds partial-install handling for install. |
| cloudsmith_cli/cli/commands/credential_helper/init.py | Registers the new npm subcommand. |
| cloudsmith_cli/cli/tests/commands/test_credential_helper_install.py | Adds NPM installer/manage command coverage and extends launcher tests. |
Suppressed comments (5)
cloudsmith_cli/credential_helpers/npm/rc.py:42
- Leading whitespace preservation is computed incorrectly:
entry[: len(stripped_entry) - len(entry)]produces an unrelated slice (often most of the line) instead of just the leading whitespace. This will corrupt written.npmrclines that were indented.
# remove any starting whitespace
stripped_entry = entry.lstrip()
# track the starting whitespace
self._leading = entry[: len(stripped_entry) - len(entry)]
if not stripped_entry.startswith("/"):
raise ValueError("invalid url, should start with ``//``")
cloudsmith_cli/credential_helpers/npm/rc.py:93
__contains__usesitem._value is not Noneas the wildcard condition, which means an entry with a specific value is treated as a match as long as the key exists (even if the stored value differs). After makingfrom_values(..., value=None)set_value=None, the wildcard check should be inverted.
def __contains__(self, item: str | URLEntry) -> bool:
if isinstance(item, NPMRC.URLEntry):
return item.id in self._mapping and (
item._value is not None or self._mapping[item.id] == item._value
)
cloudsmith_cli/credential_helpers/npm/installer.py:67
- Typo in docstring: "crednetial" → "credential".
"""Install the NPM crednetial helper.
cloudsmith_cli/credential_helpers/npm/installer.py:180
- When not running in dry-run mode, successful
.npmrcmutations don't add any action strings (unlike DockerInstaller, which reports the keys it set). This makescredential-helper install npmoutput incomplete and harder to audit.
if dry_run:
if added:
actions.append(f"would set {entry} in {config_path}")
else:
actions.append(
cloudsmith_cli/cli/commands/credential_helper/npm.py:12
- Avoid
import *here; it obscures what the command depends on and differs from the Docker helper command (which importsexecuteexplicitly).
from ....credential_helpers.npm import *
from ...decorators import common_api_auth_options, resolve_credentials
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
4883fb7 to
97edd56
Compare
cloudsmith-iduffy
left a comment
There was a problem hiding this comment.
Ran it locally and it worked great, few small comments but nothing major.
Add pattern to exclude test packages at deeper nesting levels (e.g. cloudsmith_cli.credential_helpers.npm.tests) from the built wheel distribution. This prevents duplicate __init__.py files in the wheel and ensures test files are not packaged with the CLI.
… expects an absolute path and therefore doesn't need to be in PATH
* beginning on npm -> pnpm rename * `resolve_bin_dir` will now resolve dirs as absolute instead of relative * silently fail handling malformed url entries in npmrc, testing them instead as a normal line * fix typo * tests where apply for the above
also, add tests around this, and make sure that the dry run reports that a value will be written
given that tokenHelper is a pnpm config item.
2c9d5b6 to
99bd6f2
Compare
|
@cloudsmith-iduffy feedback implemented there + tests to cover the cases you found, this is ready for another look |
cloudsmith-iduffy
left a comment
There was a problem hiding this comment.
One small comment but otherwise good!
Description
Provide a credential helper of npm, which pnpm can use, in order to authenticate without hard coded tokens.
It adds the token as a best attempt, only if a given domain hasn't already had auth configured. Any collisions are reported as errors.
Type of Change