Repository: readthedocs/readthedocs.org

Issue:
Unorthodox MkDocs layouts cause docs to become stale
My [docs](https://django-class-settings.rtfd.io/) haven't been updating for a while now so I've looked into the problem. It started when I changed how they were laid out, or more specifically when I took the MkDocs configuration file out of the root folder, in this [commit](https://github.com/orlnub123/django-class-settings/commit/629bae1f2362129498fc9989af9881b99f96801b). The only hint was the difference at the end of the build outputs from the commit before and the commits since that successfully built.

Here's the output from the commit before:
```
[rtd-command-info] start-time: 2018-12-12T15:24:31.500295Z, end-time: 2018-12-12T15:24:32.154653Z, duration: 0, exit-code: 0
python /home/docs/checkouts/readthedocs.org/user_builds/django-class-settings/envs/latest/bin/mkdocs build --clean --site-dir _build/html --config-file /home/docs/checkouts/readthedocs.org/user_builds/django-class-settings/checkouts/latest/mkdocs.yml
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: /home/docs/checkouts/readthedocs.org/user_builds/django-class-settings/checkouts/latest/_build/html
```
And the output from the earliest successfully built commit after:
```
[rtd-command-info] start-time: 2019-03-06T09:01:08.583601Z, end-time: 2019-03-06T09:01:09.203502Z, duration: 0, exit-code: 0
python /home/docs/checkouts/readthedocs.org/user_builds/django-class-settings/envs/latest/bin/mkdocs build --clean --site-dir _build/html --config-file /home/docs/checkouts/readthedocs.org/user_builds/django-class-settings/checkouts/latest/docs/mkdocs.yml
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: /home/docs/checkouts/readthedocs.org/user_builds/django-class-settings/checkouts/latest/docs/_build/html
```

If you look closely you'll see that while the first one builds into `_build/html`, the one after builds into `docs/_build/html`. I haven't tested it but I'm guessing this discrepancy is why the docs aren't updating, even after environment resets.

The reason it's getting built into a different directory is because of the build command: https://github.com/rtfd/readthedocs.org/blob/5f78337874cb7dd0f73864d43283fe819d03594d/readthedocs/doc_builder/backends/mkdocs.py#L249-L258

The directory passed to `--site-dir`, `self.build_dir`, gets set to `_build/html` here: https://github.com/rtfd/readthedocs.org/blob/5f78337874cb7dd0f73864d43283fe819d03594d/readthedocs/doc_builder/backends/mkdocs.py#L294-L297

This is a problem because MkDocs assumes local paths to be local to the configuration file, not to the current working directory. The change happens here: https://github.com/mkdocs/mkdocs/blob/eb5f3f84e533cff42e13492af2a5e1ab391865e9/mkdocs/config/config_options.py#L341-L342

A fix would be to change `self.build_dir` to be an absolute path if the MkDocs configuration file isn't inside the root directory.


Discussion:

Resolving patch:
diff --git a/readthedocs/doc_builder/backends/mkdocs.py b/readthedocs/doc_builder/backends/mkdocs.py
--- a/readthedocs/doc_builder/backends/mkdocs.py
+++ b/readthedocs/doc_builder/backends/mkdocs.py
@@ -45,12 +45,12 @@ class BaseMkdocs(BaseBuilder):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
+        self.yaml_file = self.get_yaml_config()
         self.old_artifact_path = os.path.join(
-            self.version.project.checkout_path(self.version.slug),
+            os.path.dirname(self.yaml_file),
             self.build_dir,
         )
         self.root_path = self.version.project.checkout_path(self.version.slug)
-        self.yaml_file = self.get_yaml_config()
 
         # README: historically, the default theme was ``readthedocs`` but in
         # https://github.com/rtfd/readthedocs.org/pull/4556 we change it to
@@ -76,8 +76,6 @@ def get_yaml_config(self):
                 self.project.checkout_path(self.version.slug),
                 'mkdocs.yml',
             )
-            if not os.path.exists(mkdoc_path):
-                return None
         return mkdoc_path
 
     def load_yaml_config(self):
@@ -112,9 +110,6 @@ def append_conf(self, **__):
         :raises: ``MkDocsYAMLParseError`` if failed due to known type errors
                  (i.e. expecting a list and a string is found).
         """
-        if not self.yaml_file:
-            self.yaml_file = os.path.join(self.root_path, 'mkdocs.yml')
-
         user_config = self.load_yaml_config()
 
         # Handle custom docs dirs


Test patch: