launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #16173
[Merge] lp:~wgrant/launchpad/slimmer-bfjo into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/slimmer-bfjo into lp:launchpad.
Commit message:
Eliminate most of IBuildFarmJobOld.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/slimmer-bfjo/+merge/194767
Inline IBuildFarmJobOld.{processor,virtualized,jobStarted,jobCancelled,jobReset} and move IBuildFarmJobOld.{addCandidateSelectionCriteria,postprocessCandidate} to ISpecificBuildFarmJobSource.
IBuildFarmJobOld will shortly perish.
--
https://code.launchpad.net/~wgrant/launchpad/slimmer-bfjo/+merge/194767
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/slimmer-bfjo into lp:launchpad.
=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py'
--- lib/lp/buildmaster/interfaces/buildfarmjob.py 2013-09-02 12:45:50 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjob.py 2013-11-11 23:47:32 +0000
@@ -59,67 +59,9 @@
BuildQueue have been transitioned to the new database schema.
"""
- processor = Reference(
- IProcessor, title=_("Processor"), required=False, readonly=True,
- description=_(
- "The Processor required by this build farm job. "
- "This should be None for processor-independent job types."))
-
- virtualized = Bool(
- title=_('Virtualized'), required=False, readonly=True,
- description=_(
- "The virtualization setting required by this build farm job. "
- "This should be None for job types that do not care whether "
- "they run virtualized."))
-
def score():
"""Calculate a job score appropriate for the job type in question."""
- def jobStarted():
- """'Job started' life cycle event, handle as appropriate."""
-
- def jobReset():
- """'Job reset' life cycle event, handle as appropriate."""
-
- def jobCancel():
- """'Job cancel' life cycle event."""
-
- def addCandidateSelectionCriteria(processor, virtualized):
- """Provide a sub-query to refine the candidate job selection.
-
- Return a sub-query to narrow down the list of candidate jobs.
- The sub-query will become part of an "outer query" and is free to
- refer to the `BuildQueue` and `Job` tables already utilized in the
- latter.
-
- Example (please see the `BuildPackageJob` implementation for a
- complete example):
-
- SELECT TRUE
- FROM Archive, Build, BuildPackageJob, DistroArchSeries
- WHERE
- BuildPackageJob.job = Job.id AND
- ..
-
- :param processor: the type of processor that the candidate jobs are
- expected to run on.
- :param virtualized: whether the candidate jobs are expected to run on
- the `processor` natively or inside a virtual machine.
- :return: a string containing a sub-query that narrows down the list of
- candidate jobs.
- """
-
- def postprocessCandidate(job, logger):
- """True if the candidate job is fine and should be dispatched
- to a builder, False otherwise.
-
- :param job: The `BuildQueue` instance to be scrutinized.
- :param logger: The logger to use.
-
- :return: True if the candidate job should be dispatched
- to a builder, False otherwise.
- """
-
def getByJob(job):
"""Get the specific `IBuildFarmJob` for the given `Job`.
@@ -328,6 +270,42 @@
job.
"""
+ def addCandidateSelectionCriteria(processor, virtualized):
+ """Provide a sub-query to refine the candidate job selection.
+
+ Return a sub-query to narrow down the list of candidate jobs.
+ The sub-query will become part of an "outer query" and is free to
+ refer to the `BuildQueue` and `Job` tables already utilized in the
+ latter.
+
+ Example (please see the `BuildPackageJob` implementation for a
+ complete example):
+
+ SELECT TRUE
+ FROM Archive, Build, BuildPackageJob, DistroArchSeries
+ WHERE
+ BuildPackageJob.job = Job.id AND
+ ..
+
+ :param processor: the type of processor that the candidate jobs are
+ expected to run on.
+ :param virtualized: whether the candidate jobs are expected to run on
+ the `processor` natively or inside a virtual machine.
+ :return: a string containing a sub-query that narrows down the list of
+ candidate jobs.
+ """
+
+ def postprocessCandidate(job, logger):
+ """True if the candidate job is fine and should be dispatched
+ to a builder, False otherwise.
+
+ :param job: The `BuildQueue` instance to be scrutinized.
+ :param logger: The logger to use.
+
+ :return: True if the candidate job should be dispatched
+ to a builder, False otherwise.
+ """
+
class IBuildFarmJobSource(Interface):
"""A utility of BuildFarmJob used to create _things_."""
=== modified file 'lib/lp/buildmaster/model/builder.py'
--- lib/lp/buildmaster/model/builder.py 2013-10-26 11:00:53 +0000
+++ lib/lp/buildmaster/model/builder.py 2013-11-11 23:47:32 +0000
@@ -35,7 +35,7 @@
from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
from lp.buildmaster.model.buildqueue import (
BuildQueue,
- specific_job_classes,
+ specific_build_farm_job_sources,
)
from lp.registry.interfaces.person import validate_public_person
from lp.services.database.interfaces import (
@@ -206,9 +206,9 @@
order_clause = " ORDER BY buildqueue.lastscore DESC, buildqueue.id"
extra_queries = []
- job_classes = specific_job_classes()
- for job_type, job_class in job_classes.iteritems():
- query = job_class.addCandidateSelectionCriteria(
+ job_sources = specific_build_farm_job_sources()
+ for job_type, job_source in job_sources.iteritems():
+ query = job_source.addCandidateSelectionCriteria(
self.processor, self.virtualized)
if query == '':
# This job class does not need to refine candidate jobs
@@ -224,8 +224,8 @@
for (candidate_id,) in candidate_jobs:
candidate = getUtility(IBuildQueueSet).get(candidate_id)
- job_class = job_classes[candidate.job_type]
- candidate_approved = job_class.postprocessCandidate(
+ job_source = job_sources[candidate.job_type]
+ candidate_approved = job_source.postprocessCandidate(
candidate, logger)
if candidate_approved:
return candidate
=== modified file 'lib/lp/buildmaster/model/buildfarmjob.py'
--- lib/lp/buildmaster/model/buildfarmjob.py 2013-09-02 12:45:50 +0000
+++ lib/lp/buildmaster/model/buildfarmjob.py 2013-11-11 23:47:32 +0000
@@ -6,6 +6,7 @@
'BuildFarmJob',
'BuildFarmJobMixin',
'BuildFarmJobOld',
+ 'SpecificBuildFarmJobSourceMixin',
]
import datetime
@@ -50,9 +51,6 @@
implements(IBuildFarmJobOld)
- processor = None
- virtualized = None
-
@staticmethod
def preloadBuildFarmJobs(jobs):
"""Preload the build farm jobs to which the given jobs will delegate.
@@ -83,29 +81,6 @@
"""
Store.of(self).remove(self)
- @staticmethod
- def addCandidateSelectionCriteria(processor, virtualized):
- """See `IBuildFarmJobOld`."""
- return ('')
-
- @staticmethod
- def postprocessCandidate(job, logger):
- """See `IBuildFarmJobOld`."""
- return True
-
- def jobStarted(self):
- """See `IBuildFarmJobOld`."""
- # XXX wgrant: builder should be set here.
- self.build.updateStatus(BuildStatus.BUILDING)
-
- def jobReset(self):
- """See `IBuildFarmJob`."""
- self.build.updateStatus(BuildStatus.NEEDSBUILD)
-
- def jobCancel(self):
- """See `IBuildFarmJob`."""
- self.build.updateStatus(BuildStatus.CANCELLED)
-
class BuildFarmJob(Storm):
"""A base implementation for `IBuildFarmJob` classes."""
@@ -249,6 +224,19 @@
self.failure_count += 1
+class SpecificBuildFarmJobSourceMixin:
+
+ @staticmethod
+ def addCandidateSelectionCriteria(processor, virtualized):
+ """See `ISpecificBuildFarmJobSource`."""
+ return ('')
+
+ @staticmethod
+ def postprocessCandidate(job, logger):
+ """See `ISpecificBuildFarmJobSource`."""
+ return True
+
+
class BuildFarmJobSet:
implements(IBuildFarmJobSet)
=== modified file 'lib/lp/buildmaster/model/buildqueue.py'
--- lib/lp/buildmaster/model/buildqueue.py 2013-11-10 23:56:44 +0000
+++ lib/lp/buildmaster/model/buildqueue.py 2013-11-11 23:47:32 +0000
@@ -7,6 +7,7 @@
'BuildQueue',
'BuildQueueSet',
'specific_job_classes',
+ 'specific_build_farm_job_sources',
]
from datetime import datetime
@@ -21,11 +22,18 @@
IntervalCol,
StringCol,
)
+from storm.store import Store
from zope.component import getSiteManager
from zope.interface import implements
-from lp.buildmaster.enums import BuildFarmJobType
-from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
+from lp.buildmaster.enums import (
+ BuildFarmJobType,
+ BuildStatus,
+ )
+from lp.buildmaster.interfaces.buildfarmjob import (
+ IBuildFarmJob,
+ ISpecificBuildFarmJobSource,
+ )
from lp.buildmaster.interfaces.buildqueue import (
IBuildQueue,
IBuildQueueSet,
@@ -58,6 +66,26 @@
return job_classes
+def specific_build_farm_job_sources():
+ """Sources for specific jobs that may run on the build farm."""
+ job_sources = dict()
+ # Get all components that implement the `ISpecificBuildFarmJobSource`
+ # interface.
+ components = getSiteManager()
+ implementations = sorted(
+ components.getUtilitiesFor(ISpecificBuildFarmJobSource))
+ # The above yields a collection of 2-tuples where the first element
+ # is the name of the `BuildFarmJobType` enum and the second element
+ # is the implementing class respectively.
+ for job_enum_name, job_source in implementations:
+ if not job_enum_name:
+ continue
+ job_enum = getattr(BuildFarmJobType, job_enum_name)
+ job_sources[job_enum] = job_source
+
+ return job_sources
+
+
class BuildQueue(SQLBase):
implements(IBuildQueue)
_table = "BuildQueue"
@@ -133,8 +161,9 @@
job = self.job
specific_job = self.specific_job
builder = self.builder
- SQLBase.destroySelf(self)
+ Store.of(self).remove(self)
specific_job.cleanUp()
+ Store.of(self).flush()
job.destroySelf()
if builder is not None:
del get_property_cache(builder).currentjob
@@ -158,7 +187,7 @@
self.builder = builder
if self.job.status != JobStatus.RUNNING:
self.job.start()
- self.specific_job.jobStarted()
+ self.specific_job.build.updateStatus(BuildStatus.BUILDING)
if builder is not None:
del get_property_cache(builder).currentjob
@@ -171,13 +200,13 @@
self.job.date_started = None
self.job.date_finished = None
self.logtail = None
- self.specific_job.jobReset()
+ self.specific_job.build.updateStatus(BuildStatus.NEEDSBUILD)
if builder is not None:
del get_property_cache(builder).currentjob
def cancel(self):
"""See `IBuildQueue`."""
- self.specific_job.jobCancel()
+ self.specific_job.build.updateStatus(BuildStatus.CANCELLED)
self.destroySelf()
def getEstimatedJobStartTime(self, now=None):
=== modified file 'lib/lp/buildmaster/model/packagebuild.py'
--- lib/lp/buildmaster/model/packagebuild.py 2013-08-28 04:40:32 +0000
+++ lib/lp/buildmaster/model/packagebuild.py 2013-11-11 23:47:32 +0000
@@ -120,11 +120,10 @@
duration_estimate = self.estimateDuration()
job = specific_job.job
- processor = specific_job.processor
queue_entry = BuildQueue(
estimated_duration=duration_estimate,
job_type=self.job_type,
- job=job, processor=processor,
- virtualized=specific_job.virtualized)
+ job=job, processor=self.processor,
+ virtualized=self.virtualized)
Store.of(self).add(queue_entry)
return queue_entry
=== modified file 'lib/lp/buildmaster/tests/test_buildqueue.py'
--- lib/lp/buildmaster/tests/test_buildqueue.py 2013-10-31 06:29:13 +0000
+++ lib/lp/buildmaster/tests/test_buildqueue.py 2013-11-11 23:47:32 +0000
@@ -14,9 +14,11 @@
BuildStatus,
)
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
-from lp.buildmaster.model.builder import specific_job_classes
from lp.buildmaster.model.buildfarmjob import BuildFarmJobMixin
-from lp.buildmaster.model.buildqueue import BuildQueue
+from lp.buildmaster.model.buildqueue import (
+ BuildQueue,
+ specific_job_classes,
+ )
from lp.services.database.interfaces import IStore
from lp.soyuz.enums import (
ArchivePurpose,
=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2013-09-11 06:05:44 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2013-11-11 23:47:32 +0000
@@ -1614,6 +1614,8 @@
owner=self.user, name=u'my-recipe')
distro_series = self.factory.makeDistroSeries(
name='squirrel', distribution=archive.distribution)
+ removeSecurityProxy(distro_series).nominatedarchindep = (
+ self.factory.makeDistroArchSeries(distroseries=distro_series))
build = self.factory.makeSourcePackageRecipeBuild(
requester=self.user, archive=archive, recipe=recipe,
distroseries=distro_series)
=== modified file 'lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py'
--- lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py 2013-01-23 10:16:18 +0000
+++ lib/lp/code/mail/tests/test_sourcepackagerecipebuild.py 2013-11-11 23:47:32 +0000
@@ -60,6 +60,8 @@
pantry_owner = self.factory.makePerson(name='archiveowner')
pantry = self.factory.makeArchive(name='ppa', owner=pantry_owner)
secret = self.factory.makeDistroSeries(name=u'distroseries')
+ removeSecurityProxy(secret).nominatedarchindep = (
+ self.factory.makeDistroArchSeries(distroseries=secret))
build = self.factory.makeSourcePackageRecipeBuild(
recipe=cake, distroseries=secret, archive=pantry,
status=BuildStatus.FULLYBUILT, duration=timedelta(minutes=5))
@@ -95,6 +97,8 @@
pantry_owner = self.factory.makePerson(name='archiveowner')
pantry = self.factory.makeArchive(name='ppa', owner=pantry_owner)
secret = self.factory.makeDistroSeries(name=u'distroseries')
+ removeSecurityProxy(secret).nominatedarchindep = (
+ self.factory.makeDistroArchSeries(distroseries=secret))
build = self.factory.makeSourcePackageRecipeBuild(
recipe=cake, distroseries=secret, archive=pantry,
status=BuildStatus.SUPERSEDED)
=== modified file 'lib/lp/code/model/sourcepackagerecipebuild.py'
--- lib/lp/code/model/sourcepackagerecipebuild.py 2013-09-24 05:45:06 +0000
+++ lib/lp/code/model/sourcepackagerecipebuild.py 2013-11-11 23:47:32 +0000
@@ -43,6 +43,7 @@
from lp.buildmaster.model.buildfarmjob import (
BuildFarmJob,
BuildFarmJobOld,
+ SpecificBuildFarmJobSourceMixin,
)
from lp.buildmaster.model.buildqueue import BuildQueue
from lp.buildmaster.model.packagebuild import PackageBuildMixin
@@ -78,7 +79,8 @@
from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
-class SourcePackageRecipeBuild(PackageBuildMixin, Storm):
+class SourcePackageRecipeBuild(SpecificBuildFarmJobSourceMixin,
+ PackageBuildMixin, Storm):
__storm_table__ = 'SourcePackageRecipeBuild'
@@ -212,6 +214,7 @@
self.archive = archive
self.pocket = pocket
self.status = BuildStatus.NEEDSBUILD
+ self.processor = self.distroseries.nominatedarchindep.processor
self.virtualized = True
if date_created is not None:
self.date_created = date_created
@@ -431,15 +434,6 @@
build = Reference(
build_id, 'SourcePackageRecipeBuild.id')
- @property
- def processor(self):
- return self.build.distroseries.nominatedarchindep.processor
-
- @property
- def virtualized(self):
- """See `IBuildFarmJob`."""
- return self.build.is_virtualized
-
def __init__(self, build, job):
self.build = build
self.job = job
=== modified file 'lib/lp/code/model/tests/test_recipebuilder.py'
--- lib/lp/code/model/tests/test_recipebuilder.py 2013-10-01 00:32:26 +0000
+++ lib/lp/code/model/tests/test_recipebuilder.py 2013-11-11 23:47:32 +0000
@@ -9,8 +9,6 @@
import tempfile
from textwrap import dedent
-from zope.component import getUtility
-
from testtools import run_test_with
from testtools.deferredruntest import (
assert_fails_with,
@@ -20,6 +18,7 @@
import transaction
from twisted.internet import defer
from twisted.trial.unittest import TestCase as TrialTestCase
+from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
from lp.buildmaster.enums import (
@@ -72,7 +71,7 @@
distroseries = self.factory.makeDistroSeries(name="mydistro",
distribution=distro)
processor = getUtility(IProcessorSet).getByName('386')
- distroseries.newArch(
+ distroseries.nominatedarchindep = distroseries.newArch(
'i386', processor, True, self.factory.makePerson())
sourcepackage = self.factory.makeSourcePackage(spn, distroseries)
if recipe_registrant is None:
=== modified file 'lib/lp/code/model/tests/test_sourcepackagerecipebuild.py'
--- lib/lp/code/model/tests/test_sourcepackagerecipebuild.py 2013-09-24 05:45:06 +0000
+++ lib/lp/code/model/tests/test_sourcepackagerecipebuild.py 2013-11-11 23:47:32 +0000
@@ -423,6 +423,8 @@
requester = self.factory.makePerson()
recipe = self.factory.makeSourcePackageRecipe()
series = self.factory.makeDistroSeries()
+ removeSecurityProxy(series).nominatedarchindep = (
+ self.factory.makeDistroArchSeries(distroseries=series))
now = self.factory.getUniqueDate()
build = self.factory.makeSourcePackageRecipeBuild(recipe=recipe,
requester=requester)
@@ -526,6 +528,8 @@
name=u'recipe', owner=person)
pantry = self.factory.makeArchive(name='ppa')
secret = self.factory.makeDistroSeries(name=u'distroseries')
+ secret.nominatedarchindep = self.factory.makeDistroArchSeries(
+ distroseries=secret)
build = self.factory.makeSourcePackageRecipeBuild(
recipe=cake, distroseries=secret, archive=pantry)
build.updateStatus(BuildStatus.FULLYBUILT)
@@ -556,6 +560,8 @@
name=u'recipe', owner=person)
pantry = self.factory.makeArchive(name='ppa')
secret = self.factory.makeDistroSeries(name=u'distroseries')
+ secret.nominatedarchindep = self.factory.makeDistroArchSeries(
+ distroseries=secret)
build = self.factory.makeSourcePackageRecipeBuild(
recipe=cake, distroseries=secret, archive=pantry)
build.updateStatus(BuildStatus.FULLYBUILT)
=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
--- lib/lp/soyuz/model/binarypackagebuild.py 2013-08-28 12:03:57 +0000
+++ lib/lp/soyuz/model/binarypackagebuild.py 2013-11-11 23:47:32 +0000
@@ -44,12 +44,16 @@
)
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSource
from lp.buildmaster.model.builder import Builder
-from lp.buildmaster.model.buildfarmjob import BuildFarmJob
+from lp.buildmaster.model.buildfarmjob import (
+ BuildFarmJob,
+ SpecificBuildFarmJobSourceMixin,
+ )
from lp.buildmaster.model.buildqueue import BuildQueue
from lp.buildmaster.model.packagebuild import PackageBuildMixin
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distroseries import IDistroSeries
from lp.registry.interfaces.pocket import PackagePublishingPocket
+from lp.registry.interfaces.series import SeriesStatus
from lp.registry.model.sourcepackagename import SourcePackageName
from lp.services.config import config
from lp.services.database.bulk import load_related
@@ -75,7 +79,10 @@
simple_sendmail,
)
from lp.services.webapp import canonical_url
-from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.enums import (
+ ArchivePurpose,
+ PackagePublishingStatus,
+ )
from lp.soyuz.interfaces.binarypackagebuild import (
BuildSetStatus,
CannotBeRescored,
@@ -825,7 +832,7 @@
return changes.signer
-class BinaryPackageBuildSet:
+class BinaryPackageBuildSet(SpecificBuildFarmJobSourceMixin):
implements(IBinaryPackageBuildSet)
def new(self, distro_arch_series, source_package_release, processor,
@@ -1204,3 +1211,75 @@
return IStore(BinaryPackageBuild).using(*origin).find(
(BuildQueue, Builder, BuildPackageJob),
BinaryPackageBuild.id.is_in(build_ids))
+
+ @staticmethod
+ def addCandidateSelectionCriteria(processor, virtualized):
+ """See `ISpecificBuildFarmJobSource`."""
+ private_statuses = (
+ PackagePublishingStatus.PUBLISHED,
+ PackagePublishingStatus.SUPERSEDED,
+ PackagePublishingStatus.DELETED,
+ )
+ return """
+ SELECT TRUE FROM Archive, BinaryPackageBuild, BuildPackageJob,
+ DistroArchSeries
+ WHERE
+ BuildPackageJob.job = Job.id AND
+ BuildPackageJob.build = BinaryPackageBuild.id AND
+ BinaryPackageBuild.distro_arch_series =
+ DistroArchSeries.id AND
+ BinaryPackageBuild.archive = Archive.id AND
+ ((Archive.private IS TRUE AND
+ EXISTS (
+ SELECT SourcePackagePublishingHistory.id
+ FROM SourcePackagePublishingHistory
+ WHERE
+ SourcePackagePublishingHistory.distroseries =
+ DistroArchSeries.distroseries AND
+ SourcePackagePublishingHistory.sourcepackagerelease =
+ BinaryPackageBuild.source_package_release AND
+ SourcePackagePublishingHistory.archive = Archive.id AND
+ SourcePackagePublishingHistory.status IN %s))
+ OR
+ archive.private IS FALSE) AND
+ BinaryPackageBuild.status = %s
+ """ % sqlvalues(private_statuses, BuildStatus.NEEDSBUILD)
+
+ @staticmethod
+ def postprocessCandidate(job, logger):
+ """See `ISpecificBuildFarmJobSource`."""
+ # Mark build records targeted to old source versions as SUPERSEDED
+ # and build records target to SECURITY pocket or against an OBSOLETE
+ # distroseries without a flag as FAILEDTOBUILD.
+ # Builds in those situation should not be built because they will
+ # be wasting build-time. In the former case, there is already a
+ # newer source; the latter case needs an overhaul of the way
+ # security builds are handled (by copying from a PPA) to avoid
+ # creating duplicate builds.
+ build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
+ distroseries = build.distro_arch_series.distroseries
+ if (
+ build.pocket == PackagePublishingPocket.SECURITY or
+ (distroseries.status == SeriesStatus.OBSOLETE and
+ not build.archive.permit_obsolete_series_uploads)):
+ # We never build anything in the security pocket, or for obsolete
+ # series without the flag set.
+ logger.debug(
+ "Build %s FAILEDTOBUILD, queue item %s REMOVED"
+ % (build.id, job.id))
+ build.updateStatus(BuildStatus.FAILEDTOBUILD)
+ job.destroySelf()
+ return False
+
+ publication = build.current_source_publication
+ if publication is None:
+ # The build should be superseded if it no longer has a
+ # current publishing record.
+ logger.debug(
+ "Build %s SUPERSEDED, queue item %s REMOVED"
+ % (build.id, job.id))
+ build.updateStatus(BuildStatus.SUPERSEDED)
+ job.destroySelf()
+ return False
+
+ return True
=== modified file 'lib/lp/soyuz/model/buildpackagejob.py'
--- lib/lp/soyuz/model/buildpackagejob.py 2013-09-04 08:04:25 +0000
+++ lib/lp/soyuz/model/buildpackagejob.py 2013-11-11 23:47:32 +0000
@@ -15,14 +15,9 @@
from zope.component import getUtility
from zope.interface import implements
-from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.model.buildfarmjob import BuildFarmJobOld
-from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.registry.interfaces.series import SeriesStatus
from lp.services.database.bulk import load_related
from lp.services.database.interfaces import IStore
-from lp.services.database.sqlbase import sqlvalues
-from lp.soyuz.enums import PackagePublishingStatus
from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
from lp.soyuz.interfaces.buildpackagejob import (
COPY_ARCHIVE_SCORE_PENALTY,
@@ -99,16 +94,6 @@
return score
- @property
- def processor(self):
- """See `IBuildFarmJob`."""
- return self.build.processor
-
- @property
- def virtualized(self):
- """See `IBuildFarmJob`."""
- return self.build.is_virtualized
-
@classmethod
def preloadJobsData(cls, jobs):
from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
@@ -116,75 +101,3 @@
load_related(Job, jobs, ['job_id'])
builds = load_related(BinaryPackageBuild, jobs, ['build_id'])
getUtility(IBinaryPackageBuildSet).preloadBuildsData(list(builds))
-
- @staticmethod
- def addCandidateSelectionCriteria(processor, virtualized):
- """See `IBuildFarmJob`."""
- private_statuses = (
- PackagePublishingStatus.PUBLISHED,
- PackagePublishingStatus.SUPERSEDED,
- PackagePublishingStatus.DELETED,
- )
- return """
- SELECT TRUE FROM Archive, BinaryPackageBuild, BuildPackageJob,
- DistroArchSeries
- WHERE
- BuildPackageJob.job = Job.id AND
- BuildPackageJob.build = BinaryPackageBuild.id AND
- BinaryPackageBuild.distro_arch_series =
- DistroArchSeries.id AND
- BinaryPackageBuild.archive = Archive.id AND
- ((Archive.private IS TRUE AND
- EXISTS (
- SELECT SourcePackagePublishingHistory.id
- FROM SourcePackagePublishingHistory
- WHERE
- SourcePackagePublishingHistory.distroseries =
- DistroArchSeries.distroseries AND
- SourcePackagePublishingHistory.sourcepackagerelease =
- BinaryPackageBuild.source_package_release AND
- SourcePackagePublishingHistory.archive = Archive.id AND
- SourcePackagePublishingHistory.status IN %s))
- OR
- archive.private IS FALSE) AND
- BinaryPackageBuild.status = %s
- """ % sqlvalues(private_statuses, BuildStatus.NEEDSBUILD)
-
- @staticmethod
- def postprocessCandidate(job, logger):
- """See `IBuildFarmJob`."""
- # Mark build records targeted to old source versions as SUPERSEDED
- # and build records target to SECURITY pocket or against an OBSOLETE
- # distroseries without a flag as FAILEDTOBUILD.
- # Builds in those situation should not be built because they will
- # be wasting build-time. In the former case, there is already a
- # newer source; the latter case needs an overhaul of the way
- # security builds are handled (by copying from a PPA) to avoid
- # creating duplicate builds.
- build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
- distroseries = build.distro_arch_series.distroseries
- if (
- build.pocket == PackagePublishingPocket.SECURITY or
- (distroseries.status == SeriesStatus.OBSOLETE and
- not build.archive.permit_obsolete_series_uploads)):
- # We never build anything in the security pocket, or for obsolete
- # series without the flag set.
- logger.debug(
- "Build %s FAILEDTOBUILD, queue item %s REMOVED"
- % (build.id, job.id))
- build.updateStatus(BuildStatus.FAILEDTOBUILD)
- job.destroySelf()
- return False
-
- publication = build.current_source_publication
- if publication is None:
- # The build should be superseded if it no longer has a
- # current publishing record.
- logger.debug(
- "Build %s SUPERSEDED, queue item %s REMOVED"
- % (build.id, job.id))
- build.updateStatus(BuildStatus.SUPERSEDED)
- job.destroySelf()
- return False
-
- return True
=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuild.py'
--- lib/lp/soyuz/tests/test_binarypackagebuild.py 2013-09-10 06:28:26 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuild.py 2013-11-11 23:47:32 +0000
@@ -17,7 +17,9 @@
from lp.buildmaster.interfaces.buildqueue import IBuildQueue
from lp.buildmaster.interfaces.packagebuild import IPackageBuild
from lp.buildmaster.model.buildqueue import BuildQueue
+from lp.registry.interfaces.series import SeriesStatus
from lp.services.job.model.job import Job
+from lp.services.log.logger import DevNullLogger
from lp.services.webapp.interaction import ANONYMOUS
from lp.services.webapp.interfaces import OAuthPermission
from lp.soyuz.enums import (
@@ -31,7 +33,10 @@
)
from lp.soyuz.interfaces.buildpackagejob import IBuildPackageJob
from lp.soyuz.interfaces.component import IComponentSet
-from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
+from lp.soyuz.model.binarypackagebuild import (
+ BinaryPackageBuild,
+ BinaryPackageBuildSet,
+ )
from lp.soyuz.model.buildpackagejob import BuildPackageJob
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
from lp.testing import (
@@ -497,3 +502,42 @@
logout()
entry = self.webservice.get(build_url, api_version='devel').jsonBody()
self.assertEndsWith(entry['builder_link'], builder_url)
+
+
+class TestPostprocessCandidate(TestCaseWithFactory):
+
+ layer = DatabaseFunctionalLayer
+
+ def makeBuildJob(self, pocket="RELEASE"):
+ build = self.factory.makeBinaryPackageBuild(pocket=pocket)
+ return build.queueBuild()
+
+ def test_release_job(self):
+ job = self.makeBuildJob()
+ build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
+ self.assertTrue(BinaryPackageBuildSet.postprocessCandidate(job, None))
+ self.assertEqual(BuildStatus.NEEDSBUILD, build.status)
+
+ def test_security_job_is_failed(self):
+ job = self.makeBuildJob(pocket="SECURITY")
+ build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
+ BinaryPackageBuildSet.postprocessCandidate(job, DevNullLogger())
+ self.assertEqual(BuildStatus.FAILEDTOBUILD, build.status)
+
+ def test_obsolete_job_without_flag_is_failed(self):
+ job = self.makeBuildJob()
+ build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
+ distroseries = build.distro_arch_series.distroseries
+ removeSecurityProxy(distroseries).status = SeriesStatus.OBSOLETE
+ BinaryPackageBuildSet.postprocessCandidate(job, DevNullLogger())
+ self.assertEqual(BuildStatus.FAILEDTOBUILD, build.status)
+
+ def test_obsolete_job_with_flag_is_not_failed(self):
+ job = self.makeBuildJob()
+ build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
+ distroseries = build.distro_arch_series.distroseries
+ archive = build.archive
+ removeSecurityProxy(distroseries).status = SeriesStatus.OBSOLETE
+ removeSecurityProxy(archive).permit_obsolete_series_uploads = True
+ BinaryPackageBuildSet.postprocessCandidate(job, DevNullLogger())
+ self.assertEqual(BuildStatus.NEEDSBUILD, build.status)
=== modified file 'lib/lp/soyuz/tests/test_buildpackagejob.py'
--- lib/lp/soyuz/tests/test_buildpackagejob.py 2013-09-10 06:28:26 +0000
+++ lib/lp/soyuz/tests/test_buildpackagejob.py 2013-11-11 23:47:32 +0000
@@ -13,16 +13,13 @@
from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interfaces.builder import IBuilderSet
from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.registry.interfaces.series import SeriesStatus
from lp.registry.interfaces.sourcepackage import SourcePackageUrgency
from lp.services.database.interfaces import IStore
-from lp.services.log.logger import DevNullLogger
from lp.services.webapp.interfaces import OAuthPermission
from lp.soyuz.enums import (
ArchivePurpose,
PackagePublishingStatus,
)
-from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
from lp.soyuz.interfaces.buildfarmbuildjob import IBuildFarmBuildJob
from lp.soyuz.interfaces.buildpackagejob import (
COPY_ARCHIVE_SCORE_PENALTY,
@@ -34,7 +31,6 @@
)
from lp.soyuz.interfaces.processor import IProcessorSet
from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
-from lp.soyuz.model.buildpackagejob import BuildPackageJob
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
from lp.testing import (
anonymous_logged_in,
@@ -197,24 +193,6 @@
removeSecurityProxy(bq).estimated_duration = timedelta(
seconds=duration)
- def test_processor(self):
- # Test that BuildPackageJob returns the correct processor.
- build, bq = find_job(self, 'gcc', '386')
- bpj = bq.specific_job
- self.assertEqual(bpj.processor.id, 1)
- build, bq = find_job(self, 'bison', 'hppa')
- bpj = bq.specific_job
- self.assertEqual(bpj.processor.id, 3)
-
- def test_virtualized(self):
- # Test that BuildPackageJob returns the correct virtualized flag.
- build, bq = find_job(self, 'apg', '386')
- bpj = bq.specific_job
- self.assertEqual(bpj.virtualized, False)
- build, bq = find_job(self, 'flex', 'hppa')
- bpj = bq.specific_job
- self.assertEqual(bpj.virtualized, False)
-
def test_providesInterfaces(self):
# Ensure that a BuildPackageJob generates an appropriate cookie.
build, bq = find_job(self, 'gcc', '386')
@@ -222,17 +200,6 @@
self.assertProvides(build_farm_job, IBuildPackageJob)
self.assertProvides(build_farm_job, IBuildFarmBuildJob)
- def test_jobStarted(self):
- # Starting a build updates the status.
- build, bq = find_job(self, 'gcc', '386')
- build_package_job = bq.specific_job
- build_package_job.jobStarted()
- self.assertEqual(
- BuildStatus.BUILDING, build_package_job.build.status)
- self.assertIsNot(None, build_package_job.build.date_started)
- self.assertIsNot(None, build_package_job.build.date_first_dispatched)
- self.assertIs(None, build_package_job.build.date_finished)
-
class TestBuildPackageJobScore(TestCaseWithFactory):
@@ -469,42 +436,3 @@
with anonymous_logged_in():
self.assertScoreWriteableByTeam(
archive, getUtility(ILaunchpadCelebrities).commercial_admin)
-
-
-class TestBuildPackageJobPostProcess(TestCaseWithFactory):
-
- layer = DatabaseFunctionalLayer
-
- def makeBuildJob(self, pocket="RELEASE"):
- build = self.factory.makeBinaryPackageBuild(pocket=pocket)
- return build.queueBuild()
-
- def test_release_job(self):
- job = self.makeBuildJob()
- build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
- self.assertTrue(BuildPackageJob.postprocessCandidate(job, None))
- self.assertEqual(BuildStatus.NEEDSBUILD, build.status)
-
- def test_security_job_is_failed(self):
- job = self.makeBuildJob(pocket="SECURITY")
- build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
- BuildPackageJob.postprocessCandidate(job, DevNullLogger())
- self.assertEqual(BuildStatus.FAILEDTOBUILD, build.status)
-
- def test_obsolete_job_without_flag_is_failed(self):
- job = self.makeBuildJob()
- build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
- distroseries = build.distro_arch_series.distroseries
- removeSecurityProxy(distroseries).status = SeriesStatus.OBSOLETE
- BuildPackageJob.postprocessCandidate(job, DevNullLogger())
- self.assertEqual(BuildStatus.FAILEDTOBUILD, build.status)
-
- def test_obsolete_job_with_flag_is_not_failed(self):
- job = self.makeBuildJob()
- build = getUtility(IBinaryPackageBuildSet).getByQueueEntry(job)
- distroseries = build.distro_arch_series.distroseries
- archive = build.archive
- removeSecurityProxy(distroseries).status = SeriesStatus.OBSOLETE
- removeSecurityProxy(archive).permit_obsolete_series_uploads = True
- BuildPackageJob.postprocessCandidate(job, DevNullLogger())
- self.assertEqual(BuildStatus.NEEDSBUILD, build.status)
=== modified file 'lib/lp/translations/model/translationtemplatesbuild.py'
--- lib/lp/translations/model/translationtemplatesbuild.py 2013-09-24 05:45:06 +0000
+++ lib/lp/translations/model/translationtemplatesbuild.py 2013-11-11 23:47:32 +0000
@@ -28,7 +28,10 @@
BuildStatus,
)
from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJobSource
-from lp.buildmaster.model.buildfarmjob import BuildFarmJobMixin
+from lp.buildmaster.model.buildfarmjob import (
+ BuildFarmJobMixin,
+ SpecificBuildFarmJobSourceMixin,
+ )
from lp.code.model.branch import Branch
from lp.code.model.branchcollection import GenericBranchCollection
from lp.code.model.branchjob import (
@@ -49,7 +52,8 @@
)
-class TranslationTemplatesBuild(BuildFarmJobMixin, Storm):
+class TranslationTemplatesBuild(SpecificBuildFarmJobSourceMixin,
+ BuildFarmJobMixin, Storm):
"""A `BuildFarmJob` extension for translation templates builds."""
implements(ITranslationTemplatesBuild)
Follow ups