Skip to content

Builds: restart build commands before a new build #7999

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 18, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions readthedocs/api/v2/views/model_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,25 @@ def retrieve(self, *args, **kwargs):
)
return Response(data)

@decorators.action(
detail=True,
permission_classes=[permissions.IsAdminUser],
methods=['post'],
)
def restart(self, request, **kwargs):
"""
Restart the build so it can be re-used when re-trying.

Dates and states are usually overriden by the build,
we care more about deleting the commands.
"""
instance = self.get_object()
instance.output = ''
instance.cold_storage = False
instance.commands.all().delete()
instance.save()
return Response(status=status.HTTP_204_NO_CONTENT)


class BuildCommandViewSet(UserSelectViewSet):
parser_classes = [JSONParser, MultiPartParser]
Expand Down
4 changes: 3 additions & 1 deletion readthedocs/projects/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
from readthedocs.projects.models import APIProject, Feature
from readthedocs.search.utils import index_new_files, remove_indexed_files
from readthedocs.sphinx_domains.models import SphinxDomain
from readthedocs.storage import build_media_storage, build_environment_storage
from readthedocs.storage import build_environment_storage, build_media_storage
from readthedocs.vcs_support import utils as vcs_support_utils
from readthedocs.worker import app

Expand Down Expand Up @@ -670,6 +670,8 @@ def run_setup(self, record=True):

Return True if successful.
"""
api_v2.build(self.build['id']).restart.post()

if settings.DOCKER_ENABLE:
env_cls = DockerBuildEnvironment
else:
Expand Down
26 changes: 26 additions & 0 deletions readthedocs/rtd_tests/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
class APIBuildTests(TestCase):
fixtures = ['eric.json', 'test_data.json']

def setUp(self):
self.user = User.objects.get(username='eric')
self.project = get(Project, users=[self.user])
self.version = self.project.versions.get(slug=LATEST)

def test_make_build(self):
"""Test that a superuser can use the API."""
client = APIClient()
Expand Down Expand Up @@ -82,6 +87,27 @@ def test_make_build(self):
self.assertEqual(build['output'], 'Test Output')
self.assertEqual(build['state_display'], 'Cloning')

def test_restart_build(self):
build = get(
Build,
project=self.project,
version=self.version,
)
command = get(
BuildCommandResult,
build=build,
)
build.commands.add(command)

self.assertEqual(build.commands.count(), 1)

client = APIClient()
client.force_login(self.user)
r = client.post(reverse('build-restart', args=(build.pk,)))
self.assertEqual(r.status_code, 204)
self.assertEqual(build.commands.count(), 0)


def test_api_does_not_have_private_config_key_superuser(self):
client = APIClient()
client.login(username='super', password='test')
Expand Down
12 changes: 5 additions & 7 deletions readthedocs/rtd_tests/tests/test_builds.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
# -*- coding: utf-8 -*-
import datetime
import os

from unittest import mock

from allauth.socialaccount.models import SocialAccount
from django.contrib.auth.models import User
from django.test import TestCase
from django_dynamic_fixture import fixture, get
from django.utils import timezone

from allauth.socialaccount.models import SocialAccount
from django_dynamic_fixture import fixture, get

from readthedocs.builds.constants import (
BRANCH,
EXTERNAL,
GENERIC_EXTERNAL_VERSION_NAME,
GITHUB_EXTERNAL_VERSION_NAME,
GITLAB_EXTERNAL_VERSION_NAME,
GENERIC_EXTERNAL_VERSION_NAME
)
from readthedocs.builds.models import Build, Version
from readthedocs.core.utils import trigger_build
Expand Down Expand Up @@ -325,7 +323,7 @@ def test_save_config_in_build_model(self, load_config, api_v2):
task.run_setup()
build_config = task.build['config']
# For patch
api_v2.build.assert_called_once()
api_v2.build().patch.assert_called_once()
assert build_config['version'] == '1'
assert 'sphinx' in build_config
assert build_config['doctype'] == 'sphinx'
Expand Down
1 change: 1 addition & 0 deletions readthedocs/rtd_tests/tests/test_privacy_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ def setUp(self):
}
self.response_data = {
'build-concurrent': {'status_code': 403},
'build-restart': {'status_code': 403},
'project-sync-versions': {'status_code': 403},
'project-token': {'status_code': 403},
'emailhook-list': {'status_code': 403},
Expand Down