diff --git a/docs/manual/admin/admin-ui/buildbot-settings.txt b/docs/manual/admin/admin-ui/buildbot-settings.txt
--- /dev/null
+++ b/docs/manual/admin/admin-ui/buildbot-settings.txt
@@ -0,0 +1,58 @@
+.. _buildbot-settings:
+
+=================
+Buildbot Settings
+=================
+
+If enabled, Buildbot integration allows users with appropriate permissions
+to test what would happen if the proposed change was committed to the repository.
+
+This requires that the Buildbot server is running a "TryScheduler", which is 
+described in the Buildbot manual. The Reviewboard integration uses the 
+"user+password (PB)" approach (i.e. "Try_Userpass"), although only a single
+user / password is required for Reviewboard. A typical stanza in the Buildbot
+master configuration file might look something like::
+  from buildbot.scheduler import Try_Userpass
+  c['schedulers'].append(Try_Userpass("rb-try", ["fedora1-full"],
+				      port=8031, userpass=[("reviewboard", "rb-pass")] ) )
+
+It is important to understand that Buildbot integration is not without some risks.
+Buildbot masters can run arbitrary commands on Buildbot slaves (as the Buildbot slave
+user). This is normally mitigated in Buildbot since only people who can commit to the 
+repository can change what is run. However the TryScheduler applies a patch after source
+checkout, and before other commands are run. That means that the patch may be able to
+modify the buildsystem or other scripts that are run to do something malicious.
+
+**It is critically important that patches are inspected prior to running them on the
+Buildbot.**
+
+It is also important that the password used is a strong one (i.e. do not use *rb-pass* as
+shown in the example above). Do not share this account - it is easy to add extra entries
+to the userpass list.
+
+It would also be good to secure the Buildbot port. Ideally, this port would be firewalled
+off, and Reviewboard and Buildbot would be on the same machine.
+
+* **Enable Buildbot integration:**
+    Determines whether Buildbot integration is available to users. Users
+    also need to have sufficient rights to submit patches for testing.
+
+* **Buildbot server:**
+    The Buildbot server host name (or IP address).
+
+* **Buildbot 'try' port:**
+    The Buildbot "try" server port. This is the same as the "port="
+    argument in the Try_Userpass scheduler configuration in the
+    Buildbot master configuration file (in the example above, 8031).
+
+* **Username:**
+    The user name needed to connect to the buildbot "try" port. In the 
+    example above, this would be "reviewboard".
+
+* **Password:**
+    The password needed to connect to the buildbot "try" port. In the 
+    example above, this would be "rb-pass", however note that it should
+    be a strong password.
+
+
+.. comment: vim: ft=rst et
diff --git a/docs/manual/admin/admin-ui/settings.txt b/docs/manual/admin/admin-ui/settings.txt
--- a/docs/manual/admin/admin-ui/settings.txt
+++ b/docs/manual/admin/admin-ui/settings.txt
@@ -21,6 +21,7 @@ available settings pages, which consists of:
    email-settings
    diffviewer-settings
    logging-settings
+   buildbot-settings
 
 
 .. comment: vim: ft=rst et
diff --git a/reviewboard/admin/checks.py b/reviewboard/admin/checks.py
--- a/reviewboard/admin/checks.py
+++ b/reviewboard/admin/checks.py
@@ -206,3 +206,15 @@ def get_can_use_couchdb():
         return (False, _(
             'CouchDB depends on django-storages, which is not installed'
         ))
+
+def get_can_enable_buildbot():
+    """Checks whether Buildbot integration can be enabled."""
+    try:
+        imp.find_module("buildbot")
+        return (True, None)
+    except ImportError:
+        return (False, _(
+            'Buildbot integration requires the buildbot tools, which '
+            'are not installed. See http://buildbot.net/trac for more '
+            'information.'
+        ))
diff --git a/reviewboard/admin/forms.py b/reviewboard/admin/forms.py
--- a/reviewboard/admin/forms.py
+++ b/reviewboard/admin/forms.py
@@ -43,7 +43,8 @@ from reviewboard.admin.checks import get_can_enable_dns, \
                                      get_can_enable_search, \
                                      get_can_enable_syntax_highlighting, \
                                      get_can_use_amazon_s3, \
