internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: readthedocs/readthedocs.org

Issue:
Build: dump user's command into a shell script before running it
We attemped to fix this issue multiple times and we found problems when deploying those changes to production.

This not perfect, but simple solution, could help us to support multi-line commands for now without manipulating "too much" the `PATH` variable, that was the one causing us issues.

Let me know what you think about this approach and how to move forward if you prefer a different one.

Closes #10103
Reference #10206 
Reference #10172 
Reference #10133 


Discussion:
I'm not sure if it makes sense to move forward with this PR or not due the doubts and concerns of this implementation. However, I ran out of ideas trying to solve this problem. If there are better ideas, I'm happy to implement them.
How about just passing the multiline script as a parameter to `sh -c` instead of writing it out to a file? eg.
```bash
sh -c 'export PATH={bin_path}$PATH
{command}'
```
Seems like it would require fewer changes.
Actually - thinking about it, just changing the relevant part of the code from `command = "PATH=foo {command}"` to `command = "export PATH=foo; {command}"` should do the trick, no multiline trickery needed.

Resolving patch:
diff --git a/readthedocs/doc_builder/environments.py b/readthedocs/doc_builder/environments.py
--- a/readthedocs/doc_builder/environments.py
+++ b/readthedocs/doc_builder/environments.py
@@ -376,10 +376,13 @@ def get_wrapped_command(self):
                 for part in self.command
             )
         )
-        return "/bin/sh -c '{prefix}{cmd}'".format(
-            prefix=prefix,
-            cmd=command,
-        )
+        if prefix:
+            # Using `;` or `\n` to separate the `prefix` where we define the
+            # variables with the `command` itself, have the same effect.
+            # However, using `;` is more explicit.
+            # See https://github.com/readthedocs/readthedocs.org/pull/10334
+            return f"/bin/sh -c '{prefix}; {command}'"
+        return f"/bin/sh -c '{command}'"
 
     def _escape_command(self, cmd):
         r"""Escape the command by prefixing suspicious chars with `\`."""


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Docs: Config file deprecation warnings
* [x] Upgrade v1 docs to clearly indicate that it's removed in September 2023 and link to the v2 version
* [x] Add warning banners in various places

References https://github.com/readthedocs/readthedocs.org/issues/10342


Discussion:

Resolving patch:
diff --git a/docs/conf.py b/docs/conf.py
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -102,6 +102,7 @@
     "rst-to-myst": ("https://rst-to-myst.readthedocs.io/en/stable/", None),
     "rtd": ("https://docs.readthedocs.io/en/stable/", None),
     "rtd-dev": ("https://dev.readthedocs.io/en/latest/", None),
+    "rtd-blog": ("https://blog.readthedocs.com/", None),
     "jupyter": ("https://docs.jupyter.org/en/latest/", None),
 }
 


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Proxito: improve query to check for addons
Small improvement until we work on https://github.com/readthedocs/readthedocs.org/issues/10456


Discussion:

Resolving patch:
diff --git a/readthedocs/proxito/middleware.py b/readthedocs/proxito/middleware.py
--- a/readthedocs/proxito/middleware.py
+++ b/readthedocs/proxito/middleware.py
@@ -16,6 +16,7 @@
 from django.urls import reverse
 from django.utils.deprecation import MiddlewareMixin
 
+from readthedocs.builds.models import Version
 from readthedocs.core.unresolver import (
     InvalidCustomDomainError,
     InvalidExternalDomainError,
@@ -25,7 +26,7 @@
     unresolver,
 )
 from readthedocs.core.utils import get_cache_tag
-from readthedocs.projects.models import Feature, Project
+from readthedocs.projects.models import Feature
 from readthedocs.proxito.cache import add_cache_tags, cache_response, private_response
 from readthedocs.proxito.redirects import redirect_to_https
 
@@ -293,20 +294,12 @@ def add_hosting_integrations_headers(self, request, response):
         project_slug = getattr(request, "path_project_slug", "")
         version_slug = getattr(request, "path_version_slug", "")
 
