Skip to content

Commit cbdd7ff

Browse files
authored
ci: merge main to release (#9459)
2 parents 83168f3 + 0ee7011 commit cbdd7ff

File tree

13 files changed

+199
-47
lines changed

13 files changed

+199
-47
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ jobs:
454454
token: ${{ secrets.GH_INFRA_K8S_TOKEN }}
455455
inputs: '{ "environment":"${{ secrets.GHA_K8S_CLUSTER }}", "app":"datatracker", "manifest":"postgres", "forceRecreate":true, "waitClusterReady":true }'
456456
wait-for-completion: true
457-
wait-for-completion-timeout: 10m
457+
wait-for-completion-timeout: 30m
458458
wait-for-completion-interval: 20s
459459
display-workflow-run-url: false
460460

ietf/doc/admin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ class StateTypeAdmin(admin.ModelAdmin):
2222
admin.site.register(StateType, StateTypeAdmin)
2323

2424
class StateAdmin(admin.ModelAdmin):
25-
list_display = ["slug", "type", 'name', 'order', 'desc']
26-
list_filter = ["type", ]
25+
list_display = ["slug", "type", 'name', 'order', 'desc', "used"]
26+
list_filter = ["type", "used"]
2727
search_fields = ["slug", "type__label", "type__slug", "name", "desc"]
2828
filter_horizontal = ["next_states"]
2929
admin.site.register(State, StateAdmin)

ietf/group/templatetags/group_filters.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,10 @@ def role_person_link(role, **kwargs):
3737
plain_name = role.person.plain_name()
3838
email = role.email.address
3939
return {'name': name, 'plain_name': plain_name, 'email': email, 'title': title, 'class': cls}
40+
41+
@register.filter
42+
def name_with_conditional_acronym(group):
43+
if group.type_id in ("sdo", "isoc", "individ", "nomcom", "ietf", "irtf", ):
44+
return group.name
45+
else:
46+
return f"{group.name} ({group.acronym})"

ietf/liaisons/forms.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ def internal_groups_for_person(person: Optional[Person]):
105105
"Secretariat",
106106
"IETF Chair",
107107
"IAB Chair",
108-
"IAB Executive Director",
109108
"Liaison Manager",
110109
"Liaison Coordinator",
111110
"Authorized Individual",
@@ -115,7 +114,7 @@ def internal_groups_for_person(person: Optional[Person]):
115114
# Interesting roles, as Group queries
116115
queries = [
117116
Q(role__person=person, role__name="chair", acronym="ietf"),
118-
Q(role__person=person, role__name__in=("chair", "execdir"), acronym="iab"),
117+
Q(role__person=person, role__name="chair", acronym="iab"),
119118
Q(role__person=person, role__name="ad", type="area", state="active"),
120119
Q(
121120
role__person=person,

ietf/liaisons/tests.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,6 @@ def test_get_cc(self):
123123
cc = get_cc(Group.objects.get(acronym='iab'))
124124
self.assertTrue(EMAIL_ALIASES['IAB'] in cc)
125125
self.assertTrue(EMAIL_ALIASES['IABCHAIR'] in cc)
126-
self.assertTrue(EMAIL_ALIASES['IABEXECUTIVEDIRECTOR'] in cc)
127126
# test an Area
128127
area = Group.objects.filter(type='area').first()
129128
cc = get_cc(area)
@@ -166,7 +165,6 @@ def test_get_contacts_for_group(self):
166165
# test iab
167166
contacts = get_contacts_for_group(Group.objects.get(acronym='iab'))
168167
self.assertTrue(EMAIL_ALIASES['IABCHAIR'] in contacts)
169-
self.assertTrue(EMAIL_ALIASES['IABEXECUTIVEDIRECTOR'] in contacts)
170168
# test iesg
171169
contacts = get_contacts_for_group(Group.objects.get(acronym='iesg'))
172170
self.assertTrue(EMAIL_ALIASES['IESG'] in contacts)
@@ -534,7 +532,6 @@ def test_outgoing_access(self):
534532
RoleFactory(name_id='liaison_coordinator', group__acronym='iab', person__user__username='liaison-coordinator')
535533
mars = RoleFactory(name_id='chair',person__user__username='marschairman',group__acronym='mars').group
536534
RoleFactory(name_id='secr',group=mars,person__user__username='mars-secr')
537-
RoleFactory(name_id='execdir',group=Group.objects.get(acronym='iab'),person__user__username='iab-execdir')
538535

539536
url = urlreverse('ietf.liaisons.views.liaison_list')
540537
addurl = urlreverse('ietf.liaisons.views.liaison_add', kwargs={'type':'outgoing'})
@@ -592,15 +589,6 @@ def test_outgoing_access(self):
592589
r = self.client.get(addurl)
593590
self.assertEqual(r.status_code, 200)
594591

595-
# IAB Executive Director
596-
self.assertTrue(self.client.login(username="iab-execdir", password="iab-execdir+password"))
597-
r = self.client.get(url)
598-
self.assertEqual(r.status_code, 200)
599-
q = PyQuery(r.content)
600-
self.assertEqual(len(q("a.btn:contains('New outgoing liaison')")), 1)
601-
r = self.client.get(addurl)
602-
self.assertEqual(r.status_code, 200)
603-
604592
# Liaison Manager has access
605593
self.assertTrue(self.client.login(username="ulm-liaiman", password="ulm-liaiman+password"))
606594
r = self.client.get(url)

ietf/liaisons/tests_forms.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,6 @@ def test_all_internal_groups(self):
9494
def test_internal_groups_for_person(self):
9595
# test relies on the data created in ietf.utils.test_data.make_immutable_test_data()
9696
# todo add liaison coordinator when modeled
97-
RoleFactory(
98-
name_id="execdir",
99-
group=Group.objects.get(acronym="iab"),
100-
person__user__username="iab-execdir",
101-
)
10297
RoleFactory(
10398
name_id="auth",
10499
group__type_id="sdo",
@@ -121,7 +116,6 @@ def test_internal_groups_for_person(self):
121116
"secretary",
122117
"ietf-chair",
123118
"iab-chair",
124-
"iab-execdir",
125119
"sdo-authperson",
126120
):
127121
returned_queryset = internal_groups_for_person(
@@ -151,11 +145,6 @@ def test_internal_groups_for_person(self):
151145
)
152146

153147
def test_external_groups_for_person(self):
154-
RoleFactory(
155-
name_id="execdir",
156-
group=Group.objects.get(acronym="iab"),
157-
person__user__username="iab-execdir",
158-
)
159148
RoleFactory(name_id="liaison_coordinator", group__acronym="iab", person__user__username="liaison-coordinator")
160149
the_sdo = GroupFactory(type_id="sdo", acronym="the-sdo")
161150
liaison_manager = RoleFactory(name_id="liaiman", group=the_sdo).person
@@ -166,7 +155,6 @@ def test_external_groups_for_person(self):
166155
"secretary",
167156
"ietf-chair",
168157
"iab-chair",
169-
"iab-execdir",
170158
"liaison-coordinator",
171159
"ad",
172160
"sopschairman",

ietf/liaisons/utils.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
OUTGOING_LIAISON_ROLES = [
99
"Area Director",
1010
"IAB Chair",
11-
"IAB Executive Director",
1211
"IETF Chair",
1312
"Liaison Manager",
1413
"Liaison Coordinator",

ietf/liaisons/views.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@
3030
from ietf.utils.response import permission_denied
3131

3232
EMAIL_ALIASES = {
33-
'IETFCHAIR':'The IETF Chair <[email protected]>',
34-
'IESG':'The IESG <[email protected]>',
35-
'IAB':'The IAB <[email protected]>',
36-
'IABCHAIR':'The IAB Chair <[email protected]>',
37-
'IABEXECUTIVEDIRECTOR':'The IAB Executive Director <[email protected]>'}
33+
"IETFCHAIR": "The IETF Chair <[email protected]>",
34+
"IESG": "The IESG <[email protected]>",
35+
"IAB": "The IAB <[email protected]>",
36+
"IABCHAIR": "The IAB Chair <[email protected]>",
37+
}
38+
3839

3940
# -------------------------------------------------
4041
# Helper Functions
@@ -84,8 +85,6 @@ def _find_person_in_emails(liaison, person):
8485
return True
8586
elif addr in ('[email protected]', '[email protected]') and has_role(person.user, "IAB Chair"):
8687
return True
87-
elif addr in ('[email protected]', ) and has_role(person.user, "IAB Executive Director"):
88-
return True
8988

9089
return False
9190

@@ -110,7 +109,6 @@ def get_cc(group):
110109
elif group.acronym in ('iab'):
111110
emails.append(EMAIL_ALIASES['IAB'])
112111
emails.append(EMAIL_ALIASES['IABCHAIR'])
113-
emails.append(EMAIL_ALIASES['IABEXECUTIVEDIRECTOR'])
114112
elif group.type_id == 'area':
115113
emails.append(EMAIL_ALIASES['IETFCHAIR'])
116114
ad_roles = group.role_set.filter(name='ad')
@@ -151,7 +149,6 @@ def get_contacts_for_group(group):
151149
contacts.append(EMAIL_ALIASES['IETFCHAIR'])
152150
elif group.acronym == 'iab':
153151
contacts.append(EMAIL_ALIASES['IABCHAIR'])
154-
contacts.append(EMAIL_ALIASES['IABEXECUTIVEDIRECTOR'])
155152
elif group.acronym == 'iesg':
156153
contacts.append(EMAIL_ALIASES['IESG'])
157154

@@ -171,7 +168,7 @@ def needs_approval(group,person):
171168
user = person.user
172169
if group.acronym in ('ietf','iesg') and has_role(user, 'IETF Chair'):
173170
return False
174-
if group.acronym == 'iab' and (has_role(user,'IAB Chair') or has_role(user,'IAB Executive Director')):
171+
if group.acronym == 'iab' and has_role(user,'IAB Chair'):
175172
return False
176173
if group.type_id == 'area' and group.role_set.filter(name='ad',person=person):
177174
return False

ietf/mailtrigger/admin.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
# Copyright The IETF Trust 2015-2019, All Rights Reserved
1+
# Copyright The IETF Trust 2015-2025, All Rights Reserved
22
from django.contrib import admin
3+
from simple_history.admin import SimpleHistoryAdmin
34

45
from ietf.mailtrigger.models import MailTrigger, Recipient
56

6-
class RecipientAdmin(admin.ModelAdmin):
7+
class RecipientAdmin(SimpleHistoryAdmin):
78
list_display = [ 'slug', 'desc', 'template', 'has_code', ]
89
def has_code(self, obj):
910
return hasattr(obj,'gather_%s'%obj.slug)
1011
has_code.boolean = True # type: ignore # https://github.com/python/mypy/issues/2087
1112
admin.site.register(Recipient, RecipientAdmin)
1213

1314

14-
class MailTriggerAdmin(admin.ModelAdmin):
15+
class MailTriggerAdmin(SimpleHistoryAdmin):
1516
list_display = [ 'slug', 'desc', ]
1617
filter_horizontal = [ 'to', 'cc', ]
1718
admin.site.register(MailTrigger, MailTriggerAdmin)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Copyright The IETF Trust 2025, All Rights Reserved
2+
from io import StringIO
3+
4+
from django.conf import settings
5+
from django.core import management
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
import simple_history.models
9+
10+
from ietf.utils.log import log
11+
12+
13+
def forward(apps, schema_editor):
14+
# Fill in history for existing data using the populate_history management command
15+
captured_stdout = StringIO()
16+
captured_stderr = StringIO()
17+
try:
18+
management.call_command(
19+
"populate_history",
20+
"mailtrigger.MailTrigger",
21+
"mailtrigger.Recipient",
22+
stdout=captured_stdout,
23+
stderr=captured_stderr,
24+
)
25+
except management.CommandError as err:
26+
log(
27+
"Failed to populate history for mailtrigger models.\n"
28+
"\n"
29+
f"stdout:\n{captured_stdout.getvalue() or '<none>'}\n"
30+
"\n"
31+
f"stderr:\n{captured_stderr.getvalue() or '<none>'}\n"
32+
)
33+
raise RuntimeError("Failed to populate history for mailtrigger models") from err
34+
log(
35+
"Populated history for mailtrigger models.\n"
36+
"\n"
37+
f"stdout:\n{captured_stdout.getvalue() or '<none>'}\n"
38+
"\n"
39+
f"stderr:\n{captured_stderr.getvalue() or '<none>'}\n"
40+
)
41+
42+
43+
def reverse(apps, schema_editor):
44+
pass # nothing to do
45+
46+
47+
class Migration(migrations.Migration):
48+
dependencies = [
49+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
50+
("mailtrigger", "0006_call_for_adoption_and_last_call_issued"),
51+
]
52+
53+
operations = [
54+
migrations.CreateModel(
55+
name="HistoricalRecipient",
56+
fields=[
57+
("slug", models.CharField(db_index=True, max_length=32)),
58+
("desc", models.TextField(blank=True)),
59+
("template", models.TextField(blank=True, null=True)),
60+
("history_id", models.AutoField(primary_key=True, serialize=False)),
61+
("history_date", models.DateTimeField(db_index=True)),
62+
("history_change_reason", models.CharField(max_length=100, null=True)),
63+
(
64+
"history_type",
65+
models.CharField(
66+
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
67+
max_length=1,
68+
),
69+
),
70+
(
71+
"history_user",
72+
models.ForeignKey(
73+
null=True,
74+
on_delete=django.db.models.deletion.SET_NULL,
75+
related_name="+",
76+
to=settings.AUTH_USER_MODEL,
77+
),
78+
),
79+
],
80+
options={
81+
"verbose_name": "historical recipient",
82+
"verbose_name_plural": "historical recipients",
83+
"ordering": ("-history_date", "-history_id"),
84+
"get_latest_by": ("history_date", "history_id"),
85+
},
86+
bases=(simple_history.models.HistoricalChanges, models.Model),
87+
),
88+
migrations.CreateModel(
89+
name="HistoricalMailTrigger",
90+
fields=[
91+
("slug", models.CharField(db_index=True, max_length=64)),
92+
("desc", models.TextField(blank=True)),
93+
("history_id", models.AutoField(primary_key=True, serialize=False)),
94+
("history_date", models.DateTimeField(db_index=True)),
95+
("history_change_reason", models.CharField(max_length=100, null=True)),
96+
(
97+
"history_type",
98+
models.CharField(
99+
choices=[("+", "Created"), ("~", "Changed"), ("-", "Deleted")],
100+
max_length=1,
101+
),
102+
),
103+
(
104+
"history_user",
105+
models.ForeignKey(
106+
null=True,
107+
on_delete=django.db.models.deletion.SET_NULL,
108+
related_name="+",
109+
to=settings.AUTH_USER_MODEL,
110+
),
111+
),
112+
],
113+
options={
114+
"verbose_name": "historical mail trigger",
115+
"verbose_name_plural": "historical mail triggers",
116+
"ordering": ("-history_date", "-history_id"),
117+
"get_latest_by": ("history_date", "history_id"),
118+
},
119+
bases=(simple_history.models.HistoricalChanges, models.Model),
120+
),
121+
migrations.RunPython(forward, reverse),
122+
]

0 commit comments

Comments
 (0)