launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #05272
[Merge] lp:~danilo/launchpad/bug-817398 into lp:launchpad
Данило Шеган has proposed merging lp:~danilo/launchpad/bug-817398 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #817398 in Launchpad itself: "Launchpad doesn't generate translation templates"
https://bugs.launchpad.net/launchpad/+bug/817398
For more details, see:
https://code.launchpad.net/~danilo/launchpad/bug-817398/+merge/79571
= Bug 817398: template generation (WIP) =
Template generation has stopped working when buildd default image has switched to Ubuntu Natty (as the development version). That included Python 2.7 by default and generate-translation-templates hard-coded Python 2.6 module path.
This is easy to fix, but this has been broken for quite some time (maybe a full year even) because there is no proper logging for TranslationTemplatesBuild jobs. I decided to introduce that to avoid further breakage going unnoticed for this long.
== Implementation details ==
1. configs/development/launchpad-lazr.conf: change the default development poppy port so it doesn't conflict with codehosting port, thus allowing both to be run locally simultaneously
2. utilities/make-lp-user fails for me with no default timeout function set, so setting one makes it work
3. generate-translation-templates is an actual fix for the bug 817398; as an extra measure of protection, I pass PYTHONPATH in the ultimate script run to ensure modules are found even if Python 2.8 ever comes out for instance
4. configure.zcml copies a similar declaration that SourcePackageRecipeBuild is using (otherwise, a removeSecurityProxy would have to be used inside buildmaster/model/manager.py when .status is being set, and in other places introduced in this branch)
5. translationtemplatebuild.py provides a nicer title for TranslationTemplateBuilds compared to the default, and provides a direct link to librarian files for logs from the builds (since we do not support private branches for template generation, no need to proxy these URLs).
6. translationtemplatesbuildbehavior.py introduces fetching of the log files and saving them like PackageBuildDerived does
I've only did the minimal test changes. I don't think I can spend more time on this branch, but I did spend a lot of time trying stuff out locally. Ideally, most of this code would be refactored to use the "generic" infrastructure provided by things like PackageBuildDerived, but that's more involved than it sounds.
== Tests ==
bin/test -vvt translationtemplatesbuild -t xx-build-behavior.txt -t TestPoppy
== Demo and Q/A ==
* Set up translation import for a project (translations.l.n/<project/+configure-translations and translations.l.n/<project>/trunk/+translations-settings
* Push a branch which should generate translation template (eg. lp:eog) to staging, link it to the trunk series (what was set-up above)
* Run cronscripts/scan-branches.py to scan the branch and generate translation templates build job
* Wait for build-manager to pick it up and build it (you may need to ask for it to be run on staging as "bin/twistd --logile ... --pidfile ... -y daemons/buildd-manager.tac -n" — -n to not daemonize it so you could see any exceptions if they happen)
* When the job finishes, it should keep the log in the builder history available from the builder page on launchpad.net/builders
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
configs/development/launchpad-lazr.conf
lib/canonical/buildd/generate-translation-templates
lib/canonical/buildd/debian/changelog
lib/lp/poppy/tests/test_poppy.py
lib/lp/translations/configure.zcml
lib/lp/translations/model/translationtemplatesbuild.py
lib/lp/translations/model/translationtemplatesbuildbehavior.py
lib/lp/translations/stories/buildfarm/xx-build-summary.txt
lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py
utilities/make-lp-user
./configs/development/launchpad-lazr.conf
92: Line exceeds 78 characters.
111: Line exceeds 78 characters.
125: Line exceeds 78 characters.
./lib/canonical/buildd/generate-translation-templates
59: Line exceeds 78 characters.
./lib/canonical/buildd/debian/changelog
232: Line exceeds 78 characters.
298: Line exceeds 78 characters.
488: Line exceeds 78 characters.
495: Line exceeds 78 characters.
516: Line exceeds 78 characters.
522: Line exceeds 78 characters.
528: Line exceeds 78 characters.
534: Line exceeds 78 characters.
541: Line exceeds 78 characters.
549: Line exceeds 78 characters.
556: Line exceeds 78 characters.
570: Line exceeds 78 characters.
576: Line exceeds 78 characters.
582: Line exceeds 78 characters.
590: Line exceeds 78 characters.
596: Line exceeds 78 characters.
603: Line exceeds 78 characters.
614: Line exceeds 78 characters.
623: Line exceeds 78 characters.
630: Line exceeds 78 characters.
636: Line exceeds 78 characters.
643: Line exceeds 78 characters.
649: Line exceeds 78 characters.
655: Line exceeds 78 characters.
662: Line exceeds 78 characters.
669: Line exceeds 78 characters.
676: Line exceeds 78 characters.
683: Line exceeds 78 characters.
689: Line exceeds 78 characters.
--
https://code.launchpad.net/~danilo/launchpad/bug-817398/+merge/79571
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~danilo/launchpad/bug-817398 into lp:launchpad.
=== modified file 'configs/development/launchpad-lazr.conf'
--- configs/development/launchpad-lazr.conf 2011-09-30 16:01:42 +0000
+++ configs/development/launchpad-lazr.conf 2011-10-19 09:02:48 +0000
@@ -239,6 +239,7 @@
authentication_endpoint: http://xmlrpc-private.launchpad.dev:8087/authserver
host_key_private=lib/lp/poppy/tests/poppy-sftp
host_key_public=lib/lp/poppy/tests/poppy-sftp.pub
+port: tcp:5023
[rabbitmq]
launch: True
=== modified file 'lib/canonical/buildd/debian/changelog'
--- lib/canonical/buildd/debian/changelog 2011-09-26 06:30:07 +0000
+++ lib/canonical/buildd/debian/changelog 2011-10-19 09:02:48 +0000
@@ -1,3 +1,9 @@
+launchpad-buildd (81) hardy-cat; urgency=low
+
+ * generate-translation-templates: switch to Python 2.7.
+
+ -- Danilo Šegan <danilo@xxxxxxxxxxxxx> Mon, 17 Oct 2011 14:46:13 +0200
+
launchpad-buildd (80) hardy-cat; urgency=low
* binfmt-support demonstrated umount ordering issues for us. LP: #851934
=== modified file 'lib/canonical/buildd/generate-translation-templates'
--- lib/canonical/buildd/generate-translation-templates 2010-12-21 17:52:32 +0000
+++ lib/canonical/buildd/generate-translation-templates 2011-10-19 09:02:48 +0000
@@ -41,7 +41,7 @@
BUILDD_PACKAGE=canonical/buildd
POTTERY=$BUILDD_PACKAGE/pottery
# The script should be smarter about detecting the python version.
-PYMODULES=/usr/lib/pymodules/python2.6
+PYMODULES=/usr/lib/pymodules/python2.7
echo -n "Default Python in the chroot is: "
$BUILD_CHROOT/usr/bin/python --version
@@ -62,4 +62,5 @@
# Enter chroot, switch back to unprivileged user, execute the generate script.
$SUDO $CHROOT $BUILD_CHROOT \
- $SU - $USER -c "$GENERATE_SCRIPT $BRANCH_URL $RESULT_NAME"
+ $SU - $USER \
+ -c "PYTHONPATH=$PYMODULES $GENERATE_SCRIPT $BRANCH_URL $RESULT_NAME"
=== modified file 'lib/lp/poppy/tests/test_poppy.py'
--- lib/lp/poppy/tests/test_poppy.py 2011-02-24 17:38:19 +0000
+++ lib/lp/poppy/tests/test_poppy.py 2011-10-19 09:02:48 +0000
@@ -83,7 +83,7 @@
def __init__(self, root_dir, factory):
self.root_dir = root_dir
self._factory = factory
- self.port = 5022
+ self.port = 5023
def addSSHKey(self, person, public_key_path):
f = open(public_key_path, 'r')
@@ -221,7 +221,7 @@
if transport is None:
transport = self.server.getTransport()
- transport.stat('foo/bar') # .stat will implicity chdir for us
+ transport.stat('foo/bar') # .stat will implicity chdir for us
self.server.disconnect(transport)
self.server.waitForClose()
@@ -400,7 +400,7 @@
self.assertRaises(
ftplib.error_perm,
f.storbinary,
- 'STOR '+'foo_source.changes',
+ 'STOR ' + 'foo_source.changes',
fake_file)
=== modified file 'lib/lp/translations/configure.zcml'
--- lib/lp/translations/configure.zcml 2011-08-29 00:13:22 +0000
+++ lib/lp/translations/configure.zcml 2011-10-19 09:02:48 +0000
@@ -659,7 +659,13 @@
<!-- TranslationTemplatesBuild -->
<class
class="lp.translations.model.translationtemplatesbuild.TranslationTemplatesBuild">
- <allow interface="lp.translations.interfaces.translationtemplatesbuild.ITranslationTemplatesBuild"/>
+ <require permission="launchpad.View" interface="lp.translations.interfaces.translationtemplatesbuild.ITranslationTemplatesBuild"/>
+ <!-- This is needed for BuildManager to run. The permission isn't
+ important; launchpad.Edit isn't actually held by anybody.
+ Inspired by the similar change for SourcePackageRecipeBuild. -->
+ <require permission="launchpad.Edit"
+ set_attributes="builder date_finished date_started log status" />
+
</class>
<securedutility
component="lp.translations.model.translationtemplatesbuild.TranslationTemplatesBuild"
=== modified file 'lib/lp/translations/model/translationtemplatesbuild.py'
--- lib/lp/translations/model/translationtemplatesbuild.py 2011-05-04 04:10:58 +0000
+++ lib/lp/translations/model/translationtemplatesbuild.py 2011-10-19 09:02:48 +0000
@@ -13,12 +13,10 @@
Reference,
Storm,
)
-from storm.store import Store
from zope.interface import (
classProvides,
implements,
)
-from zope.security.proxy import ProxyFactory
from canonical.launchpad.interfaces.lpstorm import IStore
from lp.buildmaster.model.buildfarmjob import BuildFarmJobDerived
@@ -49,6 +47,11 @@
branch_id = Int(name='branch', allow_none=False)
branch = Reference(branch_id, 'Branch.id')
+ @property
+ def title(self):
+ return u'Translation template build for %s' % (
+ self.branch.displayname)
+
def __init__(self, build_farm_job, branch):
super(TranslationTemplatesBuild, self).__init__()
self.build_farm_job = build_farm_job
@@ -110,3 +113,10 @@
return store.find(
TranslationTemplatesBuild,
TranslationTemplatesBuild.branch == branch)
+
+ @property
+ def log_url(self):
+ """See `IBuildFarmJob`."""
+ if self.log is None:
+ return None
+ return self.log.http_url
=== modified file 'lib/lp/translations/model/translationtemplatesbuildbehavior.py'
--- lib/lp/translations/model/translationtemplatesbuildbehavior.py 2011-09-07 15:10:38 +0000
+++ lib/lp/translations/model/translationtemplatesbuildbehavior.py 2011-10-19 09:02:48 +0000
@@ -11,7 +11,9 @@
'TranslationTemplatesBuildBehavior',
]
+import datetime
import os
+import pytz
import tempfile
from twisted.internet import defer
@@ -20,6 +22,7 @@
from zope.security.proxy import removeSecurityProxy
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
+from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interfaces.buildfarmjobbehavior import (
IBuildFarmJobBehavior,
)
@@ -111,6 +114,35 @@
if len(raw_slave_status) >= 4:
status['filemap'] = raw_slave_status[3]
+ def setBuildStatus(self, status):
+ self.build.status = status
+
+ @staticmethod
+ def getLogFromSlave(templates_build, queue_item):
+ """See `IPackageBuild`."""
+ SLAVE_LOG_FILENAME = 'buildlog'
+ builder = queue_item.builder
+ d = builder.transferSlaveFileToLibrarian(
+ SLAVE_LOG_FILENAME,
+ templates_build.buildfarmjob.getLogFileName(),
+ False)
+ return d
+
+ @staticmethod
+ def storeBuildInfo(build, queue_item, build_status):
+ """See `IPackageBuild`."""
+ def got_log(lfa_id):
+ build.build.log = lfa_id
+ build.build.builder = queue_item.builder
+ build.build.date_started = queue_item.date_started
+ # XXX cprov 20060615 bug=120584: Currently buildduration includes
+ # the scanner latency, it should really be asking the slave for
+ # the duration spent building locally.
+ build.build.date_finished = datetime.datetime.now(pytz.UTC)
+
+ d = build.getLogFromSlave(build, queue_item)
+ return d.addCallback(got_log)
+
def updateBuild_WAITING(self, queue_item, slave_status, logtail, logger):
"""Deal with a finished ("WAITING" state, perversely) build job.
@@ -139,6 +171,7 @@
# dangerous.
if filename is None:
logger.error("Build produced no tarball.")
+ self.setBuildStatus(BuildStatus.FULLYBUILT)
return
tarball_file = open(filename)
@@ -152,15 +185,23 @@
queue_item.specific_job.branch, tarball, logger)
logger.debug("Upload complete.")
finally:
+ self.setBuildStatus(BuildStatus.FULLYBUILT)
tarball_file.close()
os.remove(filename)
- if build_status == 'OK':
- logger.debug("Processing successful templates build.")
- filemap = slave_status.get('filemap')
- d = self._readTarball(queue_item, filemap, logger)
- d.addCallback(got_tarball)
- d.addCallback(clean_slave)
- return d
-
- return clean_slave(None)
+ def build_info_stored(ignored):
+ if build_status == 'OK':
+ self.setBuildStatus(BuildStatus.UPLOADING)
+ logger.debug("Processing successful templates build.")
+ filemap = slave_status.get('filemap')
+ d = self._readTarball(queue_item, filemap, logger)
+ d.addCallback(got_tarball)
+ d.addCallback(clean_slave)
+ return d
+
+ self.setBuildStatus(BuildStatus.FAILEDTOBUILD)
+ return clean_slave(None)
+
+ d = self.storeBuildInfo(self, queue_item, build_status)
+ d.addCallback(build_info_stored)
+ return d
=== modified file 'lib/lp/translations/stories/buildfarm/xx-build-summary.txt'
--- lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2011-07-01 19:17:03 +0000
+++ lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2011-10-19 09:02:48 +0000
@@ -157,5 +157,5 @@
Build history for ...
1 ... 1 of 1 result
...
- Translation template build
+ Translation template build for lp://dev/qblark
Build started ... and finished ... taking 5 minutes
=== modified file 'lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py'
--- lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2011-05-27 21:12:25 +0000
+++ lib/lp/translations/tests/test_translationtemplatesbuildbehavior.py 2011-10-19 09:02:48 +0000
@@ -3,8 +3,10 @@
"""Unit tests for TranslationTemplatesBuildBehavior."""
+import datetime
import logging
import os
+import pytz
from testtools.deferredruntest import AsynchronousDeferredRunTest
import transaction
@@ -17,6 +19,7 @@
from canonical.librarian.utils import copy_and_close
from canonical.testing.layers import LaunchpadZopelessLayer
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
+from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interfaces.buildfarmjobbehavior import (
IBuildFarmJobBehavior,
)
@@ -57,6 +60,7 @@
"""
self.builder = behavior._builder
self.specific_job = behavior.buildfarmjob
+ self.date_started = datetime.datetime.now(pytz.UTC)
self.destroySelf = FakeMethod()
@@ -161,6 +165,7 @@
path = behavior.templates_tarball_path
# Poke the file we're expecting into the mock slave.
behavior._builder.slave.valid_file_hashes.append(path)
+
def got_tarball(filename):
tarball = open(filename, 'r')
try:
@@ -201,6 +206,9 @@
queue_item, slave_status, None, logging), slave_call_log
def build_updated(ignored):
+ self.assertEqual(BuildStatus.FULLYBUILT, behavior.build.status)
+ # Log file is stored.
+ self.assertIsNotNone(behavior.build.log)
slave_call_log = behavior._builder.slave.call_log
self.assertEqual(1, queue_item.destroySelf.call_count)
self.assertIn('clean', slave_call_log)
@@ -240,6 +248,9 @@
queue_item, status_dict, None, logging)
def build_updated(ignored):
+ self.assertEqual(BuildStatus.FAILEDTOBUILD, behavior.build.status)
+ # Log file is stored.
+ self.assertIsNotNone(behavior.build.log)
self.assertEqual(1, queue_item.destroySelf.call_count)
slave_call_log = behavior._builder.slave.call_log
self.assertIn('clean', slave_call_log)
@@ -278,6 +289,7 @@
queue_item, status_dict, None, logging)
def build_updated(ignored):
+ self.assertEqual(BuildStatus.FULLYBUILT, behavior.build.status)
self.assertEqual(1, queue_item.destroySelf.call_count)
slave_call_log = behavior._builder.slave.call_log
self.assertIn('clean', slave_call_log)
@@ -321,6 +333,7 @@
queue_item, slave_status, None, logging)
def build_updated(ignored):
+ self.assertEqual(BuildStatus.FULLYBUILT, behavior.build.status)
entries = getUtility(
ITranslationImportQueue).getAllEntries(target=productseries)
expected_templates = [
=== modified file 'utilities/make-lp-user'
--- utilities/make-lp-user 2011-07-11 03:49:12 +0000
+++ utilities/make-lp-user 2011-10-19 09:02:48 +0000
@@ -44,6 +44,7 @@
from canonical.launchpad.interfaces.gpghandler import IGPGHandler
from canonical.launchpad.scripts import execute_zcml_for_scripts
+from canonical.lazr.timeout import set_default_timeout_function
from lp.registry.interfaces.gpg import GPGKeyAlgorithm, IGPGKeySet
from lp.registry.interfaces.person import IPersonSet
from lp.registry.interfaces.ssh import ISSHKeySet
@@ -57,6 +58,7 @@
DEFAULT_PASSWORD = 'test'
factory = LaunchpadObjectFactory()
+set_default_timeout_function(lambda: 100)
def make_person(username, email):
"""Create and return a person with the given username.
@@ -119,7 +121,7 @@
print 'Registered SSH key: %s' % (filename,)
break
else:
- print 'No SSH key files found in %s' % ssh_dir
+ print 'No SSH key files found in %s' % ssh_dir
def parse_fingerprints(gpg_output):