Review Board

beta

Show an "Updates Required" page when we require manual updates from the administrator

Updated 9 months, 2 weeks ago

Christian Hammond Reviewers
trunk reviewboard
None Review Board SVN
There are unfortunately times when upgrading Review Board is not as simple as running "svn up." We've so far been unhelpful with this. Now that we're going to require some changes for the media locations and users aren't necessarily going to see the message on the listserv, I felt we should have a nice way of communicating to the user.

This change introduces the ability to add checks on startup. These may include schema changes in the future, but right now they check if the media setup is what we expect. If not, an error page is displayed with helpful information. Once the user fixes the problem and restarts Review Board, the normal URLs will be activated.

This can also be useful for first-time users who currently have very little aid.
Tried this change with a branch using the old media setup and saw that it told me how to fix the problem instead of taking me to any URLs.

Tried it on a branch with the new media setup and Review Board operated as normal.
/trunk/reviewboard/settings.py
Revision 1233 New Change
1
# Django settings for reviewboard project.
1
# Django settings for reviewboard project.
2
2
3
import os
3
import os
4
import sys
4
import sys
5
5
6
6
DEBUG = True
7
DEBUG = True
7
8
8
ADMINS = (
9
ADMINS = (
9
    ('Example Joe', 'admin@example.com')
10
    ('Example Joe', 'admin@example.com')
10
)
11
)
85
    'django.contrib.sessions',
86
    'django.contrib.sessions',
86
    'djblets.datagrid',
87
    'djblets.datagrid',
87
    'djblets.util',
88
    'djblets.util',
88
    'djblets.webapi',
89
    'djblets.webapi',
89
    'reviewboard.accounts',
90
    'reviewboard.accounts',
91
    'reviewboard.admin',
90
    'reviewboard.diffviewer',
92
    'reviewboard.diffviewer',
91
    'reviewboard.iphone',
93
    'reviewboard.iphone',
92
    'reviewboard.reports',
94
    'reviewboard.reports',
93
    'reviewboard.reviews',
95
    'reviewboard.reviews',
94
    'reviewboard.scmtools',
96
    'reviewboard.scmtools',
/trunk/reviewboard/urls.py
Revision 1233 New Change
1
import os.path
1
import os.path
2
2
3
from django.conf import settings
3
from django.conf import settings
4
from django.conf.urls.defaults import patterns, include, handler404, handler500
4
from django.conf.urls.defaults import patterns, include, handler404, handler500
5
5
6
from reviewboard.admin.checks import check_updates_required
6
from reviewboard.reviews.feeds import RssReviewsFeed, AtomReviewsFeed, \
7
from reviewboard.reviews.feeds import RssReviewsFeed, AtomReviewsFeed, \
7
                                      RssSubmitterReviewsFeed, \
8
                                      RssSubmitterReviewsFeed, \
8
                                      AtomSubmitterReviewsFeed, \
9
                                      AtomSubmitterReviewsFeed, \
9
                                      RssGroupReviewsFeed, \
10
                                      RssGroupReviewsFeed, \
10
                                      AtomGroupReviewsFeed
11
                                      AtomGroupReviewsFeed
11
12
12
13
14
# URLs global to all modes
15
urlpatterns = patterns('',
16
    (r'^admin/', include('django.contrib.admin.urls')),
17
)
18
19
# Add static media if running in DEBUG mode
20
if settings.DEBUG:
21
    def htdocs_path(leaf):
22
        return os.path.join(settings.HTDOCS_ROOT, leaf)
23
24
    urlpatterns += patterns('django.views.static',
25
        (r'^css/(?P<path>.*)$', 'serve', {
26
            'show_indexes': True,
27
            'document_root': htdocs_path('css'),
28
            }),
29
        (r'^images/(?P<path>.*)$', 'serve', {
30
            'show_indexes': True,
31
            'document_root': htdocs_path('images'),
32
            }),
33
        (r'^scripts/(?P<path>.*)$', 'serve', {
34
            'show_indexes': True,
35
            'document_root': htdocs_path('scripts')
36
            }),
37
    )
