Skip to content

Commit 3aa2f46

Browse files
committed
Version: new field addons
This `addons` field will be used to tell El Proxito this version was built using `build.commands`. Then, El Proxito will use this field to inject the HTTP header that tells Cloudflare that it should inject the new JS client. This commit is a replacement of #10219 to avoid the time-consuming query that checks the config file of the latest build for the version. Closes #10331
1 parent 3b35753 commit 3aa2f46

File tree

6 files changed

+63
-1
lines changed

6 files changed

+63
-1
lines changed

readthedocs/api/v2/serializers.py

+2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class VersionAdminSerializer(VersionSerializer):
128128
project = ProjectAdminSerializer()
129129
canonical_url = serializers.SerializerMethodField()
130130
build_data = serializers.JSONField(required=False, write_only=True, allow_null=True)
131+
addons = serializers.BooleanField(required=False, write_only=True, allow_null=False)
131132

132133
def get_canonical_url(self, obj):
133134
return obj.project.get_docs_url(
@@ -138,6 +139,7 @@ def get_canonical_url(self, obj):
138139

139140
class Meta(VersionSerializer.Meta):
140141
fields = VersionSerializer.Meta.fields + [
142+
"addons",
141143
"build_data",
142144
"canonical_url",
143145
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 3.2.19 on 2023-05-23 07:07
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("builds", "0050_build_readthedocs_yaml_path"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="version",
15+
name="addons",
16+
field=models.BooleanField(
17+
blank=True,
18+
default=False,
19+
null=True,
20+
verbose_name="Inject new addons js library for this version",
21+
),
22+
),
23+
]

readthedocs/builds/models.py

+16
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ class Version(TimeStampedModel):
145145
populate_from='verbose_name',
146146
)
147147

148+
# TODO: this field (`supported`) could be removed. It's returned only on
149+
# the footer API response but I don't think anybody is using this field at
150+
# all.
148151
supported = models.BooleanField(_('Supported'), default=True)
152+
149153
active = models.BooleanField(_('Active'), default=False)
150154
state = models.CharField(
151155
_("State"),
@@ -156,7 +160,12 @@ class Version(TimeStampedModel):
156160
help_text=_("State of the PR/MR associated to this version."),
157161
)
158162
built = models.BooleanField(_("Built"), default=False)
163+
164+
# TODO: this field (`uploaded`) could be removed. It was used to mark a
165+
# version as "Manually uploaded" by the core team, but this is not required
166+
# anymore. Users can use `build.commands` for these cases now.
159167
uploaded = models.BooleanField(_("Uploaded"), default=False)
168+
160169
privacy_level = models.CharField(
161170
_('Privacy Level'),
162171
max_length=20,
@@ -192,6 +201,13 @@ class Version(TimeStampedModel):
192201
null=True,
193202
)
194203

204+
addons = models.BooleanField(
205+
_("Inject new addons js library for this version"),
206+
null=True,
207+
blank=True,
208+
default=False,
209+
)
210+
195211
objects = VersionManager.from_queryset(VersionQuerySet)()
196212
# Only include BRANCH, TAG, UNKNOWN type Versions.
197213
internal = InternalVersionManager.from_queryset(partial(VersionQuerySet, internal_only=True))()

readthedocs/doc_builder/director.py

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def __init__(self, data):
5959
"""
6060
self.data = data
6161

62+
# Reset `addons` field. It will be set to `True` only when it's built via `build.commands`
63+
self.data.version.addons = False
64+
6265
def setup_vcs(self):
6366
"""
6467
Perform all VCS related steps.
@@ -422,6 +425,10 @@ def run_build_commands(self):
422425
# Update the `Version.documentation_type` to match the doctype defined
423426
# by the config file. When using `build.commands` it will be `GENERIC`
424427
self.data.version.documentation_type = self.data.config.doctype
428+
429+
# Mark this version to inject the new js client when serving it via El Proxito
430+
self.data.version.addons = True
431+
425432
self.store_readthedocs_build_yaml()
426433

427434
def install_build_tools(self):

readthedocs/projects/tasks/builds.py

+1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@ def on_success(self, retval, task_id, args, kwargs):
600600
"has_epub": "epub" in valid_artifacts,
601601
"has_htmlzip": "htmlzip" in valid_artifacts,
602602
"build_data": self.data.version.build_data,
603+
"addons": self.data.version.addons,
603604
}
604605
)
605606
except HttpClientError:

readthedocs/proxito/middleware.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,24 @@ def process_request(self, request): # noqa
289289
return None
290290

291291
def add_hosting_integrations_headers(self, request, response):
292+
addons = False
292293
project_slug = getattr(request, "path_project_slug", "")
294+
version_slug = getattr(request, "path_version_slug", "")
295+
293296
if project_slug:
294297
project = Project.objects.get(slug=project_slug)
298+
299+
# Check for the feature flag
295300
if project.has_feature(Feature.HOSTING_INTEGRATIONS):
296-
response["X-RTD-Hosting-Integrations"] = "true"
301+
addons = True
302+
303+
# Check if the version forces injecting the addons (e.g. using `build.commands`)
304+
version = project.versions.filter(slug=version_slug).first()
305+
if version and version.addons:
306+
addons = True
307+
308+
if addons:
309+
response["X-RTD-Hosting-Integrations"] = "true"
297310

298311
def _get_https_redirect(self, request):
299312
"""

0 commit comments

Comments
 (0)