Repository: readthedocs/readthedocs.org

Issue:
Be more defensive in how we insert our mkdocs media
This logic can be executed multiple times on [some builds](https://readthedocs.org/projects/phpspreadsheet/builds/8340376/) (see the `mkdocs.yml`):

https://github.com/rtfd/readthedocs.org/blob/ed8dd29a68d009fc08929fabf7155883482619c1/readthedocs/doc_builder/backends/mkdocs.py#L143-L152

If we have an issue reseting the branch/tag of the docs, we will end up inserting our media files twice, which causes them to be executed twice.

## Solution

This code should check if one of the files we insert is already in the list:

```
if 'readthedocs-data.js' not in user_config.get('extra_javascript'):
```


Discussion:
Can I work on This Issue?
If I understood the problem correctly we need to add conditions for `'extra_javascript'` and `'extra_css'`
to check if the static files already exist in the `user_config` if not then add the files. Please Correct me if I'm Wrong.

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
@@ -140,15 +140,25 @@ def append_conf(self, **__):
                     ),
                 )
 
-        user_config.setdefault('extra_javascript', []).extend([
+        extra_javascript_list = [
             'readthedocs-data.js',
             '%score/js/readthedocs-doc-embed.js' % static_url,
             '%sjavascript/readthedocs-analytics.js' % static_url,
-        ])
-        user_config.setdefault('extra_css', []).extend([
+        ]
+        extra_css_list = [
             '%scss/badge_only.css' % static_url,
             '%scss/readthedocs-doc-embed.css' % static_url,
-        ])
+        ]
+
+        # Only add static file if the files are not already in the list
+        user_config.setdefault('extra_javascript', []).extend(
+            [js for js in extra_javascript_list if js not in user_config.get(
+                'extra_javascript')]
+        )
+        user_config.setdefault('extra_css', []).extend(
+            [css for css in extra_css_list if css not in user_config.get(
+                'extra_css')]
+        )
 
         # The docs path is relative to the location
         # of the mkdocs configuration file.


Test patch:
diff --git a/readthedocs/rtd_tests/tests/test_doc_builder.py b/readthedocs/rtd_tests/tests/test_doc_builder.py
--- a/readthedocs/rtd_tests/tests/test_doc_builder.py
+++ b/readthedocs/rtd_tests/tests/test_doc_builder.py
@@ -279,7 +279,6 @@ def test_get_theme_name_with_feature_flag(self, checkout_path, run):
                 mock.ANY,
             )
 
-
     @patch('readthedocs.doc_builder.base.BaseBuilder.run')
     @patch('readthedocs.projects.models.Project.checkout_path')
     def test_append_conf_create_yaml(self, checkout_path, run):
@@ -420,7 +419,6 @@ def test_append_conf_existing_yaml_on_root_with_invalid_setting(self, checkout_p
             with self.assertRaises(MkDocsYAMLParseError):
                 self.searchbuilder.append_conf()
 
-
     @patch('readthedocs.doc_builder.base.BaseBuilder.run')
     @patch('readthedocs.projects.models.Project.checkout_path')
     def test_dont_override_theme(self, checkout_path, run):
@@ -489,3 +487,54 @@ def test_write_js_data_docs_dir(self, checkout_path, run, generate_rtd_data):
             docs_dir='docs',
             mkdocs_config=mock.ANY,
         )
+
+    @patch('readthedocs.doc_builder.base.BaseBuilder.run')
+    @patch('readthedocs.projects.models.Project.checkout_path')
+    def test_append_conf_existing_yaml_with_extra(self, checkout_path, run):
+        tmpdir = tempfile.mkdtemp()
+        os.mkdir(os.path.join(tmpdir, 'docs'))
+        yaml_file = os.path.join(tmpdir, 'mkdocs.yml')
+        yaml.safe_dump(
+            {
+                'site_name': 'mkdocs',
+                'google_analytics': ['UA-1234-5', 'mkdocs.org'],
+                'docs_dir': 'docs',
+                'extra_css': [
+                    'http://readthedocs.org/static/css/badge_only.css'
+                ],
+                'extra_javascript': ['readthedocs-data.js'],
+            },
+            open(yaml_file, 'w'),
+        )
+        checkout_path.return_value = tmpdir
+
+        python_env = Virtualenv(
+            version=self.version,
+            build_env=self.build_env,
+            config=None,
+        )
+        self.searchbuilder = MkdocsHTML(
+            build_env=self.build_env,
+            python_env=python_env,
+        )
+        self.searchbuilder.append_conf()
+
+        run.assert_called_with('cat', 'mkdocs.yml', cwd=mock.ANY)
+
+        config = yaml.safe_load(open(yaml_file))
+
+        self.assertEqual(
+            config['extra_css'],
+            [
+                'http://readthedocs.org/static/css/badge_only.css',
+                'http://readthedocs.org/static/css/readthedocs-doc-embed.css',
+            ],
+        )
+        self.assertEqual(
+            config['extra_javascript'],
+            [
+                'readthedocs-data.js',
+                'http://readthedocs.org/static/core/js/readthedocs-doc-embed.js',
+                'http://readthedocs.org/static/javascript/readthedocs-analytics.js',
+            ],
+        )