diff mbox series

[layerindex-web,1/2] layerindex/views: fix publishing layers with multiple branches

Message ID 20261008142738.29958-1-tim.orling@konsulko.com
State New
Headers show
Series [layerindex-web,1/2] layerindex/views: fix publishing layers with multiple branches | expand

Commit Message

Tim Orling Oct. 8, 2026, 2:27 p.m. UTC
From: Michael Halstead <mhalstead@linuxfoundation.org>

publish_view assumed a layer had exactly one branch: get_object_or_404()
on LayerBranch raised MultipleObjectsReturned (HTTP 500) for any layer
with more than one, and passing the Branch object rather than its name to
reverse() produced a mangled URL when the branch had a short_description.

Collect active maintainers across all of the layer's branches, keyed by
email address so the greeting names and the recipient list cannot diverge
and the ordering is stable between sends, and list every branch the layer
is indexed on in the email body. A layer with no branches or no active
maintainers is now published without an email rather than returning 404.

Signed-off-by: Michael Halstead <mhalstead@linuxfoundation.org>
Signed-off-by: Tim Orling <tim.orling@konsulko.com>
---
 layerindex/views.py                   | 65 ++++++++++++++++-----------
 templates/layerindex/publishemail.txt |  6 ++-
 2 files changed, 44 insertions(+), 27 deletions(-)
diff mbox series

Patch

diff --git a/layerindex/views.py b/layerindex/views.py
index c671cc5..4f8e64e 100644
--- a/layerindex/views.py
+++ b/layerindex/views.py
@@ -31,7 +31,7 @@  from django.db.models.query import QuerySet
 from django.db.models.signals import pre_save
 from django.dispatch import receiver
 from django.http import Http404, HttpResponse, HttpResponseRedirect
-from django.shortcuts import get_list_or_404, get_object_or_404, render
+from django.shortcuts import get_object_or_404, render
 from django.template.loader import get_template
 from django.utils.decorators import method_decorator
 from django.utils.html import escape
@@ -376,31 +376,44 @@  def publish_view(request, name):
 
     if getattr(settings, 'SEND_PUBLISH_EMAIL', True):
         layeritem = get_object_or_404(LayerItem, name=name)
-        layerbranch = get_object_or_404(LayerBranch, layer=layeritem)
-        layer_url = request.build_absolute_uri(reverse('layer_item', args=(layerbranch.branch, layeritem.name)))
-        maintainers = get_list_or_404(LayerMaintainer, layerbranch=layerbranch)
-        from_email = settings.SUBMIT_EMAIL_FROM
-        subjecttext = get_template('layerindex/publishemailsubject.txt')
-        bodytext = get_template('layerindex/publishemail.txt')
-        maintainer_names = [m.name for m in maintainers]
-
-        # create subject from subject template
-        d = {
-            'layer_name': layeritem.name,
-            'site_name': request.META['HTTP_HOST'],
-        }
-        subject = subjecttext.render(d).rstrip()
-
-        #create body from body template
-        d = {
-            'maintainers': maintainer_names,
-            'layer_name': layeritem.name,
-            'layer_url': layer_url,
-            'help_contact': _get_help_contact(),
-        }
-        body = bodytext.render(d)
-
-        tasks.send_email.apply_async((subject, body, from_email, [m.email for m in maintainers]))
+        layerbranches = list(LayerBranch.objects.filter(layer=layeritem).select_related('branch'))
+
+        # Collect active maintainers across all branches of this layer, keyed by
+        # email so names and addresses stay in step and the order is stable.
+        maintainers = {}
+        for m in LayerMaintainer.objects.filter(layerbranch__layer=layeritem,
+                                                 status='A').order_by('name', 'email'):
+            maintainers.setdefault(m.email, m.name)
+
+        if layerbranches and maintainers:
+            branch_info = [{'branch': lb.branch.name,
+                             'url': request.build_absolute_uri(
+                                 reverse('layer_item', args=(lb.branch.name, layeritem.name)))}
+                            for lb in layerbranches]
+
+            # Prefer master as the primary link, otherwise the first branch
+            primary = next((b for b in branch_info if b['branch'] == 'master'), branch_info[0])
+
+            from_email = settings.SUBMIT_EMAIL_FROM
+            subjecttext = get_template('layerindex/publishemailsubject.txt')
+            bodytext = get_template('layerindex/publishemail.txt')
+
+            d = {
+                'layer_name': layeritem.name,
+                'site_name': request.META.get('HTTP_HOST', ''),
+            }
+            subject = subjecttext.render(d).rstrip()
+
+            d = {
+                'maintainers': list(maintainers.values()),
+                'layer_name': layeritem.name,
+                'layer_url': primary['url'],
+                'branches': branch_info,
+                'help_contact': _get_help_contact(),
+            }
+            body = bodytext.render(d)
+
+            tasks.send_email.apply_async((subject, body, from_email, list(maintainers.keys())))
 
     return _statuschange(request, name, 'P')
 
diff --git a/templates/layerindex/publishemail.txt b/templates/layerindex/publishemail.txt
index 5d703d8..068eca1 100644
--- a/templates/layerindex/publishemail.txt
+++ b/templates/layerindex/publishemail.txt
@@ -3,7 +3,11 @@  Hi {{ maintainers|slice:":-1"|join:", "}}{% if maintainers|length > 2 %},{% endi
 You are listed as the {% if maintainers|length > 1 %}maintainers{% else %}maintainer{% endif %} for the new layer, {{ layer_name }}. This layer has now been published. You can view it at the following URL:
 
  {{ layer_url }}
-
+{% if branches|length > 1 %}
+This layer is indexed on the following branches:
+{% for b in branches %}
+ {{ b.branch }} - {{ b.url }}{% endfor %}
+{% endif %}
 If you need to make changes to this layer's entry in the index in the future, create an account (using this email address) if you haven't already, and you should then be able to click on "Edit layer" on the layer's detail page and make the desired changes. If you need any assistance please contact {% if help_contact.first_name and help_contact.last_name %}{{ help_contact.first_name }} {{ help_contact.last_name}}{% else %}{{ help_contact.username }}{% endif %} <{{ help_contact.email }}>.
 
 Thanks!