Merge ~ines-almeida/launchpad:invert-bug-webhook-feature-flag into launchpad:master

Proposed by Ines Almeida
Status: Merged
Approved by: Ines Almeida
Approved revision: 34b6034b26009fc3b6155fbe350f11c69f88b884
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~ines-almeida/launchpad:invert-bug-webhook-feature-flag
Merge into: launchpad:master
Diff against target: 234 lines (+17/-30)
10 files modified
lib/lp/bugs/interfaces/bugtarget.py (+2/-2)
lib/lp/bugs/subscribers/webhooks.py (+3/-3)
lib/lp/bugs/tests/test_subscribers.py (+2/-2)
lib/lp/registry/browser/distribution.py (+2/-2)
lib/lp/registry/browser/distributionsourcepackage.py (+2/-2)
lib/lp/registry/browser/product.py (+2/-2)
lib/lp/services/features/flags.py (+3/-2)
lib/lp/services/webhooks/tests/test_browser.py (+0/-4)
lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst (+1/-0)
lib/lp/soyuz/tests/test_packagecopyjob.py (+0/-11)
Reviewer Review Type Date Requested Status
Guruprasad Approve
Review via email: mp+445657@code.launchpad.net

Commit message

Invert bug webhooks feature flag to be enabled by default

For feature flags that we intend to keep enabled (and particularly for the unit tests to run with the newly added feature) this change is inverting this feature flag so that the feature is enabled by default. To disable the feature, one just needs to set the "bugs.webhooks.disabled" feature flag

Description of the change

I haven't run the full test suite in this (I ran enough to feel confident to MP it), so we might discover a couple extra places that are missing permissions when all the full test suite runs after merge.

