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 (community) 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
diff --git a/database/schema/security.cfg b/database/schema/security.cfg
index 39822d1..03c81f2 100644
--- a/database/schema/security.cfg
+++ b/database/schema/security.cfg
@@ -2534,6 +2534,7 @@ public.potmsgset = SELECT, DELETE
2534public.previewdiff = SELECT, DELETE2534public.previewdiff = SELECT, DELETE
2535public.revisionauthor = SELECT, UPDATE2535public.revisionauthor = SELECT, UPDATE
2536public.revisioncache = SELECT, DELETE2536public.revisioncache = SELECT, DELETE
2537public.signedcodeofconduct = SELECT, UPDATE
2537public.snap = SELECT, UPDATE2538public.snap = SELECT, UPDATE
2538public.snapbase = SELECT2539public.snapbase = SELECT
2539public.snapbuild = SELECT, UPDATE2540public.snapbuild = SELECT, UPDATE
diff --git a/lib/lp/scripts/garbo.py b/lib/lp/scripts/garbo.py
index e2471dc..ce28426 100644
--- a/lib/lp/scripts/garbo.py
+++ b/lib/lp/scripts/garbo.py
@@ -75,6 +75,7 @@ from lp.code.model.revision import (
75 )75 )
76from lp.oci.model.ocirecipebuild import OCIFile76from lp.oci.model.ocirecipebuild import OCIFile
77from lp.registry.interfaces.person import IPersonSet77from lp.registry.interfaces.person import IPersonSet
78from lp.registry.model.codeofconduct import SignedCodeOfConduct
78from lp.registry.model.person import Person79from lp.registry.model.person import Person
79from lp.registry.model.product import Product80from lp.registry.model.product import Product
80from lp.registry.model.sourcepackagename import SourcePackageName81from lp.registry.model.sourcepackagename import SourcePackageName
@@ -1764,6 +1765,29 @@ class PopulateSnapBuildStoreRevision(TunableLoop):
1764 transaction.commit()1765 transaction.commit()
17651766
17661767
1768class PopulateSignedCodeOfConductAffirmed(TunableLoop):
1769 """Populates SignedCodeOfConduct.affirmed if not set"""
1770
1771 maximum_chunk_size = 5000
1772
1773 def __init__(self, log, abort_time=None):
1774 super().__init__(log, abort_time)
1775 self.store = IMasterStore(SignedCodeOfConduct)
1776
1777 def findSignedCodeOfConducts(self):
1778 return self.store.find(
1779 SignedCodeOfConduct,
1780 SignedCodeOfConduct.affirmed == None
1781 )
1782
1783 def isDone(self):
1784 return self.findSignedCodeOfConducts().is_empty()
1785
1786 def __call__(self, chunk_size):
1787 self.findSignedCodeOfConducts()[:chunk_size].set(affirmed=False)
1788 transaction.commit()
1789
1790
1767class BaseDatabaseGarbageCollector(LaunchpadCronScript):1791class BaseDatabaseGarbageCollector(LaunchpadCronScript):
1768 """Abstract base class to run a collection of TunableLoops."""1792 """Abstract base class to run a collection of TunableLoops."""
1769 script_name = None # Script name for locking and database user. Override.1793 script_name = None # Script name for locking and database user. Override.
@@ -2024,6 +2048,7 @@ class HourlyDatabaseGarbageCollector(BaseDatabaseGarbageCollector):
2024 GitRepositoryPruner,2048 GitRepositoryPruner,
2025 RevisionCachePruner,2049 RevisionCachePruner,
2026 UnusedSessionPruner,2050 UnusedSessionPruner,
2051 PopulateSignedCodeOfConductAffirmed,
2027 ]2052 ]
2028 experimental_tunable_loops = []2053 experimental_tunable_loops = []
20292054
diff --git a/lib/lp/scripts/tests/test_garbo.py b/lib/lp/scripts/tests/test_garbo.py
index bb2bfb2..220d439 100644
--- a/lib/lp/scripts/tests/test_garbo.py
+++ b/lib/lp/scripts/tests/test_garbo.py
@@ -84,6 +84,7 @@ from lp.registry.enums import (
84from lp.registry.interfaces.accesspolicy import IAccessPolicySource84from lp.registry.interfaces.accesspolicy import IAccessPolicySource
85from lp.registry.interfaces.person import IPersonSet85from lp.registry.interfaces.person import IPersonSet
86from lp.registry.interfaces.teammembership import TeamMembershipStatus86from lp.registry.interfaces.teammembership import TeamMembershipStatus
87from lp.registry.model.codeofconduct import SignedCodeOfConduct
87from lp.registry.model.commercialsubscription import CommercialSubscription88from lp.registry.model.commercialsubscription import CommercialSubscription
88from lp.registry.model.teammembership import TeamMembership89from lp.registry.model.teammembership import TeamMembership
89from lp.scripts.garbo import (90from lp.scripts.garbo import (
@@ -96,6 +97,7 @@ from lp.scripts.garbo import (
96 load_garbo_job_state,97 load_garbo_job_state,
97 LoginTokenPruner,98 LoginTokenPruner,
98 OpenIDConsumerAssociationPruner,99 OpenIDConsumerAssociationPruner,
100 PopulateSignedCodeOfConductAffirmed,
99 PopulateSnapBuildStoreRevision,101 PopulateSnapBuildStoreRevision,
100 ProductVCSPopulator,102 ProductVCSPopulator,
101 save_garbo_job_state,103 save_garbo_job_state,
@@ -2045,6 +2047,21 @@ class TestGarbo(FakeAdapterMixin, TestCaseWithFactory):
2045 switch_dbuser('testadmin')2047 switch_dbuser('testadmin')
2046 self.assertEqual(build1._store_upload_revision, 1)2048 self.assertEqual(build1._store_upload_revision, 1)
20472049
2050 def test_PopulateSignedCodeOfConductAffirmed(self):
2051 switch_dbuser('testadmin')
2052 populator = PopulateSignedCodeOfConductAffirmed(log=None)
2053 for _ in range(5):
2054 person = self.factory.makePerson()
2055 SignedCodeOfConduct(owner=person).affirmed = None
2056
2057 result_set = populator.findSignedCodeOfConducts()
2058 self.assertGreater(result_set.count(), 0)
2059
2060 self.runHourly()
2061
2062 result_set = populator.findSignedCodeOfConducts()
2063 self.assertTrue(result_set.is_empty())
2064
20482065
2049class TestGarboTasks(TestCaseWithFactory):2066class TestGarboTasks(TestCaseWithFactory):
2050 layer = LaunchpadZopelessLayer2067 layer = LaunchpadZopelessLayer

Subscribers

People subscribed via source and target branches

to status/vote changes: