Merge ~jugmac00/launchpad:populate-signedcodeofconduct.affirmed into launchpad:master

Proposed by Jürgen Gmach
Status: Merged
Approved by: Jürgen Gmach
Approved revision: 793c1946c14b56ecf6c433f17bb363ce4076565b
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~jugmac00/launchpad:populate-signedcodeofconduct.affirmed
Merge into: launchpad:master
Diff against target: 104 lines (+43/-0)
3 files modified
database/schema/security.cfg (+1/-0)
lib/lp/scripts/garbo.py (+25/-0)
lib/lp/scripts/tests/test_garbo.py (+17/-0)
Reviewer Review Type Date Requested Status
Colin Watson Approve
Review via email: mp+410227@code.launchpad.net

Commit message

Populate SignedCodeOfConduct.affirmed

To post a comment you must log in.
Revision history for this message
Jürgen Gmach (jugmac00) wrote (last edit ):

Attention: this is work in progress - the test currently does not pass.

It fails / errors with:

 lp.scripts.tests.test_garbo.TestGarbo.test_PopulateSignedCodeOfConductAffirmed

Error in test lp.scripts.tests.test_garbo.TestGarbo.test_PopulateSignedCodeOfConductAffirmed
Traceback (most recent call last):
testtools.testresult.real._StringException: librarian-log: {{{
2021-10-14 21:06:29+0530 [-] Loading /home/jugmac00/launchpad/launchpad/daemons/librarian.tac...
2021-10-14 21:06:31+0530 [-] Loaded.
2021-10-14 21:06:31+0530 [-] twistd 20.3.0 (/home/jugmac00/launchpad/launchpad/env/bin/python3 3.5.2) starting up.
2021-10-14 21:06:31+0530 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
2021-10-14 21:06:31+0530 [-] FileUploadFactory starting on 46629
2021-10-14 21:06:31+0530 [-] Starting factory <lp.services.librarianserver.libraryprotocol.FileUploadFactory object at 0x7efd137e7048>
2021-10-14 21:06:31+0530 [-] Site starting on 33159
2021-10-14 21:06:31+0530 [-] Starting factory <twisted.web.server.Site object at 0x7efd13798cc0>
2021-10-14 21:06:31+0530 [-] FileUploadFactory starting on 40011
2021-10-14 21:06:31+0530 [-] Starting factory <lp.services.librarianserver.libraryprotocol.FileUploadFactory object at 0x7efd131386a0>
2021-10-14 21:06:31+0530 [-] Site starting on 40651
2021-10-14 21:06:31+0530 [-] Starting factory <twisted.web.server.Site object at 0x7efd130f1f98>
2021-10-14 21:06:31+0530 [-] Not using upstream librarian
2021-10-14 21:06:31+0530 [-] daemon ready!
}}}

Traceback (most recent call last):
  File "/home/jugmac00/launchpad/launchpad/lib/lp/scripts/tests/test_garbo.py", line 448, in setUp
    self.runHourly()
  File "/home/jugmac00/launchpad/launchpad/lib/lp/scripts/tests/test_garbo.py", line 479, in runHourly
    collector.main()
  File "/home/jugmac00/launchpad/launchpad/lib/lp/scripts/garbo.py", line 1877, in main
    raise SilentLaunchpadScriptFailure(self.failure_count)
lp.services.scripts.base.SilentLaunchpadScriptFailure: 1

The "populator" itself works, ie when instantiating it with `PopulateSignedCodeOfConductAffirmed(log=None)`, which is even more puzzling.

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

I think your problem is probably that the "garbo" database user doesn't have the necessary permissions on that table. You can fix this in `database/schema/security.cfg`: the `[garbo]` section will need something like `public.signedcodeofconduct = SELECT, UPDATE`.

security.cfg changes are applied automatically on rollouts to our various instances, but in a development setup you'll need to run `for db in launchpad_empty launchpad_dev_template launchpad_dev launchpad_ftest_template launchpad_ftest_playground; do database/schema/security.py -d $db; done` (or `make schema`, but that wipes and replaces your local database rather than changing its permissions in place).

Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Thank you! Worked out nicely.

MP needs a new review.

Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Jürgen Gmach (jugmac00) wrote :

