launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #23229
[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