async function startServerAndDetermineUrls(options) {
  const urlsAsArray = Array.isArray(options.url) ? options.url : options.url ? [options.url] : [];
  if (!options.staticDistDir) {
    if (!urlsAsArray.length) throw new Error(`No URLs provided to collect`);

    let close = async () => undefined;
    if (options.startServerCommand) {
      const regexPattern = new RegExp(options.startServerReadyPattern, 'i');
      const {child, patternMatch, stdout, stderr} = await runCommandAndWaitForPattern(
        options.startServerCommand,
        regexPattern,
        {timeout: options.startServerReadyTimeout}
      );
      process.stdout.write(`Started a web server with "${options.startServerCommand}"...\n`);
      close = () => killProcessTree(child.pid);

      if (!patternMatch) {
        // This `message` variable is only for readability.
        const message = `Ensure the server prints a pattern that matches ${regexPattern} when it is ready.\n`;
        process.stdout.write(`WARNING: Timed out waiting for the server to start listening.\n`);
        process.stdout.write(`         ${message}`);
        if (process.env.CI) process.stderr.write(`\nServer Output:\n${stdout}\n${stderr}\n`);
      }
    }

    return {
      urls: urlsAsArray,
      close,
    };
  }

  const pathToBuildDir = path.resolve(process.cwd(), options.staticDistDir);
  const server = new FallbackServer(pathToBuildDir, options.isSinglePageApplication);
  await server.listen();
  process.stdout.write(`Started a web server on port ${server.port}...\n`);

  const urls = urlsAsArray;
  if (!urls.length) {
    const maxNumberOfUrls = options.maxAutodiscoverUrls || Infinity;
    const autodiscoverUrlBlocklistAsArray = Array.isArray(options.autodiscoverUrlBlocklist)
      ? options.autodiscoverUrlBlocklist
      : options.autodiscoverUrlBlocklist
      ? [options.autodiscoverUrlBlocklist]
      : [];
    const maxStaticDirFileDiscoveryDepth = options.staticDirFileDiscoveryDepth || 2;
    const availableUrls = server.getAvailableUrls(maxStaticDirFileDiscoveryDepth);
    const normalizedBlocklist = autodiscoverUrlBlocklistAsArray.map(rawUrl => {
      const url = new URL(rawUrl, 'http://localhost');
      url.port = server.port.toString();
      return url.href;
    });
    const urlsToUse = availableUrls
      .filter(url => !normalizedBlocklist.includes(url))
      .slice(0, maxNumberOfUrls);
    urls.push(...urlsToUse);
  }

  if (!urls.length) {
    throw new Error(`No URLs provided to collect and no HTML files found in staticDistDir`);
  }

  urls.forEach((rawUrl, i) => {
    const url = new URL(rawUrl, 'http://localhost');
    url.port = server.port.toString();
    urls[i] = url.href;
  });

  return {urls, close: async () => server.close()};
}
@param {LHCI.CollectCommand.Options} options
@return {Promise<{urls: Array<string>, close: () => Promise<void>}>}