launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #32469
[Merge] ~ruinedyourlife/launchpad:craft-build-webhook into launchpad:master
Quentin Debhi has proposed merging ~ruinedyourlife/launchpad:craft-build-webhook into launchpad:master.
Commit message:
Add webhook integration to sourcecraft builds
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~ruinedyourlife/launchpad/+git/launchpad/+merge/485534
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~ruinedyourlife/launchpad:craft-build-webhook into launchpad:master.
diff --git a/lib/lp/crafts/configure.zcml b/lib/lp/crafts/configure.zcml
index 59d8621..a0fca60 100644
--- a/lib/lp/crafts/configure.zcml
+++ b/lib/lp/crafts/configure.zcml
@@ -65,7 +65,7 @@
<subscriber
for="lp.crafts.interfaces.craftrecipebuild.ICraftRecipeBuild
- lp.crafts.interfaces.craftrecipebuild.ICraftRecipeBuildStatusChangedEvent"
+ lazr.lifecycle.interfaces.IObjectModifiedEvent"
handler="lp.crafts.subscribers.craftrecipebuild.craft_build_status_changed" />
<!-- CraftRecipeBuildSet -->
diff --git a/lib/lp/crafts/interfaces/craftrecipebuild.py b/lib/lp/crafts/interfaces/craftrecipebuild.py
index 60e2a54..7b57a27 100644
--- a/lib/lp/crafts/interfaces/craftrecipebuild.py
+++ b/lib/lp/crafts/interfaces/craftrecipebuild.py
@@ -7,7 +7,6 @@ __all__ = [
"ICraftFile",
"ICraftRecipeBuild",
"ICraftRecipeBuildSet",
- "ICraftRecipeBuildStatusChangedEvent",
]
from lazr.restful.declarations import (
@@ -18,7 +17,6 @@ from lazr.restful.declarations import (
)
from lazr.restful.fields import Reference
from zope.interface import Attribute, Interface
-from zope.interface.interfaces import IObjectEvent
from zope.schema import Bool, Datetime, Dict, Int, TextLine
from lp import _
@@ -40,10 +38,6 @@ from lp.services.librarian.interfaces import ILibraryFileAlias
from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
-class ICraftRecipeBuildStatusChangedEvent(IObjectEvent):
- """The status of a craft recipe build changed."""
-
-
class ICraftRecipeBuildView(IPackageBuildView):
"""ICraftRecipeBuild attributes that require launchpad.View."""
diff --git a/lib/lp/crafts/model/craftrecipe.py b/lib/lp/crafts/model/craftrecipe.py
index 1701ffd..9a5b41e 100644
--- a/lib/lp/crafts/model/craftrecipe.py
+++ b/lib/lp/crafts/model/craftrecipe.py
@@ -108,6 +108,8 @@ from lp.services.job.interfaces.job import JobStatus
from lp.services.job.model.job import Job
from lp.services.librarian.model import LibraryFileAlias
from lp.services.propertycache import cachedproperty, get_property_cache
+from lp.services.webhooks.interfaces import IWebhookSet
+from lp.services.webhooks.model import WebhookTargetMixin
from lp.soyuz.model.distroarchseries import DistroArchSeries, PocketChroot
@@ -121,7 +123,7 @@ def craft_recipe_modified(recipe, event):
@implementer(ICraftRecipe)
-class CraftRecipe(StormBase):
+class CraftRecipe(StormBase, WebhookTargetMixin):
"""See `ICraftRecipe`."""
__storm_table__ = "CraftRecipe"
@@ -323,6 +325,10 @@ class CraftRecipe(StormBase):
"""See `ICraftRecipe`."""
self._store_channels = value or None
+ @property
+ def valid_webhook_event_types(self):
+ return ["craft-recipe:build:0.1"]
+
def getAllowedInformationTypes(self, user):
"""See `ICraftRecipe`."""
# Allow both public and private information types
@@ -399,8 +405,9 @@ class CraftRecipe(StormBase):
@property
def can_upload_to_store(self):
- # no store upload planned for the initial implementation, as artifacts
- # get pulled from Launchpad for now only.
+ # XXX ruinedyourlife 2025-05-02: remove this property all together as
+ # we do not use it anywhere. we do thorough checks for this in the
+ # publishing job itself `CraftPublishingJob`.
return False
def destroySelf(self):
@@ -439,8 +446,7 @@ class CraftRecipe(StormBase):
And(CraftRecipeJob.job == Job.id, CraftRecipeJob.recipe == self),
)
store.find(Job, Job.id.is_in(affected_jobs)).remove()
- # XXX ruinedyourlife 2024-10-02: we need to remove webhooks once
- # implemented getUtility(IWebhookSet).delete(self.webhooks)
+ getUtility(IWebhookSet).delete(self.webhooks)
store.remove(self)
store.find(
BuildFarmJob, BuildFarmJob.id.is_in(build_farm_job_ids)
diff --git a/lib/lp/crafts/model/craftrecipebuild.py b/lib/lp/crafts/model/craftrecipebuild.py
index 1ecd39c..8fa4baa 100644
--- a/lib/lp/crafts/model/craftrecipebuild.py
+++ b/lib/lp/crafts/model/craftrecipebuild.py
@@ -6,7 +6,6 @@
__all__ = [
"CraftFile",
"CraftRecipeBuild",
- "ICraftRecipeBuildStatusChangedEvent",
]
from datetime import timedelta, timezone
@@ -17,7 +16,6 @@ from storm.locals import Bool, DateTime, Desc, Int, Reference, Store, Unicode
from storm.store import EmptyResultSet
from zope.component import getUtility
from zope.interface import implementer
-from zope.interface.interfaces import ObjectEvent
from zope.security.proxy import removeSecurityProxy
from lp.app.errors import NotFoundError
@@ -35,7 +33,6 @@ from lp.crafts.interfaces.craftrecipebuild import (
ICraftFile,
ICraftRecipeBuild,
ICraftRecipeBuildSet,
- ICraftRecipeBuildStatusChangedEvent,
)
from lp.crafts.mail.craftrecipebuild import CraftRecipeBuildMailer
from lp.registry.interfaces.pocket import PackagePublishingPocket
@@ -63,11 +60,6 @@ from lp.services.webapp.snapshot import notify_modified
from lp.soyuz.model.distroarchseries import DistroArchSeries
-@implementer(ICraftRecipeBuildStatusChangedEvent)
-class CraftRecipeBuildStatusChangedEvent(ObjectEvent):
- """See `ICraftRecipeBuildStatusChangedEvent`."""
-
-
@implementer(ICraftRecipeBuild)
class CraftRecipeBuild(PackageBuildMixin, StormBase):
"""See `ICraftRecipeBuild`."""
diff --git a/lib/lp/services/webhooks/model.py b/lib/lp/services/webhooks/model.py
index 77f96aa..c8c8619 100644
--- a/lib/lp/services/webhooks/model.py
+++ b/lib/lp/services/webhooks/model.py
@@ -103,6 +103,9 @@ class Webhook(StormBase):
charm_recipe_id = Int(name="charm_recipe")
charm_recipe = Reference(charm_recipe_id, "CharmRecipe.id")
+ craft_recipe_id = Int(name="craft_recipe")
+ craft_recipe = Reference(craft_recipe_id, "CraftRecipe.id")
+
project_id = Int(name="project")
project = Reference(project_id, "Product.id")
@@ -217,6 +220,7 @@ class WebhookSet:
from lp.charms.interfaces.charmrecipe import ICharmRecipe
from lp.code.interfaces.branch import IBranch
from lp.code.interfaces.gitrepository import IGitRepository
+ from lp.crafts.interfaces.craftrecipe import ICraftRecipe
from lp.oci.interfaces.ocirecipe import IOCIRecipe
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distributionsourcepackage import (
@@ -246,7 +250,8 @@ class WebhookSet:
elif IDistributionSourcePackage.providedBy(target):
hook.distribution = target.distribution
hook.source_package_name = target.sourcepackagename
-
+ elif ICraftRecipe.providedBy(target):
+ hook.craft_recipe = target
else:
raise AssertionError("Unsupported target: %r" % (target,))
hook.registrant = registrant
@@ -273,6 +278,7 @@ class WebhookSet:
from lp.charms.interfaces.charmrecipe import ICharmRecipe
from lp.code.interfaces.branch import IBranch
from lp.code.interfaces.gitrepository import IGitRepository
+ from lp.crafts.interfaces.craftrecipe import ICraftRecipe
from lp.oci.interfaces.ocirecipe import IOCIRecipe
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distributionsourcepackage import (
@@ -306,6 +312,8 @@ class WebhookSet:
Webhook.distribution == target.distribution,
Webhook.source_package_name == target.sourcepackagename,
)
+ elif ICraftRecipe.providedBy(target):
+ target_filter = Webhook.craft_recipe == target
else:
raise AssertionError("Unsupported target: %r" % (target,))
return (
Follow ups