-        if project_slug:
-            project = Project.objects.get(slug=project_slug)
-
-            # Check for the feature flag
-            if project.has_feature(Feature.HOSTING_INTEGRATIONS):
-                addons = True
-            else:
-                # Check if the version forces injecting the addons (e.g. using `build.commands`)
-                version = (
-                    project.versions.filter(slug=version_slug).only("addons").first()
-                )
-                if version and version.addons:
-                    addons = True
-
+        if project_slug and version_slug:
+            addons = Version.objects.filter(
+                project__slug=project_slug,
+                slug=version_slug,
+                addons=True,
+            ).exists()
             if addons:
                 response["X-RTD-Hosting-Integrations"] = "true"
 


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Feature flag: MkDocs use latest has its logic inverted
Take a look at this code, https://github.com/readthedocs/readthedocs.org/blob/bcf45cd666b75d63319bc0d0b6fa18fec24967dc/readthedocs/doc_builder/python_environments.py#L212-L216

It seems when `DEFAULT_TO_MKDOCS_0_17_3=False` and `USE_MKDOCS_LATEST=True`, we are installing `mkdocs<1.1` when we should be installing `mkdocs` (latest).

Reverting this logic is easy. However, we should take a look at our data in Metabase to know how many projects this will affect and decide what/how to do.

Related #9779


Discussion:
@ericholscher are we OK just inverting this logic or do we want to do something before making the change? I'd like to start installing the latest MkDocs for projects instead of an old version 😄 
@humitos I'm 👍 on unbreaking mkdocs, so let's do it. Alternatively, we just remove the feature flag, if old projects were already upgraded? 
> Alternatively, we just remove the feature flag

I'll keep the flag for now, but fixing the logic as the first step. We will be using #10508 sooner than later anyways.

Resolving patch:
diff --git a/readthedocs/doc_builder/python_environments.py b/readthedocs/doc_builder/python_environments.py
--- a/readthedocs/doc_builder/python_environments.py
+++ b/readthedocs/doc_builder/python_environments.py
@@ -209,12 +209,8 @@ def install_core_requirements(self):
                 self.project.get_feature_value(
                     Feature.DEFAULT_TO_MKDOCS_0_17_3,
                     positive='mkdocs==0.17.3',
-                    negative=self.project.get_feature_value(
-                        Feature.USE_MKDOCS_LATEST,
-                        positive='mkdocs<1.1',
-                        negative='mkdocs',
-                    ),
-                ),
+                    negative="mkdocs",
+                )
             )
         else:
             requirements.extend(
diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py
--- a/readthedocs/projects/models.py
+++ b/readthedocs/projects/models.py
@@ -1927,7 +1927,6 @@ def add_features(sender, **kwargs):
     DONT_INSTALL_LATEST_PIP = 'dont_install_latest_pip'
     USE_SPHINX_LATEST = 'use_sphinx_latest'
     DEFAULT_TO_MKDOCS_0_17_3 = 'default_to_mkdocs_0_17_3'
-    USE_MKDOCS_LATEST = 'use_mkdocs_latest'
     USE_SPHINX_RTD_EXT_LATEST = 'rtd_sphinx_ext_latest'
 
     # Search related features
@@ -2034,7 +2033,6 @@ def add_features(sender, **kwargs):
             DEFAULT_TO_MKDOCS_0_17_3,
             _("MkDOcs: Install mkdocs 0.17.3 by default"),
         ),
-        (USE_MKDOCS_LATEST, _("MkDocs: Use latest version of MkDocs")),
         (
             USE_SPHINX_RTD_EXT_LATEST,
             _("Sphinx: Use latest version of the Read the Docs Sphinx extension"),


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
API: allow remote repo full name query
The new dashboard is still using the API v2 remote repo API, which does not allow for expansion on project results and doesn't have all of the fields that I'd like to use in the results listing. The API v3 needs the v2 API implementation for searching by full_name, the current pattern for searching `full_name` by icontains on the v2 API works okay for now.

I didn't want to alter the v2 API further, as we should really be moving towards the v3 API, but if it's just easier to add expansion there for some reason, that is also fine.

Note: this also gives expansion on the nested projects in the result, so we can get fields like the avatar_url, etc. The current v2 search only returns the project slug and a link to the project dashboard.


Discussion:

Resolving patch:
diff --git a/readthedocs/api/v3/filters.py b/readthedocs/api/v3/filters.py
--- a/readthedocs/api/v3/filters.py
+++ b/readthedocs/api/v3/filters.py
@@ -60,15 +60,17 @@ def get_running(self, queryset, name, value):
 
 
 class RemoteRepositoryFilter(filters.FilterSet):
-    name = filters.CharFilter(field_name='name', lookup_expr='icontains')
-    organization = filters.CharFilter(field_name='organization__slug')
+    name = filters.CharFilter(field_name="name", lookup_expr="icontains")
+    full_name = filters.CharFilter(field_name="full_name", lookup_expr="icontains")
+    organization = filters.CharFilter(field_name="organization__slug")
 
     class Meta:
         model = RemoteRepository
         fields = [
-            'name',
-            'vcs_provider',
-            'organization',
+            "name",
+            "full_name",
+            "vcs_provider",
+            "organization",
         ]
 
 


Test patch:
diff --git a/readthedocs/api/v3/tests/test_remoterepositories.py b/readthedocs/api/v3/tests/test_remoterepositories.py
--- a/readthedocs/api/v3/tests/test_remoterepositories.py
+++ b/readthedocs/api/v3/tests/test_remoterepositories.py
@@ -103,3 +103,19 @@ def test_remote_repository_list_name_filter(self):
             response_data,
             self._get_response_dict('remoterepositories-list'),
         )
