Skip to content

Commit 052d069

Browse files
committed
Merge tag '11.7.0' into rel
2 parents 3a95337 + 6aa2757 commit 052d069

File tree

19 files changed

+206
-68
lines changed

19 files changed

+206
-68
lines changed

CHANGELOG.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
Version 11.7.0
2+
--------------
3+
4+
:Date: August 27, 2024
5+
6+
* `@github-actions[bot] <https://github.com/github-actions[bot]>`__: Dependencies: all packages updated via pip-tools (`#11566 <https://github.com/readthedocs/readthedocs.org/pull/11566>`__)
7+
* `@kurtmckee <https://github.com/kurtmckee>`__: Fix a minor typo (`#11565 <https://github.com/readthedocs/readthedocs.org/pull/11565>`__)
8+
* `@agjohnson <https://github.com/agjohnson>`__: Use clone_url for remote repository field (`#11564 <https://github.com/readthedocs/readthedocs.org/pull/11564>`__)
9+
* `@stsewd <https://github.com/stsewd>`__: Tasks: delete closed PRs every 30 minutes (`#11563 <https://github.com/readthedocs/readthedocs.org/pull/11563>`__)
10+
* `@stsewd <https://github.com/stsewd>`__: Settings: define threshold setting for removing projects from ES (`#11560 <https://github.com/readthedocs/readthedocs.org/pull/11560>`__)
11+
* `@humitos <https://github.com/humitos>`__: Add project: improve way to get the `basics` form (`#11558 <https://github.com/readthedocs/readthedocs.org/pull/11558>`__)
12+
* `@stsewd <https://github.com/stsewd>`__: Search: add function to re-index a project (`#11555 <https://github.com/readthedocs/readthedocs.org/pull/11555>`__)
13+
* `@humitos <https://github.com/humitos>`__: Release 11.6.0 (`#11554 <https://github.com/readthedocs/readthedocs.org/pull/11554>`__)
14+
* `@humitos <https://github.com/humitos>`__: Docs: make URLs not linkable (`#11553 <https://github.com/readthedocs/readthedocs.org/pull/11553>`__)
15+
* `@stsewd <https://github.com/stsewd>`__: Update common (`#11552 <https://github.com/readthedocs/readthedocs.org/pull/11552>`__)
16+
* `@humitos <https://github.com/humitos>`__: Docs: make translation section more generic (`#11549 <https://github.com/readthedocs/readthedocs.org/pull/11549>`__)
17+
* `@mgeier <https://github.com/mgeier>`__: Update instructions for Jupyter notebook galleries (`#11545 <https://github.com/readthedocs/readthedocs.org/pull/11545>`__)
18+
* `@stsewd <https://github.com/stsewd>`__: Allauth: 2FA (`#11524 <https://github.com/readthedocs/readthedocs.org/pull/11524>`__)
19+
* `@ericholscher <https://github.com/ericholscher>`__: Release 10.21.0 (`#11185 <https://github.com/readthedocs/readthedocs.org/pull/11185>`__)
20+
* `@humitos <https://github.com/humitos>`__: Build: show the YAML config file before validating it (`#11175 <https://github.com/readthedocs/readthedocs.org/pull/11175>`__)
21+
* `@humitos <https://github.com/humitos>`__: Release 10.18.0 (`#11096 <https://github.com/readthedocs/readthedocs.org/pull/11096>`__)
22+
* `@github-actions[bot] <https://github.com/github-actions[bot]>`__: Dependencies: all packages updated via pip-tools (`#11090 <https://github.com/readthedocs/readthedocs.org/pull/11090>`__)
23+
* `@stsewd <https://github.com/stsewd>`__: Build: use version slug for get_version_slug (`#11085 <https://github.com/readthedocs/readthedocs.org/pull/11085>`__)
24+
* `@stsewd <https://github.com/stsewd>`__: Integrations: Don't allow webhooks without a secret (`#11083 <https://github.com/readthedocs/readthedocs.org/pull/11083>`__)
25+
* `@humitos <https://github.com/humitos>`__: Addons: sorting algorithm for versions customizable on flyout (`#11069 <https://github.com/readthedocs/readthedocs.org/pull/11069>`__)
26+
127
Version 11.6.0
228
--------------
329

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676

7777
master_doc = "index"
7878
copyright = "Read the Docs, Inc & contributors"
79-
version = "11.6.0"
79+
version = "11.7.0"
8080
release = version
8181
exclude_patterns = ["_build", "shared", "_includes"]
8282
default_role = "obj"