-                                     get_can_use_couchdb
+                                     get_can_use_couchdb, \
+                                     get_can_enable_buildbot
 from reviewboard.admin.siteconfig import load_site_config
 
 
@@ -830,3 +831,64 @@ class StorageSettingsForm(SiteSettingsForm):
                 'fields':  ('couchdb_default_server',),
             },
         )
+
+
+class BuildbotSettingsForm(SiteSettingsForm):
+    """
+    Buildbot integration settings for Review Board.
+    """
+    buildbot_enable_integration = forms.BooleanField(
+        label=_("Enable Buildbot integration"),
+        help_text=_('Whether to turn on support for the Buildbot "try" '
+                    'functions, which can be used to test patches before '
+                    'committing them to the repository. This has some '
+                    'potential security issues, so read the documentation '
+                    'before enabling this.'),
+        required=False)
+    buildbot_host = forms.CharField(
+        label=_("Buildbot server"),
+        help_text=_('The hostname (or IP address) of the buildbot server '
+                    'to use for testing.'),
+        required=False)
+    buildbot_port = forms.IntegerField(
+        label=_("Buildbot 'try' port"),
+        help_text=_('The special port to use for submissions. This is the '
+                    'same as the "port" number specified in the Buildbot '
+                    '"Try_Userpass" scheduler configuration.'),
+        required=False)
+    buildbot_try_user = forms.CharField(
+        label=_("Username"),
+        help_text=_('The user name to use for authentication to the Buildbot '
+                    'server. This is the same as the first part of the '
+                    '"userpass=" argument to the Buildbot '
+                    '"Try_Userpass" scheduler configuration.'),
+        required=False)
+    buildbot_try_password = forms.CharField(
+        widget=forms.PasswordInput,
+        label=_("Password"),
+        help_text=_('The password to use for authentication to the Buildbot '
+                    'server. This is the same as the second part of the '
+                    '"userpass=" argument to the Buildbot '
+                    '"Try_Userpass" scheduler configuration.'),
+        required=False)
+
+    def load(self):
+        can_enable_buildbot, reason = get_can_enable_buildbot()
+        if not can_enable_buildbot:
+            self.disabled_fields['buildbot_enable_integration'] = True
+            self.disabled_fields['buildbot_host'] = True
+            self.disabled_fields['buildbot_port'] = True
+            self.disabled_fields['buildbot_try_user'] = True
+            self.disabled_fields['buildbot_try_password'] = True
+            self.disabled_reasons['buildbot_enable_integration'] = reason
+
+        super(BuildbotSettingsForm, self).load()
+
+    def save(self):
+        super(BuildbotSettingsForm, self).save()
+        # Reload any important changes into the Django settings.
+        load_site_config()
+
+
+    class Meta:
+        title = _("Buildbot Settings")
diff --git a/reviewboard/admin/siteconfig.py b/reviewboard/admin/siteconfig.py
--- a/reviewboard/admin/siteconfig.py
+++ b/reviewboard/admin/siteconfig.py
@@ -123,6 +123,11 @@ defaults.update({
     'auth_x509_username_field':            'SSL_CLIENT_S_DN_CN',
     'auth_x509_username_regex':            '',
     'auth_x509_autocreate_users':          False,
+    'buildbot_enable_integration':         False,
+    'buildbot_host':                       '',
+    'buildbot_port':                       8031,
+    'buildbot_try_user':                   '',
+    'buildbot_try_password':               '',
     'diffviewer_context_num_lines':        5,
     'diffviewer_include_space_patterns':   [],
     'diffviewer_paginate_by':              20,
diff --git a/reviewboard/admin/urls.py b/reviewboard/admin/urls.py
--- a/reviewboard/admin/urls.py
+++ b/reviewboard/admin/urls.py
@@ -62,6 +62,10 @@ urlpatterns = patterns('reviewboard.admin.views',
         {'form_class': forms.StorageSettingsForm,
          'template_name': 'admin/storage_settings.html'},
         name="settings-storage"),
+    url(r'^settings/buildbot/$', 'site_settings',
+        {'form_class': forms.BuildbotSettingsForm,
+         'template_name': 'admin/settings.html'},
+        name="settings-buildbot"),
 )
 
 urlpatterns += patterns('',
diff --git a/reviewboard/reviews/forms.py b/reviewboard/reviews/forms.py
--- a/reviewboard/reviews/forms.py
+++ b/reviewboard/reviews/forms.py
@@ -10,7 +10,8 @@ from reviewboard.diffviewer import forms as diffviewer_forms
 from reviewboard.diffviewer.models import DiffSet
 from reviewboard.reviews.errors import OwnershipError
 from reviewboard.reviews.models import DefaultReviewer, ReviewRequest, \
-                                       ReviewRequestDraft, Screenshot
+                                       ReviewRequestDraft, Screenshot, \
+                                       BuildbotTryRequest
 from reviewboard.scmtools.errors import SCMError, ChangeNumberInUseError, \
                                         InvalidChangeNumberError, \
                                         ChangeSetError
@@ -273,3 +274,17 @@ class UploadScreenshotForm(forms.Form):
         draft.save()
 
         return screenshot
+
+class SubmitBuildbotTryForm(forms.Form):
+    """
+    A form that handles submission of diffs to the Buildbot "try --diff"
+    pseudo-scheduler.
+    """
+    builders = forms.CharField(required=True)
+
+    def create(self, file, review_request):
+        logging.warn("create warning")
+        tryRequest = BuildbotTryRequest()
+        tryRequest.submit(builders=self.cleaned_data['builders'])
+
+
diff --git a/reviewboard/reviews/models.py b/reviewboard/reviews/models.py
--- a/reviewboard/reviews/models.py
+++ b/reviewboard/reviews/models.py
@@ -548,6 +548,7 @@ class ReviewRequest(models.Model):
             ("can_change_status", "Can change status"),
             ("can_submit_as_another_user", "Can submit as another user"),
             ("can_edit_reviewrequest", "Can edit review request"),
+            ("can_try_diff", "Can submit Buildbot Try request"),
         )
 
 
@@ -1182,3 +1183,21 @@ class Review(models.Model):
     class Meta:
         ordering = ['timestamp']
         get_latest_by = 'timestamp'
+
+class BuildbotTryRequest(models.Model):
+    """
+    A buildbot 'try --diff' submission.
+    """
+    def submitRequest(self, builders):
+        logging.warn("about to try a buildbot try --diff")
+        callstring = "buildbot try --diff=" + test.diff
+        callstring += " --connect=pb --master=" + settings.buildbot_host + ":" + settings.buildbot_port
+        callstring += " --username=" + settings.buildbot_try_user
+        callstring += " --passwd=" + settings.buildbot_try_password
+        # TODO: need to extend this to multiple builders
+        callstring += " --builder=" + builders
+        logging.debug("Submitting " + callstring)
+        os.system(callstring)
+
+    def __unicode__(self):
+        return u"Buildbot Review Request"
diff --git a/reviewboard/reviews/views.py b/reviewboard/reviews/views.py
--- a/reviewboard/reviews/views.py
+++ b/reviewboard/reviews/views.py
@@ -41,7 +41,8 @@ from reviewboard.reviews.datagrids import DashboardDataGrid, \
 from reviewboard.reviews.errors import OwnershipError
 from reviewboard.reviews.forms import NewReviewRequestForm, \
                                       UploadDiffForm, \
-                                      UploadScreenshotForm
+                                      UploadScreenshotForm, \
+                                      SubmitBuildbotTryForm
 from reviewboard.reviews.models import Comment, ReviewRequest, \
                                        ReviewRequestDraft, Review, Group, \
                                        Screenshot, ScreenshotComment
@@ -223,6 +224,7 @@ def review_detail(request, review_request_id,
         'request': request,
         'upload_diff_form': UploadDiffForm(review_request),
         'upload_screenshot_form': UploadScreenshotForm(),
+        'submit_buildbot_try_form': SubmitBuildbotTryForm(),
         'scmtool': repository.get_scmtool(),
         'PRE_CREATION': PRE_CREATION,
     }))