+
+    def test_remote_repository_list_full_name_filter(self):
+        self.client.credentials(HTTP_AUTHORIZATION=f"Token {self.token.key}")
+        response = self.client.get(
+            reverse("remoterepositories-list"),
+            {"expand": ("projects," "remote_organization"), "full_name": "proj"},
+        )
+        self.assertEqual(response.status_code, 200)
+
+        response_data = response.json()
+        self.assertEqual(len(response_data["results"]), 1)
+
+        self.assertDictEqual(
+            response_data,
+            self._get_response_dict("remoterepositories-list"),
+        )
Repository: readthedocs/readthedocs.org

Issue:
Change profile edit form success page
Currently, when a user saves the profile edit form, the success page is not the profile form page, the user gets redirected to the profile public view page. This is quite confusing UX but might be baked into Allauth. I would expect this end up on the profile edit form page instead.


Discussion:
Moving this off of the dashboard issue tracker, it's an application issue

Resolving patch:
diff --git a/readthedocs/profiles/views.py b/readthedocs/profiles/views.py
--- a/readthedocs/profiles/views.py
+++ b/readthedocs/profiles/views.py
@@ -61,8 +61,7 @@ def get_object(self):
 
     def get_success_url(self):
         return reverse(
-            'profiles_profile_detail',
-            kwargs={'username': self.request.user.username},
+            "profiles_profile_edit",
         )
 
 


Test patch:
diff --git a/readthedocs/rtd_tests/tests/test_profile_views.py b/readthedocs/rtd_tests/tests/test_profile_views.py
--- a/readthedocs/rtd_tests/tests/test_profile_views.py
+++ b/readthedocs/rtd_tests/tests/test_profile_views.py
@@ -36,6 +36,7 @@ def test_edit_profile(self):
             },
         )
         self.assertTrue(resp.status_code, 200)
+        self.assertEqual(resp["Location"], "/accounts/edit/")
 
         self.user.refresh_from_db()
         self.user.profile.refresh_from_db()
Repository: readthedocs/readthedocs.org

Issue:
Django: adapt admin code for 3.x
It seems that we missed an upgrade to make it fully compatible with Django 3.x

We are using `admin.ACTION_CHECKBOX_NAME` when it was deprecated and it was removed already:

> The compatibility import of django.contrib.admin.helpers.ACTION_CHECKBOX_NAME in django.contrib.admin is removed.