Thanks for the review!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/database/schema/security.cfg b/database/schema/security.cfg
2index 39822d1..03c81f2 100644
3--- a/database/schema/security.cfg
4+++ b/database/schema/security.cfg
5@@ -2534,6 +2534,7 @@ public.potmsgset = SELECT, DELETE
6 public.previewdiff = SELECT, DELETE
7 public.revisionauthor = SELECT, UPDATE
8 public.revisioncache = SELECT, DELETE
9+public.signedcodeofconduct = SELECT, UPDATE
10 public.snap = SELECT, UPDATE
11 public.snapbase = SELECT
12 public.snapbuild = SELECT, UPDATE
13diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
14index e2471dc..ce28426 100644
15--- a/lib/lp/scripts/garbo.py
16+++ b/lib/lp/scripts/garbo.py
17@@ -75,6 +75,7 @@ from lp.code.model.revision import (
18 )
19 from lp.oci.model.ocirecipebuild import OCIFile
20 from lp.registry.interfaces.person import IPersonSet
21+from lp.registry.model.codeofconduct import SignedCodeOfConduct
22 from lp.registry.model.person import Person
23 from lp.registry.model.product import Product
24 from lp.registry.model.sourcepackagename import SourcePackageName
25@@ -1764,6 +1765,29 @@ class PopulateSnapBuildStoreRevision(TunableLoop):
26 transaction.commit()
27
28
29+class PopulateSignedCodeOfConductAffirmed(TunableLoop):
30+ """Populates SignedCodeOfConduct.affirmed if not set"""
31+
32+ maximum_chunk_size = 5000
33+
34+ def __init__(self, log, abort_time=None):
35+ super().__init__(log, abort_time)
36+ self.store = IMasterStore(SignedCodeOfConduct)
37+
38+ def findSignedCodeOfConducts(self):
39+ return self.store.find(
40+ SignedCodeOfConduct,
41+ SignedCodeOfConduct.affirmed == None
42+ )
43+
44+ def isDone(self):
45+ return self.findSignedCodeOfConducts().is_empty()
46+
47+ def __call__(self, chunk_size):
48+ self.findSignedCodeOfConducts()[:chunk_size].set(affirmed=False)
49+ transaction.commit()
50+
51+
52 class BaseDatabaseGarbageCollector(LaunchpadCronScript):
53 """Abstract base class to run a collection of TunableLoops."""
54 script_name = None # Script name for locking and database user. Override.
55@@ -2024,6 +2048,7 @@ class HourlyDatabaseGarbageCollector(BaseDatabaseGarbageCollector):
56 GitRepositoryPruner,
57 RevisionCachePruner,
58 UnusedSessionPruner,
59+ PopulateSignedCodeOfConductAffirmed,
60 ]
61 experimental_tunable_loops = []
62
63diff --git a/lib/lp/scripts/tests/test_garbo.py b/lib/lp/scripts/tests/test_garbo.py
64index bb2bfb2..220d439 100644
65--- a/lib/lp/scripts/tests/test_garbo.py
66+++ b/lib/lp/scripts/tests/test_garbo.py
67@@ -84,6 +84,7 @@ from lp.registry.enums import (
68 from lp.registry.interfaces.accesspolicy import IAccessPolicySource
69 from lp.registry.interfaces.person import IPersonSet
70 from lp.registry.interfaces.teammembership import TeamMembershipStatus
71+from lp.registry.model.codeofconduct import SignedCodeOfConduct
72 from lp.registry.model.commercialsubscription import CommercialSubscription
73 from lp.registry.model.teammembership import TeamMembership
74 from lp.scripts.garbo import (
75@@ -96,6 +97,7 @@ from lp.scripts.garbo import (
76 load_garbo_job_state,
77 LoginTokenPruner,
78 OpenIDConsumerAssociationPruner,
79+ PopulateSignedCodeOfConductAffirmed,
80 PopulateSnapBuildStoreRevision,
81 ProductVCSPopulator,
82 save_garbo_job_state,
83@@ -2045,6 +2047,21 @@ class TestGarbo(FakeAdapterMixin, TestCaseWithFactory):
84 switch_dbuser('testadmin')
85 self.assertEqual(build1._store_upload_revision, 1)
86
87+ def test_PopulateSignedCodeOfConductAffirmed(self):
88+ switch_dbuser('testadmin')
89+ populator = PopulateSignedCodeOfConductAffirmed(log=None)
90+ for _ in range(5):
91+ person = self.factory.makePerson()
92+ SignedCodeOfConduct(owner=person).affirmed = None
93+
94+ result_set = populator.findSignedCodeOfConducts()
95+ self.assertGreater(result_set.count(), 0)
96+
97+ self.runHourly()
98+
99+ result_set = populator.findSignedCodeOfConducts()
100+ self.assertTrue(result_set.is_empty())
101+
102
103 class TestGarboTasks(TestCaseWithFactory):
104 layer = LaunchpadZopelessLayer

Subscribers

People subscribed via source and target branches

to status/vote changes: