Skip to content

Commit db55dbd

Browse files
committed
Builds: move send_build_status to builds/tasks.py
Mostly to avoid a circular import in #7548 (comment) Also, make projects/tasks.py more project related and small :D
1 parent 44b2d7d commit db55dbd

File tree

3 files changed

+108
-107
lines changed

3 files changed

+108
-107
lines changed

readthedocs/builds/tasks.py

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
)
1717
from readthedocs.builds.models import Build, Version
1818
from readthedocs.builds.utils import memcache_lock
19-
from readthedocs.projects.tasks import send_build_status
19+
from readthedocs.oauth.models import RemoteRepository
20+
from readthedocs.oauth.notifications import GitBuildStatusFailureNotification
21+
from readthedocs.projects.constants import GITHUB_BRAND, GITLAB_BRAND
2022
from readthedocs.worker import app
2123

2224
log = logging.getLogger(__name__)
@@ -206,3 +208,100 @@ def delete_inactive_external_versions(limit=200, days=30 * 3):
206208
version.project.slug, version.slug,
207209
)
208210
version.delete()
211+
212+
213+
@app.task(queue='web')
214+
def send_build_status(build_pk, commit, status, link_to_build=False):
215+
"""
216+
Send Build Status to Git Status API for project external versions.
217+
218+
It tries using these services' account in order:
219+
220+
1. user's account that imported the project
221+
2. each user's account from the project's maintainers
222+
223+
:param build_pk: Build primary key
224+
:param commit: commit sha of the pull/merge request
225+
:param status: build status failed, pending, or success to be sent.
226+
"""
227+
# TODO: Send build status for BitBucket.
228+
service = None
229+
success = None
230+
build = Build.objects.get(pk=build_pk)
231+
provider_name = build.project.git_provider_name
232+
233+
log.info('Sending build status. build=%s, project=%s', build.pk, build.project.slug)
234+
235+
if provider_name in [GITHUB_BRAND, GITLAB_BRAND]:
236+
# get the service class for the project e.g: GitHubService.
237+
service_class = build.project.git_service_class()
238+
239+
# First, try using user who imported the project's account
240+
try:
241+
service = service_class(
242+
build.project.remote_repository.users.first(),
243+
build.project.remote_repository.account
244+
)
245+
246+
except RemoteRepository.DoesNotExist:
247+
log.warning(
248+
'Project does not have a RemoteRepository. project=%s',
249+
build.project.slug,
250+
)
251+
252+
if service is not None:
253+
# Send status report using the API.
254+
success = service.send_build_status(
255+
build=build,
256+
commit=commit,
257+
state=status,
258+
link_to_build=link_to_build,
259+
)
260+
261+
if success:
262+
log.info(
263+
'Build status report sent correctly. project=%s build=%s status=%s commit=%s',
264+
build.project.slug,
265+
build.pk,
266+
status,
267+
commit,
268+
)
269+
return True
270+
271+
# Try using any of the users' maintainer accounts
272+
# Try to loop through all project users to get their social accounts
273+
users = build.project.users.all()
274+
for user in users:
275+
user_accounts = service_class.for_user(user)
276+
# Try to loop through users all social accounts to send a successful request
277+
for account in user_accounts:
278+
if account.provider_name == provider_name:
279+
success = account.send_build_status(build, commit, status)
280+
if success:
281+
log.info(
282+
'Build status report sent correctly using an user account. '
283+
'project=%s build=%s status=%s commit=%s user=%s',
284+
build.project.slug,
285+
build.pk,
286+
status,
287+
commit,
288+
user.username,
289+
)
290+
return True
291+
292+
for user in users:
293+
# Send Site notification about Build status reporting failure
294+
# to all the users of the project.
295+
notification = GitBuildStatusFailureNotification(
296+
context_object=build.project,
297+
extra_context={'provider_name': provider_name},
298+
user=user,
299+
success=False,
300+
)
301+
notification.send()
302+
303+
log.info(
304+
'No social account or repository permission available for %s',
305+
build.project.slug
306+
)
307+
return False

readthedocs/projects/tasks.py

Lines changed: 1 addition & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
)
4646
from readthedocs.builds.models import APIVersion, Build, Version
4747
from readthedocs.builds.signals import build_complete
48+
from readthedocs.builds.tasks import send_build_status
4849
from readthedocs.config import ConfigError
4950
from readthedocs.core.resolver import resolve_path
5051
from readthedocs.core.utils import send_email
@@ -67,9 +68,6 @@
6768
)
6869
from readthedocs.doc_builder.loader import get_builder_class
6970
from readthedocs.doc_builder.python_environments import Conda, Virtualenv
70-
from readthedocs.oauth.models import RemoteRepository
71-
from readthedocs.oauth.notifications import GitBuildStatusFailureNotification
72-
from readthedocs.projects.constants import GITHUB_BRAND, GITLAB_BRAND
7371
from readthedocs.projects.models import APIProject, Feature
7472
from readthedocs.search.utils import index_new_files, remove_indexed_files
7573
from readthedocs.sphinx_domains.models import SphinxDomain
@@ -1891,103 +1889,6 @@ def retry_domain_verification(domain_pk):
18911889
)
18921890

18931891