(from https://docs.djangoproject.com/en/4.0/releases/3.1/#id1)

The code lives at https://github.com/readthedocs/readthedocs.org/blob/e94c26074e9abdf7056b4e6502c52f8a6b128055/readthedocs/notifications/views.py#L48


Discussion:

Resolving patch:
diff --git a/readthedocs/notifications/views.py b/readthedocs/notifications/views.py
--- a/readthedocs/notifications/views.py
+++ b/readthedocs/notifications/views.py
@@ -1,5 +1,5 @@
 """Django views for the notifications app."""
-from django.contrib import admin, messages
+from django.contrib import messages
 from django.http import HttpResponseRedirect
 from django.views.generic import FormView
 
@@ -42,9 +42,7 @@ def get_form_kwargs(self):
     def get_initial(self):
         """Add selected ids to initial form data."""
         initial = super().get_initial()
-        initial["_selected_action"] = self.request.POST.getlist(
-            admin.ACTION_CHECKBOX_NAME,
-        )
+        initial["_selected_action"] = self.request.POST.getlist("_selected_action")
         return initial
 
     def form_valid(self, form):


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Addons: don't return any version when project is "single version"
If you go to https://pycamp.es/ you will see the flyout shows two versions: latest and 2022. However, this project is marked as "Single version". If you click on them, they give you 404 URLs.

https://github.com/readthedocs/readthedocs.org/blob/6816afe5d88bb3986a0ff4a4381f2ccf4cd7c7ea/readthedocs/proxito/views/hosting.py#L272-L279


Discussion:

Resolving patch:
diff --git a/readthedocs/proxito/views/hosting.py b/readthedocs/proxito/views/hosting.py
--- a/readthedocs/proxito/views/hosting.py
+++ b/readthedocs/proxito/views/hosting.py
@@ -174,12 +174,21 @@ def _v0(self, project, version, build, filename):
         It tries to follow some similarity with the APIv3 for already-known resources
         (Project, Version, Build, etc).
         """
-        versions_active_built_not_hidden = (
-            Version.internal.public(project=project, only_active=True, only_built=True)
-            .exclude(hidden=True)
-            .only("slug")
-            .order_by("slug")
-        )
+        version_downloads = []
+        versions_active_built_not_hidden = Version.objects.none()
+
+        if not project.single_version:
+            versions_active_built_not_hidden = (
+                Version.internal.public(
+                    project=project, only_active=True, only_built=True
+                )
+                .exclude(hidden=True)
+                .only("slug")
+                .order_by("slug")
+            )
+            if version:
+                version_downloads = version.get_downloads(pretty=True).items()
+
         project_translations = (
             project.translations.all().only("language").order_by("language")
         )
@@ -283,7 +292,7 @@ def _v0(self, project, version, build, filename):
                             "name": name,
                             "url": url,
                         }
-                        for name, url in version.get_downloads(pretty=True).items()
+                        for name, url in version_downloads
                     ],
                     # TODO: find a way to get this data in a reliably way.
                     # We don't have a simple way to map a URL to a file in the repository.


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
no documentation/guidance on what to do with pdfs, epubs, offline
the docs for pdfs here:  http://read-the-docs.readthedocs.org/en/latest/features.html#pdf-generation

"When you build your project on RTD, we automatically build a PDF of your projects documentation. We also build them for every version that you upload, so we can host the PDFs of your latest documentation, as well as your latest stable releases as well."

and that's it !

Here's some useful information:
1. what is the link for the PDF ?
2. how do I make my docs link to these PDFs?
3. how about the links to epubs etc. ?

Django is doing it, they have a little thing on the side: "Offline (Django 1.3): HTML | PDF | ePub "

how do other projects get all those little links on their sidebar ?  at least the PDF ?   the path seems to be "media.readthedocs.org/pdf/[projname]/[version]/[projname].pdf".   I don't see how I could get at the current "version" tag from within my templates.   



Discussion:
This is mainly a UI issue. I think the whole dashboard UI needs a refresh, and this stuff will be exposed then.

I replaced the individual links to each download for latest in the bar with a link to a Downloads page, that should list all active DLs for a project. This will work for now, though we need to get some fancier styling and integration for this.


Resolving patch:
diff --git a/readthedocs/proxito/views/hosting.py b/readthedocs/proxito/views/hosting.py
--- a/readthedocs/proxito/views/hosting.py
+++ b/readthedocs/proxito/views/hosting.py
@@ -17,6 +17,7 @@
     ProjectSerializer,
     VersionSerializer,
 )
+from readthedocs.builds.constants import LATEST
 from readthedocs.builds.models import Version
 from readthedocs.core.resolver import resolver
 from readthedocs.core.unresolver import UnresolverError, unresolver
@@ -306,7 +307,9 @@ def _v0(self, project, version, build, filename, user):
                     # "http://test-builds-local.devthedocs.org/en/latest/index.html"
                     "base_url": resolver.resolve(
                         project=project,
-                        version_slug=project.get_default_version(),
+                        # NOTE: we are using LATEST version to compare against to for now.
+                        # Ideally, this should be configurable by the user.
+                        version_slug=LATEST,
                         language=project.language,
                         filename=filename,
                     )


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Teams: project form doesn't allow for null/empty project list
I found trying to remove a project from a team that it was impossible to remove the project if it was the last project attached to the team. The form expects some non-null value and throws a validation error if the list is empty.

To reproduce:

- Add a team
- Add a project to the team
- Try to remove the project from the team
- You'll get a validation error on the form

Instead, this should be a valid form submission and the team should have 0 projects attached.


Discussion:

Resolving patch:
diff --git a/readthedocs/organizations/forms.py b/readthedocs/organizations/forms.py
--- a/readthedocs/organizations/forms.py
+++ b/readthedocs/organizations/forms.py
@@ -208,6 +208,7 @@ def __init__(self, *args, **kwargs):
         self.fields["projects"] = forms.ModelMultipleChoiceField(
             queryset=self.organization.projects,
             widget=forms.CheckboxSelectMultiple,
+            required=False,
         )
 
 


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Notifications: cancel notifications when status changes
There are some notifications that depend on a specific status (e.g unpaid subscription). We need to find out what are those and create a periodic Celery task together with Django signals in charge of cancelling those notifications if the status has change (e.g. the user has paid the subscription).

Note that this may also apply to changes made via Django forms.

Another good example is for custom domain pending validation. I'm sure there are more, but I don't have all of them in mind currently.

This is a new feature, so there may be also good _new notifications_ where this pattern could be applied.


Discussion:
Current notifications affected by this:

* `core:email:validation-pending`
* `project:domain:validation-pending`
* `project:domain:validation-expired`
* `project:invalid:skip-builds`
* `organization:disabled`

Resolving patch:
diff --git a/readthedocs/notifications/migrations/0003_notification_indexes.py b/readthedocs/notifications/migrations/0003_notification_indexes.py
new file mode 100644
--- /dev/null
+++ b/readthedocs/notifications/migrations/0003_notification_indexes.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.2.9 on 2024-01-23 10:50
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("notifications", "0002_notification_format_values"),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name="notification",
+            options={},
+        ),
+        migrations.AddIndex(
+            model_name="notification",
+            index=models.Index(
+                fields=["attached_to_content_type", "attached_to_id"],
+                name="notificatio_attache_c6aa1d_idx",
+            ),
+        ),
+    ]
diff --git a/readthedocs/notifications/models.py b/readthedocs/notifications/models.py
--- a/readthedocs/notifications/models.py
+++ b/readthedocs/notifications/models.py
@@ -58,6 +58,11 @@ class Notification(TimeStampedModel):
     # notifications attached to the same object.
     objects = NotificationQuerySet.as_manager()
 
+    class Meta:
+        indexes = [
+            models.Index(fields=["attached_to_content_type", "attached_to_id"]),
+        ]
+
     def __str__(self):
         return self.message_id
 


Test patch:
Repository: readthedocs/readthedocs.org

Issue:
Analytics: make this feature opt-in by default
We want to make analytics feature opt-in by default because it hits the db for each page view and there are bunch of projects that are not interested in this data. They can always go to the project's setting and enable it if they want.

* Reference: https://github.com/readthedocs/meta/discussions/130#discussioncomment-7043655


Discussion:

Resolving patch:
diff --git a/readthedocs/projects/migrations/0112_disable_analytics_addons.py b/readthedocs/projects/migrations/0112_disable_analytics_addons.py
new file mode 100644
--- /dev/null
+++ b/readthedocs/projects/migrations/0112_disable_analytics_addons.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.2.9 on 2024-01-23 16:54
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("projects", "0111_add_multiple_versions_without_translations"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="addonsconfig",
+            name="analytics_enabled",
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py
--- a/readthedocs/projects/models.py
+++ b/readthedocs/projects/models.py
@@ -158,7 +158,10 @@ class AddonsConfig(TimeStampedModel):
     )
 
     # Analytics
-    analytics_enabled = models.BooleanField(default=True)
+
+    # NOTE: we keep analytics disabled by default to save resources.
+    # Most projects won't be taking a look at these numbers.
+    analytics_enabled = models.BooleanField(default=False)
 
     # Docdiff
     doc_diff_enabled = models.BooleanField(default=True)


Test patch:
diff --git a/readthedocs/proxito/tests/responses/v0.json b/readthedocs/proxito/tests/responses/v0.json
--- a/readthedocs/proxito/tests/responses/v0.json
+++ b/readthedocs/proxito/tests/responses/v0.json
@@ -79,7 +79,7 @@
   },
   "addons": {
     "analytics": {
-      "enabled": true,
+      "enabled": false,
       "code": null
     },
     "external_version_warning": {