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

tn pushed a commit to branch add-project-model
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git


The following commit(s) were added to refs/heads/add-project-model by this push:
     new 5829387  further updates
5829387 is described below

commit 5829387f153f38110034f7fd57f38ec240cab038
Author: Thomas Neidhart <t...@apache.org>
AuthorDate: Tue Mar 11 16:14:13 2025 +0100

    further updates
---
 atr/blueprints/admin/admin.py        | 66 ++++++++++++++++++------------------
 atr/datasources/apache.py            | 15 ++++++++
 atr/db/models.py                     |  6 ++--
 atr/templates/pmc-directory.html     |  6 +++-
 atr/templates/pmc-view.html          | 21 ++++++++++--
 atr/templates/project-directory.html |  6 +++-
 atr/templates/project-view.html      |  2 +-
 7 files changed, 81 insertions(+), 41 deletions(-)

diff --git a/atr/blueprints/admin/admin.py b/atr/blueprints/admin/admin.py
index 3f3d716..f721dd1 100644
--- a/atr/blueprints/admin/admin.py
+++ b/atr/blueprints/admin/admin.py
@@ -30,9 +30,7 @@ from werkzeug.wrappers.response import Response
 from asfquart.base import ASFQuartException
 from asfquart.session import read as session_read
 from atr.datasources.apache import (
-    get_active_committee_data,
     get_current_podlings_data,
-    get_groups_data,
     get_ldap_projects_data,
     get_projects_data,
 )
