← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~twom/launchpad/manually-rescan-link into lp:launchpad

 

Tom Wardill has proposed merging lp:~twom/launchpad/manually-rescan-link into lp:launchpad.

Commit message:
Add 'rescan' button when a scan of a branch has failed.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~twom/launchpad/manually-rescan-link/+merge/362139

Adds a button to the Branch view, only when the latest scan has failed or there are no scan jobs for a branch.

Also add a view at +rescan so a rescan can be manually triggered otherwise.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~twom/launchpad/manually-rescan-link into lp:launchpad.
=== modified file 'lib/lp/code/browser/branch.py'
--- lib/lp/code/browser/branch.py	2018-07-16 00:49:00 +0000
+++ lib/lp/code/browser/branch.py	2019-01-23 16:23:25 +0000
@@ -118,6 +118,7 @@
     english_list,
     truncate_text,
     )
+from lp.services.job.interfaces.job import JobStatus
 from lp.services.propertycache import cachedproperty
 from lp.services.webapp import (
     canonical_url,
@@ -587,6 +588,16 @@
         """Only show the link if there are more than five."""
         return len(self.landing_candidates) > 5
 
+    @property
+    def show_rescan_link(self):
+        """Only show the rescan button if the latest scan has failed"""
+        scan_job = self.context.getLatestScanJob()
+        # If there are no jobs, we failed to create one for some reason,
+        # so we should allow a rescan
+        if not scan_job:
+            return True
+        return scan_job.job.status == JobStatus.FAILED
+
     @cachedproperty
     def linked_bugtasks(self):
         """Return a list of bugtasks linked to the branch."""
@@ -635,6 +646,23 @@
         return self.context.getSpecificationLinks(self.user)
 
 
+class BranchRescanView(LaunchpadEditFormView):
+
+    schema = Interface
+
+    field_names = []
+
+    @action('Rescan', name='rescan')
+    def rescan(self, action, data):
+        result = self.context.unscan(rescan=True)
+        if result:
+            message = "Branch scan scheduled"
+        else:
+            message = "Branch scan schedule failed"
+        self.request.response.addNotification(message)
+        self.next_url = canonical_url(self.context)
+
+
 class BranchEditFormView(LaunchpadEditFormView):
     """Base class for forms that edit a branch."""
 

=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml	2018-11-09 22:46:32 +0000
+++ lib/lp/code/browser/configure.zcml	2019-01-23 16:23:25 +0000
@@ -437,6 +437,12 @@
         permission="launchpad.Edit"
         template="../../app/templates/generic-edit.pt"/>
     <browser:page
+        name="+rescan"
+        for="lp.code.interfaces.branch.IBranch"
+        class="lp.code.browser.branch.BranchRescanView"
+        permission="launchpad.Edit"
+        template="../templates/branch-rescan.pt"/>
+    <browser:page
         name="+edit-import"
         for="lp.code.interfaces.branch.IBranch"
         class="lp.code.browser.codeimport.CodeImportEditView"

=== modified file 'lib/lp/code/browser/tests/test_branch.py'
--- lib/lp/code/browser/tests/test_branch.py	2018-09-10 14:10:26 +0000
+++ lib/lp/code/browser/tests/test_branch.py	2019-01-23 16:23:25 +0000
@@ -34,6 +34,7 @@
     RepositoryFormat,
     )
 from lp.code.enums import BranchType
+from lp.code.model.branchjob import BranchScanJob
 from lp.code.tests.helpers import BranchHostingFixture
 from lp.registry.enums import BranchSharingPolicy
 from lp.registry.interfaces.accesspolicy import IAccessPolicySource
@@ -43,6 +44,7 @@
 from lp.services.database.constants import UTC_NOW
 from lp.services.features.testing import FeatureFixture
 from lp.services.helpers import truncate_text
+from lp.services.job.interfaces.job import JobStatus
 from lp.services.webapp.publisher import canonical_url
 from lp.services.webapp.servers import LaunchpadTestRequest
 from lp.testing import (
@@ -299,6 +301,38 @@
             '<a href="+recipes">2 recipes</a> using this branch.',
             view.recipes_link)
 
+    def test_show_rescan_link(self):
+        branch = self.factory.makeAnyBranch()
+        job = BranchScanJob.create(branch)
+        job.job._status = JobStatus.FAILED
+        view = create_initialized_view(branch, '+index')
+        result = view.show_rescan_link
+        self.assertTrue(result)
+
+    def test_show_rescan_link_no_failures(self):
+        branch = self.factory.makeAnyBranch()
+        job = BranchScanJob.create(branch)
+        job.job._status = JobStatus.COMPLETED
+        view = create_initialized_view(branch, '+index')
+        result = view.show_rescan_link
+        self.assertFalse(result)
+
+    def test_show_rescan_link_no_scan_jobs(self):
+        branch = self.factory.makeAnyBranch()
+        view = create_initialized_view(branch, '+index')
+        result = view.show_rescan_link
+        self.assertTrue(result)
+
+    def test_show_rescan_link_latest_didnt_fail(self):
+        branch = self.factory.makeAnyBranch()
+        job = BranchScanJob.create(branch)
+        job.job._status = JobStatus.FAILED
+        job = BranchScanJob.create(branch)
+        job.job._status = JobStatus.COMPLETED
+        view = create_initialized_view(branch, '+index')
+        result = view.show_rescan_link
+        self.assertTrue(result)
+
     def _addBugLinks(self, branch):
         for status in BugTaskStatus.items:
             bug = self.factory.makeBug(status=status)
@@ -611,7 +645,7 @@
         logout()
         with StormStatementRecorder() as recorder:
             browser.open(branch_url)
