@@ -1387,7 +1387,7 @@ class Monorepo(BaseModel):
13871387 package_folder : str
13881388
13891389
1390- class PiPyRepo (BaseModel ):
1390+ class PyPiRepo (BaseModel ):
13911391 """PyPi model.
13921392 Attributes:
13931393 name (str): The name of the pypi package.
@@ -1475,6 +1475,99 @@ def validate_version_constraint(cls, version_constraint: str | None) -> str | No
14751475 return version_constraint if version_constraint != "" else None
14761476
14771477
1478+ class GitRepo (BaseModel ):
1479+ """Git repository model.
1480+ Attributes:
1481+ git_repository: The URL of the git repository.
1482+ git_branch_tag_commit: The branch, tag or commit of the git repository.
1483+ """
1484+
1485+ git_repository : str = Field (
1486+ title = "URL" ,
1487+ description = 'The URL of the git repository. (e.g., "https://github.com/example/plugin.git")' ,
1488+ )
1489+ git_branch_tag_commit : Optional [str ] = Field (
1490+ title = "Branch, tag or commit" ,
1491+ description = "The branch, tag or commit of the git repository." ,
1492+ )
1493+
1494+ @field_validator ("git_repository" , mode = "after" )
1495+ @classmethod
1496+ def validate_git_repository (cls , git_repository : str | None ) -> str | None :
1497+ """Validate Git repository URL format.
1498+
1499+ Args:
1500+ git_repository: The Git repository URL to validate.
1501+
1502+ Returns:
1503+ The validated repository URL or None if none is set.
1504+
1505+ Raises:
1506+ ValueError: If the repository URL is invalid.
1507+ """
1508+ if git_repository is not None and git_repository != "" :
1509+ if not git_repository .strip ():
1510+ raise ValueError ("Git repository URL cannot be empty or whitespace" )
1511+
1512+ # Support common Git URL formats: https://, git://, ssh://, git@
1513+ git_url_pattern = re .compile (
1514+ r"^(https?://|git://|git@)" r"[a-zA-Z0-9._-]+" r"(/|:)" r"[a-zA-Z0-9._/-]+" r"(\.git)?$"
1515+ )
1516+
1517+ if not git_url_pattern .match (git_repository ):
1518+ raise ValueError (
1519+ f"Invalid Git repository URL '{ git_repository } '. "
1520+ "Must be a valid Git URL (e.g., https://github.com/user/repo.git, "
1521+ "git@github.com:user/repo.git)"
1522+ )
1523+
1524+ # Additional validation for https/http URLs using existing validator
1525+ if git_repository .startswith (("http://" , "https://" )):
1526+ validate_plugin_url (git_repository , "Git repository URL" )
1527+
1528+ return git_repository if git_repository != "" else None
1529+
1530+ @field_validator ("git_branch_tag_commit" , mode = "after" )
1531+ @classmethod
1532+ def validate_git_branch_tag_commit (cls , git_branch_tag_commit : str | None ) -> str | None :
1533+ """Validate Git branch, tag, or commit reference.
1534+
1535+ Args:
1536+ git_branch_tag_commit: The Git reference to validate.
1537+
1538+ Returns:
1539+ The validated reference or None if none is set.
1540+
1541+ Raises:
1542+ ValueError: If the reference is invalid.
1543+ """
1544+ if git_branch_tag_commit is not None and git_branch_tag_commit != "" :
1545+ if not git_branch_tag_commit .strip ():
1546+ raise ValueError ("Git branch/tag/commit cannot be empty or whitespace" )
1547+
1548+ # Git refs can contain alphanumeric characters, hyphens, underscores, slashes, and periods
1549+ # Commit hashes are typically 7-40 hex characters
1550+ if not re .match (r"^[a-zA-Z0-9._/-]+$" , git_branch_tag_commit ):
1551+ raise ValueError (
1552+ f"Invalid Git branch/tag/commit '{ git_branch_tag_commit } '. "
1553+ "Must contain only alphanumeric characters, hyphens, underscores, slashes, and periods."
1554+ )
1555+
1556+ # Check for common invalid patterns
1557+ if git_branch_tag_commit .startswith (("/" , "." , "-" )) or git_branch_tag_commit .endswith (("/" , "." )):
1558+ raise ValueError (
1559+ f"Invalid Git branch/tag/commit '{ git_branch_tag_commit } '. "
1560+ "Cannot start with /, ., or - or end with / or ."
1561+ )
1562+
1563+ if len (git_branch_tag_commit ) > 255 :
1564+ raise ValueError (
1565+ f"Git branch/tag/commit '{ git_branch_tag_commit } ' exceeds maximum length of 255 characters"
1566+ )
1567+
1568+ return git_branch_tag_commit if git_branch_tag_commit != "" else None
1569+
1570+
14781571class PluginManifest (BaseModel ):
14791572 """Plugin manifest.
14801573
@@ -1487,6 +1580,10 @@ class PluginManifest(BaseModel):
14871580 tags (list[str]): a list of tags for making the plugin searchable.
14881581 available_hooks (list[str]): a list of the hook points where the plugin is callable.
14891582 default_config (dict[str, Any]): the default configurations.
1583+ monorepo (Monorepo): A git monorepo where the plugin originates (Initialized by cepx cli during plugin installation)
1584+ package_info: (PyPiRepo): The package name and version constraint of the package (Initialized by cepx cli during plugin installation)
1585+ local: The path to the locally installed plugin (Initialized by cepx cli during plugin installation)
1586+ git_repo: GitRepo: The git repo where the plugin originates (Initialized by cepx cli during plugin installation)
14901587 """
14911588
14921589 name : str
@@ -1498,7 +1595,9 @@ class PluginManifest(BaseModel):
14981595 available_hooks : list [str ]
14991596 default_config : dict [str , Any ]
15001597 monorepo : Optional [Monorepo ] = None
1501- package_info : Optional [PiPyRepo ] = None
1598+ package_info : Optional [PyPiRepo ] = None
1599+ local : Optional [str ] = None
1600+ git_repo : Optional [GitRepo ] = None
15021601
15031602 def suggest_instance_name (self ) -> str :
15041603 """Suggest a name for the plugin instance.
0 commit comments