launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #27678
[Merge] ~cjwatson/launchpad:mark-charm-recipes-stale into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:mark-charm-recipes-stale into launchpad:master.
Commit message:
Mark charm recipes stale when their source branches changed
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #1950005 in Launchpad itself: "Not getting automated charm builds"
https://bugs.launchpad.net/launchpad/+bug/1950005
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/411464
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:mark-charm-recipes-stale into launchpad:master.
diff --git a/lib/lp/code/interfaces/gitrepository.py b/lib/lp/code/interfaces/gitrepository.py
index 363356d..cb12a5d 100644
--- a/lib/lp/code/interfaces/gitrepository.py
+++ b/lib/lp/code/interfaces/gitrepository.py
@@ -644,6 +644,14 @@ class IGitRepositoryView(IHasRecipes):
based on one of these paths will be marked as stale.
"""
+ def markCharmRecipesStale(paths):
+ """Mark charm recipes associated with this repository as stale.
+
+ :param paths: A list of reference paths. Any charm recipes that
+ include an entry that points to this repository and that are
+ based on one of these paths will be marked as stale.
+ """
+
def detectMerges(paths, logger=None):
"""Detect merges of landing candidates.
diff --git a/lib/lp/code/model/gitrepository.py b/lib/lp/code/model/gitrepository.py
index 99d451b..796ab80 100644
--- a/lib/lp/code/model/gitrepository.py
+++ b/lib/lp/code/model/gitrepository.py
@@ -1290,6 +1290,16 @@ class GitRepository(StormBase, WebhookTargetMixin, AccessTokenTargetMixin,
# this.
removeSecurityProxy(snap).is_stale = True
+ def markCharmRecipesStale(self, paths):
+ """See `IGitRepository`."""
+ recipes = getUtility(ICharmRecipeSet).findByGitRepository(
+ self, paths=paths, check_permissions=False)
+ for recipe in recipes:
+ # ICharmRecipeSet.findByGitRepository returns security-proxied
+ # CharmRecipe objects on which the is_stale attribute is
+ # read-only. Bypass this.
+ removeSecurityProxy(recipe).is_stale = True
+
def _markProposalMerged(self, proposal, merged_revision_id, logger=None):
if logger is not None:
logger.info(
diff --git a/lib/lp/code/model/tests/test_gitrepository.py b/lib/lp/code/model/tests/test_gitrepository.py
index e1579ee..dbdf8d9 100644
--- a/lib/lp/code/model/tests/test_gitrepository.py
+++ b/lib/lp/code/model/tests/test_gitrepository.py
@@ -55,7 +55,10 @@ from lp.app.enums import (
)
from lp.app.errors import NotFoundError
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
-from lp.charms.interfaces.charmrecipe import CHARM_RECIPE_ALLOW_CREATE
+from lp.charms.interfaces.charmrecipe import (
+ CHARM_RECIPE_ALLOW_CREATE,
+ CHARM_RECIPE_PRIVATE_FEATURE_FLAG,
+ )
from lp.code.enums import (
BranchMergeProposalStatus,
BranchSubscriptionDiffSize,
@@ -2796,6 +2799,48 @@ class TestGitRepositoryMarkSnapsStale(TestCaseWithFactory):
self.assertTrue(snap.is_stale)
+class TestGitRepositoryMarkCharmRecipesStale(TestCaseWithFactory):
+
+ layer = ZopelessDatabaseLayer
+
+ def setUp(self):
+ super().setUp()
+ self.useFixture(FeatureFixture({
+ CHARM_RECIPE_ALLOW_CREATE: "on",
+ CHARM_RECIPE_PRIVATE_FEATURE_FLAG: "on",
+ }))
+
+ def test_same_repository(self):
+ # On ref changes, charm recipes using this ref become stale.
+ [ref] = self.factory.makeGitRefs()
+ recipe = self.factory.makeCharmRecipe(git_ref=ref)
+ removeSecurityProxy(recipe).is_stale = False
+ ref.repository.createOrUpdateRefs(
+ {ref.path: {"sha1": "0" * 40, "type": GitObjectType.COMMIT}})
+ self.assertTrue(recipe.is_stale)
+
+ def test_same_repository_different_ref(self):
+ # On ref changes, charm recipes using a different ref in the same
+ # repository are left alone.
+ ref1, ref2 = self.factory.makeGitRefs(
+ paths=["refs/heads/a", "refs/heads/b"])
+ recipe = self.factory.makeCharmRecipe(git_ref=ref1)
+ removeSecurityProxy(recipe).is_stale = False
+ ref1.repository.createOrUpdateRefs(
+ {ref2.path: {"sha1": "0" * 40, "type": GitObjectType.COMMIT}})
+ self.assertFalse(recipe.is_stale)
+
+ def test_different_repository(self):
+ # On ref changes, unrelated charm recipes are left alone.
+ [ref] = self.factory.makeGitRefs()
+ recipe = self.factory.makeCharmRecipe(
+ git_ref=self.factory.makeGitRefs()[0])
+ removeSecurityProxy(recipe).is_stale = False
+ ref.repository.createOrUpdateRefs(
+ {ref.path: {"sha1": "0" * 40, "type": GitObjectType.COMMIT}})
+ self.assertFalse(recipe.is_stale)
+
+
class TestGitRepositoryFork(TestCaseWithFactory):
layer = DatabaseFunctionalLayer
diff --git a/lib/lp/code/subscribers/git.py b/lib/lp/code/subscribers/git.py
index 5a4ad04..30b432e 100644
--- a/lib/lp/code/subscribers/git.py
+++ b/lib/lp/code/subscribers/git.py
@@ -9,4 +9,5 @@ def refs_updated(repository, event):
repository.updateLandingTargets(event.paths)
repository.markRecipesStale(event.paths)
repository.markSnapsStale(event.paths)
+ repository.markCharmRecipesStale(event.paths)
repository.detectMerges(event.paths, logger=event.logger)