Subject: [PATCH] yarnrc.yml
---
Index: package.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json	(revision 2448c5efdc5a096405e335528513d79c5d2af43f)
+++ b/package.json	(date 1758941146510)
@@ -8,6 +8,7 @@
   "license": "Apache-2.0",
   "dependencies": {
     "google-auth-library": "^9.14.0",
+    "js-yaml": "^4.1.0",
     "yargs": "^17.1.1"
   },
   "bin": {
Index: src/update-yarn.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/update-yarn.js b/src/update-yarn.js
new file mode 100644
--- /dev/null	(date 1758941146502)
+++ b/src/update-yarn.js	(date 1758941146502)
@@ -0,0 +1,62 @@
+// Copyright 2025 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const fs = require('fs');
+const path = require('path');
+const yaml = require('js-yaml');
+const {logger} = require('./logger');
+
+/**
+ * Update the project and user yarnrc.yml files.
+ *
+ * @param {string} fromConfigPath Path to the yarnrc.yml file to read scope registry configs from, should be the project yarnrc.yml file.
+ * @param {string} toConfigPath Path to yarnrc.yml file to write authentication configs to, should be the user yarnrc.yml file.
+ * @param {string} creds Encrypted credentials.
+ * @return {!Promise<undefined>}
+ */
+async function updateYarnConfigFiles(fromConfigPath, toConfigPath, creds) {
+  fromConfigPath = path.resolve(fromConfigPath);
+  toConfigPath = path.resolve(toConfigPath);
+
+  const fromDoc = yaml.load(fs.readFileSync(fromConfigPath, 'utf8'));
+  const toDoc = fs.existsSync(toConfigPath)
+    ? yaml.load(fs.readFileSync(toConfigPath, 'utf8'))
+    : {};
+
+  if (fromDoc.npmScopes) {
+    for (const scope in fromDoc.npmScopes) {
+      const fromScope = fromDoc.npmScopes[scope];
+      if (fromScope.npmRegistryServer) {
+        const registry = fromScope.npmRegistryServer;
+        logger.debug(`Found registry ${registry} in ${fromConfigPath}`);
+        if (!toDoc.npmScopes) {
+          toDoc.npmScopes = {};
+        }
+        if (!toDoc.npmScopes[scope]) {
+          toDoc.npmScopes[scope] = {};
+        }
+        const toScope = toDoc.npmScopes[scope];
+        toScope.npmRegistryServer = registry;
+        toScope.npmAlwaysAuth = true;
+        toScope.npmAuthToken = creds;
+      }
+    }
+  }
+
+  await fs.promises.writeFile(toConfigPath, yaml.dump(toDoc));
+}
+
+module.exports = {
+  updateYarnConfigFiles,
+};
Index: src/main.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/main.js b/src/main.js
--- a/src/main.js	(revision 2448c5efdc5a096405e335528513d79c5d2af43f)
+++ b/src/main.js	(date 1758941146478)
@@ -21,6 +21,7 @@
 const { logger } = require('./logger');
 const update = require('./update');
 const fs = require('fs');
+const updateYarn = require('./update-yarn');
 
 /**
  * Determine which npmrc file should be the default repo configuration
@@ -38,6 +39,22 @@
   }
 }
 
+/**
+ * Determine which yarnrc.yml file should be the default repo configuration
+ * 
+ * This will determine if a project-level yarnrc.yml file exists, otherwise default to the user-level yarnrc.yml file
+ * 
+ * return {!Promise<String>}
+ */
+async function determineDefaultYarnRepoConfig() {
+  try {
+    await fs.promises.stat('.yarnrc.yml')
+    return '.yarnrc.yml'
+  } catch (e) {
+    return `${os.homedir()}/.yarnrc.yml`
+  }
+}
+
 /**
  * Get credentials and update .npmrc file.
  *
@@ -70,6 +87,16 @@
         describe: 'Path to the .npmrc file to write credentials to, usually the user-level npmrc file',
         default: `${os.homedir()}/.npmrc`,
       })
+      .option('repo-config-yarn', {
+        type: 'string',
+        describe: 'Path to the .yarnrc.yml file to read registry configs from, will use the project-level yarnrc.yml file if it exists, otherwise the user-level yarnrc.yml file',
+        default: await determineDefaultYarnRepoConfig(),
+      })
+      .option('credential-config-yarn', {
+        type: 'string',
+        describe: 'Path to the .yarnrc.yml file to write credentials to, usually the user-level yarnrc.yml file',
+        default: `${os.homedir()}/.yarnrc.yml`,
+      })
       .option('verbose', {
         type: 'boolean',
         describe: 'Set log level to verbose',
@@ -99,7 +126,8 @@
           + 'in future versions. Run the plugin with `--repo-config` and `--credential-config`.');
       await update.updateConfigFile(configPath, creds);
     } else {
-      await update.updateConfigFiles(allArgs.repoConfig, allArgs.credentialConfig, creds, allArgs.allowAllDomains);
+        await update.updateConfigFiles(allArgs.repoConfig, allArgs.credentialConfig, creds, allArgs.allowAllDomains);
+        await updateYarn.updateYarnConfigFiles(allArgs.repoConfigYarn, allArgs.credentialConfigYarn, creds);
     }
     console.log("Success!");
   } catch (err) {
Index: test/test.update-yarn.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/test/test.update-yarn.js b/test/test.update-yarn.js
new file mode 100644
--- /dev/null	(date 1758941146506)
+++ b/test/test.update-yarn.js	(date 1758941146506)
@@ -0,0 +1,58 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+const assert = require('assert');
+const fs = require('fs');
+const path = require('path');
+const {updateYarnConfigFiles} = require('../src/update-yarn');
+const yaml = require('js-yaml');
+
+const testDir = path.join(__dirname, '.');
+const fromConfigPath = path.join(testDir, '.yarnrc.yml');
+const toConfigPath = path.join(testDir, 'user.yarnrc.yml');
+
+describe('updateYarnConfigFiles', () => {
+  afterEach(() => {
+    if (fs.existsSync(fromConfigPath)) {
+      fs.unlinkSync(fromConfigPath);
+    }
+    if (fs.existsSync(toConfigPath)) {
+      fs.unlinkSync(toConfigPath);
+    }
+  });
+
+  it('should update yarnrc.yml with auth token', async () => {
+    const fromContent = {
+      npmScopes: {
+        workspace: {
+          npmRegistryServer: 'https://region-npm.pkg.dev/project/repo',
+        },
+      },
+    };
+    fs.writeFileSync(fromConfigPath, yaml.dump(fromContent));
+
+    await updateYarnConfigFiles(fromConfigPath, toConfigPath, 'my-secret-token');
+
+    const toContent = yaml.load(fs.readFileSync(toConfigPath, 'utf8'));
+    assert.deepStrictEqual(toContent, {
+      npmScopes: {
+        workspace: {
+          npmRegistryServer: 'https://region-npm.pkg.dev/project/repo',
+          npmAlwaysAuth: true,
+          npmAuthToken: 'my-secret-token',
+        },
+      },
+    });
+  });
+});
Index: package-lock.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/package-lock.json b/package-lock.json
--- a/package-lock.json	(revision 2448c5efdc5a096405e335528513d79c5d2af43f)
+++ b/package-lock.json	(date 1758941146590)
@@ -10,6 +10,7 @@
       "license": "Apache-2.0",
       "dependencies": {
         "google-auth-library": "^9.14.0",
+        "js-yaml": "^4.1.0",
         "yargs": "^17.1.1"
       },
       "bin": {
@@ -161,13 +162,9 @@
       }
     },
     "node_modules/argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dev": true,
-      "dependencies": {
-        "sprintf-js": "~1.0.2"
-      }
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
     },
     "node_modules/astral-regex": {
       "version": "1.0.0",
@@ -665,6 +662,28 @@
         "node": ">=6"
       }
     },
+    "node_modules/eslint/node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
+    "node_modules/eslint/node_modules/js-yaml": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+      "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
     "node_modules/eslint/node_modules/semver": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -1502,13 +1521,11 @@
       "dev": true
     },
     "node_modules/js-yaml": {
-      "version": "3.13.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
-      "dev": true,
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
       "dependencies": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
+        "argparse": "^2.0.1"
       },
       "bin": {
         "js-yaml": "bin/js-yaml.js"
@@ -1684,6 +1701,15 @@
         "node": ">=6"
       }
     },
+    "node_modules/mocha/node_modules/argparse": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+      "dev": true,
+      "dependencies": {
+        "sprintf-js": "~1.0.2"
+      }
+    },
     "node_modules/mocha/node_modules/cliui": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -1705,6 +1731,19 @@
         "ms": "^2.1.1"
       }
     },
+    "node_modules/mocha/node_modules/js-yaml": {
+      "version": "3.13.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^1.0.7",
+        "esprima": "^4.0.0"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
     "node_modules/mocha/node_modules/ms": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@@ -2200,7 +2239,7 @@
     "node_modules/sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
       "dev": true
     },
     "node_modules/string-width": {
@@ -2884,13 +2923,9 @@
       }
     },
     "argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dev": true,
-      "requires": {
-        "sprintf-js": "~1.0.2"
-      }
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
     },
     "astral-regex": {
       "version": "1.0.0",
@@ -3248,6 +3283,25 @@
           "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
           "dev": true
         },
+        "argparse": {
+          "version": "1.0.10",
+          "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+          "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+          "dev": true,
+          "requires": {
+            "sprintf-js": "~1.0.2"
+          }
+        },
+        "js-yaml": {
+          "version": "3.14.1",
+          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+          "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+          "dev": true,
+          "requires": {
+            "argparse": "^1.0.7",
+            "esprima": "^4.0.0"
+          }
+        },
         "semver": {
           "version": "6.3.0",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -3869,13 +3923,11 @@
       "dev": true
     },
     "js-yaml": {
-      "version": "3.13.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
-      "dev": true,
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
       "requires": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
+        "argparse": "^2.0.1"
       }
     },
     "json-bigint": {
@@ -4019,6 +4071,15 @@
           "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
           "dev": true
         },
+        "argparse": {
+          "version": "1.0.10",
+          "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+          "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+          "dev": true,
+          "requires": {
+            "sprintf-js": "~1.0.2"
+          }
+        },
         "cliui": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -4039,6 +4100,16 @@
             "ms": "^2.1.1"
           }
         },
+        "js-yaml": {
+          "version": "3.13.1",
+          "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+          "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+          "dev": true,
+          "requires": {
+            "argparse": "^1.0.7",
+            "esprima": "^4.0.0"
+          }
+        },
         "ms": {
           "version": "2.1.1",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@@ -4409,7 +4480,7 @@
     "sprintf-js": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
       "dev": true
     },
     "string-width": {
