Repository: iterative/cml (js)

Issue:
Move `REPO_TOKEN` to `CML_` environment variable namespace
Use `CML_TOKEN` (or similar, e.g. `CML_CI_TOKEN` etc.) instead of `REPO_TOKEN` to

- avoid potential namespace clashes
- better reflect that it could be a project token, org token, bot token, encoded username & password, etc
- better reflect that it's mostly used to *launch* runners and also is used *by* runners

---

- from https://github.com/iterative/cml.dev/pull/122#issuecomment-941330742
- related #738, #741, #712

Pull request description:
Rename `--token` to `--driver-token`
Also fixes environment variable parsing by using a global `cml` prefix; previously, they were being silently ignored. Closes #763.

Patch:
diff --git a/bin/cml.js b/bin/cml.js
index 4dae111..39d0a45 100755
--- a/bin/cml.js
+++ b/bin/cml.js
@@ -3,6 +3,7 @@
 const { basename } = require('path');
 const { pseudoexec } = require('pseudoexec');
 
+const kebabcaseKeys = require('kebabcase-keys');
 const which = require('which');
 const winston = require('winston');
 const yargs = require('yargs');
@@ -12,12 +13,23 @@ const { jitsuEventPayload, send } = require('../src/analytics');
 
 const aliasLegacyEnvironmentVariables = () => {
   const legacyEnvironmentPrefixes = {
-    CML_CI: 'CML_REPO',
-    CML_PUBLISH: 'CML_ASSET',
-    CML_RERUN_WORKFLOW: 'CML_WORKFLOW',
-    CML_SEND_COMMENT: 'CML_COMMENT',
-    CML_SEND_GITHUB_CHECK: 'CML_CHECK',
-    CML_TENSORBOARD_DEV: 'CML_TENSORBOARD'
+    CML_CI: 'CML',
+    CML_PUBLISH: 'CML',
+    CML_RERUN_WORKFLOW: 'CML',
+    CML_SEND_COMMENT: 'CML',
+    CML_SEND_GITHUB_CHECK: 'CML',
+    CML_TENSORBOARD_DEV: 'CML',
+    // Remap environment variable prefixes so e.g. CML_COMMAND_OPTION becomes an
+    // an alias for CML_OPTION, regardless of the command it't referring to.
+    // See also https://github.com/yargs/yargs/issues/873#issuecomment-917441475
+    CML_ASSET: 'CML',
+    CML_CHECK: 'CML',
+    CML_COMMENT: 'CML',
+    CML_PR: 'CML',
+    CML_REPO: 'CML',
+    CML_RUNNER: 'CML',
+    CML_TENSORBOARD: 'CML',
+    CML_WORKFLOW: 'CML'
   };
 
   for (const [oldPrefix, newPrefix] of Object.entries(
@@ -124,35 +136,37 @@ const handleError = (message, error) => {
 
   try {
     await yargs
-      .env('CML')
-      .options({
-        log: {
-          type: 'string',
-          description: 'Logging verbosity',
-          choices: ['error', 'warn', 'info', 'debug'],
-          default: 'info',
-          group: 'Global Options:'
-        },
-        driver: {
-          type: 'string',
-          choices: ['github', 'gitlab', 'bitbucket'],
-          defaultDescription: 'infer from the environment',
-          description: 'Git provider where the repository is hosted',
-          group: 'Global Options:'
-        },
-        repo: {
-          type: 'string',
-          defaultDescription: 'infer from the environment',
-          description: 'Repository URL or slug',
-          group: 'Global Options:'
-        },
-        token: {
-          type: 'string',
-          defaultDescription: 'infer from the environment',
-          description: 'Personal access token',
-          group: 'Global Options:'
-        }
-      })
+      .options(
+        kebabcaseKeys({
+          log: {
+            type: 'string',
+            description: 'Logging verbosity',
+            choices: ['error', 'warn', 'info', 'debug'],
+            default: 'info',
+            group: 'Global Options:'
+          },
+          driver: {
+            type: 'string',
+            choices: ['github', 'gitlab', 'bitbucket'],
+            defaultDescription: 'infer from the environment',
+            description: 'Git provider where the repository is hosted',
+            group: 'Global Options:'
+          },
+          repo: {
+            type: 'string',
+            defaultDescription: 'infer from the environment',
+            description: 'Repository URL or slug',
+            group: 'Global Options:'
+          },
+          driverToken: {
+            type: 'string',
+            alias: 'token',
+            defaultDescription: 'infer from the environment',
+            description: 'CI driver personal/project access token (PAT)',
+            group: 'Global Options:'
+          }
+        })
+      )
       .global('version', false)
       .group('help', 'Global Options:')
       .fail(handleError)
diff --git a/bin/cml/asset/publish.js b/bin/cml/asset/publish.js
index fa07e16..a5ed093 100644
--- a/bin/cml/asset/publish.js
+++ b/bin/cml/asset/publish.js
@@ -28,7 +28,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_ASSET')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/check/create.js b/bin/cml/check/create.js
index 7eb86d9..1703e18 100755
--- a/bin/cml/check/create.js
+++ b/bin/cml/check/create.js
@@ -15,7 +15,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_CHECK')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/comment/create.js b/bin/cml/comment/create.js
index 918b3b4..ceddb34 100644
--- a/bin/cml/comment/create.js
+++ b/bin/cml/comment/create.js
@@ -13,7 +13,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_COMMENT')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/pr.js b/bin/cml/pr.js
index a28ec4b..a9ea39f 100644
--- a/bin/cml/pr.js
+++ b/bin/cml/pr.js
@@ -7,7 +7,7 @@ exports.builder = (yargs) =>
   yargs
     .commandDir('./pr', { exclude: /\.test\.js$/ })
     .recommendCommands()
-    .env('CML_PR')
+    .env('CML')
     .options(
       Object.fromEntries(
         Object.entries(options).map(([key, value]) => [
diff --git a/bin/cml/pr/create.js b/bin/cml/pr/create.js
index 035937c..dafabac 100755
--- a/bin/cml/pr/create.js
+++ b/bin/cml/pr/create.js
@@ -21,7 +21,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_PR')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/repo/prepare.js b/bin/cml/repo/prepare.js
index 82ae22a..88d191d 100644
--- a/bin/cml/repo/prepare.js
+++ b/bin/cml/repo/prepare.js
@@ -15,7 +15,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_REPO')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/runner.js b/bin/cml/runner.js
index c97d0a0..c0430f2 100644
--- a/bin/cml/runner.js
+++ b/bin/cml/runner.js
@@ -7,7 +7,7 @@ exports.builder = (yargs) =>
   yargs
     .commandDir('./runner', { exclude: /\.test\.js$/ })
     .recommendCommands()
-    .env('CML_RUNNER')
+    .env('CML')
     .options(
       Object.fromEntries(
         Object.entries(options).map(([key, value]) => [
diff --git a/bin/cml/runner/launch.js b/bin/cml/runner/launch.js
index f194cd8..2b0c662 100755
--- a/bin/cml/runner/launch.js
+++ b/bin/cml/runner/launch.js
@@ -427,7 +427,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_RUNNER')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/tensorboard/connect.js b/bin/cml/tensorboard/connect.js
index 8d6aa78..2d8aa9a 100644
--- a/bin/cml/tensorboard/connect.js
+++ b/bin/cml/tensorboard/connect.js
@@ -101,7 +101,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_TENSORBOARD')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 
diff --git a/bin/cml/workflow/rerun.js b/bin/cml/workflow/rerun.js
index 4d9b434..c24c9bc 100644
--- a/bin/cml/workflow/rerun.js
+++ b/bin/cml/workflow/rerun.js
@@ -13,7 +13,7 @@ exports.handler = async (opts) => {
 
 exports.builder = (yargs) =>
   yargs
-    .env('CML_WORKFLOW')
+    .env('CML')
     .option('options', { default: exports.options, hidden: true })
     .options(exports.options);
 


Test patch:
diff --git a/bin/cml.test.js b/bin/cml.test.js
index d106953..06d19ce 100644
--- a/bin/cml.test.js
+++ b/bin/cml.test.js
@@ -18,14 +18,16 @@ describe('command-line interface tests', () => {
         cml.js ci                 Prepare Git repository for CML operations
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   Personal access token [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]
+        --repo                   Repository URL or slug
+                                        [string] [default: infer from the environment]
+        --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]
 
       Options:
         --version  Show version number                                       [boolean]"
diff --git a/bin/cml/asset/publish.test.js b/bin/cml/asset/publish.test.js
index c5213d9..90c708d 100644
--- a/bin/cml/asset/publish.test.js
+++ b/bin/cml/asset/publish.test.js
@@ -8,16 +8,17 @@ describe('CML cli test', () => {
       "cml.js publish <asset>
 
       Global Options:
-            --log     Logging verbosity
+            --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-            --driver  Git provider where the repository is hosted
+            --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-            --repo    Specifies the repo to be used. If not specified is extracted
-                      from the CI ENV.  [string] [default: infer from the environment]
-            --token   Personal access token
+            --repo                   Specifies the repo to be used. If not specified
+                                     is extracted from the CI ENV.
                                         [string] [default: infer from the environment]
-            --help    Show help                                              [boolean]
+            --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+            --help                   Show help                               [boolean]
 
       Options:
             --md         Output in markdown format [title || name](url)      [boolean]
diff --git a/bin/cml/check/create.test.js b/bin/cml/check/create.test.js
index 01f60de..3428d6a 100644
--- a/bin/cml/check/create.test.js
+++ b/bin/cml/check/create.test.js
@@ -13,15 +13,17 @@ describe('CML e2e', () => {
       "cml.js send-github-check <markdown file>
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   GITHUB_TOKEN or Github App token. Personal access token won't work
+        --repo                   Repository URL or slug
                                         [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]
+        --driver-token, --token  GITHUB_TOKEN or Github App token. Personal access
+                                 token won't work
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]
 
       Options:
         --commit-sha, --head-sha  Commit SHA linked to this comment
diff --git a/bin/cml/comment/create.test.js b/bin/cml/comment/create.test.js
index e01676f..5cf11fc 100644
--- a/bin/cml/comment/create.test.js
+++ b/bin/cml/comment/create.test.js
@@ -7,14 +7,16 @@ describe('Comment integration tests', () => {
       "cml.js send-comment <markdown file>
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   Personal access token [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]
+        --repo                   Repository URL or slug
+                                        [string] [default: infer from the environment]
+        --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]
 
       Options:
         --target                    Comment type (\`commit\`, \`pr\`, \`commit/f00bar\`,
diff --git a/bin/cml/pr/create.e2e.test.js b/bin/cml/pr/create.e2e.test.js
index 0510c2d..0396b66 100644
--- a/bin/cml/pr/create.e2e.test.js
+++ b/bin/cml/pr/create.e2e.test.js
@@ -15,14 +15,16 @@ describe('CML e2e', () => {
                                          https://cml.dev/doc/ref/pr
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   Personal access token [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]"
+        --repo                   Repository URL or slug
+                                        [string] [default: infer from the environment]
+        --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]"
     `);
   });
 });
diff --git a/bin/cml/repo/prepare.test.js b/bin/cml/repo/prepare.test.js
index 994296d..f050f4b 100644
--- a/bin/cml/repo/prepare.test.js
+++ b/bin/cml/repo/prepare.test.js
@@ -10,14 +10,16 @@ describe('CML e2e', () => {
       Prepare Git repository for CML operations
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   Personal access token [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]
+        --repo                   Repository URL or slug
+                                        [string] [default: infer from the environment]
+        --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]
 
       Options:
         --fetch-depth  Number of commits to fetch (use \`0\` for all branches & tags)
diff --git a/bin/cml/runner/launch.test.js b/bin/cml/runner/launch.test.js
index 8fed32f..62612b9 100644
--- a/bin/cml/runner/launch.test.js
+++ b/bin/cml/runner/launch.test.js
@@ -14,14 +14,16 @@ describe('CML e2e', () => {
                               https://cml.dev/doc/ref/runner
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   Personal access token [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]"
+        --repo                   Repository URL or slug
+                                        [string] [default: infer from the environment]
+        --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]"
     `);
   });
 });
diff --git a/bin/cml/tensorboard/connect.test.js b/bin/cml/tensorboard/connect.test.js
index 07a4a69..e9338c8 100644
--- a/bin/cml/tensorboard/connect.test.js
+++ b/bin/cml/tensorboard/connect.test.js
@@ -13,16 +13,16 @@ describe('CML e2e', () => {
       "cml.js tensorboard-dev
 
       Global Options:
-            --log     Logging verbosity
+            --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-            --driver  Git provider where the repository is hosted
+            --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-            --repo    Repository URL or slug
+            --repo                   Repository URL or slug
                                         [string] [default: infer from the environment]
-            --token   Personal access token
+            --driver-token, --token  CI driver personal/project access token (PAT)
                                         [string] [default: infer from the environment]
-            --help    Show help                                              [boolean]
+            --help                   Show help                               [boolean]
 
       Options:
         -c, --credentials  TensorBoard credentials as JSON, usually found at
diff --git a/bin/cml/workflow/rerun.test.js b/bin/cml/workflow/rerun.test.js
index ebd1718..374cab0 100644
--- a/bin/cml/workflow/rerun.test.js
+++ b/bin/cml/workflow/rerun.test.js
@@ -13,14 +13,16 @@ describe('CML e2e', () => {
       "cml.js rerun-workflow
 
       Global Options:
-        --log     Logging verbosity
+        --log                    Logging verbosity
                 [string] [choices: \\"error\\", \\"warn\\", \\"info\\", \\"debug\\"] [default: \\"info\\"]
-        --driver  Git provider where the repository is hosted
+        --driver                 Git provider where the repository is hosted
           [string] [choices: \\"github\\", \\"gitlab\\", \\"bitbucket\\"] [default: infer from the
                                                                           environment]
-        --repo    Repository URL or slug[string] [default: infer from the environment]
-        --token   Personal access token [string] [default: infer from the environment]
-        --help    Show help                                                  [boolean]
+        --repo                   Repository URL or slug
+                                        [string] [default: infer from the environment]
+        --driver-token, --token  CI driver personal/project access token (PAT)
+                                        [string] [default: infer from the environment]
+        --help                   Show help                                   [boolean]
 
       Options:
         --id  Run identifier to be rerun                                      [string]"