docs: def make_parser(project_config_file: str) -> configargparse.ArgumentParser:
      """Return the argument parser.
  
      :param project_config_file: Absolute path to project-specific config file.
  
      If cached parser already exists - return it immediately.
      Otherwise, initialize a new `ConfigArgParser` that is able to take default
      values from a hierarchy of config files and environment variables, as well
      as standard ArgParse command-line parsing behavior.
  
      We take default values from configuration files:
  
      - System-wide (see code for location)
      - User-level overrides (see code for location, hopefully under home dir)
      - If a project-specific config file is available, it will override both
        of the above.
  
      Environment variables will override all configuration files.
      For an option `--foo-bar`, if an environment variable named `YBT_FOO_VAR`
      exists, the option value will be taken from there.
  
      Of course, options specified directly on the command-line always win.
      """
      global PARSER  # pylint: disable=global-statement
      if PARSER is None:
          config_files = ['/etc/yabt.conf', '~/.yconfig']
          if project_config_file:
              config_files.append(project_config_file)
          PARSER = configargparse.getArgumentParser(
              # Support loading default values from system-wide or
              # user-specific config files (user-level overrides system-wide)
              default_config_files=config_files,
              # Show default values in help message
              formatter_class=configargparse.DefaultsFormatter,
              auto_env_var_prefix='ybt_',
              args_for_setting_config_path=['--config'],
              args_for_writing_out_config_file=['--write-out-config-file'])
          # PARSER.add('--config', is_config_file=True, help='Config file path')
          PARSER.add('--artifacts-metadata-file',
                     help='Output file to write artifacts metadata to')
          PARSER.add('--continue-after-fail', default=False, action='store_true',
                     help='If a target fails continue independent targets')
          PARSER.add('--bin-output-dir', default='ybt_bin')
          PARSER.add('--build-file-name', default='YBuild')
          PARSER.add('--build-base-images', action='store_true')
          PARSER.add('--builders-workspace-dir', default='yabtwork')
          PARSER.add('--default-target-name', default='@default')
          PARSER.add('--docker-pull-cmd', default='docker pull',
                     help='Command to use for pulling images from registries')
          PARSER.add('--docker-push-cmd', default='docker push',
                     help='Command to use for pushing images to registries')
          PARSER.add('--docker-volume',
                     help='Use the specified docker volume as buildenv /project')
          PARSER.add('-f', '--flavor', help='Choose build flavor (AKA profile)')
          PARSER.add('--force-pull', action='store_true')
          PARSER.add('-j', '--jobs', type=int, default=1)
          # TODO(itamar): support auto-detection of interactivity-mode
          PARSER.add('--non-interactive', action='store_true')
          PARSER.add('--offline', action='store_true')
          PARSER.add('--output-dot-file', default=None,
                     help='Output file for dot graph (default: stdin)')
          # TODO(itamar): this flag should come from the builder, not from here
          PARSER.add('--push', action='store_true')
          PARSER.add('--scm-provider')
          PARSER.add('--no-build-cache', action='store_true',
                     help='Disable YBT build cache')
          PARSER.add('--no-docker-cache', action='store_true',
                     help='Disable YBT Docker cache')
          PARSER.add('--no-policies', action='store_true')
          PARSER.add('--no-test-cache', action='store_true',
                     help='Disable YBT test cache')
          PARSER.add('--test-attempts', type=int, default=1)
          PARSER.add('-v', '--verbose', action='store_true',
                     help='More verbose output to STDOUT')
          PARSER.add('--with-tini-entrypoint', action='store_true')
          # Logging flags
          PARSER.add('--logtostderr', action='store_true',
                     help='Whether to log to STDERR')
          PARSER.add('--logtostdout', action='store_true',
                     help='Whether to log to STDOUT')
          PARSER.add('--loglevel', default='INFO', choices=LOG_LEVELS_CHOICES,
                     help='Log level threshold')
          PARSER.add('--show-buildenv-deps', type=bool, default=False,
                     help='When running dot, if set to True then the buildenv '
                          'targets are printed to the graph too')
          PARSER.add('cmd', choices=['build', 'dot', 'test', 'tree', 'version'])
          PARSER.add('targets', nargs='*')
      return PARSER