feat: add NETRC support#216
Conversation
34e2c70 to
618a6d4
Compare
|
Thanks for putting this together and for including comprehensive tests and documentation. NETRC support would be a useful addition. Before merging, could you please address these cases?
All 798 tests and lint passed locally. Since this is still a draft, I’d be happy to review it again after the next update. Thanks again! |
618a6d4 to
21b56bb
Compare
|
Thanks for your review, great catches on all the points! I've pushed the fixes :) |
|
Thanks for the quick turnaround! I re-reviewed the updated branch — all three points from the previous review are properly addressed and covered by tests (quoted-value parsing, trailing-slash Cloud domain, bearer machine-only matching with a stale email). All 802 tests and lint pass locally. While re-reviewing, I found two new issues that I could reproduce by running the code, so I'd like to ask for fixes before merging: 1.
|
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
21b56bb to
b718863
Compare
pchuri
left a comment
There was a problem hiding this comment.
Thanks for the PR — this is a well-built feature. The netrc parser handles macdef bodies, quoted/escaped values, comment lines, and CRLF, the test coverage is thorough (precedence, email mismatch, mTLS exclusion), and the docs are updated accurately. A few findings below.
🔴 Regression: inferApiPath lost case-insensitivity
The old code lowercased the domain before checking .atlassian.net, but the new extractHost() doesn't:
const extractHost = (rawValue) => {
return (rawValue || '').trim()
.replace(/^https?:\/\//i, '')
.replace(/\/.*$/, ''); // no toLowerCase()
};
const inferApiPath = (domain) => {
const host = extractHost(domain);
if (host.endsWith('.atlassian.net')) { ... }A domain like MyCompany.Atlassian.NET used to infer /wiki/rest/api and now falls back to /rest/api. Adding .toLowerCase() inside extractHost fixes this in one line and also keeps netrc matching and API-path inference consistent (lookupNetrc already lowercases internally, so it's unaffected). A test with an uppercase domain → /wiki/rest/api would lock this in.
🟡 Design gap: netrc doesn't work with env-based config
The netrc fallback only runs on the stored-profile path. A curl-style setup — CONFLUENCE_DOMAIN set via env, token in .netrc — doesn't work: with no token, hasEnvAuth is false, so the env path is skipped and config falls through to profile resolution ("No configuration found!" if there's no config file). SKILL.md does say "profiles", so this looks intentional, but the users most likely to want netrc (CI, dotfiles-managed setups) overlap heavily with env-only users. I'd suggest either documenting the limitation in the README or extending the fallback to the env path.
🟡 Parser edge cases
- Mid-line comments: only lines starting with
#are skipped. Inmachine foo # my password here, the#token hits thedefaultcase (which unconditionally swallows one following token), and the subsequentpasswordkeyword survives — the entry ends up withpassword='here'. Inline comments aren't standard netrc (curl also only skips line-leading#), but the unconditionali++in the default case makes the parser fragile against arbitrary trailing text. defaultentries are never matched: recording them with a null host deviates from standard netrc semantics (wheredefaultis a fallback). The code comment explains the intent — a one-line note in the README's netrc section would help users who expect curl-like behavior.
🟡 Security suggestion: no file-permission check
The project enforces 0600/0700 when saving its own config (saveConfigFile), but a world-readable .netrc is read silently. Following the ftp/curl convention of warning (or refusing) when the file has group/other read bits would keep the security posture consistent. A POSIX-only fs.statSync(filePath).mode & 0o077 check would suffice.
🔵 Nits
- README precedence wording ("environment variable /
--token→ profile token →.netrc"):--tokenis an init-time storage flag rather than a per-request override, and the env token only applies whenCONFLUENCE_DOMAINis also set (pre-existing behavior). Not wrong, just a bit oversimplified. - Login matching is case-sensitive (
entry.login === login) while host matching is case-insensitive. Emails are case-insensitive in practice, so a case mismatch could be confusing to debug. extractHostdoesn't strip a port, so a domain with:8443requires the port in the netrcmachinetoo (curl ignores ports when matching). Worth a line in the docs for on-prem users.
Verdict
The inferApiPath case regression is the only thing I'd consider blocking — everything else is optional or documentation. The domain normalization (scheme/trailing-slash stripping) bundled in here is a genuine fix given base URLs are built as ${protocol}://${domain}${apiPath}, and it comes with tests. Nice work overall.
|
Closing this one, sorry. These reviews are LLM-generated, and the issue with asking a model to "review this PR" is that it will always come back with something. Two of the points in your last comment are intentional behavior, not bugs. I don't have the time to keep revising against that. Feel free to pull the branch and make whatever changes you want before merging; otherwise I'll use the patch locally. |
# [2.17.0](v2.16.2...v2.17.0) (2026-07-17) ### Features * add NETRC support ([#216](#216)) ([79d1757](79d1757))
|
🎉 This PR is included in version 2.17.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
|
You're right, and I owe you an apology. The last review was AI-assisted and I posted it without filtering it properly — two of the points flagged behavior you had deliberately designed and documented (the env-only scope and ignoring I didn't want that process failure to bury good work, so I've reopened and merged the PR as-is — it shipped in v2.17.0 with your authorship intact. The only follow-up I applied on Thanks for the contribution and for the direct feedback — I'll review the reviews before posting them from now on. You'd be welcome back anytime. |
Description
Adds support for a NETRC file. Marked as draft while I test it on my own setup.
Type of Change
Testing
Checklist