38
39
40
# Check that we're actually able to run. There may have been changes that
41
# require the user to manually update things on the server and restart.
42
if check_updates_required():
43
    # There's updates required. Disable the main URLs for now, since it might
44
    # be useless.
45
46
    urlpatterns += patterns('',
47
        (r'^.*', 'reviewboard.admin.views.manual_updates_required'),
48
    )
49
else:
13
rss_feeds = {
50
    rss_feeds = {
14
    'r': RssReviewsFeed,
51
        'r': RssReviewsFeed,
15
    'users': RssSubmitterReviewsFeed,
52
        'users': RssSubmitterReviewsFeed,
16
    'groups': RssGroupReviewsFeed,
53
        'groups': RssGroupReviewsFeed,
17
}
54
    }
23
    'groups': AtomGroupReviewsFeed,
60
        'groups': AtomGroupReviewsFeed,
24
}
61
    }
25
62
26
63
27
# Main includes
64
    # Main includes
28
urlpatterns = patterns('',
65
    urlpatterns += patterns('',
29
    (r'^admin/', include('django.contrib.admin.urls')),
66
        (r'^admin/', include('django.contrib.admin.urls')),
30
    (r'^api/json/', include('reviewboard.webapi.urls')),
67
        (r'^api/json/', include('reviewboard.webapi.urls')),
31
    (r'^r/', include('reviewboard.reviews.urls')),
68
        (r'^r/', include('reviewboard.reviews.urls')),
32
    (r'^reports/', include('reviewboard.reports.urls')),
69
        (r'^reports/', include('reviewboard.reports.urls')),
33
)
70
    )
60
)
97
    )
61
98
62
99
63
# And the rest ...
100
    # And the rest ...
