Skip to content

Commit 151582f

Browse files
authored
Add project: use an instance variable to avoid 500 (#11795)
Closes readthedocs/ext-theme#477
1 parent 8774e68 commit 151582f

File tree

1 file changed

+76
-56
lines changed

1 file changed

+76
-56
lines changed

readthedocs/projects/views/private.py

+76-56
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Project views for authenticated users."""
22

3+
34
import structlog
45
from allauth.socialaccount.models import SocialAccount
56
from django.conf import settings
@@ -314,6 +315,79 @@ def post(self, request, *args, **kwargs):
314315
return HttpResponseRedirect(self.get_success_url())
315316

316317

318+
def show_config_step(wizard):
319+
"""
320+
Decide whether or not show the config step on "Add project" wizard.
321+
322+
If the `.readthedocs.yaml` file already exist in the default branch, we
323+
don't show this step.
324+
"""
325+
326+
# try to get the cleaned data of step 1
327+
cleaned_data = wizard.get_cleaned_data_for_step("basics") or {}
328+
repo = cleaned_data.get("repo")
329+
remote_repository = cleaned_data.get("remote_repository")
330+
default_branch = cleaned_data.get("default_branch")
331+
332+
if (
333+
repo
334+
and default_branch
335+
and remote_repository
336+
and remote_repository.vcs_provider == GITHUB
337+
):
338+
# I don't know why `show_config_step` is called multiple times (at least 4).
339+
# This is a problem for us because we perform external calls here and add messages to the request.
340+
# Due to that, we are adding this instance variable to prevent this function to run multiple times.
341+
# Maybe related to https://github.com/jazzband/django-formtools/issues/134
342+
if hasattr(wizard, "_show_config_step_executed"):
343+
return False
344+
345+
remote_repository_relations = (
346+
remote_repository.remote_repository_relations.filter(
347+
user=wizard.request.user,
348+
account__isnull=False,
349+
)
350+
.select_related("account", "user")
351+
.only("user", "account")
352+
)
353+
for relation in remote_repository_relations:
354+
service = GitHubService(relation.user, relation.account)
355+
session = service.get_session()
356+
357+
for yaml in [
358+
".readthedocs.yaml",
359+
".readthedocs.yml",
360+
"readthedocs.yaml",
361+
"readthedocs.yml",
362+
]:
363+
try:
364+
querystrings = f"?ref={default_branch}" if default_branch else ""
365+
response = session.head(
366+
f"https://api.github.com/repos/{remote_repository.full_name}/contents/{yaml}{querystrings}",
367+
timeout=1,
368+
)
369+
if response.ok:
370+
log.info(
371+
"Read the Docs YAML file found for this repository.",
372+
filename=yaml,
373+
)
374+
messages.success(
375+
wizard.request,
376+
_(
377+
"We detected a configuration file in your repository and started your project's first build."
378+
),
379+
)
380+
wizard._show_config_step_executed = True
381+
return False
382+
except Exception:
383+
log.warning(
384+
"Failed when hitting GitHub API to check for .readthedocs.yaml file.",
385+
filename=yaml,
386+
)
387+
continue
388+
return True
389+
390+
317391
class ImportWizardView(ProjectImportMixin, PrivateViewMixin, SessionWizardView):
318392

319393
"""
@@ -323,13 +397,13 @@ class ImportWizardView(ProjectImportMixin, PrivateViewMixin, SessionWizardView):
323397
per session (since it's per class).
324398
"""
325399

400+
initial_dict_key = "initial-data"
401+
condition_dict = {"config": show_config_step}
326402
form_list = [
327403
("basics", ProjectBasicsForm),
328404
("config", ProjectConfigForm),
329405
]
330406

331-
initial_dict_key = "initial-data"
332-
333407
def get(self, *args, **kwargs):
334408
# The method from the parent should run first,
335409
# as the storage is initialized there.
@@ -366,60 +440,6 @@ def get_template_names(self):
366440
"""Return template names based on step name."""
367441
return f"projects/import_{self.steps.current}.html"
368442

369-
def process_step(self, form):
370-
# pylint: disable=too-many-nested-blocks
371-
if isinstance(form, ProjectBasicsForm):
372-
remote_repository = form.cleaned_data.get("remote_repository")
373-
default_branch = form.cleaned_data.get("default_branch")
374-
if remote_repository and remote_repository.vcs_provider == GITHUB:
375-
remote_repository_relations = (
376-
remote_repository.remote_repository_relations.filter(
377-
user=self.request.user,
378-
account__isnull=False,
379-
)
380-
.select_related("account", "user")
381-
.only("user", "account")
382-
)
383-
for relation in remote_repository_relations:
384-
service = GitHubService(relation.user, relation.account)
385-
session = service.get_session()
386-
387-
for yaml in [
388-
".readthedocs.yaml",
389-
".readthedocs.yml",
390-
"readthedocs.yaml",
391-
"readthedocs.yml",
392-
]:
393-
try:
394-
querystrings = (
395-
f"?ref={default_branch}" if default_branch else ""
396-
)
397-
response = session.head(
398-
f"https://api.github.com/repos/{remote_repository.full_name}/contents/{yaml}{querystrings}",
399-
timeout=1,
400-
)
401-
if response.ok:
402-
log.info(
403-
"Read the Docs YAML file found for this repository.",
404-
filename=yaml,
405-
)
406-
messages.success(
407-
self.request,
408-
_(
409-
"We detected a configuration file in your repository and started your project's first build."
410-
),
411-
)
412-
self.form_list.pop("config")
413-
break
414-
except Exception:
415-
log.warning(
416-
"Failed when hitting GitHub API to check for .readthedocs.yaml file.",
417-
filename=yaml,
418-
)
419-
continue
420-
421-
return super().process_step(form)
422-
423443
def done(self, form_list, **kwargs):
424444
"""
425445
Save form data as object instance.

0 commit comments

Comments
 (0)