Skip to content

Add custom user config file #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions change/change-f41db53a-b9bb-4906-80c8-11a61b3d21cc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"changes": [
{
"type": "minor",
"comment": "Add custom user config file option",
"packageName": "ado-npm-auth",
"email": "[email protected]",
"dependentChangeType": "patch"
},
{
"type": "patch",
"comment": "Add custom user config file option",
"packageName": "azureauth",
"email": "[email protected]",
"dependentChangeType": "patch"
}
]
}
20 changes: 17 additions & 3 deletions packages/ado-npm-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ It will then perform a quick "pre-flight" check to assess if the token is valid,

### Beware the chicken and egg problem

You may need to set the registry to the public NPM feed when running `npm exec` or `npx`.
You may need to set the registry to the public NPM feed when running `npm exec` or `npx`.

There are 2 options to address this case:

Expand All @@ -49,12 +49,26 @@ popd
```

### 2: configure registry explicilty
If that's the case, set the environment variable `npm_config_registry=https://registry.npmjs.org`.
If that's the case, set the environment variable `npm_config_registry=https://registry.npmjs.org`.

That will ensure that `npx` or `npm exec` grabs from the public NPM feed, bypassing the soon-to-be authenticated ADO feed.
That will ensure that `npx` or `npm exec` grabs from the public NPM feed, bypassing the soon-to-be authenticated ADO feed.

```json
"scripts": {
"preinstall": "npm_config_registry=https://registry.npmjs.org npm exec ado-npm-auth"
},
```

### User Config File Location

By default ado-npm-auth tries locate the user config file for storing registry auth tokens from the system home directory, which is set to `$HOME` and `$USERPROFILE` environment variables for MacOS/Linux and Windows respectively. However, if your project is not located under your home directory, you will still experience unauthorized errors from the registry.

To customize where ado-npm-auth should locate your user config file, you have two options.

### 1: Set `ADO_NPM_AUTH_USER_CONFIG` environment variable

Set the `ADO_NPM_AUTH_USER_CONFIG` environment variable to the directory where your user config file is located, i.e. `C:\projects`

### 2. Pass `--userConfigFile` option

Pass `--userConfigFile` option to the CLI pointing to the user config file, i.e. `C:\projects\.yarnrc.yml`
9 changes: 8 additions & 1 deletion packages/ado-npm-auth/src/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface Args {
doValidCheck: boolean;
skipAuth: boolean;
configFile?: string;
userConfigFile?: string;
}

export function parseArgs(args: string[]): Args {
Expand All @@ -21,8 +22,13 @@ export function parseArgs(args: string[]): Args {
configFile: {
alias: "c",
type: "string",
description: "Skip checking the validity of the feeds",
description: "Custom workspace config file path",
},
userConfigFile: {
alias: "u",
type: "string",
description: "Custom user config file path",
}
})
.help()
.parseSync();
Expand All @@ -31,5 +37,6 @@ export function parseArgs(args: string[]): Args {
skipAuth: argv.skipAuth || false,
doValidCheck: !argv.skipCheck,
configFile: argv.configFile,
userConfigFile: argv.userConfigFile
};
}
4 changes: 2 additions & 2 deletions packages/ado-npm-auth/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { YarnRcFileProvider } from "./yarnrc/yarnrcFileProvider.js";

export const run = async (args: Args): Promise<null | boolean> => {
const fileProviders = [
new NpmrcFileProvider(args.configFile),
new YarnRcFileProvider(args.configFile),
new NpmrcFileProvider(args.configFile, args.userConfigFile),
new YarnRcFileProvider(args.configFile, args.userConfigFile),
];

const validatedFeeds: ValidatedFeed[] = [];
Expand Down
11 changes: 8 additions & 3 deletions packages/ado-npm-auth/src/fileProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export abstract class FileProvider {
public id: string,
public workspaceFileName: string,
configFile?: string,
userConfigFile?: string,
) {
let workspaceFilePath = undefined;
if (configFile && path.basename(configFile) === this.workspaceFileName) {
Expand All @@ -50,9 +51,13 @@ export abstract class FileProvider {
}
this.workspaceFilePath = workspaceFilePath;

const userHome =
process.env["HOME"] || process.env["USERPROFILE"] || homedir() || "";
this.userFilePath = join(userHome, workspaceFileName);
if (userConfigFile && path.basename(userConfigFile) === this.workspaceFileName) {
this.userFilePath = userConfigFile;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the expected behavior if the user passes --userConfigFile and the user when the passed in file does not match the workspace filename (i.e. missing the dot for npmrc file: --userConfigFile npmrc) then userFilePath will be undefined.

Should this be an error or should we chang the else block to check if userFilePath has not been set yet?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the filename from provided userConfigFile does not match workspace filename, then the if condition is false then the else condition will be triggered therefore setting the default userFilePath.

} else {
const userHome =
process.env["ADO_NPM_AUTH_USER_CONFIG"] || process.env["HOME"] || process.env["USERPROFILE"] || homedir() || "";
this.userFilePath = join(userHome, workspaceFileName);
}
this.feeds = new Map<string, Feed>();
}

Expand Down
4 changes: 2 additions & 2 deletions packages/ado-npm-auth/src/npmrc/npmrcFileProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { fromBase64, toBase64 } from "../utils/encoding.js";
import path from "node:path";

export class NpmrcFileProvider extends FileProvider {
constructor(configFile?: string) {
super("NpmRc", ".npmrc", configFile);
constructor(configFile?: string, userConfigFile?: string) {
super("NpmRc", ".npmrc", configFile, userConfigFile);
}

override async prepUserFile(): Promise<void> {
Expand Down
11 changes: 8 additions & 3 deletions packages/ado-npm-auth/src/yarnrc/yarnrcFileProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import { getOrganizationFromFeedUrl } from "../utils/get-organization-from-feed-
import { getFeedWithoutProtocol } from "../utils/get-feed-without-protocol.js";

export class YarnRcFileProvider extends FileProvider {
constructor(configFile?: string) {
super("YarnRc", ".yarnrc.yml", configFile);
constructor(configFile?: string, userConfigFile?: string) {
super("YarnRc", ".yarnrc.yml", configFile, userConfigFile);
}

override async prepUserFile(): Promise<void> {
// no need to do anything
try {
await fs.readFile(this.userFilePath, "utf-8");
} catch (error) {
// user yarnrc does not exist so make an empty one
await fs.writeFile(this.userFilePath, "");
}
}

override async getUserFeeds(): Promise<Map<string, Feed>> {
Expand Down
Empty file modified packages/node-azureauth/scripts/azureauth.cjs
100644 → 100755
Empty file.
Loading