@@ -440,6 +442,7 @@ def diff(request, review_request_id, revision=None, interdiff_revision=None,
         'num_diffs': num_diffs,
         'upload_diff_form': UploadDiffForm(review_request),
         'upload_screenshot_form': UploadScreenshotForm(),
+        'submit_buildbot_try_form': SubmitBuildbotTryForm(),
         'scmtool': repository.get_scmtool(),
         'last_activity_time': last_activity_time,
         'specific_diff_requested': revision is not None or
diff --git a/reviewboard/scmtools/svn.py b/reviewboard/scmtools/svn.py
--- a/reviewboard/scmtools/svn.py
+++ b/reviewboard/scmtools/svn.py
@@ -1,3 +1,4 @@
+import logging
 import re
 import urllib
 import urlparse
diff --git a/reviewboard/templates/admin/settings.html b/reviewboard/templates/admin/settings.html
--- a/reviewboard/templates/admin/settings.html
+++ b/reviewboard/templates/admin/settings.html
@@ -10,5 +10,6 @@
  {% admin_subnav "settings-diffs" _("Diff Viewer") %}
  {% admin_subnav "settings-logging" _("Logging") %}
  {% admin_subnav "settings-storage" _("File Storage") %}
+ {% admin_subnav "settings-buildbot" _("Buildbot") %}
 </ul>
 {% endblock %}
diff --git a/reviewboard/templates/reviews/review_detail.html b/reviewboard/templates/reviews/review_detail.html
--- a/reviewboard/templates/reviews/review_detail.html
+++ b/reviewboard/templates/reviews/review_detail.html
@@ -45,6 +45,7 @@
 {% if review_request_details.diffset or review_request.diffset_history.diffsets.count %}
  <li class="primary"><a href="diff/#index_header">{% trans "View Diff" %}</a></li>
 {% endif %}
+{% include "reviews/review_request_actions_buildbot_try.html" %}
 </ul>
 
 <div class="main">
diff --git a/reviewboard/templates/reviews/review_request_actions_buildbot_try.html b/reviewboard/templates/reviews/review_request_actions_buildbot_try.html
--- /dev/null
+++ b/reviewboard/templates/reviews/review_request_actions_buildbot_try.html
@@ -0,0 +1,5 @@
+{% load djblets_utils %}
+{% load i18n %}
+{% ifuserorperm review_request.submitter "reviews.can_try_diff" %}
+ <li><a id="submit-buildbot-try" href="#">{% trans "Test Diff" %}</a></li>
+{% endifuserorperm %}
\ No newline at end of file
diff --git a/reviewboard/templates/reviews/review_request_dlgs.html b/reviewboard/templates/reviews/review_request_dlgs.html
--- a/reviewboard/templates/reviews/review_request_dlgs.html
+++ b/reviewboard/templates/reviews/review_request_dlgs.html
@@ -38,3 +38,20 @@
   });
 </script>
 {% endifuserorperm %}
+
+{% ifuserorperm review_request.submitter "reviews.can_try_diff" %}
+<script type="text/javascript">
+    $(document).ready(function() {
+    $("#submit-buildbot-try").click(function() {
+      $("<div/>").formDlg({
+        title: "{% trans "Test Diff" %}",
+        confirmLabel: "{% trans "Submit Patch for Test" %}",
+        width: "50em",
+        fields: {% form_dialog_fields submit_buildbot_try_form %}
+      });
+
+      return true;
+    });
+  });
+</script>
+{% endifuserorperm %}