-        self.assertThat(recorder, HasQueryCount(Equals(28)))
+        self.assertThat(recorder, HasQueryCount(Equals(30)))
 
 
 class TestBranchViewPrivateArtifacts(BrowserTestCase):

=== modified file 'lib/lp/code/interfaces/branch.py'
--- lib/lp/code/interfaces/branch.py	2018-05-17 14:10:29 +0000
+++ lib/lp/code/interfaces/branch.py	2019-01-23 16:23:25 +0000
@@ -1034,6 +1034,9 @@
             detail page.
         """
 
+    def getLatestScanJob():
+        """Get the lastest IBranchScanJob for this branch"""
+
     def checkUpgrade():
         """Check whether an upgrade should be performed, and raise if not.
 

=== modified file 'lib/lp/code/model/branch.py'
--- lib/lp/code/model/branch.py	2018-12-10 13:54:34 +0000
+++ lib/lp/code/model/branch.py	2019-01-23 16:23:25 +0000
@@ -167,7 +167,7 @@
 from lp.services.database.datetimecol import UtcDateTimeCol
 from lp.services.database.decoratedresultset import DecoratedResultSet
 from lp.services.database.enumcol import EnumCol
-from lp.services.database.interfaces import IMasterStore
+from lp.services.database.interfaces import IMasterStore, IStore
 from lp.services.database.sqlbase import (
     SQLBase,
     sqlvalues,
@@ -1295,6 +1295,15 @@
             job.celeryRunOnCommit()
         return (self.last_mirrored_id, old_scanned_id)
 
+    def getLatestScanJob(self):
+        from lp.code.model.branchjob import BranchJob, BranchScanJob
+        latest_job = IStore(BranchJob).find(
+            BranchJob,
+            branch=self,
+            job_type=BranchScanJob.class_job_type).order_by(
+                BranchJob.id).first()
+        return latest_job
+
     def requestMirror(self):
         """See `IBranch`."""
         if self.branch_type in (BranchType.REMOTE, BranchType.HOSTED):

=== modified file 'lib/lp/code/model/tests/test_branch.py'
--- lib/lp/code/model/tests/test_branch.py	2018-07-09 09:27:06 +0000
+++ lib/lp/code/model/tests/test_branch.py	2019-01-23 16:23:25 +0000
@@ -3502,6 +3502,19 @@
                 getUtility(ILaunchpadCelebrities).commercial_admin):
             branch.unscan()
 
+    def test_getLatestScanJob(self):
+        branch = self.factory.makeAnyBranch()
+        with person_logged_in(branch.owner):
+            branch.unscan(rescan=True)
+        found = Store.of(branch).find(BranchJob, branch=branch)[0]
+        result = branch.getLatestScanJob()
+        self.assertEqual(found, result)
+
+    def test_getLatestScanJob_no_scans(self):
+        branch = self.factory.makeAnyBranch()
+        result = branch.getLatestScanJob()
+        self.assertIsNone(result)
+
 
 class TestWebservice(TestCaseWithFactory):
     """Tests for the webservice."""

=== modified file 'lib/lp/code/templates/branch-index.pt'
--- lib/lp/code/templates/branch-index.pt	2017-11-06 09:32:45 +0000
+++ lib/lp/code/templates/branch-index.pt	2019-01-23 16:23:25 +0000
@@ -130,18 +130,38 @@
 
   </div>
 
-  <div class="yui-g" tal:condition="view/pending_updates">
+  <tal:rescan condition="not:view/show_rescan_link">
+    <div class="yui-g" tal:condition="view/pending_updates">
+      <div class="portlet">
+        <div id="branch-pending-updates" class="pending-update">
+          <h3>Updating branch...</h3>
+          <p>
+            Launchpad is processing new changes to this branch which will be
+            available in a few minutes. Reload to see the changes.
+          </p>
+        </div>
+      </div>
+    </div>
+  </tal:rescan>
+
+  <div class="yui-g" tal:condition="view/show_rescan_link">
     <div class="portlet">
-      <div id="branch-pending-updates" class="pending-update">
-        <h3>Updating branch...</h3>
-        <p>
-          Launchpad is processing new changes to this branch which will be
-          available in a few minutes. Reload to see the changes.
+      <div id="branch-scan-failed" class="pending-update">
+        <h3>Branch scan failed</h3>
+        <p>
+          Scanning this branch for changes has failed, you can manually rescan if required.
+        </p>
+        <p>
+          <form action="./+rescan" name="launchpadform" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
+            <input id="field.actions.rescan" class="button" type="submit"
+             name="field.actions.rescan" value="Rescan" />
+          </form>
         </p>
       </div>
     </div>
   </div>
 
+
   <div class="yui-g">
     <div class="portlet" id="recent-revisions">
       <h2>Recent revisions</h2>

=== added file 'lib/lp/code/templates/branch-rescan.pt'
--- lib/lp/code/templates/branch-rescan.pt	1970-01-01 00:00:00 +0000
+++ lib/lp/code/templates/branch-rescan.pt	2019-01-23 16:23:25 +0000
@@ -0,0 +1,14 @@
+<html
+  xmlns="http://www.w3.org/1999/xhtml";
+  xmlns:tal="http://xml.zope.org/namespaces/tal";
+  xmlns:metal="http://xml.zope.org/namespaces/metal";
+  xmlns:i18n="http://xml.zope.org/namespaces/i18n";
+  metal:use-macro="view/macro:page/main_only"
+  i18n:domain="launchpad">
+  <body>
+    <div metal:fill-slot="main">
+      <p>You can schedule a rescan for this branch if it appears the branch is out of date.</p>
+      <div metal:use-macro="context/@@launchpad_form/form" />
+    </div>
+  </body>
+</html>


Follow ups