[Buildbot-devel] [PATCH 10/11] Allow patches to be submitted through the web interface.

Benoit Sigoure tsuna at lrde.epita.fr
Fri Nov 16 17:13:00 UTC 2007


	If and only if user authentication is used to allow force/stop
	builds, users can also attach a patch to the `force build' request.
	* buildbot/sourcestamp.py (SourceStamp.__init__): Enhance the
	documentation.
	(make_force_build_form): Add fields to upload a patch and specify a
	patch-level.
	* buildbot/status/web/builder.py (StatusResourceBuilder.force):
	Handle the new fields of the form to allow patches for authenticated
	users.

Signed-off-by: Benoit Sigoure <tsuna at lrde.epita.fr>
---
 buildbot/sourcestamp.py        |    3 ++-
 buildbot/status/web/base.py    |   17 +++++++++++++++--
 buildbot/status/web/builder.py |   30 ++++++++++++++++++++++++------
 3 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/buildbot/sourcestamp.py b/buildbot/sourcestamp.py
index 69d3c30..a388014 100644
--- a/buildbot/sourcestamp.py
+++ b/buildbot/sourcestamp.py
@@ -12,7 +12,8 @@ class SourceStamp(util.ComparableMixin):
        None, build the HEAD revision from the given branch.
      - (revision=REV, patchspec=(LEVEL, DIFF), changes=None): checkout REV,
        then apply a patch to the source, with C{patch -pPATCHLEVEL <DIFF}.
-       If REV is None, checkout HEAD and patch it.
+       If REV is C{None}, checkout HEAD and patch it.  DIFF is a string that
+       contains the unified diff to apply.
      - (revision=None, patchspec=None, changes=[CHANGES]): let the Source
        step check out the latest revision indicated by the given Changes.
        CHANGES is a tuple of L{buildbot.changes.changes.Change} instances,
diff --git a/buildbot/status/web/base.py b/buildbot/status/web/base.py
index 4577767..93d6f14 100644
--- a/buildbot/status/web/base.py
+++ b/buildbot/status/web/base.py
@@ -86,9 +86,21 @@ def make_force_build_form(forceURL, useLoginPassword):
     """Create a form whose submit button sends the request to C{forceURL}.  If
     C{useLoginPassword} is true, this form will have a password field."""
 
-    data = """<form action="%s" class="command forcebuild">
+    if useLoginPassword:
+        form_type = ' method="post" enctype="multipart/form-data"'
+        form_attach = (make_row("Build with a patch?",
+                                '<input type="file" name="patch" />')
+                       + make_row("Patch level:",
+                                  '<input type="text" name="plevel" size="2" '
+                                  'maxlength="2" value="1" />'))
+    else:
+        form_attach = ""
+        form_type = ""
+
+    data = """<form action="%s"%s class="command forcebuild">
       <p>To force a build, fill out the following fields and
-      click the `Force Build' button</p>""" % forceURL
+      click the `Force Build' button</p>
+    """ % (forceURL, form_type)
     return (data
       + make_name_login_password_form(useLoginPassword)
       + make_row("Reason for build:",
@@ -97,6 +109,7 @@ def make_force_build_form(forceURL, useLoginPassword):
                  '<input type="text" name="branch" />')
       + make_row("Revision to build:",
                  '<input type="text" name="revision" />')
+      + form_attach
       + '<input type="submit" value="Force Build" /></form>\n')
 
 colormap = {
diff --git a/buildbot/status/web/builder.py b/buildbot/status/web/builder.py
index e028c9d..900a33f 100644
--- a/buildbot/status/web/builder.py
+++ b/buildbot/status/web/builder.py
@@ -128,12 +128,26 @@ class StatusResourceBuilder(HtmlResource, OneLineMixin):
         reason = req.args.get("comments", ["<no reason specified>"])[0]
         branch = req.args.get("branch", [""])[0]
         revision = req.args.get("revision", [""])[0]
+        patch = req.args.get("patch", [""])[0]
+        if patch:
+            patch_level = req.args.get("plevel", ["1"])[0]
+            try:
+                patch_level = int(patch_level)
+            except ValueError:
+                # TODO: tell the web user that their request was invalid
+                return Redirect("..")
+            patch = (patch_level, patch)
+            has_patch = "yes"
+        else:
+            has_patch = "no"
+            patch = None
 
-        r = "The web-page 'force build' button was pressed by '%s': %s\n" \
-            % (name, reason)
-        log.msg("web forcebuild of builder '%s', branch='%s', revision='%s'"
-                "by user '%s'" % (self.builder_status.getName(), branch,
-                                  revision, name))
+        r = "The web-page 'force build' button was pressed by '%s': %s" \
+            "(patch: %s)\n" % (name, reason, has_patch)
+        log.msg("web forcebuild of builder '%s', branch='%s', "
+                "revision='%s', by user '%s' (patch: %s)" \
+                % (self.builder_status.getName(), branch, revision, name,
+                   has_patch))
 
         if not self.builder_control:
             # TODO: tell the web user that their request was denied
@@ -144,6 +158,10 @@ class StatusResourceBuilder(HtmlResource, OneLineMixin):
             if not self.authUser(req):
                 # TODO: tell the web user that their request was denied
                 return Redirect("..")
+        else:
+            if patch:
+                log.msg("user is not authenticated: discarding the patch")
+            patch = None
 
         # keep weird stuff out of the branch and revision strings. TODO:
         # centralize this somewhere.
@@ -164,7 +182,7 @@ class StatusResourceBuilder(HtmlResource, OneLineMixin):
         # buildbot.changes.changes.Change instance which doesn't really fit
         # this use case (it requires a list of changed files which is tedious
         # to compute at this stage)
-        s = SourceStamp(branch=branch, revision=revision)
+        s = SourceStamp(branch=branch, revision=revision, patch=patch)
         req = BuildRequest(r, s, self.builder_status.getName())
         try:
             self.builder_control.requestBuildSoon(req)
-- 
1.5.3.5.654.gdd5ec





More information about the devel mailing list