64
urlpatterns += patterns('',
101
    urlpatterns += patterns('',
65
    (r'^$', 'django.views.generic.simple.redirect_to', {'url': 'dashboard/'}),
102
        (r'^$', 'django.views.generic.simple.redirect_to',
103
         {'url': 'dashboard/'}),
66
104
67
    # Authentication and accounts
105
        # Authentication and accounts
68
    (r'^account/login/$', 'djblets.auth.views.login',
106
        (r'^account/login/$', 'djblets.auth.views.login',
69
     {'next_page': settings.SITE_ROOT + 'dashboard/',
107
         {'next_page': settings.SITE_ROOT + 'dashboard/',
70
      'extra_context': {'BUILTIN_AUTH': settings.BUILTIN_AUTH}}),
108
          'extra_context': {'BUILTIN_AUTH': settings.BUILTIN_AUTH}}),
82
else:
120
    else:
83
    urlpatterns += patterns('',
121
        urlpatterns += patterns('',
84
        (r'^account/register/$',
122
            (r'^account/register/$',
85
         'django.views.generic.simple.redirect_to',
123
             'django.views.generic.simple.redirect_to',
86
         {'url': settings.SITE_ROOT + 'account/login/'}))
124
             {'url': settings.SITE_ROOT + 'account/login/'}))
87
88
89
# Add static media if running in DEBUG mode
90
if settings.DEBUG:
91
    def htdocs_path(leaf):
92
        return os.path.join(settings.HTDOCS_ROOT, leaf)
93
94
    urlpatterns += patterns('django.views.static',
95
        (r'^css/(?P<path>.*)$', 'serve', {
96
            'show_indexes': True,
97
            'document_root': htdocs_path('css'),
98
            }),
99
        (r'^images/(?P<path>.*)$', 'serve', {
100
            'show_indexes': True,
101
            'document_root': htdocs_path('images'),
102
            }),
103
        (r'^scripts/(?P<path>.*)$', 'serve', {
104
            'show_indexes': True,
105
            'document_root': htdocs_path('scripts')
106
            }),
107
    )
/trunk/reviewboard/admin/checks.py
New File
1
import os
2
3
from django.conf import settings
4
5
6
_updates_required = []
7
_install_fine = False
8
9
10
def check_updates_required():
11
    """
12
    Checks if there are manual updates required before Review Board can be
13
    used on this server.
14
    """
15
    global _updates_required
16
    global _install_fine
17
18
    if not _updates_required and not _install_fine:
19
        # Check if there's a media/uploaded/images directory. If not, this is
20
        # either a new install or is using the old-style media setup and needs
21
        # to be manually upgraded.
22
        uploaded_dir = os.path.join(settings.MEDIA_ROOT, "uploaded")
23
24
        if not os.path.isdir(uploaded_dir) or \
25
           not os.path.isdir(os.path.join(uploaded_dir, "images")):
26
            _updates_required.append(
27
                ("admin/manual-updates/media-upload-dir.html", {}))
28
29
        # TODO: Put checks here for schema changes.
30
        _install_fine = not _updates_required
31
32
    return _updates_required
/trunk/reviewboard/admin/views.py
New File
1
from django.shortcuts import render_to_response
2
from django.template.context import RequestContext
3
from django.template.loader import render_to_string
4
5
from reviewboard.admin.checks import check_updates_required
6
7
8
def manual_updates_required(request,
9
                            template_name="admin/manual_updates_required.html"):
10
    updates = check_updates_required()
11
12
    return render_to_response(template_name, RequestContext(request, {
13
        'updates': [render_to_string(template_name,
14
                                     RequestContext(request, extra_context))
15
                    for (template_name, extra_context) in updates],
16
    }))
/trunk/reviewboard/templates/admin/manual_updates_required.html
New File
1
{% extends "base.html" %}
2
{% load djblets_deco %}
3
4
{% block title %}Manual server updates required{% endblock %}
5
6
{% block content %}
7
{% box "important" %}
8
 <h1>Manual server updates required</h1>
9
 <p>
10
  A recent change requires manual updates to be made on this server. After
11
  these changes are made, you should restart your server.
12
 </p>
13
 <p>
14
  To keep track of future updates, please visit the
15
  <a href="http://code.google.com/p/reviewboard/wiki/RequiredServerUpdates">Required
16
  Server Updates</a> page, or subscribe to the
17
  <a href="http://groups.google.com/group/reviewboard">mailing list</a>.
18
 </p>
19
{% endbox %}
20
{% for update in updates %}
21
{% box %}
22
{{update}}
23
{% endbox %}
24
{% endfor %}
25
26
{% endblock %}
/trunk/reviewboard/templates/admin/manual-updates/media-upload-dir.html
New File
1
<h1 class="title">Media directory changes</h1>
2
<div class="main">
3
 <p>
4
  Your Review Board installation does not have a {{settings.MEDIA_ROOT}}/uploaded/images directory.
5
 </p>
6
 <h3>If this is a new installation...</h3>
7
 <p>
8
  Create both <tt>{{settings.MEDIA_ROOT}}/uploaded</tt> and
9
  <tt>{{settings.MEDIA_ROOT}}/uploaded/images</tt> on the server and make both directories writable by the web
10
  server. You can do so with the following commands:
11
 </p>
12
 <pre>
13
  $ cd {{settings.MEDIA_ROOT}}
14
  $ mkdir -p uploaded/images
15
  $ sudo chown -R www-data.www-data uploaded
16
 </pre>
17
 <h3>If this is an existing installation...</h3>
18
 <p>
19
  A recent update has changed the media setup on the server. This may require manual updates to
20
  the web server configuration. Please see the "Media Changes" section on the
21
  <a href="http://code.google.com/p/reviewboard/wiki/RequiredServerUpdates">Required Server
22
  Updates</a> page for instructions on fixing your setup.
23
 </p>
24
</div>
  1. /trunk/reviewboard/settings.py: 2 changes [ 1 2 ]
  2. /trunk/reviewboard/urls.py: 6 changes [ 1 2 3 4 5 6 ]
  3. /trunk/reviewboard/admin/checks.py: 1 change [ new content ]
  4. /trunk/reviewboard/admin/views.py: 1 change [ new content ]
  5. /trunk/reviewboard/templates/admin/manual_updates_required.html: 1 change [ new content ]
  6. /trunk/reviewboard/templates/admin/manual-updates/media-upload-dir.html: 1 change [ new content ]