launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #04936
lp:~allenap/launchpad/series-init-failure-explanations-bug-835024-ui into lp:launchpad
Gavin Panella has proposed merging lp:~allenap/launchpad/series-init-failure-explanations-bug-835024-ui into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #835024 in Launchpad itself: "Unclear why series initialization failed"
https://bugs.launchpad.net/launchpad/+bug/835024
For more details, see:
https://code.launchpad.net/~allenap/launchpad/series-init-failure-explanations-bug-835024-ui/+merge/74974
Show derivation failure messages in the portlet on DistroSeries:+index.
Needs feature flag soyuz.derived_series_ui.enabled.
--
https://code.launchpad.net/~allenap/launchpad/series-init-failure-explanations-bug-835024-ui/+merge/74974
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~allenap/launchpad/series-init-failure-explanations-bug-835024-ui into lp:launchpad.
=== modified file 'lib/lp/registry/browser/tests/test_distroseries.py'
--- lib/lp/registry/browser/tests/test_distroseries.py 2011-08-19 06:57:33 +0000
+++ lib/lp/registry/browser/tests/test_distroseries.py 2011-09-12 11:42:05 +0000
@@ -28,10 +28,17 @@
LessThan,
Not,
)
+import transaction
from zope.component import getUtility
-from zope.security.proxy import removeSecurityProxy
+from zope.security.proxy import (
+ ProxyFactory,
+ removeSecurityProxy,
+ )
-from canonical.config import config
+from canonical.config import (
+ config,
+ dbconfig,
+ )
from canonical.database.constants import UTC_NOW
from canonical.database.sqlbase import flush_database_caches
from canonical.launchpad.testing.pages import (
@@ -41,13 +48,19 @@
from canonical.launchpad.webapp.authorization import check_permission
from canonical.launchpad.webapp.batching import BatchNavigator
from canonical.launchpad.webapp.interaction import get_current_principal
-from canonical.launchpad.webapp.interfaces import BrowserNotificationLevel
+from canonical.launchpad.webapp.interfaces import (
+ BrowserNotificationLevel,
+ IStoreSelector,
+ MAIN_STORE,
+ MASTER_FLAVOR,
+ )
from canonical.launchpad.webapp.publisher import canonical_url
from canonical.launchpad.webapp.url import urlappend
from canonical.testing.layers import (
DatabaseFunctionalLayer,
LaunchpadFunctionalLayer,
LaunchpadZopelessLayer,
+ reconnect_stores,
)
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
from lp.archivepublisher.debversion import Version
@@ -87,7 +100,9 @@
)
from lp.soyuz.model import distroseriesdifferencejob
from lp.soyuz.model.archivepermission import ArchivePermission
+from lp.soyuz.model.initializedistroseriesjob import InitializeDistroSeriesJob
from lp.soyuz.model.packagecopyjob import PlainPackageCopyJob
+from lp.soyuz.scripts.initialize_distroseries import InitializationError
from lp.testing import (
ANONYMOUS,
anonymous_logged_in,
@@ -584,6 +599,51 @@
"You cannot attempt initialization again, but a "
"member of Team Teamy Team Team may be able to help."))
+ def load_afresh(self, thing):
+ store = getUtility(IStoreSelector).get(MAIN_STORE, MASTER_FLAVOR)
+ naked_thing = removeSecurityProxy(thing)
+ naked_thing = store.get(naked_thing.__class__, naked_thing.id)
+ return ProxyFactory(naked_thing)
+
+ def fail_job_with_error(self, job, error):
+ # We need to switch to the initializedistroseries user to set the
+ # error_description on the given job. Which is a PITA.
+ distroseries = job.distroseries
+ transaction.commit()
+ starting_database_config_section = dbconfig.getSectionName()
+ reconnect_stores("initializedistroseries")
+ job = self.job_source.get(distroseries)
+ job.start()
+ job.fail()
+ job.notifyUserError(error)
+ transaction.commit()
+ reconnect_stores(starting_database_config_section)
+
+ def test_initialization_failure_explanation_shown(self):
+ # When initialization has failed an explanation of the failure can be
+ # displayed. It depends on the nature of the failure; only some error
+ # types are displayed.
+ set_derived_series_ui_feature_flag(self)
+ series = self.factory.makeDistroSeries()
+ parent = self.factory.makeDistroSeries()
+ job = self.job_source.create(series, [parent.id])
+ self.fail_job_with_error(
+ job, InitializationError(
+ "You cannot be serious. That's really going "
+ "to hurt. Put it away."))
+ # Load series again because the connection was closed in
+ # fail_job_with_error().
+ series = self.load_afresh(series)
+ with person_logged_in(series.owner):
+ view = create_initialized_view(series, '+portlet-derivation')
+ html_content = view()
+ self.assertThat(
+ extract_text(html_content), DocTestMatches(
+ "Series initialization has failed\n"
+ "You cannot be serious. That's really going "
+ "to hurt. Put it away.\n"
+ "You can attempt initialization again."))
+
class TestMilestoneBatchNavigatorAttribute(TestCaseWithFactory):
"""Test the series.milestone_batch_navigator attribute."""
=== modified file 'lib/lp/registry/templates/distroseries-portlet-derivation.pt'
--- lib/lp/registry/templates/distroseries-portlet-derivation.pt 2011-09-02 10:57:52 +0000
+++ lib/lp/registry/templates/distroseries-portlet-derivation.pt 2011-09-12 11:42:05 +0000
@@ -75,6 +75,9 @@
define="job context/getInitializationJob"
condition="job/status/enumvalue:FAILED|nothing">
<h2>Series initialization has failed</h2>
+ <p tal:condition="job/error_description"
+ tal:content="job/error_description">
+ </p>
<tal:retry
define="can_retry context/@@+initseries/required:launchpad.Edit ">
<tal:can_retry condition="can_retry">
=== modified file 'lib/lp/soyuz/interfaces/distributionjob.py'
--- lib/lp/soyuz/interfaces/distributionjob.py 2011-08-26 06:46:43 +0000
+++ lib/lp/soyuz/interfaces/distributionjob.py 2011-09-12 11:42:05 +0000
@@ -25,6 +25,7 @@
from zope.schema import (
Int,
Object,
+ Text,
)
from canonical.launchpad import _
@@ -117,6 +118,14 @@
class IInitializeDistroSeriesJob(IRunnableJob):
"""A Job that performs actions on a distribution."""
+ error_description = Text(
+ title=_("Error description"),
+ description=_(
+ "A short description of the last error this "
+ "job encountered, if any."),
+ readonly=True,
+ required=False)
+
class IDistroSeriesDifferenceJobSource(IJobSource):
"""An `IJob` for creating `DistroSeriesDifference`s."""