Browse Source

Add Verdaccio helper to prepare for releaser (#10494)

Jeremy Tuloup 3 years ago
parent
commit
8dc1b93c30
5 changed files with 904 additions and 9 deletions
  1. 8 2
      buildutils/package.json
  2. 1 0
      buildutils/src/ensure-repo.ts
  3. 200 0
      buildutils/src/local-repository.ts
  4. 8 0
      scripts/ci_script.sh
  5. 687 7
      yarn.lock

+ 8 - 2
buildutils/package.json

@@ -16,6 +16,7 @@
   "types": "lib/index.d.ts",
   "bin": {
     "get-dependency": "./lib/get-dependency.js",
+    "local-repository": "./lib/local-repository.js",
     "remove-dependency": "./lib/remove-dependency.js",
     "update-dependency": "./lib/update-dependency.js",
     "update-dist-tag": "./lib/update-dist-tag.js"
@@ -29,7 +30,8 @@
     "lib/*.js",
     "template/package.json",
     "template/tsconfig.json",
-    "template/src/index.ts"
+    "template/src/index.ts",
+    "verdaccio.yml"
   ],
   "scripts": {
     "build": "tsc",
@@ -48,11 +50,15 @@
     "glob": "~7.1.6",
     "inquirer": "^7.0.0",
     "minimatch": "~3.0.4",
+    "npm-cli-login": "^0.1.1",
+    "os": "~0.1.1",
     "package-json": "^6.5.0",
     "prettier": "^2.1.1",
+    "process": "^0.11.10",
     "semver": "^7.3.2",
     "sort-package-json": "~1.44.0",
-    "typescript": "~4.1.3"
+    "typescript": "~4.1.3",
+    "verdaccio": "^5.1.1"
   },
   "devDependencies": {
     "@types/fs-extra": "^9.0.1",

+ 1 - 0
buildutils/src/ensure-repo.ts

@@ -67,6 +67,7 @@ const UNUSED: Dict<string[]> = {
     'webpack-cli',
     'worker-loader'
   ],
+  '@jupyterlab/buildutils': ['npm-cli-login', 'verdaccio'],
   '@jupyterlab/coreutils': ['path-browserify'],
   '@jupyterlab/services': ['node-fetch', 'ws'],
   '@jupyterlab/rendermime': ['@jupyterlab/mathjax2'],

+ 200 - 0
buildutils/src/local-repository.ts

@@ -0,0 +1,200 @@
+import * as fs from 'fs-extra';
+import * as child_process from 'child_process';
+import * as path from 'path';
+import * as os from 'os';
+import * as ps from 'process';
+
+import { Command } from 'commander';
+
+import * as utils from './utils';
+
+const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
+const DEFAULT_OUT_DIR = path.join(os.tmpdir(), 'verdaccio');
+const DEFAULT_PORT = 4873;
+
+/**
+ * Start a local npm registry.
+ */
+async function startLocalRegistry(out_dir: string, port = DEFAULT_PORT) {
+  await stopLocalRegistry(out_dir);
+
+  // make the out dir if it does not exist
+  if (!fs.existsSync(out_dir)) {
+    fs.mkdirSync(out_dir);
+  }
+
+  // Get current registry values
+  const prev_npm =
+    utils.run('npm config get registry', { stdio: 'pipe' }, true) ||
+    'https://registry.npmjs.org/';
+  let prev_yarn = '';
+  try {
+    prev_yarn = utils.run('yarn config get registry', { stdio: 'pipe' }, true);
+  } catch (e) {
+    // Do nothing
+  }
+
+  // write the config file
+  const config = path.join(out_dir, 'verdaccio.yml');
+  const config_text = `
+storage: ${out_dir}/storage
+auth:
+  htpasswd:
+    file: ${out_dir}/htpasswd
+uplinks:
+    npmjs:
+        url: ${prev_npm}
+packages:
+  '@*/*':
+    access: $all
+    publish: $authenticated
+    unpublish: $authenticated
+    proxy: npmjs
+  '**':
+    access: $all
+    publish: $authenticated
+    unpublish: $authenticated
+    proxy: npmjs`;
+  fs.writeFileSync(config, config_text, { encoding: 'utf-8' });
+
+  const log_file = path.join(out_dir, 'verdaccio.log');
+
+  // Start local registry
+  const args = `-c verdaccio.yml -l localhost:${port}`;
+  console.log(`Starting verdaccio on port ${port} in ${out_dir}`);
+
+  // Ensure a clean log file
+  if (fs.existsSync(log_file)) {
+    fs.unlinkSync(log_file);
+  }
+
+  // Assign as `any`` for compatibility with spawn `OpenMode`` options
+  const out: any = fs.openSync(log_file, 'a');
+  const err: any = fs.openSync(log_file, 'a');
+
+  const options = { cwd: out_dir, detached: true, stdio: ['ignore', out, err] };
+
+  const bin_dir = utils.run('npm bin', { stdio: 'pipe' }, true);
+  const verdaccio_bin = path.join(bin_dir, 'verdaccio');
+  const subproc = child_process.spawn(verdaccio_bin, args.split(' '), options);
+  subproc.unref();
+
+  // Wait for Verdaccio to boot
+  let content = '';
+  let delays = 0;
+  while (delays < 100) {
+    ps.stdout.write('.');
+    if (content.indexOf('http address') !== -1) {
+      break;
+    }
+    if (content.toLowerCase().indexOf('error') !== -1) {
+      console.error(content);
+      ps.exit(1);
+    }
+    await delay(100);
+    if (fs.existsSync(log_file)) {
+      content = fs.readFileSync(log_file, { encoding: 'utf-8' });
+    }
+    delays += 1;
+  }
+  if (delays === 100) {
+    console.error('Timed out!');
+    process.exit(1);
+  }
+  console.log('\nVerdaccio started');
+
+  // Store registry values and pid in files
+  const info_file = path.join(out_dir, 'info.json');
+  const data = {
+    prev_npm,
+    prev_yarn,
+    pid: subproc.pid
+  };
+  utils.writeJSONFile(info_file, data);
+
+  // Set registry to local registry
+  const local_registry = `http://localhost:${port}`;
+  child_process.execSync(`npm config set registry "${local_registry}"`);
+  try {
+    child_process.execSync(`yarn config set registry "${local_registry}"`);
+  } catch (e) {
+    // yarn not available
+  }
+
+  // Log in using cli and temp credentials
+  const env = {
+    ...process.env,
+    NPM_USER: 'foo',
+    NPM_PASS: 'bar',
+    NPM_EMAIL: 'foo@bar.com',
+    NPM_REGISTRY: local_registry
+  };
+  const npm_cli_login_bin = path.join(bin_dir, 'npm-cli-login');
+  console.log('Logging in');
+  child_process.execSync(npm_cli_login_bin, { env, stdio: 'pipe' });
+
+  console.log('Running in', out_dir);
+  ps.exit(0);
+}
+
+/**
+ * Stop the local npm registry running in the given directory
+ */
+async function stopLocalRegistry(out_dir: string) {
+  if (!fs.existsSync(out_dir)) {
+    return;
+  }
+  const info_file = path.join(out_dir, 'info.json');
+  if (!fs.existsSync(info_file)) {
+    return;
+  }
+  const data = utils.readJSONFile(info_file);
+
+  // Kill the pid
+  console.log(`Killing existing process ${data.pid}`);
+  try {
+    ps.kill(data.pid);
+  } catch (e) {
+    // No process running
+  }
+
+  // Restore the previous registry entries
+  console.log('Restoring registry settings');
+  if (data.prev_npm) {
+    child_process.execSync(`npm set registry ${data.prev_npm}`);
+  } else {
+    child_process.execSync(`npm config rm registry`);
+  }
+  if (data.prev_yarn) {
+    child_process.execSync(`yarn config set registry ${data.prev_yarn}`);
+  } else {
+    try {
+      child_process.execSync(`yarn config delete registry`);
+    } catch (e) {
+      // yarn not available
+    }
+  }
+}
+
+const program = new Command();
+
+program
+  .command('start')
+  .option('--port', 'Port to use for the registry')
+  .option('--path', 'Path to use for the registry')
+  .action(async (options: any) => {
+    const out_dir = options.path || DEFAULT_OUT_DIR;
+    await startLocalRegistry(out_dir, options.port || DEFAULT_PORT);
+  });
+
+program
+  .command('stop')
+  .option('--path', 'Path to use for the registry')
+  .action(async (options: any) => {
+    const out_dir = options.path || DEFAULT_OUT_DIR;
+    await stopLocalRegistry(out_dir);
+  });
+
+if (require.main === module) {
+  program.parse(process.argv);
+}

+ 8 - 0
scripts/ci_script.sh

@@ -164,6 +164,14 @@ if [[ $GROUP == release_check ]]; then
     jlpm run publish:js --dry-run
     jlpm run prepare:python-release
     ./scripts/release_test.sh
+
+    # Prep for using verdaccio during publish
+    node buildutils/lib/local-repository.js start
+    pushd packages/application
+    npm version patch
+    npm publish
+    popd
+    node buildutils/lib/local-repository.js stop
 fi
 
 if [[ $GROUP == examples ]]; then

File diff suppressed because it is too large
+ 687 - 7
yarn.lock


Some files were not shown because too many files changed in this diff