We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Notifications: always show notifications on build details' page
It seems that in https://github.com/readthedocs/readthedocs.org/pull/11117 we introduced a bug that it only shows the notifications for the build to users that have permissions over that project in particular --which is wrong. Since the project is public, it should show the notifications to all the users with access to the build detail's page.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `readthedocs/builds/views.py`
Content:
```
1 """Views for builds app."""
2 
3 import textwrap
4 from urllib.parse import urlparse
5 
6 import structlog
7 from django.conf import settings
8 from django.contrib import messages
9 from django.contrib.auth.decorators import login_required
10 from django.http import HttpResponseForbidden, HttpResponseRedirect
11 from django.shortcuts import get_object_or_404
12 from django.urls import reverse
13 from django.utils.decorators import method_decorator
14 from django.views.generic import DetailView, ListView
15 from requests.utils import quote
16 
17 from readthedocs.builds.constants import BUILD_FINAL_STATES
18 from readthedocs.builds.filters import BuildListFilter
19 from readthedocs.builds.models import Build, Version
20 from readthedocs.core.permissions import AdminPermission
21 from readthedocs.core.utils import cancel_build, trigger_build
22 from readthedocs.doc_builder.exceptions import BuildAppError
23 from readthedocs.projects.models import Project
24 
25 log = structlog.get_logger(__name__)
26 
27 
28 class BuildBase:
29     model = Build
30 
31     def get_queryset(self):
32         self.project_slug = self.kwargs.get("project_slug", None)
33         self.project = get_object_or_404(
34             Project.objects.public(self.request.user),
35             slug=self.project_slug,
36         )
37         queryset = Build.objects.public(
38             user=self.request.user,
39             project=self.project,
40         ).select_related("project", "version")
41 
42         return queryset
43 
44 
45 class BuildTriggerMixin:
46     @method_decorator(login_required)
47     def post(self, request, project_slug):
48         commit_to_retrigger = None
49         project = get_object_or_404(Project, slug=project_slug)
50 
51         if not AdminPermission.is_admin(request.user, project):
52             return HttpResponseForbidden()
53 
54         version_slug = request.POST.get("version_slug")
55         build_pk = request.POST.get("build_pk")
56 
57         if build_pk:
58             # Filter over external versions only when re-triggering a specific build
59             version = get_object_or_404(
60                 Version.external.public(self.request.user),
61                 slug=version_slug,
62                 project=project,
63             )
64 
65             build_to_retrigger = get_object_or_404(
66                 Build.objects.all(),
67                 pk=build_pk,
68                 version=version,
69             )
70             if build_to_retrigger != Build.objects.filter(version=version).first():
71                 messages.add_message(
72                     request,
73                     messages.ERROR,
74                     "This build can't be re-triggered because it's "
75                     "not the latest build for this version.",
76                 )
77                 return HttpResponseRedirect(request.path)
78 
79             # Set either the build to re-trigger it or None
80             if build_to_retrigger:
81                 commit_to_retrigger = build_to_retrigger.commit
82                 log.info(
83                     "Re-triggering build.",
84                     project_slug=project.slug,
85                     version_slug=version.slug,
86                     build_commit=build_to_retrigger.commit,
87                     build_id=build_to_retrigger.pk,
88                 )
89         else:
90             # Use generic query when triggering a normal build
91             version = get_object_or_404(
92                 self._get_versions(project),
93                 slug=version_slug,
94             )
95 
96         update_docs_task, build = trigger_build(
97             project=project,
98             version=version,
99             commit=commit_to_retrigger,
100         )
101         if (update_docs_task, build) == (None, None):
102             # Build was skipped
103             messages.add_message(
104                 request,
105                 messages.WARNING,
106                 "This project is currently disabled and can't trigger new builds.",
107             )
108             return HttpResponseRedirect(
109                 reverse("builds_project_list", args=[project.slug]),
110             )
111 
112         return HttpResponseRedirect(
113             reverse("builds_detail", args=[project.slug, build.pk]),
114         )
115 
116     def _get_versions(self, project):
117         return Version.internal.public(
118             user=self.request.user,
119             project=project,
120         )
121 
122 
123 class BuildList(BuildBase, BuildTriggerMixin, ListView):
124     def get_context_data(self, **kwargs):
125         context = super().get_context_data(**kwargs)
126 
127         active_builds = (
128             self.get_queryset()
129             .exclude(
130                 state__in=BUILD_FINAL_STATES,
131             )
132             .values("id")
133         )
134 
135         context["project"] = self.project
136         context["active_builds"] = active_builds
137         context["versions"] = self._get_versions(self.project)
138 
139         builds = self.get_queryset()
140         if settings.RTD_EXT_THEME_ENABLED:
141             filter = BuildListFilter(self.request.GET, queryset=builds)
142             context["filter"] = filter
143             builds = filter.qs
144         context["build_qs"] = builds
145 
146         return context
147 
148 
149 class BuildDetail(BuildBase, DetailView):
150     pk_url_kwarg = "build_pk"
151 
152     @method_decorator(login_required)
153     def post(self, request, project_slug, build_pk):
154         project = get_object_or_404(Project, slug=project_slug)
155         build = get_object_or_404(project.builds, pk=build_pk)
156 
157         if not AdminPermission.is_admin(request.user, project):
158             return HttpResponseForbidden()
159 
160         cancel_build(build)
161 
162         return HttpResponseRedirect(
163             reverse("builds_detail", args=[project.slug, build.pk]),
164         )
165 
166     def get_context_data(self, **kwargs):
167         context = super().get_context_data(**kwargs)
168         context["project"] = self.project
169 
170         build = self.get_object()
171 
172         if not build.notifications.filter(
173             message_id=BuildAppError.GENERIC_WITH_BUILD_ID
174         ).exists():
175             # Do not suggest to open an issue if the error is not generic
176             return context
177 
178         scheme = (
179             "https://github.com/rtfd/readthedocs.org/issues/new"
180             "?title={title}{build_id}"
181             "&body={body}"
182         )
183 
184         # TODO: we could use ``.github/ISSUE_TEMPLATE.md`` here, but we would
185         # need to add some variables to it which could impact in the UX when
186         # filling an issue from the web
187         body = """
188         ## Details:
189 
190         * Project URL: https://readthedocs.org/projects/{project_slug}/
191         * Build URL(if applicable): https://readthedocs.org{build_path}
192         * Read the Docs username(if applicable): {username}
193 
194         ## Expected Result
195 
196         *A description of what you wanted to happen*
197 
198         ## Actual Result
199 
200         *A description of what actually happened*""".format(
201             project_slug=self.project,
202             build_path=self.request.path,
203             username=self.request.user,
204         )
205 
206         scheme_dict = {
207             "title": quote("Build error with build id #"),
208             "build_id": context["build"].id,
209             "body": quote(textwrap.dedent(body)),
210         }
211 
212         issue_url = scheme.format(**scheme_dict)
213         issue_url = urlparse(issue_url).geturl()
214         context["issue_url"] = issue_url
215         context["notifications"] = build.notifications.all()
216         return context
217
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/readthedocs/builds/views.py b/readthedocs/builds/views.py
--- a/readthedocs/builds/views.py
+++ b/readthedocs/builds/views.py
@@ -168,6 +168,7 @@
         context["project"] = self.project
 
         build = self.get_object()
+        context["notifications"] = build.notifications.all()
 
         if not build.notifications.filter(
             message_id=BuildAppError.GENERIC_WITH_BUILD_ID
@@ -212,5 +213,5 @@
         issue_url = scheme.format(**scheme_dict)
         issue_url = urlparse(issue_url).geturl()
         context["issue_url"] = issue_url
-        context["notifications"] = build.notifications.all()
+
         return context

{"golden_diff": "diff --git a/readthedocs/builds/views.py b/readthedocs/builds/views.py\n--- a/readthedocs/builds/views.py\n+++ b/readthedocs/builds/views.py\n@@ -168,6 +168,7 @@\n         context[\"project\"] = self.project\n \n         build = self.get_object()\n+        context[\"notifications\"] = build.notifications.all()\n \n         if not build.notifications.filter(\n             message_id=BuildAppError.GENERIC_WITH_BUILD_ID\n@@ -212,5 +213,5 @@\n         issue_url = scheme.format(**scheme_dict)\n         issue_url = urlparse(issue_url).geturl()\n         context[\"issue_url\"] = issue_url\n-        context[\"notifications\"] = build.notifications.all()\n+\n         return context\n", "issue": "Notifications: always show notifications on build details' page\nIt seems that in https://github.com/readthedocs/readthedocs.org/pull/11117 we introduced a bug that it only shows the notifications for the build to users that have permissions over that project in particular --which is wrong. Since the project is public, it should show the notifications to all the users with access to the build detail's page.\n", "before_files": [{"content": "\"\"\"Views for builds app.\"\"\"\n\nimport textwrap\nfrom urllib.parse import urlparse\n\nimport structlog\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.auth.decorators import login_required\nfrom django.http import HttpResponseForbidden, HttpResponseRedirect\nfrom django.shortcuts import get_object_or_404\nfrom django.urls import reverse\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import DetailView, ListView\nfrom requests.utils import quote\n\nfrom readthedocs.builds.constants import BUILD_FINAL_STATES\nfrom readthedocs.builds.filters import BuildListFilter\nfrom readthedocs.builds.models import Build, Version\nfrom readthedocs.core.permissions import AdminPermission\nfrom readthedocs.core.utils import cancel_build, trigger_build\nfrom readthedocs.doc_builder.exceptions import BuildAppError\nfrom readthedocs.projects.models import Project\n\nlog = structlog.get_logger(__name__)\n\n\nclass BuildBase:\n    model = Build\n\n    def get_queryset(self):\n        self.project_slug = self.kwargs.get(\"project_slug\", None)\n        self.project = get_object_or_404(\n            Project.objects.public(self.request.user),\n            slug=self.project_slug,\n        )\n        queryset = Build.objects.public(\n            user=self.request.user,\n            project=self.project,\n        ).select_related(\"project\", \"version\")\n\n        return queryset\n\n\nclass BuildTriggerMixin:\n    @method_decorator(login_required)\n    def post(self, request, project_slug):\n        commit_to_retrigger = None\n        project = get_object_or_404(Project, slug=project_slug)\n\n        if not AdminPermission.is_admin(request.user, project):\n            return HttpResponseForbidden()\n\n        version_slug = request.POST.get(\"version_slug\")\n        build_pk = request.POST.get(\"build_pk\")\n\n        if build_pk:\n            # Filter over external versions only when re-triggering a specific build\n            version = get_object_or_404(\n                Version.external.public(self.request.user),\n                slug=version_slug,\n                project=project,\n            )\n\n            build_to_retrigger = get_object_or_404(\n                Build.objects.all(),\n                pk=build_pk,\n                version=version,\n            )\n            if build_to_retrigger != Build.objects.filter(version=version).first():\n                messages.add_message(\n                    request,\n                    messages.ERROR,\n                    \"This build can't be re-triggered because it's \"\n                    \"not the latest build for this version.\",\n                )\n                return HttpResponseRedirect(request.path)\n\n            # Set either the build to re-trigger it or None\n            if build_to_retrigger:\n                commit_to_retrigger = build_to_retrigger.commit\n                log.info(\n                    \"Re-triggering build.\",\n                    project_slug=project.slug,\n                    version_slug=version.slug,\n                    build_commit=build_to_retrigger.commit,\n                    build_id=build_to_retrigger.pk,\n                )\n        else:\n            # Use generic query when triggering a normal build\n            version = get_object_or_404(\n                self._get_versions(project),\n                slug=version_slug,\n            )\n\n        update_docs_task, build = trigger_build(\n            project=project,\n            version=version,\n            commit=commit_to_retrigger,\n        )\n        if (update_docs_task, build) == (None, None):\n            # Build was skipped\n            messages.add_message(\n                request,\n                messages.WARNING,\n                \"This project is currently disabled and can't trigger new builds.\",\n            )\n            return HttpResponseRedirect(\n                reverse(\"builds_project_list\", args=[project.slug]),\n            )\n\n        return HttpResponseRedirect(\n            reverse(\"builds_detail\", args=[project.slug, build.pk]),\n        )\n\n    def _get_versions(self, project):\n        return Version.internal.public(\n            user=self.request.user,\n            project=project,\n        )\n\n\nclass BuildList(BuildBase, BuildTriggerMixin, ListView):\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        active_builds = (\n            self.get_queryset()\n            .exclude(\n                state__in=BUILD_FINAL_STATES,\n            )\n            .values(\"id\")\n        )\n\n        context[\"project\"] = self.project\n        context[\"active_builds\"] = active_builds\n        context[\"versions\"] = self._get_versions(self.project)\n\n        builds = self.get_queryset()\n        if settings.RTD_EXT_THEME_ENABLED:\n            filter = BuildListFilter(self.request.GET, queryset=builds)\n            context[\"filter\"] = filter\n            builds = filter.qs\n        context[\"build_qs\"] = builds\n\n        return context\n\n\nclass BuildDetail(BuildBase, DetailView):\n    pk_url_kwarg = \"build_pk\"\n\n    @method_decorator(login_required)\n    def post(self, request, project_slug, build_pk):\n        project = get_object_or_404(Project, slug=project_slug)\n        build = get_object_or_404(project.builds, pk=build_pk)\n\n        if not AdminPermission.is_admin(request.user, project):\n            return HttpResponseForbidden()\n\n        cancel_build(build)\n\n        return HttpResponseRedirect(\n            reverse(\"builds_detail\", args=[project.slug, build.pk]),\n        )\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"project\"] = self.project\n\n        build = self.get_object()\n\n        if not build.notifications.filter(\n            message_id=BuildAppError.GENERIC_WITH_BUILD_ID\n        ).exists():\n            # Do not suggest to open an issue if the error is not generic\n            return context\n\n        scheme = (\n            \"https://github.com/rtfd/readthedocs.org/issues/new\"\n            \"?title={title}{build_id}\"\n            \"&body={body}\"\n        )\n\n        # TODO: we could use ``.github/ISSUE_TEMPLATE.md`` here, but we would\n        # need to add some variables to it which could impact in the UX when\n        # filling an issue from the web\n        body = \"\"\"\n        ## Details:\n\n        * Project URL: https://readthedocs.org/projects/{project_slug}/\n        * Build URL(if applicable): https://readthedocs.org{build_path}\n        * Read the Docs username(if applicable): {username}\n\n        ## Expected Result\n\n        *A description of what you wanted to happen*\n\n        ## Actual Result\n\n        *A description of what actually happened*\"\"\".format(\n            project_slug=self.project,\n            build_path=self.request.path,\n            username=self.request.user,\n        )\n\n        scheme_dict = {\n            \"title\": quote(\"Build error with build id #\"),\n            \"build_id\": context[\"build\"].id,\n            \"body\": quote(textwrap.dedent(body)),\n        }\n\n        issue_url = scheme.format(**scheme_dict)\n        issue_url = urlparse(issue_url).geturl()\n        context[\"issue_url\"] = issue_url\n        context[\"notifications\"] = build.notifications.all()\n        return context\n", "path": "readthedocs/builds/views.py"}], "after_files": [{"content": "\"\"\"Views for builds app.\"\"\"\n\nimport textwrap\nfrom urllib.parse import urlparse\n\nimport structlog\nfrom django.conf import settings\nfrom django.contrib import messages\nfrom django.contrib.auth.decorators import login_required\nfrom django.http import HttpResponseForbidden, HttpResponseRedirect\nfrom django.shortcuts import get_object_or_404\nfrom django.urls import reverse\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import DetailView, ListView\nfrom requests.utils import quote\n\nfrom readthedocs.builds.constants import BUILD_FINAL_STATES\nfrom readthedocs.builds.filters import BuildListFilter\nfrom readthedocs.builds.models import Build, Version\nfrom readthedocs.core.permissions import AdminPermission\nfrom readthedocs.core.utils import cancel_build, trigger_build\nfrom readthedocs.doc_builder.exceptions import BuildAppError\nfrom readthedocs.projects.models import Project\n\nlog = structlog.get_logger(__name__)\n\n\nclass BuildBase:\n    model = Build\n\n    def get_queryset(self):\n        self.project_slug = self.kwargs.get(\"project_slug\", None)\n        self.project = get_object_or_404(\n            Project.objects.public(self.request.user),\n            slug=self.project_slug,\n        )\n        queryset = Build.objects.public(\n            user=self.request.user,\n            project=self.project,\n        ).select_related(\"project\", \"version\")\n\n        return queryset\n\n\nclass BuildTriggerMixin:\n    @method_decorator(login_required)\n    def post(self, request, project_slug):\n        commit_to_retrigger = None\n        project = get_object_or_404(Project, slug=project_slug)\n\n        if not AdminPermission.is_admin(request.user, project):\n            return HttpResponseForbidden()\n\n        version_slug = request.POST.get(\"version_slug\")\n        build_pk = request.POST.get(\"build_pk\")\n\n        if build_pk:\n            # Filter over external versions only when re-triggering a specific build\n            version = get_object_or_404(\n                Version.external.public(self.request.user),\n                slug=version_slug,\n                project=project,\n            )\n\n            build_to_retrigger = get_object_or_404(\n                Build.objects.all(),\n                pk=build_pk,\n                version=version,\n            )\n            if build_to_retrigger != Build.objects.filter(version=version).first():\n                messages.add_message(\n                    request,\n                    messages.ERROR,\n                    \"This build can't be re-triggered because it's \"\n                    \"not the latest build for this version.\",\n                )\n                return HttpResponseRedirect(request.path)\n\n            # Set either the build to re-trigger it or None\n            if build_to_retrigger:\n                commit_to_retrigger = build_to_retrigger.commit\n                log.info(\n                    \"Re-triggering build.\",\n                    project_slug=project.slug,\n                    version_slug=version.slug,\n                    build_commit=build_to_retrigger.commit,\n                    build_id=build_to_retrigger.pk,\n                )\n        else:\n            # Use generic query when triggering a normal build\n            version = get_object_or_404(\n                self._get_versions(project),\n                slug=version_slug,\n            )\n\n        update_docs_task, build = trigger_build(\n            project=project,\n            version=version,\n            commit=commit_to_retrigger,\n        )\n        if (update_docs_task, build) == (None, None):\n            # Build was skipped\n            messages.add_message(\n                request,\n                messages.WARNING,\n                \"This project is currently disabled and can't trigger new builds.\",\n            )\n            return HttpResponseRedirect(\n                reverse(\"builds_project_list\", args=[project.slug]),\n            )\n\n        return HttpResponseRedirect(\n            reverse(\"builds_detail\", args=[project.slug, build.pk]),\n        )\n\n    def _get_versions(self, project):\n        return Version.internal.public(\n            user=self.request.user,\n            project=project,\n        )\n\n\nclass BuildList(BuildBase, BuildTriggerMixin, ListView):\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n\n        active_builds = (\n            self.get_queryset()\n            .exclude(\n                state__in=BUILD_FINAL_STATES,\n            )\n            .values(\"id\")\n        )\n\n        context[\"project\"] = self.project\n        context[\"active_builds\"] = active_builds\n        context[\"versions\"] = self._get_versions(self.project)\n\n        builds = self.get_queryset()\n        if settings.RTD_EXT_THEME_ENABLED:\n            filter = BuildListFilter(self.request.GET, queryset=builds)\n            context[\"filter\"] = filter\n            builds = filter.qs\n        context[\"build_qs\"] = builds\n\n        return context\n\n\nclass BuildDetail(BuildBase, DetailView):\n    pk_url_kwarg = \"build_pk\"\n\n    @method_decorator(login_required)\n    def post(self, request, project_slug, build_pk):\n        project = get_object_or_404(Project, slug=project_slug)\n        build = get_object_or_404(project.builds, pk=build_pk)\n\n        if not AdminPermission.is_admin(request.user, project):\n            return HttpResponseForbidden()\n\n        cancel_build(build)\n\n        return HttpResponseRedirect(\n            reverse(\"builds_detail\", args=[project.slug, build.pk]),\n        )\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context[\"project\"] = self.project\n\n        build = self.get_object()\n        context[\"notifications\"] = build.notifications.all()\n\n        if not build.notifications.filter(\n            message_id=BuildAppError.GENERIC_WITH_BUILD_ID\n        ).exists():\n            # Do not suggest to open an issue if the error is not generic\n            return context\n\n        scheme = (\n            \"https://github.com/rtfd/readthedocs.org/issues/new\"\n            \"?title={title}{build_id}\"\n            \"&body={body}\"\n        )\n\n        # TODO: we could use ``.github/ISSUE_TEMPLATE.md`` here, but we would\n        # need to add some variables to it which could impact in the UX when\n        # filling an issue from the web\n        body = \"\"\"\n        ## Details:\n\n        * Project URL: https://readthedocs.org/projects/{project_slug}/\n        * Build URL(if applicable): https://readthedocs.org{build_path}\n        * Read the Docs username(if applicable): {username}\n\n        ## Expected Result\n\n        *A description of what you wanted to happen*\n\n        ## Actual Result\n\n        *A description of what actually happened*\"\"\".format(\n            project_slug=self.project,\n            build_path=self.request.path,\n            username=self.request.user,\n        )\n\n        scheme_dict = {\n            \"title\": quote(\"Build error with build id #\"),\n            \"build_id\": context[\"build\"].id,\n            \"body\": quote(textwrap.dedent(body)),\n        }\n\n        issue_url = scheme.format(**scheme_dict)\n        issue_url = urlparse(issue_url).geturl()\n        context[\"issue_url\"] = issue_url\n\n        return context\n", "path": "readthedocs/builds/views.py"}]}