launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #24400
[Merge] ~twom/launchpad:detatch-oci-recipe-from-source into launchpad:master
Tom Wardill has proposed merging ~twom/launchpad:detatch-oci-recipe-from-source into launchpad:master.
Commit message:
Allow an OCIRecipe to be detatched from the source git repository
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~twom/launchpad/+git/launchpad/+merge/380039
Implement the detachFromGitRepository method from snaps into the OCI recipe model.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~twom/launchpad:detatch-oci-recipe-from-source into launchpad:master.
diff --git a/lib/lp/code/model/gitrepository.py b/lib/lp/code/model/gitrepository.py
index 6260c16..5ac0288 100644
--- a/lib/lp/code/model/gitrepository.py
+++ b/lib/lp/code/model/gitrepository.py
@@ -143,6 +143,7 @@ from lp.code.model.gitrule import (
GitRuleGrant,
)
from lp.code.model.gitsubscription import GitSubscription
+from lp.oci.interfaces.ocirecipe import IOCIRecipeSet
from lp.registry.enums import PersonVisibility
from lp.registry.errors import CannotChangeInformationType
from lp.registry.interfaces.accesspolicy import (
@@ -1525,6 +1526,10 @@ class GitRepository(StormBase, WebhookTargetMixin, GitIdentityMixin):
alteration_operations.append(DeletionCallable(
None, msg("Some snap packages build from this repository."),
getUtility(ISnapSet).detachFromGitRepository, self))
+ if not getUtility(IOCIRecipeSet).findByGitRepository(self).is_empty():
+ alteration_operations.append(DeletionCallable(
+ None, msg("Some OCI recipes build from this repository."),
+ getUtility(IOCIRecipeSet).detachFromGitRepository, self))
return (alteration_operations, deletion_operations)
diff --git a/lib/lp/oci/interfaces/ocirecipe.py b/lib/lp/oci/interfaces/ocirecipe.py
index e665c1e..751326f 100644
--- a/lib/lp/oci/interfaces/ocirecipe.py
+++ b/lib/lp/oci/interfaces/ocirecipe.py
@@ -182,7 +182,7 @@ class IOCIRecipeEditableAttributes(IHasOwner):
git_repository = ReferenceChoice(
title=_("Git repository"),
schema=IGitRepository, vocabulary="GitRepository",
- required=True, readonly=False,
+ required=False, readonly=False,
description=_(
"A Git repository with a branch containing a Dockerfile "
"at the location defined by the build_file attribute."))
@@ -252,4 +252,19 @@ class IOCIRecipeSet(Interface):
"""Return all OCI recipes with the given `oci_project`."""
def preloadDataForOCIRecipes(recipes, user):
- """Load the data reloated to a list of OCI Recipes."""
+ """Load the data related to a list of OCI Recipes."""
+
+ def findByGitRepository(repository, paths=None):
+ """Return all OCI recipes for the given Git repository.
+
+ :param repository: An `IGitRepository`.
+ :param paths: If not None, only return OCI recipes for one of
+ these Git reference paths.
+ """
+
+ def detachFromGitRepository(repository):
+ """Detach all OCI recipes from the given Git repository.
+
+ After this, any OCI recipes that previously used this repository
+ will have no source and so cannot dispatch new builds.
+ """
diff --git a/lib/lp/oci/model/ocirecipe.py b/lib/lp/oci/model/ocirecipe.py
index 2bf8068..79a3b0d 100644
--- a/lib/lp/oci/model/ocirecipe.py
+++ b/lib/lp/oci/model/ocirecipe.py
@@ -97,9 +97,9 @@ class OCIRecipe(Storm):
official = Bool(name="official", default=False)
- git_repository_id = Int(name="git_repository", allow_none=False)
+ git_repository_id = Int(name="git_repository", allow_none=True)
git_repository = Reference(git_repository_id, "GitRepository.id")
- git_path = Unicode(name="git_path", allow_none=False)
+ git_path = Unicode(name="git_path", allow_none=True)
build_file = Unicode(name="build_file", allow_none=False)
require_virtualized = Bool(name="require_virtualized", default=True,
@@ -152,8 +152,8 @@ class OCIRecipe(Storm):
def git_ref(self, value):
"""See `IOCIRecipe`."""
if value is not None:
- self.git_path = value.path
self.git_repository = value.repository
+ self.git_path = value.path
else:
self.git_repository = None
self.git_path = None
@@ -306,14 +306,26 @@ class OCIRecipeSet:
return oci_recipe
def findByOwner(self, owner):
- """See `IOCIRecipe`."""
+ """See `IOCIRecipeSet`."""
return IStore(OCIRecipe).find(OCIRecipe, OCIRecipe.owner == owner)
def findByOCIProject(self, oci_project):
- """See `IOCIRecipe`."""
+ """See `IOCIRecipeSet`."""
return IStore(OCIRecipe).find(
OCIRecipe, OCIRecipe.oci_project == oci_project)
+ def findByGitRepository(self, repository, paths=None):
+ """See `IOCIRecipeSet`."""
+ clauses = [OCIRecipe.git_repository == repository]
+ if paths is not None:
+ clauses.append(OCIRecipe.git_path.is_in(paths))
+ return IStore(OCIRecipe).find(OCIRecipe, *clauses)
+
+ def detachFromGitRepository(self, repository):
+ """See `IOCIRecipeSet`."""
+ self.findByGitRepository(repository).set(
+ git_repository_id=None, git_path=None, date_last_modified=UTC_NOW)
+
def preloadDataForOCIRecipes(self, recipes, user=None):
"""See `IOCIRecipeSet`."""
recipes = [removeSecurityProxy(recipe) for recipe in recipes]
diff --git a/lib/lp/oci/tests/test_ocirecipe.py b/lib/lp/oci/tests/test_ocirecipe.py
index 5b614f0..2bcc053 100644
--- a/lib/lp/oci/tests/test_ocirecipe.py
+++ b/lib/lp/oci/tests/test_ocirecipe.py
@@ -227,3 +227,30 @@ class TestOCIRecipeSet(TestCaseWithFactory):
owner=owner,
oci_project=oci_project,
name="missing")
+
+ def test_detachFromGitRepository(self):
+ repositories = [self.factory.makeGitRepository() for i in range(2)]
+ oci_recipes = []
+ paths = []
+ refs = []
+ for repository in repositories:
+ for i in range(2):
+ [ref] = self.factory.makeGitRefs(repository=repository)
+ paths.append(ref.path)
+ refs.append(ref)
+ oci_recipes.append(self.factory.makeOCIRecipe(
+ git_ref=ref, date_created=ONE_DAY_AGO))
+ getUtility(IOCIRecipeSet).detachFromGitRepository(repositories[0])
+ self.assertEqual(
+ [None, None, repositories[1], repositories[1]],
+ [oci_recipe.git_repository for oci_recipe in oci_recipes])
+ self.assertEqual(
+ [None, None, paths[2], paths[3]],
+ [oci_recipe.git_path for oci_recipe in oci_recipes])
+ self.assertEqual(
+ [None, None, refs[2], refs[3]],
+ [oci_recipe.git_ref for oci_recipe in oci_recipes])
+ for oci_recipe in oci_recipes[:2]:
+ self.assertSqlAttributeEqualsDate(
+ oci_recipe, "date_last_modified", UTC_NOW)
+
Follow ups