diff --git a/change/change-f41db53a-b9bb-4906-80c8-11a61b3d21cc.json b/change/change-f41db53a-b9bb-4906-80c8-11a61b3d21cc.json new file mode 100644 index 0000000..c7708a7 --- /dev/null +++ b/change/change-f41db53a-b9bb-4906-80c8-11a61b3d21cc.json @@ -0,0 +1,18 @@ +{ + "changes": [ + { + "type": "minor", + "comment": "Add custom user config file option", + "packageName": "ado-npm-auth", + "email": "brwai@microsoft.com", + "dependentChangeType": "patch" + }, + { + "type": "patch", + "comment": "Add custom user config file option", + "packageName": "azureauth", + "email": "brwai@microsoft.com", + "dependentChangeType": "patch" + } + ] +} \ No newline at end of file diff --git a/packages/ado-npm-auth/README.md b/packages/ado-npm-auth/README.md index ced8e95..1a50086 100644 --- a/packages/ado-npm-auth/README.md +++ b/packages/ado-npm-auth/README.md @@ -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: @@ -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` \ No newline at end of file diff --git a/packages/ado-npm-auth/src/args.ts b/packages/ado-npm-auth/src/args.ts index 4b5fd77..0e74648 100644 --- a/packages/ado-npm-auth/src/args.ts +++ b/packages/ado-npm-auth/src/args.ts @@ -5,6 +5,7 @@ export interface Args { doValidCheck: boolean; skipAuth: boolean; configFile?: string; + userConfigFile?: string; } export function parseArgs(args: string[]): Args { @@ -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(); @@ -31,5 +37,6 @@ export function parseArgs(args: string[]): Args { skipAuth: argv.skipAuth || false, doValidCheck: !argv.skipCheck, configFile: argv.configFile, + userConfigFile: argv.userConfigFile }; } diff --git a/packages/ado-npm-auth/src/cli.ts b/packages/ado-npm-auth/src/cli.ts index 8e2ea51..e5a8b6e 100644 --- a/packages/ado-npm-auth/src/cli.ts +++ b/packages/ado-npm-auth/src/cli.ts @@ -11,8 +11,8 @@ import { YarnRcFileProvider } from "./yarnrc/yarnrcFileProvider.js"; export const run = async (args: Args): Promise => { 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[] = []; diff --git a/packages/ado-npm-auth/src/fileProvider.ts b/packages/ado-npm-auth/src/fileProvider.ts index d15d52a..c53d7f0 100644 --- a/packages/ado-npm-auth/src/fileProvider.ts +++ b/packages/ado-npm-auth/src/fileProvider.ts @@ -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) { @@ -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; + } 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(); } diff --git a/packages/ado-npm-auth/src/npmrc/npmrcFileProvider.ts b/packages/ado-npm-auth/src/npmrc/npmrcFileProvider.ts index b91b57d..c4dce60 100644 --- a/packages/ado-npm-auth/src/npmrc/npmrcFileProvider.ts +++ b/packages/ado-npm-auth/src/npmrc/npmrcFileProvider.ts @@ -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 { diff --git a/packages/ado-npm-auth/src/yarnrc/yarnrcFileProvider.ts b/packages/ado-npm-auth/src/yarnrc/yarnrcFileProvider.ts index b32d729..43285e0 100644 --- a/packages/ado-npm-auth/src/yarnrc/yarnrcFileProvider.ts +++ b/packages/ado-npm-auth/src/yarnrc/yarnrcFileProvider.ts @@ -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 { - // 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> { diff --git a/packages/node-azureauth/scripts/azureauth.cjs b/packages/node-azureauth/scripts/azureauth.cjs old mode 100644 new mode 100755