Add admin actions for building versions

This gets around not having admin access to build a project, and makes
rebuilding an arbitrary version a site admin feature.
ghowardsit
Anthony Johnson 2019-02-07 17:53:23 -07:00
parent 9ecd70c716
commit d6a69c2702
No known key found for this signature in database
GPG Key ID: 709FE91423F05AA0
2 changed files with 54 additions and 11 deletions

View File

@ -2,10 +2,11 @@
"""Django admin interface for `~builds.models.Build` and related models.""" """Django admin interface for `~builds.models.Build` and related models."""
from django.contrib import admin from django.contrib import admin, messages
from guardian.admin import GuardedModelAdmin from guardian.admin import GuardedModelAdmin
from readthedocs.builds.models import Build, BuildCommandResult, Version from readthedocs.builds.models import Build, BuildCommandResult, Version
from readthedocs.core.utils import trigger_build
class BuildCommandResultInline(admin.TabularInline): class BuildCommandResultInline(admin.TabularInline):
@ -54,7 +55,26 @@ class VersionAdmin(GuardedModelAdmin):
'built', 'built',
) )
list_filter = ('type', 'privacy_level', 'active', 'built') list_filter = ('type', 'privacy_level', 'active', 'built')
search_fields = ('slug', 'project__slug')
raw_id_fields = ('project',) raw_id_fields = ('project',)
actions = ['build_version']
def build_version(self, request, queryset):
"""Trigger a build for the project version."""
total = 0
for version in queryset:
trigger_build(
project=version.project,
version=version,
)
total += 1
messages.add_message(
request,
messages.INFO,
'Triggered builds for {} version(s).'.format(total),
)
build_version.short_description = 'Build version'
admin.site.register(Build, BuildAdmin) admin.site.register(Build, BuildAdmin)

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Django administration interface for `projects.models`""" """Django administration interface for `projects.models`."""
from django.contrib import admin, messages from django.contrib import admin, messages
from django.contrib.admin.actions import delete_selected from django.contrib.admin.actions import delete_selected
@ -9,7 +9,7 @@ from guardian.admin import GuardedModelAdmin
from readthedocs.builds.models import Version from readthedocs.builds.models import Version
from readthedocs.core.models import UserProfile from readthedocs.core.models import UserProfile
from readthedocs.core.utils import broadcast from readthedocs.core.utils import broadcast, trigger_build
from readthedocs.notifications.views import SendNotificationView from readthedocs.notifications.views import SendNotificationView
from readthedocs.redirects.models import Redirect from readthedocs.redirects.models import Redirect
@ -47,7 +47,7 @@ class ProjectSendNotificationView(SendNotificationView):
class ProjectRelationshipInline(admin.TabularInline): class ProjectRelationshipInline(admin.TabularInline):
"""Project inline relationship view for :py:class:`ProjectAdmin`""" """Project inline relationship view for :py:class:`ProjectAdmin`."""
model = ProjectRelationship model = ProjectRelationship
fk_name = 'parent' fk_name = 'parent'
@ -56,14 +56,14 @@ class ProjectRelationshipInline(admin.TabularInline):
class VersionInline(admin.TabularInline): class VersionInline(admin.TabularInline):
"""Version inline relationship view for :py:class:`ProjectAdmin`""" """Version inline relationship view for :py:class:`ProjectAdmin`."""
model = Version model = Version
class RedirectInline(admin.TabularInline): class RedirectInline(admin.TabularInline):
"""Redirect inline relationship view for :py:class:`ProjectAdmin`""" """Redirect inline relationship view for :py:class:`ProjectAdmin`."""
model = Redirect model = Redirect
@ -77,7 +77,15 @@ class DomainInline(admin.TabularInline):
# class ImpressionInline(admin.TabularInline): # class ImpressionInline(admin.TabularInline):
# from readthedocs.donate.models import ProjectImpressions # from readthedocs.donate.models import ProjectImpressions
# model = ProjectImpressions # model = ProjectImpressions
# readonly_fields = ('date', 'promo', 'offers', 'views', 'clicks', 'view_ratio', 'click_ratio') # readonly_fields = (
# 'date',
# 'promo',
# 'offers',
# 'views',
# 'clicks',
# 'view_ratio',
# 'click_ratio',
# )
# extra = 0 # extra = 0
# can_delete = False # can_delete = False
# max_num = 15 # max_num = 15
@ -137,7 +145,7 @@ class ProjectAdmin(GuardedModelAdmin):
] ]
readonly_fields = ('feature_flags',) readonly_fields = ('feature_flags',)
raw_id_fields = ('users', 'main_language_project') raw_id_fields = ('users', 'main_language_project')
actions = ['send_owner_email', 'ban_owner'] actions = ['send_owner_email', 'ban_owner', 'build_default_version']
def feature_flags(self, obj): def feature_flags(self, obj):
return ', '.join([str(f.get_feature_display()) for f in obj.features]) return ', '.join([str(f.get_feature_display()) for f in obj.features])
@ -162,8 +170,9 @@ class ProjectAdmin(GuardedModelAdmin):
for project in queryset: for project in queryset:
if project.users.count() == 1: if project.users.count() == 1:
count = ( count = (
UserProfile.objects.filter(user__projects=project UserProfile.objects.filter(
).update(banned=True) user__projects=project,
).update(banned=True)
) # yapf: disabled ) # yapf: disabled
total += count total += count
else: else:
@ -199,6 +208,20 @@ class ProjectAdmin(GuardedModelAdmin):
) )
return delete_selected(self, request, queryset) return delete_selected(self, request, queryset)
def build_default_version(self, request, queryset):
"""Trigger a build for the project version."""
total = 0
for project in queryset:
trigger_build(project=project)
total += 1
messages.add_message(
request,
messages.INFO,
'Triggered builds for {} project(s).'.format(total),
)
build_default_version.short_description = 'Build default version'
def get_actions(self, request): def get_actions(self, request):
actions = super().get_actions(request) actions = super().get_actions(request)
actions['delete_selected'] = ( actions['delete_selected'] = (
@ -211,7 +234,7 @@ class ProjectAdmin(GuardedModelAdmin):
class ImportedFileAdmin(admin.ModelAdmin): class ImportedFileAdmin(admin.ModelAdmin):
"""Admin view for :py:class:`ImportedFile`""" """Admin view for :py:class:`ImportedFile`."""
raw_id_fields = ('project', 'version') raw_id_fields = ('project', 'version')
list_display = ('path', 'name', 'version') list_display = ('path', 'name', 'version')