text: Title: Dynamic configuration / environment variables / etc with book builds
  Body: ### Describe the problem/need and solution
  
  Currently we use a static configuration file (`_config.yml`) for all of the book's configuration. However, there are some cases where you want to dynamically choose configuration at build time. For example, "set a configuration value based on an environment variable."
  
  This isn't currently possible with static configuration, but it *is* possible in Sphinx. We could find some way to allow a user to dynamically update their configuration (or run arbitrary Python code) at build time.
  
  ### Guide for implementation
  
  **Current build process**
  
  Here's where we invoke Sphinx:
  
  https://github.com/executablebooks/jupyter-book/blob/aedee257645ee41906c4d64f66f71b7f0dc7acfa/jupyter_book/cli/main.py#L307-L321
  
  In that case, we explicitly set `noconfig=True`, which means that Sphinx does not expect any `conf.py` file to exist.
  
  We then generate a dictionary of Sphinx config, and pass it to the Sphinx build command as "overrides":
  
  https://github.com/executablebooks/jupyter-book/blob/aedee257645ee41906c4d64f66f71b7f0dc7acfa/jupyter_book/sphinx.py#L114-L129
  
  We also already have the ability to generate a `conf.py` file from a `_config.yml` file:
  
  https://github.com/executablebooks/jupyter-book/blob/aedee257645ee41906c4d64f66f71b7f0dc7acfa/jupyter_book/cli/main.py#L458
  
  ### Three ideas for implementation
  
  There a few ways we could add this functionality:
  
  1. **Support `conf.py`**. We could allow users to add a `conf.py` (maybe we'd call it `_config.py`?) that we'd point to during the Sphinx build. This would behave no differently from how Sphinx currently handles it.
  2. **Generate a `conf.py` at build time, and add a `extraConfig` block**. Instead of using configuration over-rides, we could generate a **temporary `conf.py` file** that was created via the function above. We could then support a configuration block that would contain arbitrary Python code to be run, and that could over-ride / set configuration values (by being added to the end of the `conf.py` file. This is similar to [how JupyterHub uses `extraConfig`](https://zero-to-jupyterhub.readthedocs.io/en/latest/resources/reference.html#hub-extraconfig).
  3. **Pre-process config.yml with jinja**. We could also add a pre-processing step before we parse the `config.yml` file. This would let users to something like [ansible style variable injection](https://github.com/executablebooks/jupyter-book/issues/1673#issuecomment-1085388535).
  
  ### Suggestion
  
  After some discussion below, it seems like path 3 above has the most support for adding this functionality. Especially if we followed patterns that were already common in other frameworks, it would be a way to provide some dynamic configuration without supporting the total flexibility of a `conf.py` file.
  
  ### Tasks and updates
  
  _No response_