Skip to content

Commit

Permalink
Builds: move send_build_status to builds/tasks.py
Browse files Browse the repository at this point in the history
Mostly to avoid a circular import in #7548 (comment)

Also, make projects/tasks.py more project related and small :D
  • Loading branch information
stsewd committed Dec 16, 2020
1 parent 44b2d7d commit db55dbd
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 107 deletions.
101 changes: 100 additions & 1 deletion readthedocs/builds/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
)
from readthedocs.builds.models import Build, Version
from readthedocs.builds.utils import memcache_lock
from readthedocs.projects.tasks import send_build_status
from readthedocs.oauth.models import RemoteRepository
from readthedocs.oauth.notifications import GitBuildStatusFailureNotification
from readthedocs.projects.constants import GITHUB_BRAND, GITLAB_BRAND
from readthedocs.worker import app

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -206,3 +208,100 @@ def delete_inactive_external_versions(limit=200, days=30 * 3):
version.project.slug, version.slug,
)
version.delete()


@app.task(queue='web')
def send_build_status(build_pk, commit, status, link_to_build=False):
"""
Send Build Status to Git Status API for project external versions.
It tries using these services' account in order:
1. user's account that imported the project
2. each user's account from the project's maintainers
:param build_pk: Build primary key
:param commit: commit sha of the pull/merge request
:param status: build status failed, pending, or success to be sent.
"""
# TODO: Send build status for BitBucket.
service = None
success = None
build = Build.objects.get(pk=build_pk)
provider_name = build.project.git_provider_name

log.info('Sending build status. build=%s, project=%s', build.pk, build.project.slug)

if provider_name in [GITHUB_BRAND, GITLAB_BRAND]:
# get the service class for the project e.g: GitHubService.
service_class = build.project.git_service_class()

# First, try using user who imported the project's account
try:
service = service_class(
build.project.remote_repository.users.first(),
build.project.remote_repository.account
)

except RemoteRepository.DoesNotExist:
log.warning(
'Project does not have a RemoteRepository. project=%s',
build.project.slug,
)

if service is not None:
# Send status report using the API.
success = service.send_build_status(
build=build,
commit=commit,
state=status,
link_to_build=link_to_build,
)

if success:
log.info(
'Build status report sent correctly. project=%s build=%s status=%s commit=%s',
build.project.slug,
build.pk,
status,
commit,
)
return True

# Try using any of the users' maintainer accounts
# Try to loop through all project users to get their social accounts
users = build.project.users.all()
for user in users:
user_accounts = service_class.for_user(user)
# Try to loop through users all social accounts to send a successful request
for account in user_accounts:
if account.provider_name == provider_name:
success = account.send_build_status(build, commit, status)
if success:
log.info(
'Build status report sent correctly using an user account. '
'project=%s build=%s status=%s commit=%s user=%s',
build.project.slug,
build.pk,
status,
commit,
user.username,
)
return True

for user in users:
# Send Site notification about Build status reporting failure
# to all the users of the project.
notification = GitBuildStatusFailureNotification(
context_object=build.project,
extra_context={'provider_name': provider_name},
user=user,
success=False,
)
notification.send()

log.info(
'No social account or repository permission available for %s',
build.project.slug
)
return False
101 changes: 1 addition & 100 deletions readthedocs/projects/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
)
from readthedocs.builds.models import APIVersion, Build, Version
from readthedocs.builds.signals import build_complete
from readthedocs.builds.tasks import send_build_status
from readthedocs.config import ConfigError
from readthedocs.core.resolver import resolve_path
from readthedocs.core.utils import send_email
Expand All @@ -67,9 +68,6 @@
)
from readthedocs.doc_builder.loader import get_builder_class
from readthedocs.doc_builder.python_environments import Conda, Virtualenv
from readthedocs.oauth.models import RemoteRepository
from readthedocs.oauth.notifications import GitBuildStatusFailureNotification
from readthedocs.projects.constants import GITHUB_BRAND, GITLAB_BRAND
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
Expand Down Expand Up @@ -1891,103 +1889,6 @@ def retry_domain_verification(domain_pk):
)