1894-
@app.task(queue='web')
1895-
def send_build_status(build_pk, commit, status, link_to_build=False):
1896-
"""
1897-
Send Build Status to Git Status API for project external versions.
1898-
1899-
It tries using these services' account in order:
1900-
1901-
1. user's account that imported the project
1902-
2. each user's account from the project's maintainers
1903-
1904-
:param build_pk: Build primary key
1905-
:param commit: commit sha of the pull/merge request
1906-
:param status: build status failed, pending, or success to be sent.
1907-
"""
1908-
# TODO: Send build status for BitBucket.
1909-
service = None
1910-
success = None
1911-
build = Build.objects.get(pk=build_pk)
1912-
provider_name = build.project.git_provider_name
1913-
1914-
log.info('Sending build status. build=%s, project=%s', build.pk, build.project.slug)
1915-
1916-
if provider_name in [GITHUB_BRAND, GITLAB_BRAND]:
1917-
# get the service class for the project e.g: GitHubService.
1918-
service_class = build.project.git_service_class()
1919-
1920-
# First, try using user who imported the project's account
1921-
try:
1922-
service = service_class(
1923-
build.project.remote_repository.users.first(),
1924-
build.project.remote_repository.account
1925-
)
1926-
1927-
except RemoteRepository.DoesNotExist:
1928-
log.warning(
1929-
'Project does not have a RemoteRepository. project=%s',
1930-
build.project.slug,
1931-
)
1932-
1933-
if service is not None:
1934-
# Send status report using the API.
1935-
success = service.send_build_status(
1936-
build=build,
1937-
commit=commit,
1938-
state=status,
1939-
link_to_build=link_to_build,
1940-
)
1941-
1942-
if success:
1943-
log.info(
1944-
'Build status report sent correctly. project=%s build=%s status=%s commit=%s',
1945-
build.project.slug,
1946-
build.pk,
1947-
status,
1948-
commit,
1949-
)
1950-
return True
1951-
1952-
# Try using any of the users' maintainer accounts
1953-
# Try to loop through all project users to get their social accounts
1954-
users = build.project.users.all()
1955-
for user in users:
1956-
user_accounts = service_class.for_user(user)
1957-
# Try to loop through users all social accounts to send a successful request
1958-
for account in user_accounts:
1959-
if account.provider_name == provider_name:
1960-
success = account.send_build_status(build, commit, status)
1961-
if success:
1962-
log.info(
1963-
'Build status report sent correctly using an user account. '
1964-
'project=%s build=%s status=%s commit=%s user=%s',
1965-
build.project.slug,
1966-
build.pk,
1967-
status,
1968-
commit,
1969-
user.username,
1970-
)
1971-
return True
1972-
1973-
for user in users:
1974-
# Send Site notification about Build status reporting failure
1975-
# to all the users of the project.
1976-
notification = GitBuildStatusFailureNotification(
1977-
context_object=build.project,
1978-
extra_context={'provider_name': provider_name},
1979-
user=user,
1980-
success=False,
1981-
)
1982-
notification.send()
1983-
1984-
log.info(
1985-
'No social account or repository permission available for %s',
1986-
build.project.slug
1987-
)
1988-
return False
1989-
1990-
19911892
def send_external_build_status(version_type, build_pk, commit, status):
19921893
"""
19931894
Check if build is external and Send Build Status for project external versions.

readthedocs/rtd_tests/tests/test_celery.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from readthedocs.doc_builder.exceptions import VersionLockedError
2222
from readthedocs.oauth.models import RemoteRepository
2323
from readthedocs.projects import tasks
24+
from readthedocs.builds import tasks as build_tasks
2425
from readthedocs.projects.exceptions import RepositoryError
2526
from readthedocs.projects.models import Project
2627
from readthedocs.rtd_tests.mocks.mock_api import mock_api
@@ -352,7 +353,7 @@ def test_send_build_status_with_remote_repo_github(self, send_build_status):
352353
external_build = get(
353354
Build, project=self.project, version=external_version
354355
)
355-
tasks.send_build_status(
356+
build_tasks.send_build_status(
356357
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
357358
)
358359

@@ -375,7 +376,7 @@ def test_send_build_status_with_social_account_github(self, send_build_status):
375376
external_build = get(
376377
Build, project=self.project, version=external_version
377378
)
378-
tasks.send_build_status(
379+
build_tasks.send_build_status(
379380
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
380381
)
381382

@@ -392,7 +393,7 @@ def test_send_build_status_no_remote_repo_or_social_account_github(self, send_bu
392393
external_build = get(
393394
Build, project=self.project, version=external_version
394395
)
395-
tasks.send_build_status(
396+
build_tasks.send_build_status(
396397
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
397398
)
398399

@@ -412,7 +413,7 @@ def test_send_build_status_with_remote_repo_gitlab(self, send_build_status):
412413
external_build = get(
413414
Build, project=self.project, version=external_version
414415
)
415-
tasks.send_build_status(
416+
build_tasks.send_build_status(
416417
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
417418
)
418419

@@ -435,7 +436,7 @@ def test_send_build_status_with_social_account_gitlab(self, send_build_status):
435436
external_build = get(
436437
Build, project=self.project, version=external_version
437438
)
438-
tasks.send_build_status(
439+
build_tasks.send_build_status(
439440
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
440441
)
441442

@@ -452,7 +453,7 @@ def test_send_build_status_no_remote_repo_or_social_account_gitlab(self, send_bu
452453
external_build = get(
453454
Build, project=self.project, version=external_version
454455
)
455-
tasks.send_build_status(
456+
build_tasks.send_build_status(
456457
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
457458
)
458459

0 commit comments

Comments
 (0)