@@ -209,10 +207,8 @@ async def admin_projects_update() -> str | Response | 
tuple[Mapping[str, Any], i
 
 
 async def _update_pmcs() -> int:
-    committee_data = await get_active_committee_data()
     ldap_projects = await get_ldap_projects_data()
     podlings_data = await get_current_podlings_data()
-    groups_data = await get_groups_data()
     projects_data = await get_projects_data()
 
     updated_count = 0
@@ -220,37 +216,36 @@ async def _update_pmcs() -> int:
     async with create_async_db_session() as db_session:
         async with db_session.begin():
             # First update PMCs
-            for committee in committee_data.committees:
-                name = committee.name
-                # Skip non-PMC committees
-                if not committee.pmc:
+            for ldap_project_data in ldap_projects.projects:
+                name = ldap_project_data.name
+                if not ldap_project_data.pmc and ldap_project_data.podling is 
None:
                     continue
 
+                _LOGGER.debug(f"Updating PMC {name}")
+
                 # Get or create PMC
                 pmc = await get_pmc_by_name(name, db_session)
                 if not pmc:
                     pmc = PMC(name=name)
                     db_session.add(pmc)
 
-                # Update PMC data from groups.json
-                pmc_members = groups_data.get(f"{name}-pmc")
-                committers = groups_data.get(name)
-                pmc.pmc_members = pmc_members if pmc_members is not None else 
[]
-                pmc.committers = committers if committers is not None else []
-                pmc.full_name = committee.display_name
-                pmc.description = committee.description
-                # Ensure this is set for PMCs
-                pmc.is_podling = False
-
-                # For release managers, use PMC members for now
-                # TODO: Consider a more sophisticated way to determine release 
managers
-                #       from my POV, the list of release managers should be 
the list of people
-                #       that have actually cut a release for that project
-                pmc.release_managers = pmc.pmc_members
+                pmc.pmc_members = ldap_project_data.owners
+                pmc.committers = ldap_project_data.members
+                if ldap_project_data.pmc:
+                    pmc.is_podling = False
+                elif ldap_project_data.podling == "current":
+                    pmc.is_podling = True
+                else:
+                    _LOGGER.error(f"unexpected pmc/podling state for project 
{name}")
+
+                project_data = projects_data.get(name)
+                if project_data:
+                    pmc.full_name = project_data.name
+                    pmc.description = project_data.description
 
                 updated_count += 1
 
-            # Then add PPMCs (podlings)
+            # Fill PPMC data from podlings.json
             for podling_name, podling_data in podlings_data:
                 # Get or create PPMC
                 ppmc = await get_pmc_by_name(podling_name, db_session)
@@ -258,27 +253,31 @@ async def _update_pmcs() -> int:
                     ppmc = PMC(name=podling_name)
                     db_session.add(ppmc)
 
-                # Update PPMC data from groups.json
-                pmc_members = groups_data.get(f"{podling_name}-pmc")
-                committers = groups_data.get(podling_name)
-                ppmc.pmc_members = pmc_members if pmc_members is not None else 
[]
-                ppmc.committers = committers if committers is not None else []
-                # Use PPMC members as release managers
-                ppmc.release_managers = ppmc.pmc_members
                 ppmc.full_name = podling_data.name
                 ppmc.description = podling_data.description
                 ppmc.parent_pmc = await get_pmc_by_name(podling_data.pmc, 
db_session)  # type: ignore
                 ppmc.is_podling = True
 
+                podling_project = await get_project_by_name(podling_name, 
db_session)
+                if not podling_project:
+                    podling_project = Project(name=podling_name)
+                    db_session.add(podling_project)
+
+                podling_project.full_name = podling_data.name
+                podling_project.description = podling_data.description
+                podling_project.is_podling = True
+                podling_project.pmc = ppmc  # type: ignore
+
                 updated_count += 1
 
+            # TODO: this is only for testing purposes, tooling should not be a 
PMC afaict
             # Add special entry for Tooling PMC
             # Not clear why, but it's not in the Whimsy data
-            statement = select(PMC).where(PMC.name == "tooling")
-            tooling_pmc = (await 
db_session.execute(statement)).scalar_one_or_none()
+            tooling_pmc = await get_pmc_by_name("tooling", db_session)
             if not tooling_pmc:
                 tooling_pmc = PMC(name="tooling")
                 db_session.add(tooling_pmc)
+
                 updated_count += 1
 
             # Update Tooling PMC data
@@ -288,6 +287,7 @@ async def _update_pmcs() -> int:
             tooling_pmc.release_managers = ["wave"]
             tooling_pmc.is_podling = False
 
+            # create projects from projects.json
             for project_name, project_status in projects_data:
                 # Get or create Project
                 project = await get_project_by_name(project_name, db_session)
diff --git a/atr/datasources/apache.py b/atr/datasources/apache.py
index 797227a..ae1da1a 100644
--- a/atr/datasources/apache.py
+++ b/atr/datasources/apache.py
@@ -36,6 +36,7 @@ _WHIMSY_PROJECTS_URL = 
"https://whimsy.apache.org/public/public_ldap_projects.js
 _PROJECTS_PROJECTS_URL = 
"https://projects.apache.org/json/foundation/projects.json";
 _PROJECTS_PODLINGS_URL = 
"https://projects.apache.org/json/foundation/podlings.json";
 _PROJECTS_GROUPS_URL = 
"https://projects.apache.org/json/foundation/groups.json";
+_PROJECTS_PEOPLE_NAME_URL = 
"https://projects.apache.org/json/foundation/people_name.json";
 
 VT = TypeVar("VT")
 
@@ -159,6 +160,10 @@ class ProjectsData(_DictRootModel[ProjectStatus]):
     pass
 
 
+class PeopleNameData(_DictRootModel[str]):
+    pass
+
+
 async def get_ldap_projects_data() -> LDAPProjectsData:
     async with httpx.AsyncClient() as client:
         response = await client.get(_WHIMSY_PROJECTS_URL)
@@ -218,3 +223,13 @@ async def get_projects_data() -> ProjectsData:
         response.raise_for_status()
         data = response.json()
     return ProjectsData.model_validate(data)
+
+
+async def get_people_name_data() -> PeopleNameData:
+    """Returns the list users and their names."""
+
+    async with httpx.AsyncClient() as client:
+        response = await client.get(_PROJECTS_PEOPLE_NAME_URL)
+        response.raise_for_status()
+        data = response.json()
+    return PeopleNameData.model_validate(data)
diff --git a/atr/db/models.py b/atr/db/models.py
index fa05a9c..7e72b3d 100644
--- a/atr/db/models.py
+++ b/atr/db/models.py
@@ -90,9 +90,10 @@ class PMC(ATRSQLModel, table=True):
     id: int | None = sqlmodel.Field(default=None, primary_key=True)
     name: str = sqlmodel.Field(unique=True)
     full_name: str | None = sqlmodel.Field(default=None)
+    description: str | None = sqlmodel.Field(default=None)
+
     # True if this a podling PPMC
     is_podling: bool = sqlmodel.Field(default=False)
-    description: str | None = sqlmodel.Field(default=None)
 
     # One-to-many: A PMC can have parent PMC, e.g. in the case of a PPMC
     child_pmcs: list["PMC"] = sqlmodel.Relationship(
@@ -135,13 +136,14 @@ class PMC(ATRSQLModel, table=True):
     @property
     def display_name(self) -> str:
         """Get the display name for the PMC/PPMC."""
-        return self.name if self.full_name is None else self.full_name
+        return f"{self.name.capitalize()}{' (PPMC)' if self.is_podling else 
''}"
 
 
 class Project(ATRSQLModel, table=True):
     id: int | None = sqlmodel.Field(default=None, primary_key=True)
     name: str = sqlmodel.Field(unique=True)
     full_name: str | None = sqlmodel.Field(default=None)
+    description: str | None = sqlmodel.Field(default=None)
 
     # True if this a podling PPMC
     is_podling: bool = sqlmodel.Field(default=False)
diff --git a/atr/templates/pmc-directory.html b/atr/templates/pmc-directory.html
index 2fbde53..572d09e 100644
--- a/atr/templates/pmc-directory.html
+++ b/atr/templates/pmc-directory.html
@@ -109,7 +109,11 @@
           for (let card of cards) {
               const nameElement = card.getElementsByClassName("pmc-name");
               const name = nameElement[0].innerHTML;
-              card.hidden = !pmcFilter || name.search(new RegExp(pmcFilter, 
"i")) < 0;
+              if (!pmcFilter) {
+                  card.hidden = false;
+              } else {
+                  card.hidden = name.search(new RegExp(pmcFilter, "i")) < 0;
+              }
           }
       }
   </script>
diff --git a/atr/templates/pmc-view.html b/atr/templates/pmc-view.html
index f0ee969..af9e96f 100644
--- a/atr/templates/pmc-view.html
+++ b/atr/templates/pmc-view.html
@@ -79,14 +79,27 @@
 {% endblock stylesheets %}
 
 {% block content %}
-  <h1>{{ pmc.display_name | capitalize }}</h1>
+  <h1>{{ pmc.display_name }}</h1>
+
+  {% if pmc.parent_pmc %}
+  <div class="card-header">
+    <h3>Parent PMC</h3>
+    <div class="card-meta"></div>
+    <div class="card-body"></div>
+      <a href="{{ url_for('root_pmc_view', name=pmc.parent_pmc.name) }}">
+        {{ pmc.parent_pmc.display_name }}
+      </a>
+  </div>
+  {% endif %}
 
   <div class="card-header">
     <h3>PMC members</h3>
     <div class="card-meta"></div>
     <div class="card-body">
       <p>
-        {% for user in pmc.pmc_members %}{{ user }},{% endfor %}
+        {% for user in pmc.pmc_members %}
+          {{ user }},
+        {% endfor %}
       </p>
     </div>
   </div>
@@ -96,7 +109,9 @@
     <div class="card-meta"></div>
     <div class="card-body">
       <p>
-        {% for user in pmc.committers %}{{ user }},{% endfor %}
+        {% for user in pmc.committers %}
+          {{ user }},
+        {% endfor %}
       </p>
     </div>
   </div>
diff --git a/atr/templates/project-directory.html 
b/atr/templates/project-directory.html
index aca5812..f9d7c58 100644
--- a/atr/templates/project-directory.html
+++ b/atr/templates/project-directory.html
@@ -96,7 +96,11 @@
           for (let card of cards) {
               const nameElement = card.getElementsByClassName("project-name");
               const name = nameElement[0].innerHTML;
-              card.hidden = !projectFilter || name.search(new 
RegExp(projectFilter, "i")) < 0;
+              if (!projectFilter) {
+                  card.hidden = false;
+              } else {
+                  card.hidden = name.search(new RegExp(projectFilter, "i")) < 
0;
+              }
           }
       }
   </script>
diff --git a/atr/templates/project-view.html b/atr/templates/project-view.html
index 8d09a61..8048b1c 100644
--- a/atr/templates/project-view.html
+++ b/atr/templates/project-view.html
@@ -79,7 +79,7 @@
 {% endblock stylesheets %}
 
 {% block content %}
-  <h1>{{ project.display_name | capitalize }}</h1>
+  <h1>{{ project.display_name }}</h1>
 
   <div class="card-header">
     <h3>PMC</h3>


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@tooling.apache.org
For additional commands, e-mail: commits-h...@tooling.apache.org

Reply via email to