@app.task(queue='web')
def send_build_status(build_pk, commit, status, link_to_build=False):
"""
Send Build Status to Git Status API for project external versions.
It tries using these services' account in order:
1. user's account that imported the project
2. each user's account from the project's maintainers
:param build_pk: Build primary key
:param commit: commit sha of the pull/merge request
:param status: build status failed, pending, or success to be sent.
"""
# TODO: Send build status for BitBucket.
service = None
success = None
build = Build.objects.get(pk=build_pk)
provider_name = build.project.git_provider_name

log.info('Sending build status. build=%s, project=%s', build.pk, build.project.slug)

if provider_name in [GITHUB_BRAND, GITLAB_BRAND]:
# get the service class for the project e.g: GitHubService.
service_class = build.project.git_service_class()

# First, try using user who imported the project's account
try:
service = service_class(
build.project.remote_repository.users.first(),
build.project.remote_repository.account
)

except RemoteRepository.DoesNotExist:
log.warning(
'Project does not have a RemoteRepository. project=%s',
build.project.slug,
)

if service is not None:
# Send status report using the API.
success = service.send_build_status(
build=build,
commit=commit,
state=status,
link_to_build=link_to_build,
)

if success:
log.info(
'Build status report sent correctly. project=%s build=%s status=%s commit=%s',
build.project.slug,
build.pk,
status,
commit,
)
return True

# Try using any of the users' maintainer accounts
# Try to loop through all project users to get their social accounts
users = build.project.users.all()
for user in users:
user_accounts = service_class.for_user(user)
# Try to loop through users all social accounts to send a successful request
for account in user_accounts:
if account.provider_name == provider_name:
success = account.send_build_status(build, commit, status)
if success:
log.info(
'Build status report sent correctly using an user account. '
'project=%s build=%s status=%s commit=%s user=%s',
build.project.slug,
build.pk,
status,
commit,
user.username,
)
return True

for user in users:
# Send Site notification about Build status reporting failure
# to all the users of the project.
notification = GitBuildStatusFailureNotification(
context_object=build.project,
extra_context={'provider_name': provider_name},
user=user,
success=False,
)
notification.send()

log.info(
'No social account or repository permission available for %s',
build.project.slug
)
return False


def send_external_build_status(version_type, build_pk, commit, status):
"""
Check if build is external and Send Build Status for project external versions.
Expand Down
13 changes: 7 additions & 6 deletions readthedocs/rtd_tests/tests/test_celery.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from readthedocs.doc_builder.exceptions import VersionLockedError
from readthedocs.oauth.models import RemoteRepository
from readthedocs.projects import tasks
from readthedocs.builds import tasks as build_tasks
from readthedocs.projects.exceptions import RepositoryError
from readthedocs.projects.models import Project
from readthedocs.rtd_tests.mocks.mock_api import mock_api
Expand Down Expand Up @@ -352,7 +353,7 @@ def test_send_build_status_with_remote_repo_github(self, send_build_status):
external_build = get(
Build, project=self.project, version=external_version
)
tasks.send_build_status(
build_tasks.send_build_status(
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
)

Expand All @@ -375,7 +376,7 @@ def test_send_build_status_with_social_account_github(self, send_build_status):
external_build = get(
Build, project=self.project, version=external_version
)
tasks.send_build_status(
build_tasks.send_build_status(
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
)

Expand All @@ -392,7 +393,7 @@ def test_send_build_status_no_remote_repo_or_social_account_github(self, send_bu
external_build = get(
Build, project=self.project, version=external_version
)
tasks.send_build_status(
build_tasks.send_build_status(
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
)

Expand All @@ -412,7 +413,7 @@ def test_send_build_status_with_remote_repo_gitlab(self, send_build_status):
external_build = get(
Build, project=self.project, version=external_version
)
tasks.send_build_status(
build_tasks.send_build_status(
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
)

Expand All @@ -435,7 +436,7 @@ def test_send_build_status_with_social_account_gitlab(self, send_build_status):
external_build = get(
Build, project=self.project, version=external_version
)
tasks.send_build_status(
build_tasks.send_build_status(
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
)

Expand All @@ -452,7 +453,7 @@ def test_send_build_status_no_remote_repo_or_social_account_gitlab(self, send_bu
external_build = get(
Build, project=self.project, version=external_version
)
tasks.send_build_status(
build_tasks.send_build_status(
external_build.id, external_build.commit, BUILD_STATUS_SUCCESS
)

Expand Down

0 comments on commit db55dbd

Please sign in to comment.