diff --git a/docker-compose.yml b/docker-compose.yml
index f584e159..dad41ae3 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -99,6 +99,7 @@ services:
networks:
- backend
environment:
+ LOCAL_DEVELOPMENT: "true"
DEBUG_TOOLBAR: "false"
env_file:
- .env
diff --git a/docs/commands.md b/docs/commands.md
index c54c77da..fddff569 100644
--- a/docs/commands.md
+++ b/docs/commands.md
@@ -307,6 +307,8 @@ If both the `--release` and the `--library-name` are passed, the command will lo
**Purpose**: Execute a chain of commands which are necessary to run during a release. Imports new versions, beta versions, slack messages, github issues, commits, authors, maintainers, etc... Inspect the management command to see exactly which commands are being run.
+For this to work `SLACK_BOT_API` must be set in the `.env` file.
+
**Example**
```bash
diff --git a/docs/env_vars.md b/docs/env_vars.md
index 87926dc3..13997f7e 100644
--- a/docs/env_vars.md
+++ b/docs/env_vars.md
@@ -79,3 +79,6 @@ This project uses environment variables to configure certain aspects of the appl
### `MAX_CELERY_CONNECTIONS`
- If set, will set the maximum number of connections to the Celery in `settings.py`. Defaults to 60.
+
+### `SLACK_BOT_TOKEN`
+- Used to authenticate with the Slack API for pulling data for release reports.
diff --git a/env.template b/env.template
index b66072ce..4cbdf717 100644
--- a/env.template
+++ b/env.template
@@ -54,7 +54,8 @@ GITHUB_OAUTH_CLIENT_SECRET=
GOOGLE_OAUTH_CLIENT_ID=
GOOGLE_OAUTH_CLIENT_SECRET=
-SLACK_BOT_TOKEN=changeme
+# optional, needed to run reports
+SLACK_BOT_TOKEN=
DEBUG_TOOLBAR=True
# uncomment whichever is appropriate for your editor
# currently only pycharm is supported, vscode kept for example of alternative options
diff --git a/libraries/forms.py b/libraries/forms.py
index cd50fea0..543c648b 100644
--- a/libraries/forms.py
+++ b/libraries/forms.py
@@ -779,7 +779,9 @@ class CreateReportForm(CreateReportFullForm):
).aggregate(lines=Sum("deletions"))["lines"]
# we want 2 channels per pdf page, use batched to get groups of 2
slack_stats = batched(self._get_slack_stats(prior_version, version), 2)
+ committee_members = version.financial_committee_members.all()
return {
+ "committee_members": committee_members,
"lines_added": lines_added,
"lines_removed": lines_removed,
"wordcloud_base64": self._generate_hyperkitty_word_cloud(version),
diff --git a/libraries/management/commands/release_tasks.py b/libraries/management/commands/release_tasks.py
index 174ee8bf..d54906e1 100644
--- a/libraries/management/commands/release_tasks.py
+++ b/libraries/management/commands/release_tasks.py
@@ -32,6 +32,8 @@ def progress_message(message: str):
@locked(1138692)
def run_commands(progress: list[str]):
+ if not settings.SLACK_BOT_TOKEN:
+ raise ValueError("SLACK_BOT_TOKEN is not set.")
handled_commits = {}
progress.append(progress_message("Importing versions..."))
call_command("import_versions", "--new")
diff --git a/templates/admin/release_report_detail.html b/templates/admin/release_report_detail.html
index ce50f41e..dd502281 100644
--- a/templates/admin/release_report_detail.html
+++ b/templates/admin/release_report_detail.html
@@ -30,14 +30,14 @@
-
+
Boost
-
+
{% include "includes/_social_icon_links.html" %}
{{ commit_count|intcomma }} commit{{ commit_count|pluralize }} up through {{ version.display_name }}
@@ -59,12 +59,9 @@
|
- Platform
- |
-
- File
+ colspan="2"
+ class="p-3 h-8 text-base border border-b-0 border-gray-400 text-center">
+ Download Now!
|
{% for os, download_files in downloads.items %}
@@ -142,8 +139,20 @@
{% include "admin/_release_report_top_left_logo.html" %}
From the Fiscal Sponsorship Committee
-
{% endif %}
@@ -158,6 +167,7 @@
>
Boost {{ version.display_name }}
+
Git activity for this release
{{ version_commit_count|intcomma }} Commit{{ version_commit_count|pluralize }} Across {{ library_count }} Repositories
diff --git a/templates/includes/_social_icon_links.html b/templates/includes/_social_icon_links.html
index f5207370..b5d6dbac 100644
--- a/templates/includes/_social_icon_links.html
+++ b/templates/includes/_social_icon_links.html
@@ -3,3 +3,4 @@
+
diff --git a/users/admin.py b/users/admin.py
index e5e4596a..a07a063c 100644
--- a/users/admin.py
+++ b/users/admin.py
@@ -43,6 +43,10 @@ class EmailUserAdmin(UserAdmin):
)
},
),
+ (
+ _("High Quality Image"),
+ {"fields": ("hq_image",)},
+ ),
)
add_fieldsets = (
(None, {"classes": ("wide",), "fields": ("email", "password1", "password2")}),
diff --git a/users/migrations/0016_user_hq_image.py b/users/migrations/0016_user_hq_image.py
new file mode 100644
index 00000000..ff92140b
--- /dev/null
+++ b/users/migrations/0016_user_hq_image.py
@@ -0,0 +1,31 @@
+# Generated by Django 4.2.16 on 2025-01-22 22:39
+
+import core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("users", "0015_user_delete_permanently_at"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="user",
+ name="hq_image",
+ field=models.FileField(
+ blank=True,
+ help_text="A high-quality image of the user - used in profiles/reports.",
+ null=True,
+ upload_to="hiqh-quality-user-images",
+ validators=[
+ core.validators.FileTypeValidator(
+ extensions=[".jpg", ".jpeg", ".png"]
+ ),
+ core.validators.MaxFileSizeValidator(max_size=52428800),
+ ],
+ verbose_name="High Quality Image",
+ ),
+ ),
+ ]
diff --git a/users/models.py b/users/models.py
index 4c51d410..fb2661df 100644
--- a/users/models.py
+++ b/users/models.py
@@ -20,7 +20,11 @@ from django.utils.translation import gettext_lazy as _
from imagekit.models import ImageSpecField
from imagekit.processors import ResizeToFill
-from core.validators import image_validator, max_file_size_validator
+from core.validators import (
+ image_validator,
+ max_file_size_validator,
+ large_file_max_size_validator,
+)
logger = logging.getLogger(__name__)
@@ -221,6 +225,20 @@ class User(BaseUser):
format="JPEG",
options={"quality": 90},
)
+ hq_image = models.FileField(
+ upload_to="hiqh-quality-user-images",
+ help_text="A high-quality image of the user - used in profiles/reports.",
+ null=True,
+ blank=True,
+ validators=[image_validator, large_file_max_size_validator],
+ verbose_name="High Quality Image",
+ )
+ hq_image_render = ImageSpecField(
+ source="hq_image",
+ processors=[ResizeToFill(4096, 4096)],
+ format="JPEG",
+ options={"quality": 90},
+ )
claimed = models.BooleanField(
_("claimed"),
default=True,
@@ -318,6 +336,9 @@ class User(BaseUser):
self.delete_permanently_at = None
self.save()
+ def __str__(self):
+ return f"{self.first_name} {self.last_name} <{self.email}>"
+
class LastSeen(models.Model):
"""
diff --git a/versions/admin.py b/versions/admin.py
index 2b52b92b..9b24ef05 100755
--- a/versions/admin.py
+++ b/versions/admin.py
@@ -30,6 +30,7 @@ class VersionAdmin(admin.ModelAdmin):
search_fields = ["name", "description"]
date_hierarchy = "release_date"
inlines = [VersionFileInline]
+ filter_horizontal = ["financial_committee_members"]
change_list_template = "admin/version_change_list.html"
def get_urls(self):
diff --git a/versions/migrations/0018_version_financial_committee_members.py b/versions/migrations/0018_version_financial_committee_members.py
new file mode 100644
index 00000000..544ae8b8
--- /dev/null
+++ b/versions/migrations/0018_version_financial_committee_members.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.2.16 on 2025-01-21 01:15
+
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ("versions", "0017_alter_review_review_manager_alter_review_submitters"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="version",
+ name="financial_committee_members",
+ field=models.ManyToManyField(
+ blank=True,
+ help_text="Financial Committee members who are responsible for this release.",
+ to=settings.AUTH_USER_MODEL,
+ ),
+ ),
+ ]
diff --git a/versions/models.py b/versions/models.py
index 4e735ebe..393f1eba 100755
--- a/versions/models.py
+++ b/versions/models.py
@@ -47,7 +47,11 @@ class Version(models.Model):
blank=True,
help_text='Message to show in release reports on the "Fiscal Sponsorship Committee" page.', # noqa: E501
)
-
+ financial_committee_members = models.ManyToManyField(
+ User,
+ blank=True,
+ help_text="Financial Committee members who are responsible for this release.",
+ )
objects = VersionManager()
def __str__(self):