IMO, there might still be value in setting feature flags globally for testing, and I opened a ticket to potentially address that in the future (https://warthogs.atlassian.net/browse/LP-1272). For this particular case, I think this is reasonable.

To post a comment you must log in.
Revision history for this message
Guruprasad (lgp171188) wrote :

Inês, here is what our documentation on Feature Flags says about the type of change made in this MP

> The effect is typically 'enabled', 'visible', or 'timeout'. These should always be in the positive sense, not 'disabled'. If timeouts are given, they should be in seconds (decimals can be given in the value.)

I agree with this and also believe that the feature flags should be opt-in and not opt-out by default. Since your intent is to enable it globally to catch all permission issues, we should try to make the relevant test suite changes to that effect and not toggle the default behaviour of a feature flag, imho.

review: Needs Information
Revision history for this message
Colin Watson (cjwatson) wrote :

Guruprasad, you weren't here for the standup meeting where we discussed this. The problem is that test suite changes to do that would slow down the test suite globally by a non-trivial amount (adding extra SQL statements to every test that uses the database, which is most of them). `MemoryFeatureFixture` can avoid the extra SQL statements in many cases, but isn't effective for things like tests of scripts run in subprocesses, which are likely to be important here.

An opt-out feature rule does feel a little dirty, and it doesn't give us a reasonable way to enable it on a per-team basis, so the general injunction in the documentation does make sense. However, I think it can make some sense when the feature rule is intended to be short-term: that is, the intent is to make the behaviour in question unconditional, but we want a feature rule as an escape hatch to let us turn it off quickly in case of problems.

Revision history for this message
Ines Almeida (ines-almeida) wrote :

> when the feature rule is intended to be short-term

That being said, one thing to consider is to cleanup a lot of our feature flags that have been enabled for 1+ years, and cleaning this feature flag up in a few of months once we're confident.

I agree with both here. Happy to re-discuss this in a standup

Revision history for this message
Guruprasad (lgp171188) wrote :

Thanks for the details Colin and Inês!

Revision history for this message
Ines Almeida (ines-almeida) :
Revision history for this message
Guruprasad (lgp171188) wrote :

LGTM 👍

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/bugs/interfaces/bugtarget.py b/lib/lp/bugs/interfaces/bugtarget.py
2index 540079f..3a090e6 100644
3--- a/lib/lp/bugs/interfaces/bugtarget.py
4+++ b/lib/lp/bugs/interfaces/bugtarget.py
5@@ -15,7 +15,7 @@ __all__ = [
6 "ISeriesBugTarget",
7 "BUG_POLICY_ALLOWED_TYPES",
8 "BUG_POLICY_DEFAULT_TYPES",
9- "BUG_WEBHOOKS_FEATURE_FLAG",
10+ "DISABLE_BUG_WEBHOOKS_FEATURE_FLAG",
11 ]
12
13
14@@ -157,7 +157,7 @@ BUG_POLICY_DEFAULT_TYPES = {
15 }
16
17
18-BUG_WEBHOOKS_FEATURE_FLAG = "bugs.webhooks.enabled"
19+DISABLE_BUG_WEBHOOKS_FEATURE_FLAG = "bugs.webhooks.disabled"
20
21
22 @exported_as_webservice_entry(as_of="beta")
23diff --git a/lib/lp/bugs/subscribers/webhooks.py b/lib/lp/bugs/subscribers/webhooks.py
24index 4ea257f..43a51c2 100644
25--- a/lib/lp/bugs/subscribers/webhooks.py
26+++ b/lib/lp/bugs/subscribers/webhooks.py
27@@ -10,7 +10,7 @@ from zope.component import getUtility
28
29 from lp.bugs.interfaces.bug import IBug
30 from lp.bugs.interfaces.bugmessage import IBugMessage
31-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
32+from lp.bugs.interfaces.bugtarget import DISABLE_BUG_WEBHOOKS_FEATURE_FLAG
33 from lp.bugs.interfaces.bugtask import IBugTask
34 from lp.bugs.subscribers.bugactivity import what_changed
35 from lp.services.database.sqlbase import block_implicit_flushes
36@@ -27,7 +27,7 @@ def _trigger_bugtask_webhook(
37 previous_state: Union[IBug, IBugTask] = None,
38 ):
39 """Triggers 'bug' event for a specific bugtask"""
40- if not getFeatureFlag(BUG_WEBHOOKS_FEATURE_FLAG):
41+ if getFeatureFlag(DISABLE_BUG_WEBHOOKS_FEATURE_FLAG):
42 return
43
44 if IWebhookTarget.providedBy(bugtask.target):
45@@ -38,7 +38,7 @@ def _trigger_bugtask_webhook(
46 @block_implicit_flushes
47 def _trigger_bug_comment_webhook(action: str, bug_comment: IBugMessage):
48 """Triggers 'bug:comment' events for each bug target for that comment"""
49- if not getFeatureFlag(BUG_WEBHOOKS_FEATURE_FLAG):
50+ if getFeatureFlag(DISABLE_BUG_WEBHOOKS_FEATURE_FLAG):
51 return
52
53 bugtasks = bug_comment.bug.bugtasks
54diff --git a/lib/lp/bugs/tests/test_subscribers.py b/lib/lp/bugs/tests/test_subscribers.py
55index 7bddc92..938002d 100644
56--- a/lib/lp/bugs/tests/test_subscribers.py
57+++ b/lib/lp/bugs/tests/test_subscribers.py
58@@ -9,7 +9,7 @@ from testtools.matchers import Equals, MatchesDict, MatchesStructure
59 from zope.event import notify
60
61 from lp.bugs.interfaces.bug import IBug
62-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
63+from lp.bugs.interfaces.bugtarget import DISABLE_BUG_WEBHOOKS_FEATURE_FLAG
64 from lp.bugs.interfaces.bugtask import BugTaskStatus
65 from lp.bugs.subscribers.bugactivity import what_changed
66 from lp.services.features.testing import FeatureFixture
67@@ -63,7 +63,7 @@ class TestBugWebhooksTriggered(TestCaseWithFactory):
68 self.useFixture(
69 FeatureFixture(
70 {
71- BUG_WEBHOOKS_FEATURE_FLAG: "on",
72+ DISABLE_BUG_WEBHOOKS_FEATURE_FLAG: "on",
73 }
74 )
75 )
76diff --git a/lib/lp/registry/browser/distribution.py b/lib/lp/registry/browser/distribution.py
77index b990f6f..dd1f43e 100644
78--- a/lib/lp/registry/browser/distribution.py
79+++ b/lib/lp/registry/browser/distribution.py
80@@ -83,7 +83,7 @@ from lp.bugs.browser.structuralsubscription import (
81 StructuralSubscriptionTargetTraversalMixin,
82 expose_structural_subscription_data_to_js,
83 )
84-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
85+from lp.bugs.interfaces.bugtarget import DISABLE_BUG_WEBHOOKS_FEATURE_FLAG
86 from lp.buildmaster.interfaces.processor import IProcessorSet
87 from lp.code.browser.vcslisting import TargetDefaultVCSNavigationMixin
88 from lp.registry.browser import RegistryEditFormView, add_subscribe_link
89@@ -440,7 +440,7 @@ class DistributionNavigationMenu(NavigationMenu, DistributionLinksMixin):
90 "+webhooks",
91 "Manage webhooks",
92 icon="edit",
93- enabled=bool(getFeatureFlag(BUG_WEBHOOKS_FEATURE_FLAG)),
94+ enabled=not getFeatureFlag(DISABLE_BUG_WEBHOOKS_FEATURE_FLAG),
95 )
96
97
98diff --git a/lib/lp/registry/browser/distributionsourcepackage.py b/lib/lp/registry/browser/distributionsourcepackage.py
99index e0d960a..ebd3895 100644
100--- a/lib/lp/registry/browser/distributionsourcepackage.py
101+++ b/lib/lp/registry/browser/distributionsourcepackage.py
102@@ -42,7 +42,7 @@ from lp.bugs.browser.structuralsubscription import (
103 StructuralSubscriptionTargetTraversalMixin,
104 expose_structural_subscription_data_to_js,
105 )
106-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
107+from lp.bugs.interfaces.bugtarget import DISABLE_BUG_WEBHOOKS_FEATURE_FLAG
108 from lp.bugs.interfaces.bugtask import BugTaskStatus
109 from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
110 from lp.code.browser.vcslisting import TargetDefaultVCSNavigationMixin
111@@ -179,7 +179,7 @@ class DistributionSourcePackageLinksMixin:
112 "+webhooks",
113 "Manage webhooks",
114 icon="edit",
115- enabled=bool(getFeatureFlag(BUG_WEBHOOKS_FEATURE_FLAG)),
116+ enabled=not getFeatureFlag(DISABLE_BUG_WEBHOOKS_FEATURE_FLAG),
117 )
118
119
120diff --git a/lib/lp/registry/browser/product.py b/lib/lp/registry/browser/product.py
121index 907d7f1..fa45f0d 100644
122--- a/lib/lp/registry/browser/product.py
123+++ b/lib/lp/registry/browser/product.py
124@@ -111,7 +111,7 @@ from lp.bugs.browser.structuralsubscription import (
125 StructuralSubscriptionTargetTraversalMixin,
126 expose_structural_subscription_data_to_js,
127 )
128-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
129+from lp.bugs.interfaces.bugtarget import DISABLE_BUG_WEBHOOKS_FEATURE_FLAG
130 from lp.bugs.interfaces.bugtask import RESOLVED_BUGTASK_STATUSES
131 from lp.charms.browser.hascharmrecipes import HasCharmRecipesMenuMixin
132 from lp.code.browser.branchref import BranchRef
133@@ -521,7 +521,7 @@ class ProductEditLinksMixin(StructuralSubscriptionMenuMixin):
134 "+webhooks",
135 "Manage webhooks",
136 icon="edit",
137- enabled=bool(getFeatureFlag(BUG_WEBHOOKS_FEATURE_FLAG)),
138+ enabled=not getFeatureFlag(DISABLE_BUG_WEBHOOKS_FEATURE_FLAG),
139 )
140
141
142diff --git a/lib/lp/services/features/flags.py b/lib/lp/services/features/flags.py
143index 5d42d9d..4ed46ff 100644
144--- a/lib/lp/services/features/flags.py
145+++ b/lib/lp/services/features/flags.py
146@@ -296,9 +296,10 @@ flag_info = sorted(
147 "",
148 ),
149 (
150- "bugs.webhooks.enabled",
151+ "bugs.webhooks.disabled",
152 "boolean",
153- "If true, allow adding webhooks to bug updates and comments",
154+ "If true, disable webhooks from being triggered for bug updates "
155+ "and comments.",
156 "",
157 "",
158 "",
159diff --git a/lib/lp/services/webhooks/tests/test_browser.py b/lib/lp/services/webhooks/tests/test_browser.py
160index 4392228..7a73803 100644
161--- a/lib/lp/services/webhooks/tests/test_browser.py
162+++ b/lib/lp/services/webhooks/tests/test_browser.py
163@@ -10,7 +10,6 @@ import transaction
164 from testtools.matchers import MatchesAll, MatchesStructure, Not
165 from zope.component import getUtility
166
167-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
168 from lp.charms.interfaces.charmrecipe import (
169 CHARM_RECIPE_ALLOW_CREATE,
170 CHARM_RECIPE_WEBHOOKS_FEATURE_FLAG,
171@@ -192,14 +191,12 @@ class BugUpdateTestHelpersBase:
172
173 class ProductTestHelpers(BugUpdateTestHelpersBase):
174 def makeTarget(self):
175- self.useFixture(FeatureFixture({BUG_WEBHOOKS_FEATURE_FLAG: "on"}))
176 owner = self.factory.makePerson()
177 return self.factory.makeProduct(owner=owner)
178
179
180 class DistributionTestHelpers(BugUpdateTestHelpersBase):
181 def makeTarget(self):
182- self.useFixture(FeatureFixture({BUG_WEBHOOKS_FEATURE_FLAG: "on"}))
183 owner = self.factory.makePerson()
184 return self.factory.makeDistribution(owner=owner)
185
186@@ -209,7 +206,6 @@ class DistributionSourcePackageTestHelpers(BugUpdateTestHelpersBase):
187 return self.target.distribution.owner
188
189 def makeTarget(self):
190- self.useFixture(FeatureFixture({BUG_WEBHOOKS_FEATURE_FLAG: "on"}))
191 return self.factory.makeDistributionSourcePackage()
192
193
194diff --git a/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst b/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst
195index 72471e9..ab342f1 100644
196--- a/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst
197+++ b/lib/lp/soyuz/stories/distribution/xx-distribution-packages.rst
198@@ -333,6 +333,7 @@ menu, and a "Subscribers" portlet.
199 Subscribe to bug mail
200 Edit bug mail
201 Configure bug tracker
202+ Manage webhooks
203
204 >>> print(
205 ... extract_text(find_tag_by_id(user_browser.contents, "involvement"))
206diff --git a/lib/lp/soyuz/tests/test_packagecopyjob.py b/lib/lp/soyuz/tests/test_packagecopyjob.py
207index f4d2e53..ddebebd 100644
208--- a/lib/lp/soyuz/tests/test_packagecopyjob.py
209+++ b/lib/lp/soyuz/tests/test_packagecopyjob.py
210@@ -18,7 +18,6 @@ from zope.component import getUtility
211 from zope.security.interfaces import Unauthorized
212 from zope.security.proxy import removeSecurityProxy
213
214-from lp.bugs.interfaces.bugtarget import BUG_WEBHOOKS_FEATURE_FLAG
215 from lp.bugs.interfaces.bugtask import BugTaskStatus
216 from lp.registry.interfaces.pocket import PackagePublishingPocket
217 from lp.registry.interfaces.series import SeriesStatus
218@@ -1664,16 +1663,6 @@ class PlainPackageCopyJobTests(TestCaseWithFactory, LocalTestHelper):
219 def test_copying_closes_bugs_with_webhooks(self):
220 # Copying a package into a primary archive closes any bugs mentioned
221 # in its recent changelog, including triggering their webhooks.
222-
223- # Set bug webhooks feature flag on for the purpose of this test
224- self.useFixture(
225- FeatureFixture(
226- {
227- BUG_WEBHOOKS_FEATURE_FLAG: "on",
228- }
229- )
230- )
231-
232 target_archive = self.factory.makeArchive(
233 self.distroseries.distribution, purpose=ArchivePurpose.PRIMARY
234 )

Subscribers

People subscribed via source and target branches

to status/vote changes: