Merge lp:~stevenk/launchpad/drop-psc into lp:launchpad
- drop-psc
- Merge into devel
Proposed by
Steve Kowalik
Status: | Merged |
---|---|
Approved by: | Robert Collins |
Approved revision: | no longer in the source branch. |
Merged at revision: | 12850 |
Proposed branch: | lp:~stevenk/launchpad/drop-psc |
Merge into: | lp:launchpad |
Diff against target: |
340 lines (+0/-212) 3 files modified
database/schema/security.cfg (+0/-3) lib/lp/scripts/garbo.py (+0/-137) lib/lp/scripts/tests/test_garbo.py (+0/-72) |
To merge this branch: | bzr merge lp:~stevenk/launchpad/drop-psc |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Collins (community) | Approve | ||
William Grant | code* | Approve | |
Review via email: mp+57807@code.launchpad.net |
Commit message
[r=lifeless,
Description of the change
After running for one month, and processing the changelogs for as-near-
To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote : | # |
Revision history for this message
William Grant (wgrant) wrote : | # |
Looks good. No need to wait.
review:
Approve
(code*)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'database/schema/security.cfg' | |||
2 | --- database/schema/security.cfg 2011-04-06 15:35:05 +0000 | |||
3 | +++ database/schema/security.cfg 2011-04-15 05:03:31 +0000 | |||
4 | @@ -2260,9 +2260,6 @@ | |||
5 | 2260 | public.job = SELECT, INSERT, DELETE | 2260 | public.job = SELECT, INSERT, DELETE |
6 | 2261 | public.branchjob = SELECT, DELETE | 2261 | public.branchjob = SELECT, DELETE |
7 | 2262 | public.bugjob = SELECT, INSERT | 2262 | public.bugjob = SELECT, INSERT |
8 | 2263 | public.libraryfilealias = SELECT, INSERT | ||
9 | 2264 | public.libraryfilecontent = SELECT, INSERT | ||
10 | 2265 | public.sourcepackagerelease = SELECT, UPDATE | ||
11 | 2266 | 2263 | ||
12 | 2267 | [garbo_daily] | 2264 | [garbo_daily] |
13 | 2268 | type=user | 2265 | type=user |
14 | 2269 | 2266 | ||
15 | === modified file 'lib/lp/scripts/garbo.py' | |||
16 | --- lib/lp/scripts/garbo.py 2011-04-12 08:58:38 +0000 | |||
17 | +++ lib/lp/scripts/garbo.py 2011-04-15 05:03:31 +0000 | |||
18 | @@ -13,21 +13,14 @@ | |||
19 | 13 | datetime, | 13 | datetime, |
20 | 14 | timedelta, | 14 | timedelta, |
21 | 15 | ) | 15 | ) |
22 | 16 | from fixtures import TempDir | ||
23 | 17 | import logging | 16 | import logging |
24 | 18 | import multiprocessing | 17 | import multiprocessing |
25 | 19 | import os | ||
26 | 20 | import signal | ||
27 | 21 | import subprocess | ||
28 | 22 | import threading | 18 | import threading |
29 | 23 | import time | 19 | import time |
30 | 24 | 20 | ||
31 | 25 | from psycopg2 import IntegrityError | 21 | from psycopg2 import IntegrityError |
32 | 26 | import pytz | 22 | import pytz |
33 | 27 | from storm.expr import LeftJoin | ||
34 | 28 | from storm.locals import ( | 23 | from storm.locals import ( |
35 | 29 | And, | ||
36 | 30 | Count, | ||
37 | 31 | Max, | 24 | Max, |
38 | 32 | Min, | 25 | Min, |
39 | 33 | SQL, | 26 | SQL, |
40 | @@ -51,7 +44,6 @@ | |||
41 | 51 | from canonical.launchpad.database.oauth import OAuthNonce | 44 | from canonical.launchpad.database.oauth import OAuthNonce |
42 | 52 | from canonical.launchpad.database.openidconsumer import OpenIDConsumerNonce | 45 | from canonical.launchpad.database.openidconsumer import OpenIDConsumerNonce |
43 | 53 | from canonical.launchpad.interfaces.emailaddress import EmailAddressStatus | 46 | from canonical.launchpad.interfaces.emailaddress import EmailAddressStatus |
44 | 54 | from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet | ||
45 | 55 | from canonical.launchpad.interfaces.lpstorm import IMasterStore | 47 | from canonical.launchpad.interfaces.lpstorm import IMasterStore |
46 | 56 | from canonical.launchpad.utilities.looptuner import TunableLoop | 48 | from canonical.launchpad.utilities.looptuner import TunableLoop |
47 | 57 | from canonical.launchpad.webapp.interfaces import ( | 49 | from canonical.launchpad.webapp.interfaces import ( |
48 | @@ -59,9 +51,6 @@ | |||
49 | 59 | MAIN_STORE, | 51 | MAIN_STORE, |
50 | 60 | MASTER_FLAVOR, | 52 | MASTER_FLAVOR, |
51 | 61 | ) | 53 | ) |
52 | 62 | from canonical.librarian.utils import copy_and_close | ||
53 | 63 | from lp.archiveuploader.dscfile import findFile | ||
54 | 64 | from lp.archiveuploader.nascentuploadfile import UploadError | ||
55 | 65 | from lp.bugs.interfaces.bug import IBugSet | 54 | from lp.bugs.interfaces.bug import IBugSet |
56 | 66 | from lp.bugs.model.bug import Bug | 55 | from lp.bugs.model.bug import Bug |
57 | 67 | from lp.bugs.model.bugattachment import BugAttachment | 56 | from lp.bugs.model.bugattachment import BugAttachment |
58 | @@ -82,14 +71,11 @@ | |||
59 | 82 | from lp.registry.model.person import Person | 71 | from lp.registry.model.person import Person |
60 | 83 | from lp.services.job.model.job import Job | 72 | from lp.services.job.model.job import Job |
61 | 84 | from lp.services.log.logger import PrefixFilter | 73 | from lp.services.log.logger import PrefixFilter |
62 | 85 | from lp.services.memcache.interfaces import IMemcacheClient | ||
63 | 86 | from lp.services.scripts.base import ( | 74 | from lp.services.scripts.base import ( |
64 | 87 | LaunchpadCronScript, | 75 | LaunchpadCronScript, |
65 | 88 | SilentLaunchpadScriptFailure, | 76 | SilentLaunchpadScriptFailure, |
66 | 89 | ) | 77 | ) |
67 | 90 | from lp.services.session.model import SessionData | 78 | from lp.services.session.model import SessionData |
68 | 91 | from lp.soyuz.model.files import SourcePackageReleaseFile | ||
69 | 92 | from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease | ||
70 | 93 | from lp.translations.interfaces.potemplate import IPOTemplateSet | 79 | from lp.translations.interfaces.potemplate import IPOTemplateSet |
71 | 94 | from lp.translations.model.potranslation import POTranslation | 80 | from lp.translations.model.potranslation import POTranslation |
72 | 95 | 81 | ||
73 | @@ -97,10 +83,6 @@ | |||
74 | 97 | ONE_DAY_IN_SECONDS = 24*60*60 | 83 | ONE_DAY_IN_SECONDS = 24*60*60 |
75 | 98 | 84 | ||
76 | 99 | 85 | ||
77 | 100 | def subprocess_setup(): | ||
78 | 101 | signal.signal(signal.SIGPIPE, signal.SIG_DFL) | ||
79 | 102 | |||
80 | 103 | |||
81 | 104 | class BulkPruner(TunableLoop): | 86 | class BulkPruner(TunableLoop): |
82 | 105 | """A abstract ITunableLoop base class for simple pruners. | 87 | """A abstract ITunableLoop base class for simple pruners. |
83 | 106 | 88 | ||
84 | @@ -839,124 +821,6 @@ | |||
85 | 839 | self.done = True | 821 | self.done = True |
86 | 840 | 822 | ||
87 | 841 | 823 | ||
88 | 842 | class PopulateSPRChangelogs(TunableLoop): | ||
89 | 843 | maximum_chunk_size = 1 | ||
90 | 844 | |||
91 | 845 | def __init__(self, log, abort_time=None): | ||
92 | 846 | super(PopulateSPRChangelogs, self).__init__(log, abort_time) | ||
93 | 847 | value = getUtility(IMemcacheClient).get('populate-spr-changelogs') | ||
94 | 848 | if not value: | ||
95 | 849 | self.start_at = 0 | ||
96 | 850 | else: | ||
97 | 851 | self.start_at = value | ||
98 | 852 | self.finish_at = self.getCandidateSPRs(0).last() | ||
99 | 853 | |||
100 | 854 | def getCandidateSPRs(self, start_at): | ||
101 | 855 | return IMasterStore(SourcePackageRelease).using( | ||
102 | 856 | SourcePackageRelease, | ||
103 | 857 | # Find any SPRFs that have expired (LFA.content IS NULL). | ||
104 | 858 | LeftJoin( | ||
105 | 859 | SourcePackageReleaseFile, | ||
106 | 860 | SourcePackageReleaseFile.sourcepackagereleaseID == | ||
107 | 861 | SourcePackageRelease.id), | ||
108 | 862 | LeftJoin( | ||
109 | 863 | LibraryFileAlias, | ||
110 | 864 | And(LibraryFileAlias.id == | ||
111 | 865 | SourcePackageReleaseFile.libraryfileID, | ||
112 | 866 | LibraryFileAlias.content == None)), | ||
113 | 867 | # And exclude any SPRs that have any expired SPRFs. | ||
114 | 868 | ).find( | ||
115 | 869 | SourcePackageRelease.id, | ||
116 | 870 | SourcePackageRelease.id >= start_at, | ||
117 | 871 | SourcePackageRelease.changelog == None, | ||
118 | 872 | ).group_by(SourcePackageRelease.id).having( | ||
119 | 873 | Count(LibraryFileAlias) == 0 | ||
120 | 874 | ).order_by(SourcePackageRelease.id) | ||
121 | 875 | |||
122 | 876 | def isDone(self): | ||
123 | 877 | return self.start_at > self.finish_at | ||
124 | 878 | |||
125 | 879 | def __call__(self, chunk_size): | ||
126 | 880 | for sprid in self.getCandidateSPRs(self.start_at)[:chunk_size]: | ||
127 | 881 | spr = SourcePackageRelease.get(sprid) | ||
128 | 882 | with TempDir() as tmp_dir: | ||
129 | 883 | dsc_file = None | ||
130 | 884 | |||
131 | 885 | # Grab the files from the librarian into a temporary | ||
132 | 886 | # directory. | ||
133 | 887 | try: | ||
134 | 888 | for sprf in spr.files: | ||
135 | 889 | dest = os.path.join( | ||
136 | 890 | tmp_dir.path, sprf.libraryfile.filename) | ||
137 | 891 | dest_file = open(dest, 'w') | ||
138 | 892 | sprf.libraryfile.open() | ||
139 | 893 | copy_and_close(sprf.libraryfile, dest_file) | ||
140 | 894 | if dest.endswith('.dsc'): | ||
141 | 895 | dsc_file = dest | ||
142 | 896 | except LookupError: | ||
143 | 897 | self.log.warning( | ||
144 | 898 | 'SPR %d (%s %s) has missing library files.' % ( | ||
145 | 899 | spr.id, spr.name, spr.version)) | ||
146 | 900 | continue | ||
147 | 901 | |||
148 | 902 | if dsc_file is None: | ||
149 | 903 | self.log.warning( | ||
150 | 904 | 'SPR %d (%s %s) has no DSC.' % ( | ||
151 | 905 | spr.id, spr.name, spr.version)) | ||
152 | 906 | continue | ||
153 | 907 | |||
154 | 908 | # Extract the source package. Throw away stdout/stderr | ||
155 | 909 | # -- we only really care about the return code. | ||
156 | 910 | fnull = open('/dev/null', 'w') | ||
157 | 911 | ret = subprocess.call( | ||
158 | 912 | ['dpkg-source', '-x', dsc_file, os.path.join( | ||
159 | 913 | tmp_dir.path, 'extracted')], | ||
160 | 914 | stdout=fnull, stderr=fnull, | ||
161 | 915 | preexec_fn=subprocess_setup) | ||
162 | 916 | fnull.close() | ||
163 | 917 | if ret != 0: | ||
164 | 918 | self.log.warning( | ||
165 | 919 | 'SPR %d (%s %s) failed to unpack: returned %d' % ( | ||
166 | 920 | spr.id, spr.name, spr.version, ret)) | ||
167 | 921 | continue | ||
168 | 922 | |||
169 | 923 | # We have an extracted source package. Let's get the | ||
170 | 924 | # changelog. findFile ensures that it's not too huge, and | ||
171 | 925 | # not a symlink. | ||
172 | 926 | try: | ||
173 | 927 | changelog_path = findFile( | ||
174 | 928 | tmp_dir.path, 'debian/changelog') | ||
175 | 929 | except UploadError, e: | ||
176 | 930 | changelog_path = None | ||
177 | 931 | self.log.warning( | ||
178 | 932 | 'SPR %d (%s %s) changelog could not be ' | ||
179 | 933 | 'imported: %s' % ( | ||
180 | 934 | spr.id, spr.name, spr.version, e)) | ||
181 | 935 | if changelog_path: | ||
182 | 936 | # The LFA should be restricted only if there aren't any | ||
183 | 937 | # public publications. | ||
184 | 938 | restricted = not any( | ||
185 | 939 | not a.private for a in spr.published_archives) | ||
186 | 940 | spr.changelog = getUtility(ILibraryFileAliasSet).create( | ||
187 | 941 | 'changelog', | ||
188 | 942 | os.stat(changelog_path).st_size, | ||
189 | 943 | open(changelog_path, "r"), | ||
190 | 944 | "text/x-debian-source-changelog", | ||
191 | 945 | restricted=restricted) | ||
192 | 946 | self.log.info('SPR %d (%s %s) changelog imported.' % ( | ||
193 | 947 | spr.id, spr.name, spr.version)) | ||
194 | 948 | else: | ||
195 | 949 | self.log.warning('SPR %d (%s %s) had no changelog.' % ( | ||
196 | 950 | spr.id, spr.name, spr.version)) | ||
197 | 951 | |||
198 | 952 | self.start_at = spr.id + 1 | ||
199 | 953 | result = getUtility(IMemcacheClient).set( | ||
200 | 954 | 'populate-spr-changelogs', self.start_at) | ||
201 | 955 | if not result: | ||
202 | 956 | self.log.warning('Failed to set start_at in memcache.') | ||
203 | 957 | transaction.commit() | ||
204 | 958 | |||
205 | 959 | |||
206 | 960 | class BaseDatabaseGarbageCollector(LaunchpadCronScript): | 824 | class BaseDatabaseGarbageCollector(LaunchpadCronScript): |
207 | 961 | """Abstract base class to run a collection of TunableLoops.""" | 825 | """Abstract base class to run a collection of TunableLoops.""" |
208 | 962 | script_name = None # Script name for locking and database user. Override. | 826 | script_name = None # Script name for locking and database user. Override. |
209 | @@ -1122,7 +986,6 @@ | |||
210 | 1122 | UnusedSessionPruner, | 986 | UnusedSessionPruner, |
211 | 1123 | DuplicateSessionPruner, | 987 | DuplicateSessionPruner, |
212 | 1124 | BugHeatUpdater, | 988 | BugHeatUpdater, |
213 | 1125 | PopulateSPRChangelogs, | ||
214 | 1126 | ] | 989 | ] |
215 | 1127 | experimental_tunable_loops = [] | 990 | experimental_tunable_loops = [] |
216 | 1128 | 991 | ||
217 | 1129 | 992 | ||
218 | === modified file 'lib/lp/scripts/tests/test_garbo.py' | |||
219 | --- lib/lp/scripts/tests/test_garbo.py 2011-04-08 14:10:32 +0000 | |||
220 | +++ lib/lp/scripts/tests/test_garbo.py 2011-04-15 05:03:31 +0000 | |||
221 | @@ -10,11 +10,8 @@ | |||
222 | 10 | datetime, | 10 | datetime, |
223 | 11 | timedelta, | 11 | timedelta, |
224 | 12 | ) | 12 | ) |
225 | 13 | from fixtures import TempDir | ||
226 | 14 | import logging | 13 | import logging |
227 | 15 | import os | ||
228 | 16 | from StringIO import StringIO | 14 | from StringIO import StringIO |
229 | 17 | import subprocess | ||
230 | 18 | import time | 15 | import time |
231 | 19 | 16 | ||
232 | 20 | from pytz import UTC | 17 | from pytz import UTC |
233 | @@ -42,7 +39,6 @@ | |||
234 | 42 | from canonical.launchpad.database.oauth import OAuthNonce | 39 | from canonical.launchpad.database.oauth import OAuthNonce |
235 | 43 | from canonical.launchpad.database.openidconsumer import OpenIDConsumerNonce | 40 | from canonical.launchpad.database.openidconsumer import OpenIDConsumerNonce |
236 | 44 | from canonical.launchpad.interfaces.emailaddress import EmailAddressStatus | 41 | from canonical.launchpad.interfaces.emailaddress import EmailAddressStatus |
237 | 45 | from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet | ||
238 | 46 | from canonical.launchpad.interfaces.lpstorm import IMasterStore | 42 | from canonical.launchpad.interfaces.lpstorm import IMasterStore |
239 | 47 | from canonical.launchpad.scripts.tests import run_script | 43 | from canonical.launchpad.scripts.tests import run_script |
240 | 48 | from canonical.launchpad.webapp.interfaces import ( | 44 | from canonical.launchpad.webapp.interfaces import ( |
241 | @@ -56,7 +52,6 @@ | |||
242 | 56 | LaunchpadZopelessLayer, | 52 | LaunchpadZopelessLayer, |
243 | 57 | ZopelessDatabaseLayer, | 53 | ZopelessDatabaseLayer, |
244 | 58 | ) | 54 | ) |
245 | 59 | from lp.archiveuploader.dscfile import findFile | ||
246 | 60 | from lp.bugs.model.bugnotification import ( | 55 | from lp.bugs.model.bugnotification import ( |
247 | 61 | BugNotification, | 56 | BugNotification, |
248 | 62 | BugNotificationRecipient, | 57 | BugNotificationRecipient, |
249 | @@ -73,7 +68,6 @@ | |||
250 | 73 | ) | 68 | ) |
251 | 74 | from lp.code.model.codeimportevent import CodeImportEvent | 69 | from lp.code.model.codeimportevent import CodeImportEvent |
252 | 75 | from lp.code.model.codeimportresult import CodeImportResult | 70 | from lp.code.model.codeimportresult import CodeImportResult |
253 | 76 | from lp.registry.interfaces.distribution import IDistributionSet | ||
254 | 77 | from lp.registry.interfaces.person import ( | 71 | from lp.registry.interfaces.person import ( |
255 | 78 | IPersonSet, | 72 | IPersonSet, |
256 | 79 | PersonCreationRationale, | 73 | PersonCreationRationale, |
257 | @@ -93,8 +87,6 @@ | |||
258 | 93 | SessionData, | 87 | SessionData, |
259 | 94 | SessionPkgData, | 88 | SessionPkgData, |
260 | 95 | ) | 89 | ) |
261 | 96 | from lp.soyuz.enums import PackagePublishingStatus | ||
262 | 97 | from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease | ||
263 | 98 | from lp.testing import ( | 90 | from lp.testing import ( |
264 | 99 | TestCase, | 91 | TestCase, |
265 | 100 | TestCaseWithFactory, | 92 | TestCaseWithFactory, |
266 | @@ -114,13 +106,6 @@ | |||
267 | 114 | 106 | ||
268 | 115 | def test_hourly_script(self): | 107 | def test_hourly_script(self): |
269 | 116 | """Ensure garbo-hourly.py actually runs.""" | 108 | """Ensure garbo-hourly.py actually runs.""" |
270 | 117 | # Our sampledata doesn't contain anything that PopulateSPRChangelogs | ||
271 | 118 | # can process without errors, so it's easier to just set all of the | ||
272 | 119 | # changelogs to a random LFA. We can't just expire every LFA, since | ||
273 | 120 | # a bunch of SPRs have no SPRFs at all. | ||
274 | 121 | IMasterStore(SourcePackageRelease).find(SourcePackageRelease).set( | ||
275 | 122 | changelogID=1) | ||
276 | 123 | transaction.commit() # run_script() is a different process. | ||
277 | 124 | rv, out, err = run_script( | 109 | rv, out, err = run_script( |
278 | 125 | "cronscripts/garbo-hourly.py", ["-q"], expect_returncode=0) | 110 | "cronscripts/garbo-hourly.py", ["-q"], expect_returncode=0) |
279 | 126 | self.failIf(out.strip(), "Output to stdout: %s" % out) | 111 | self.failIf(out.strip(), "Output to stdout: %s" % out) |
280 | @@ -889,60 +874,3 @@ | |||
281 | 889 | """ % sqlbase.quote(template.id)).get_one() | 874 | """ % sqlbase.quote(template.id)).get_one() |
282 | 890 | 875 | ||
283 | 891 | self.assertEqual(1, count) | 876 | self.assertEqual(1, count) |
284 | 892 | |||
285 | 893 | def upload_to_debian(self, restricted=False): | ||
286 | 894 | sid = getUtility(IDistributionSet)['debian']['sid'] | ||
287 | 895 | spn = self.factory.makeSourcePackageName('9wm') | ||
288 | 896 | spr = self.factory.makeSourcePackageRelease( | ||
289 | 897 | sourcepackagename=spn, version='1.2-7', distroseries=sid) | ||
290 | 898 | archive = sid.main_archive | ||
291 | 899 | if restricted: | ||
292 | 900 | archive = self.factory.makeArchive( | ||
293 | 901 | distribution=sid.distribution, private=True) | ||
294 | 902 | self.factory.makeSourcePackagePublishingHistory( | ||
295 | 903 | sourcepackagerelease=spr, archive=archive, | ||
296 | 904 | status=PackagePublishingStatus.PUBLISHED) | ||
297 | 905 | for name in ( | ||
298 | 906 | '9wm_1.2-7.diff.gz', '9wm_1.2.orig.tar.gz', '9wm_1.2-7.dsc'): | ||
299 | 907 | path = os.path.join( | ||
300 | 908 | 'lib/lp/soyuz/scripts/tests/gina_test_archive/pool/main/9', | ||
301 | 909 | '9wm', name) | ||
302 | 910 | lfa = getUtility(ILibraryFileAliasSet).create( | ||
303 | 911 | name, os.stat(path).st_size, open(path, 'r'), | ||
304 | 912 | 'application/octet-stream', restricted=restricted) | ||
305 | 913 | spr.addFile(lfa) | ||
306 | 914 | with TempDir() as tmp_dir: | ||
307 | 915 | fnull = open('/dev/null', 'w') | ||
308 | 916 | ret = subprocess.call( | ||
309 | 917 | ['dpkg-source', '-x', path, os.path.join( | ||
310 | 918 | tmp_dir.path, 'extracted')], | ||
311 | 919 | stdout=fnull, stderr=fnull) | ||
312 | 920 | fnull.close() | ||
313 | 921 | self.assertEqual(0, ret) | ||
314 | 922 | changelog_path = findFile(tmp_dir.path, 'debian/changelog') | ||
315 | 923 | changelog = open(changelog_path, 'r').read() | ||
316 | 924 | transaction.commit() # .runHourly() switches dbuser. | ||
317 | 925 | return (spr, changelog) | ||
318 | 926 | |||
319 | 927 | def test_populateSPRChangelogs(self): | ||
320 | 928 | # We set SPR.changelog for imported records from Debian. | ||
321 | 929 | LaunchpadZopelessLayer.switchDbUser('testadmin') | ||
322 | 930 | spr, changelog = self.upload_to_debian() | ||
323 | 931 | collector = self.runHourly() | ||
324 | 932 | log = self.log_buffer.getvalue() | ||
325 | 933 | self.assertTrue( | ||
326 | 934 | 'SPR %d (9wm 1.2-7) changelog imported.' % spr.id in log) | ||
327 | 935 | self.assertFalse(spr.changelog == None) | ||
328 | 936 | self.assertFalse(spr.changelog.restricted) | ||
329 | 937 | self.assertEqual(changelog, spr.changelog.read()) | ||
330 | 938 | |||
331 | 939 | def test_populateSPRChangelogs_restricted_sprf(self): | ||
332 | 940 | LaunchpadZopelessLayer.switchDbUser('testadmin') | ||
333 | 941 | spr, changelog = self.upload_to_debian(restricted=True) | ||
334 | 942 | collector = self.runHourly() | ||
335 | 943 | log = self.log_buffer.getvalue() | ||
336 | 944 | self.assertTrue( | ||
337 | 945 | 'SPR %d (9wm 1.2-7) changelog imported.' % spr.id in log) | ||
338 | 946 | self.assertFalse(spr.changelog == None) | ||
339 | 947 | self.assertTrue(spr.changelog.restricted) | ||
340 | 948 | self.assertEqual(changelog, spr.changelog.read()) |
You should wait till staging and qastaging are fully migrated too.
Otherwise bad things will happen as you qa stuff :).