docs/user/config-file/v2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ Patterns can include one or more of the following special characters:
776776
- search.html
777777
- search/index.html
778778
- 404.html
779-
- 404/index.html'
779+
- 404/index.html
780780
781781
.. note::
782782

docs/user/subprojects.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ This is useful for:
1515

1616
For a main project ``example-project``, a subproject ``example-project-plugin`` can be made available as follows:
1717

18-
* Main project: https://example-project.readthedocs.io/en/latest/
19-
* Subproject: https://example-project.readthedocs.io/projects/plugin/en/latest/
18+
* Main project: ``https://example-project.readthedocs.io/en/latest/``
19+
* Subproject: ``https://example-project.readthedocs.io/projects/plugin/en/latest/``
2020

2121
.. seealso::
2222

@@ -38,8 +38,8 @@ If the example project ``example-project`` was set up with a custom domain,
3838
``docs.example.com``, the URLs for projects ``example-project`` and ``example-project-plugin`` with alias ``plugin`` would
3939
respectively be at:
4040

41-
* ``example-project``: https://docs.example.com/en/latest/
42-
* ``example-project-plugin``: https://docs.example.com/projects/plugin/en/latest/
41+
* ``example-project``: ``https://docs.example.com/en/latest/``
42+
* ``example-project-plugin``: ``https://docs.example.com/projects/plugin/en/latest/``
4343

4444
Using aliases
4545
-------------

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "readthedocs",
3-
"version": "11.6.0",
3+
"version": "11.7.0",
44
"description": "Read the Docs build dependencies",
55
"author": "Read the Docs, Inc <[email protected]>",
66
"scripts": {

readthedocs/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
"""Read the Docs."""
22

33

4-
__version__ = "11.6.0"
4+
__version__ = "11.7.0"

readthedocs/builds/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def delete_closed_external_versions(limit=200, days=30 * 3):
251251
queryset = Version.external.filter(
252252
state=EXTERNAL_VERSION_STATE_CLOSED,
253253
modified__lte=days_ago,
254-
)[:limit]
254+
).order_by("modified")[:limit]
255255
for version in queryset:
256256
try:
257257
last_build = version.last_build

readthedocs/projects/forms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def _get_remote_repository_choices(self):
9090
if current_remote_repo and current_remote_repo not in queryset:
9191
options.append((current_remote_repo.pk, str(current_remote_repo)))
9292

93-
options.extend((repo.pk, str(repo)) for repo in queryset)
93+
options.extend((repo.pk, repo.clone_url) for repo in queryset)
9494
return options
9595

9696
def save(self, commit=True):

readthedocs/projects/tasks/search.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import structlog
44

5-
from readthedocs.builds.constants import BUILD_STATE_FINISHED
5+
from readthedocs.builds.constants import BUILD_STATE_FINISHED, INTERNAL
66
from readthedocs.builds.models import Build, Version
77
from readthedocs.projects.models import HTMLFile, Project
88
from readthedocs.projects.signals import files_changed
@@ -95,7 +95,7 @@ def reindex_version(version_id, search_index_name=None):
9595

9696
build_config = latest_successful_build.config or {}
9797
search_config = build_config.get("search", {})
98-
search_ranking = search_config.get("ranking", [])
98+
search_ranking = search_config.get("ranking", {})
9999
search_ignore = search_config.get("ignore", [])
100100

101101
try:
@@ -109,6 +109,31 @@ def reindex_version(version_id, search_index_name=None):
109109
log.exception("Failed during creation of new files")
110110

111111

112+
@app.task(queue="reindex")
113+
def index_project(project_slug, skip_if_exists=False):
114+
"""
115+
Index all active versions of the project.
116+
117+
If ``skip_if_exists`` is True, we first check if
118+
the project has at least one version indexed,
119+
and skip the re-indexing if it does.
120+
"""
121+
log.bind(project_slug=project_slug)
122+
project = Project.objects.filter(slug=project_slug).first()
123+
if not project:
124+
log.debug("Project doesn't exist.")
125+
return
126+
127+
if skip_if_exists:
128+
if PageDocument().search().filter("term", project=project.slug).count():
129+
log.debug("Skipping search indexing. Project is already indexed.")
130+
return
131+
132+
versions = project.versions(manager=INTERNAL).filter(active=True, built=True)
133+
for version in versions:
134+
reindex_version(version_id=version.id)
135+
136+
112137
@app.task(queue="web")
113138
def remove_search_indexes(project_slug, version_slug=None):
114139
"""Wrapper around ``remove_indexed_files`` to make it a task."""

