def get_doctree(path, **kwargs):
    """
    Obtain a Sphinx doctree from the RST file at ``path``.

    Performs no Releases-specific processing; this code would, ideally, be in
    Sphinx itself, but things there are pretty tightly coupled. So we wrote
    this.

    Any additional kwargs are passed unmodified into an internal `make_app`
    call.

    :param str path: A relative or absolute file path string.

    :returns:
        A two-tuple of the generated ``sphinx.application.Sphinx`` app and the
        doctree (a ``docutils.document`` object).

    .. versionchanged:: 1.6
        Added support for passing kwargs to `make_app`.
    """
    root, filename = os.path.split(path)
    docname, _ = os.path.splitext(filename)
    # TODO: this only works for top level changelog files (i.e. ones where
    # their dirname is the project/doc root)
    app = make_app(srcdir=root, **kwargs)
    # Create & init a BuildEnvironment. Mm, tasty side effects.
    app._init_env(freshenv=True)
    env = app.env
    # More arity/API changes: Sphinx 1.3/1.4-ish require one to pass in the app
    # obj in BuildEnvironment.update(); modern Sphinx performs that inside
    # Application._init_env() (which we just called above) and so that kwarg is
    # removed from update(). EAFP.
    kwargs = dict(
        config=app.config,
        srcdir=root,
        doctreedir=app.doctreedir,
        app=app,
    )
    try:
        env.update(**kwargs)
    except TypeError:
        # Assume newer Sphinx w/o an app= kwarg
        del kwargs['app']
        env.update(**kwargs)
    # Code taken from sphinx.environment.read_doc; easier to manually call
    # it with a working Environment object, instead of doing more random crap
    # to trick the higher up build system into thinking our single changelog
    # document was "updated".
    env.temp_data['docname'] = docname
    env.app = app
    # NOTE: SphinxStandaloneReader API changed in 1.4 :(
    reader_kwargs = {
        'app': app,
        'parsers': env.config.source_parsers,
    }
    if sphinx.version_info[:2] < (1, 4):
        del reader_kwargs['app']
    # This monkeypatches (!!!) docutils to 'inject' all registered Sphinx
    # domains' roles & so forth. Without this, rendering the doctree lacks
    # almost all Sphinx magic, including things like :ref: and :doc:!
    with sphinx_domains(env):
        try:
            reader = SphinxStandaloneReader(**reader_kwargs)
        except TypeError:
            # If we import from io, this happens automagically, not in API
            del reader_kwargs['parsers']
            reader = SphinxStandaloneReader(**reader_kwargs)
        pub = Publisher(reader=reader,
                        writer=SphinxDummyWriter(),
                        destination_class=NullOutput)
        pub.set_components(None, 'restructuredtext', None)
        pub.process_programmatic_settings(None, env.settings, None)
        # NOTE: docname derived higher up, from our given path
        src_path = env.doc2path(docname)
        source = SphinxFileInput(
            app,
            env,
            source=None,
            source_path=src_path,
            encoding=env.config.source_encoding,
        )
        pub.source = source
        pub.settings._source = src_path
        pub.set_destination(None, None)
        pub.publish()
        return app, pub.document
Obtain a Sphinx doctree from the RST file at ``path``.

    Performs no Releases-specific processing; this code would, ideally, be in
    Sphinx itself, but things there are pretty tightly coupled. So we wrote
    this.

    Any additional kwargs are passed unmodified into an internal `make_app`
    call.

    :param str path: A relative or absolute file path string.

    :returns:
        A two-tuple of the generated ``sphinx.application.Sphinx`` app and the
        doctree (a ``docutils.document`` object).

    .. versionchanged:: 1.6
        Added support for passing kwargs to `make_app`.