This is an automated email from the ASF dual-hosted git repository.

juergbi pushed a commit to branch jbilleter/source-provenance
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit f18bda0550afff9027c6eff428e9383d897a4636
Author: Jürg Billeter <[email protected]>
AuthorDate: Fri Dec 19 13:47:31 2025 +0100

    wip
---
 src/buildstream/_project.py             |  5 +++++
 src/buildstream/data/projectconfig.yaml |  6 ++++++
 src/buildstream/element.py              |  2 +-
 src/buildstream/source.py               | 29 ++++++++++++++++-------------
 src/buildstream/types.py                |  5 +++--
 5 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/src/buildstream/_project.py b/src/buildstream/_project.py
index 334462df0..3f02ef885 100644
--- a/src/buildstream/_project.py
+++ b/src/buildstream/_project.py
@@ -125,6 +125,8 @@ class Project:
         self.sandbox: Optional[MappingNode] = None
         self.splits: Optional[MappingNode] = None
 
+        self.source_provenance_fields: Optional[MappingNode] = None  # Source 
provenance fields and their description
+
         #
         # Private members
         #
@@ -726,6 +728,7 @@ class Project:
                 "sources",
                 "source-caches",
                 "junctions",
+                "source-provenance-fields",
                 "(@)",
                 "(?)",
             ]
@@ -1006,6 +1009,8 @@ class Project:
 
             self._shell_host_files.append(mount)
 
+        self.source_provenance_fields: 
config.get_mapping("source-provenance-fields")
+
     # _load_pass():
     #
     # Loads parts of the project configuration that are different
diff --git a/src/buildstream/data/projectconfig.yaml 
b/src/buildstream/data/projectconfig.yaml
index 4632d7a1d..774e6056a 100644
--- a/src/buildstream/data/projectconfig.yaml
+++ b/src/buildstream/data/projectconfig.yaml
@@ -175,6 +175,12 @@ shell:
   #
   command: [ 'sh', '-i' ]
 
+# Define the set of fields accepted in `provenance` dictionaries of sources.
+#
+source-provenance-fields:
+  homepage: "The project homepage URL"
+  issue-tracker: "The project's issue tracking URL"
+
 # Defaults for bst commands
 #
 defaults:
diff --git a/src/buildstream/element.py b/src/buildstream/element.py
index fa79c2b44..c33661c3f 100644
--- a/src/buildstream/element.py
+++ b/src/buildstream/element.py
@@ -2639,7 +2639,7 @@ class Element(Plugin):
                 provenance = None
                 if provenance_node:
                     del source[Symbol.PROVENANCE]
-                    provenance = 
_SourceProvenance.new_from_node(provenance_node)
+                    provenance = _SourceProvenance.new_from_node(project, 
provenance_node)
 
                 meta_source = MetaSource(
                     self.name,
diff --git a/src/buildstream/source.py b/src/buildstream/source.py
index 6aeca25c8..e7c667187 100644
--- a/src/buildstream/source.py
+++ b/src/buildstream/source.py
@@ -48,6 +48,8 @@ any Source.
 
     The ``issue-tracker`` attribute can be used to specify the project's issue 
tracking URL
 
+TODO: document that fields can be configured in project
+
   *Since: 2.5*
 
 
@@ -553,8 +555,7 @@ class SourceInfo:
         self,
         kind: str,
         url: str,
-        homepage: Optional[str],
-        issue_tracker: Optional[str],
+        provenance: Optional[MappingNode],
         medium: Union[SourceInfoMedium, str],
         version_type: Union[SourceVersionType, str],
         version: str,
@@ -572,12 +573,18 @@ class SourceInfo:
         The url of the source input
         """
 
-        self.homepage: Optional[str] = homepage
+        self.provenance = provenance
+        """
+        The optional YAML node with source provenance attributes
+        """
+
+        # TODO
+        self.homepage: Optional[str] = provenance.get("homepage") if 
provenance else None
         """
         The project homepage URL
         """
 
-        self.issue_tracker: Optional[str] = issue_tracker
+        self.issue_tracker: Optional[str] = provenance.get("issue-tracker") if 
provenance else None
         """
         The project issue tracking URL
         """
@@ -642,6 +649,7 @@ class SourceInfo:
             "url": self.url,
         }
 
+        # TODO serialize project-defined provenance fields (need to keep 
homepage/issue-tracker [also] at the top-level for backward compat)
         if self.homepage is not None:
             version_info["homepage"] = self.homepage
         if self.issue_tracker is not None:
@@ -1393,23 +1401,18 @@ class Source(Plugin):
 
         *Since: 2.5*
         """
-        homepage = None
-        issue_tracker = None
+        project = self._get_project()
 
+        # TODO: Ensure provenance node keys are valid and values are all 
strings; same in element if we drop _SourceProvenance
         if provenance_node is not None:
-            provenance: Optional[_SourceProvenance] = 
_SourceProvenance.new_from_node(provenance_node)
+            provenance: Optional[_SourceProvenance] = 
_SourceProvenance.new_from_node(project, provenance_node)
         else:
             provenance = self.__provenance
 
-        if provenance is not None:
-            homepage = provenance.homepage
-            issue_tracker = provenance.issue_tracker
-
         return SourceInfo(
             self.get_kind(),
             url,
-            homepage,
-            issue_tracker,
+            provenance,
             medium,
             version_type,
             version,
diff --git a/src/buildstream/types.py b/src/buildstream/types.py
index d4d5e3cdb..0d75d2ea7 100644
--- a/src/buildstream/types.py
+++ b/src/buildstream/types.py
@@ -417,9 +417,10 @@ class _SourceProvenance:
     #    LoadError: If the node is malformed.
     #
     @classmethod
-    def new_from_node(cls, node: MappingNode) -> "_SourceProvenance":
-        node.validate_keys(["homepage", "issue-tracker"])
+    def new_from_node(cls, project: Project, node: MappingNode) -> 
"_SourceProvenance":
+        node.validate_keys(project.source_provenance_fields.keys())
 
+        # TODO: project-configured fields
         homepage: Optional[str] = node.get_str("homepage", None)
         issue_tracker: Optional[str] = node.get_str("issue-tracker", None)
 

Reply via email to