readthedocs/projects/views/private.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,15 @@ def done(self, form_list, **kwargs):
357357
other side effects for now, by signalling a save without commit. Then,
358358
finish by added the members to the project and saving.
359359
"""
360-
basics_form = form_list[0]
360+
361+
# We need to find the "basics" for here by iterating the list of bounded instance forms
362+
# because community and business have different steps -- it's not always the first one.
363+
basics_form = None
364+
for form in form_list:
365+
if isinstance(form, self.form_list.get("basics")):
366+
basics_form = form
367+
break
368+
361369
# Save the basics form to create the project instance, then alter
362370
# attributes directly from other forms
363371
project = basics_form.save()

readthedocs/search/tests/test_utils.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import time
2+
from unittest import mock
23

34
import pytest
45
from django.urls import reverse
56

67
from readthedocs.builds.constants import LATEST, STABLE
8+
from readthedocs.projects.models import Project
9+
from readthedocs.projects.tasks.search import index_project
710
from readthedocs.search import utils
11+
from readthedocs.search.documents import PageDocument
812
from readthedocs.search.tests.utils import get_search_query_from_project_file
913

1014

@@ -66,3 +70,25 @@ def test_remove_only_one_version_index(self, api_client, all_projects):
6670
for project in ["pipeline", "docs"]:
6771
for version in [LATEST, STABLE]:
6872
assert self.has_results(api_client, project, version)
73+
74+
@mock.patch("readthedocs.projects.tasks.search.reindex_version")
75+
def test_index_project(self, reindex_version, all_projects):
76+
project_slug = "kuma"
77+
project = Project.objects.get(slug=project_slug)
78+
# Create builds for all versions
79+
for version in project.versions.all():
80+
version.builds.create(
81+
project=project,
82+
state="finished",
83+
success=True,
84+
)
85+
86+
assert PageDocument().search().filter("term", project=project_slug).count()
87+
88+
# Re-index is skipped, since the project is already indexed.
89+
index_project(project_slug=project_slug, skip_if_exists=True)
90+
reindex_version.assert_not_called()
91+
92+
# Re-index all versions of the project.
93+
index_project(project_slug=project_slug, skip_if_exists=False)
94+
assert reindex_version.call_count == project.versions.count()

readthedocs/settings/base.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ def INSTALLED_APPS(self): # noqa
287287
"allauth.socialaccount.providers.github",
288288
"allauth.socialaccount.providers.gitlab",
289289
"allauth.socialaccount.providers.bitbucket_oauth2",
290+
"allauth.mfa",
290291
"cacheops",
291292
]
292293
if ext:
@@ -545,11 +546,11 @@ def TEMPLATES(self):
545546
"delete": True,
546547
},
547548
},
548-
"every-three-hours-delete-inactive-external-versions": {
549+
"every-30m-delete-inactive-external-versions": {
549550
"task": "readthedocs.builds.tasks.delete_closed_external_versions",
550551
# Increase the frequency because we have 255k closed versions and they keep growing.
551552
# It's better to increase this frequency than the `limit=` of the task.
552-
"schedule": crontab(minute=0, hour="*/3"),
553+
"schedule": crontab(minute="*/30", hour="*"),
553554
"options": {"queue": "web"},
554555
},
555556
"every-day-resync-remote-repositories": {
@@ -661,7 +662,7 @@ def DOCKER_LIMITS(self):
661662
)
662663
return limits
663664

664-
# All auth
665+
# Allauth
665666
ACCOUNT_ADAPTER = "readthedocs.core.adapters.AccountAdapter"
666667
ACCOUNT_EMAIL_REQUIRED = True
667668

@@ -1010,6 +1011,7 @@ def SOCIALACCOUNT_PROVIDERS(self):
10101011
RTD_SPAM_THRESHOLD_DENY_ON_ROBOTS = 200
10111012
RTD_SPAM_THRESHOLD_DONT_SHOW_DASHBOARD = 300
10121013
RTD_SPAM_THRESHOLD_DONT_SERVE_DOCS = 500
1014+
RTD_SPAM_THRESHOLD_REMOVE_FROM_SEARCH_INDEX = 500
10131015
RTD_SPAM_THRESHOLD_DELETE_PROJECT = 1000
10141016
RTD_SPAM_MAX_SCORE = 9999
10151017

requirements/deploy.txt

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ billiard==3.6.4.0
2323
# via
2424
# -r requirements/pip.txt
2525
# celery
26-
boto3==1.34.158
26+
boto3==1.35.5
2727
# via
2828
# -r requirements/pip.txt
2929
# django-storages
30-
botocore==1.34.158
30+
botocore==1.35.5
3131
# via
3232
# -r requirements/pip.txt
3333
# boto3
@@ -76,13 +76,14 @@ colorama==0.4.6
7676
# via
7777
# -r requirements/pip.txt
7878
# bumpver
79-
cron-descriptor==1.4.3
79+
cron-descriptor==1.4.5
8080
# via
8181
# -r requirements/pip.txt
8282
# django-celery-beat
8383
cryptography==43.0.0
8484
# via
8585
# -r requirements/pip.txt
86+
# fido2
8687
# pyjwt
8788
cssselect==1.2.0
8889
# via
@@ -120,15 +121,15 @@ django==4.2.15
120121
# django-timezone-field
121122
# djangorestframework
122123
# jsonfield
123-
django-allauth[saml,socialaccount]==64.0.0
124+
django-allauth[mfa,saml,socialaccount]==64.1.0
124125
# via -r requirements/pip.txt
125126
django-annoying==0.10.7
126127
# via -r requirements/pip.txt
127128
django-autoslug==1.9.9
128129
# via -r requirements/pip.txt
129130
django-cacheops==7.0.2
130131
# via -r requirements/pip.txt
131-
django-celery-beat==2.6.0
132+
django-celery-beat==2.7.0
132133
# via -r requirements/pip.txt
133134
django-cors-headers==4.4.0
134135
# via -r requirements/pip.txt
@@ -189,22 +190,26 @@ drf-extensions==0.7.1
189190
# via -r requirements/pip.txt
190191
drf-flex-fields==1.0.2
191192
# via -r requirements/pip.txt
192-
elastic-transport==8.13.1
193+
elastic-transport==8.15.0
193194
# via
194195
# -r requirements/pip.txt
195196
# elasticsearch
196-
elasticsearch==8.14.0
197+
elasticsearch==8.15.0
197198
# via
198199
# -r requirements/pip.txt
199200
# elasticsearch-dsl
200-
elasticsearch-dsl==8.14.0
201+
elasticsearch-dsl==8.15.1
201202
# via
202203
# -r requirements/pip.txt
203204
# django-elasticsearch-dsl
204205
exceptiongroup==1.2.2
205206
# via ipython
206207
executing==2.0.1
207208
# via stack-data
209+
fido2==1.1.3
210+
# via
211+
# -r requirements/pip.txt
212+
# django-allauth
208213
filelock==3.15.4
209214
# via
210215
# -r requirements/pip.txt
@@ -215,7 +220,7 @@ funcy==2.0
215220
# django-cacheops
216221
gunicorn==23.0.0
217222
# via -r requirements/pip.txt
218-
idna==3.7
223+
idna==3.8
219224
# via
220225
# -r requirements/pip.txt
221226
# requests
@@ -254,7 +259,7 @@ lxml==5.3.0
254259
# pyquery
255260
# python3-saml
256261
# xmlsec
257-
markdown==3.6
262+
markdown==3.7
258263
# via -r requirements/pip.txt
259264
matplotlib-inline==0.1.7
260265
# via ipython
@@ -312,6 +317,10 @@ pyjwt[crypto]==2.9.0
312317
# via
313318
# -r requirements/pip.txt
314319
# django-allauth
320+
pypng==0.20220715.0
321+
# via
322+
# -r requirements/pip.txt
323+
# qrcode
315324
pyquery==2.0.0
316325
# via -r requirements/pip.txt
317326
python-crontab==3.2.0
@@ -334,6 +343,10 @@ pytz==2024.1
334343
# celery
335344
pyyaml==6.0.2
336345
# via -r requirements/pip.txt
346+
qrcode==7.4.2
347+
# via
348+
# -r requirements/pip.txt
349+
# django-allauth
337350
redis==5.0.8
338351
# via
339352
# -r requirements/pip.txt
@@ -363,7 +376,7 @@ s3transfer==0.10.2
363376
# boto3
364377
selectolax==0.3.21
365378
# via -r requirements/pip.txt
366-
sentry-sdk==2.12.0
379+
sentry-sdk==2.13.0
367380
# via structlog-sentry
368381
six==1.16.0
369382
# via
@@ -414,6 +427,7 @@ typing-extensions==4.12.2
414427
# ipython
415428
# psycopg
416429
# psycopg-pool
430+
# qrcode
417431
tzdata==2024.1
418432
# via
419433
# -r requirements/pip.txt

0 commit comments

Comments
 (0)