diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index a580b31b55..3b75607959 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -952,9 +952,19 @@ class AnalyticsBouncerTest(BouncerTestCase): audit_log = RealmAuditLog.objects.all().order_by("id").last() assert audit_log is not None audit_log_max_id = audit_log.id + + remote_server = RemoteZulipServer.objects.get(uuid=self.server_uuid) + assert remote_server is not None + assert remote_server.last_version is None + send_analytics_to_push_bouncer() self.assertTrue(responses.assert_call_count(ANALYTICS_STATUS_URL, 1)) + + remote_server = RemoteZulipServer.objects.get(uuid=self.server_uuid) + assert remote_server.last_version == ZULIP_VERSION + remote_audit_log_count = RemoteRealmAuditLog.objects.count() + self.assertEqual(RemoteRealmCount.objects.count(), 0) self.assertEqual(RemoteInstallationCount.objects.count(), 0) diff --git a/zilencer/migrations/0036_remotezulipserver_last_version.py b/zilencer/migrations/0036_remotezulipserver_last_version.py new file mode 100644 index 0000000000..9f12900011 --- /dev/null +++ b/zilencer/migrations/0036_remotezulipserver_last_version.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.7 on 2023-11-17 20:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("zilencer", "0035_remoterealmcount_remote_realm_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="remotezulipserver", + name="last_version", + field=models.CharField(max_length=128, null=True), + ), + ] diff --git a/zilencer/models.py b/zilencer/models.py index ad10b16d7a..4236abd2ec 100644 --- a/zilencer/models.py +++ b/zilencer/models.py @@ -30,6 +30,7 @@ class RemoteZulipServer(models.Model): UUID_LENGTH = 36 API_KEY_LENGTH = 64 HOSTNAME_MAX_LENGTH = 128 + VERSION_MAX_LENGTH = 128 # The unique UUID (`zulip_org_id`) and API key (`zulip_org_key`) # for this remote server registration. @@ -42,6 +43,7 @@ class RemoteZulipServer(models.Model): hostname = models.CharField(max_length=HOSTNAME_MAX_LENGTH) contact_email = models.EmailField(blank=True, null=False) last_updated = models.DateTimeField("last updated", auto_now=True) + last_version = models.CharField(max_length=VERSION_MAX_LENGTH, null=True) # Whether the server registration has been deactivated. deactivated = models.BooleanField(default=False) diff --git a/zilencer/views.py b/zilencer/views.py index f39609d8f1..c2035f0162 100644 --- a/zilencer/views.py +++ b/zilencer/views.py @@ -625,13 +625,21 @@ def remote_server_post_analytics( installation_counts: Json[List[InstallationCountDataForAnalytics]], realmauditlog_rows: Optional[Json[List[RealmAuditLogDataForAnalytics]]] = None, realms: Optional[Json[List[RealmDataForAnalytics]]] = None, + version: Optional[Json[str]] = None, ) -> HttpResponse: + if version is not None: + version = version[0 : RemoteZulipServer.VERSION_MAX_LENGTH] + if version != server.last_version: + server.last_version = version + server.save(update_fields=["last_version"]) + validate_incoming_table_data( server, RemoteRealmCount, [dict(count) for count in realm_counts], True ) validate_incoming_table_data( server, RemoteInstallationCount, [dict(count) for count in installation_counts], True ) + if realmauditlog_rows is not None: validate_incoming_table_data( server, RemoteRealmAuditLog, [dict(row) for row in realmauditlog_rows]