diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dbd9fc5..859c8846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Add new field description_short to private api ([#1698](https://github.com/grafana/oncall/pull/1698)) - Added preview and migration API endpoints for route migration from regex into jinja2 ([1715](https://github.com/grafana/oncall/pull/1715)) - Helm chart: add the option to use a helm hook for the migration job ([1386](https://github.com/grafana/oncall/pull/1386)) - Add endpoints to start and stop maintenance in alert receive channel private api ([1755](https://github.com/grafana/oncall/pull/1755)) @@ -52,7 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Save selected teams filter in local storage ([1611](https://github.com/grafana/oncall/issues/1611)) +- Save selected teams filter in local storage ([#1611](https://github.com/grafana/oncall/issues/1611)) ### Changed diff --git a/engine/apps/alerts/migrations/0012_alertreceivechannel_description_short.py b/engine/apps/alerts/migrations/0012_alertreceivechannel_description_short.py new file mode 100644 index 00000000..4e35755a --- /dev/null +++ b/engine/apps/alerts/migrations/0012_alertreceivechannel_description_short.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.18 on 2023-04-17 01:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('alerts', '0011_auto_20230329_1617'), + ] + + operations = [ + migrations.AddField( + model_name='alertreceivechannel', + name='description_short', + field=models.CharField(default=None, max_length=250, null=True), + ), + ] diff --git a/engine/apps/alerts/migrations/0013_merge_20230418_0336.py b/engine/apps/alerts/migrations/0013_merge_20230418_0336.py new file mode 100644 index 00000000..0b6a15df --- /dev/null +++ b/engine/apps/alerts/migrations/0013_merge_20230418_0336.py @@ -0,0 +1,14 @@ +# Generated by Django 3.2.18 on 2023-04-18 03:36 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('alerts', '0012_alertreceivechannel_description_short'), + ('alerts', '0012_auto_20230406_1010'), + ] + + operations = [ + ] diff --git a/engine/apps/alerts/models/alert_receive_channel.py b/engine/apps/alerts/models/alert_receive_channel.py index 80e6ccb5..e26e762a 100644 --- a/engine/apps/alerts/models/alert_receive_channel.py +++ b/engine/apps/alerts/models/alert_receive_channel.py @@ -145,6 +145,7 @@ class AlertReceiveChannel(IntegrationOptionsMixin, MaintainableObject): smile_code = models.TextField(default=":slightly_smiling_face:") verbal_name = models.CharField(max_length=150, null=True, default=None) + description_short = models.CharField(max_length=250, null=True, default=None) integration_slack_channel_id = models.CharField(max_length=150, null=True, default=None) diff --git a/engine/apps/api/serializers/alert_receive_channel.py b/engine/apps/api/serializers/alert_receive_channel.py index 852c3229..a84fb5fe 100644 --- a/engine/apps/api/serializers/alert_receive_channel.py +++ b/engine/apps/api/serializers/alert_receive_channel.py @@ -47,6 +47,7 @@ class AlertReceiveChannelSerializer(EagerLoadingMixin, serializers.ModelSerializ maintenance_till = serializers.ReadOnlyField(source="till_maintenance_timestamp") heartbeat = serializers.SerializerMethodField() allow_delete = serializers.SerializerMethodField() + description_short = serializers.CharField(max_length=250, required=False) demo_alert_payload = serializers.SerializerMethodField() # integration heartbeat is in PREFETCH_RELATED not by mistake. @@ -60,6 +61,7 @@ class AlertReceiveChannelSerializer(EagerLoadingMixin, serializers.ModelSerializ fields = [ "id", "description", + "description_short", "integration", "smile_code", "verbal_name", diff --git a/engine/apps/public_api/serializers/integrations.py b/engine/apps/public_api/serializers/integrations.py index 2c42da5d..26af0fe8 100644 --- a/engine/apps/public_api/serializers/integrations.py +++ b/engine/apps/public_api/serializers/integrations.py @@ -80,6 +80,7 @@ class IntegrationSerializer(EagerLoadingMixin, serializers.ModelSerializer, Main templates = serializers.DictField(required=False) default_route = serializers.DictField(required=False) heartbeat = serializers.SerializerMethodField() + description_short = serializers.CharField(max_length=250, required=False) PREFETCH_RELATED = ["channel_filters"] SELECT_RELATED = ["organization", "integration_heartbeat"] @@ -89,6 +90,7 @@ class IntegrationSerializer(EagerLoadingMixin, serializers.ModelSerializer, Main fields = MaintainableObjectSerializerMixin.Meta.fields + [ "id", "name", + "description_short", "team_id", "link", "type", diff --git a/engine/apps/public_api/tests/test_integrations.py b/engine/apps/public_api/tests/test_integrations.py index d508e15a..6bbea4ae 100644 --- a/engine/apps/public_api/tests/test_integrations.py +++ b/engine/apps/public_api/tests/test_integrations.py @@ -17,7 +17,7 @@ def test_get_list_integrations( make_integration_heartbeat, ): organization, user, token = make_organization_and_user_with_token() - integration = make_alert_receive_channel(organization, verbal_name="grafana") + integration = make_alert_receive_channel(organization, verbal_name="grafana", description_short="Some description") default_channel_filter = make_channel_filter(integration, is_default=True) make_integration_heartbeat(integration) @@ -31,6 +31,7 @@ def test_get_list_integrations( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": "Some description", "link": integration.integration_url, "type": "grafana", "default_route": { @@ -162,6 +163,7 @@ def test_update_integration_template( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": None, "link": integration.integration_url, "type": "grafana", "default_route": { @@ -223,6 +225,7 @@ def test_update_integration_template_messaging_backend( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": None, "link": integration.integration_url, "type": "grafana", "default_route": { @@ -300,6 +303,7 @@ def test_update_resolve_signal_template( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": None, "link": integration.integration_url, "type": "grafana", "default_route": { @@ -409,6 +413,7 @@ def test_update_sms_template_with_empty_dict( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": None, "link": integration.integration_url, "type": "grafana", "default_route": { @@ -470,6 +475,69 @@ def test_update_integration_name( "id": integration.public_primary_key, "team_id": None, "name": "grafana_updated", + "description_short": None, + "link": integration.integration_url, + "type": "grafana", + "default_route": { + "escalation_chain_id": None, + "id": default_channel_filter.public_primary_key, + "slack": {"channel_id": None, "enabled": True}, + "telegram": {"id": None, "enabled": False}, + TEST_MESSAGING_BACKEND_FIELD: {"id": None, "enabled": False}, + }, + "heartbeat": { + "link": f"{integration.integration_url}heartbeat/", + }, + "templates": { + "grouping_key": None, + "resolve_signal": None, + "acknowledge_signal": None, + "source_link": None, + "slack": {"title": None, "message": None, "image_url": None}, + "web": {"title": None, "message": None, "image_url": None}, + "sms": { + "title": None, + }, + "phone_call": { + "title": None, + }, + "telegram": { + "title": None, + "message": None, + "image_url": None, + }, + TEST_MESSAGING_BACKEND_FIELD: { + "title": None, + "message": None, + "image_url": None, + }, + }, + "maintenance_mode": None, + "maintenance_started_at": None, + "maintenance_end_at": None, + } + url = reverse("api-public:integrations-detail", args=[integration.public_primary_key]) + response = client.put(url, data=data_for_update, format="json", HTTP_AUTHORIZATION=f"{token}") + assert response.status_code == status.HTTP_200_OK + assert response.data == expected_response + + +@pytest.mark.django_db +def test_update_integration_name_and_description_short( + make_organization_and_user_with_token, make_alert_receive_channel, make_channel_filter, make_integration_heartbeat +): + organization, user, token = make_organization_and_user_with_token() + integration = make_alert_receive_channel(organization, verbal_name="grafana", description_short="Some description") + default_channel_filter = make_channel_filter(integration, is_default=True) + make_integration_heartbeat(integration) + + client = APIClient() + data_for_update = {"name": "grafana_updated"} + expected_response = { + "id": integration.public_primary_key, + "team_id": None, + "name": "grafana_updated", + "description_short": "Some description", "link": integration.integration_url, "type": "grafana", "default_route": { @@ -534,6 +602,7 @@ def test_set_default_template( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": None, "link": integration.integration_url, "type": "grafana", "default_route": { @@ -601,6 +670,7 @@ def test_set_default_messaging_backend_template( "id": integration.public_primary_key, "team_id": None, "name": "grafana", + "description_short": None, "link": integration.integration_url, "type": "grafana", "default_route": {