Commit graph

12 commits

Author SHA1 Message Date
Joey Orlando
33913c5c58
chore: fix migration linter issue (#5342) 2024-12-06 14:59:20 -05:00
Joey Orlando
dd2393165d
chore: remove SlackMessage._channel_id and SlackMessage.organization fields (#5340)
# What this PR does

Follow-up cleanup PR for https://github.com/grafana/oncall/pull/5325
(and https://github.com/grafana/oncall/pull/5330)

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-12-06 13:49:24 -05:00
Joey Orlando
e115617528
chore: drop usage of SlackMessage.organization + drop orphaned SlackMessages (#5330)
# What this PR does

- Stops writing `SlackMessage.organization` + removes references to this
field. [As we
discussed](https://raintank-corp.slack.com/archives/C083TU81TCH/p1733315887463279?thread_ts=1733311105.095309&cid=C083TU81TCH),
we do not need this field on this model/table,
`SlackMessage._slack_team_identity` is sufficient (`organization` will
be dropped in a separate PR)
- Adds a data migration script which:
- drops orphaned `SlackMessage` records; ie. ones which, even after the
[`engine/apps/slack/migrations/0007_migrate_slackmessage_channel_id.py`](https://github.com/grafana/oncall/blob/dev/engine/apps/slack/migrations/0007_migrate_slackmessage_channel_id.py)
migration, still don't have a `SlackMessage.channel` id filled in (we
discussed + agreed on dropping these records
[here](https://raintank-corp.slack.com/archives/C083TU81TCH/p1733329914516859?thread_ts=1733311105.095309&cid=C083TU81TCH))
- fills in empty `SlackMessage.slack_team_identity` values (from
`slack_message.channel.slack_team_identity`)

### Other notes

On the `organization` topic.

We store records in `SlackMessage` for two purposes (AFAICT), and in
both cases, we have references back to the `organization`:
- alert groups - `slack_message.alert_group.channel.organization`
- shift swap requests - `shift_swap_request.schedule.organization`

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-12-06 11:43:40 -05:00
Joey Orlando
3977c6e9ef
chore: remove references to SlackMessage._channel_id (#5325)
# What this PR does

- As a follow-up to https://github.com/grafana/oncall/pull/5292, and now
that `SlackMessage.channel` has been migrated via
[`engine/apps/slack/migrations/0007_migrate_slackmessage_channel_id.py`](https://github.com/grafana/oncall/pull/5292/files#diff-8aebe133401715a4262baad9b2c5c9fc59367c18d6bd6ac2b3c462fcdabafd66),
this PR removes reads/writes from `SlackMessage._channel_id` to
`SlackMessage.channel`. In a separate PR I will focus on dropping that
column from the model/db.
- Drops `SlackMessage.active_update_task_id`. There're zero references
to this column in the codebase.
- Removes two Django `manage.py` commands that're no longer needed:
- `engine/engine/management/commands/alertmanager_v2_migrate.py` (and
it's associated tests)
-
`engine/engine/management/commands/batch_migrate_slack_message_channel.py`

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-12-06 09:28:26 -05:00
Joey Orlando
26946f0d43
fix: improve Slack rate limiting logic when updating alert groups (#5287)
# What this PR does

https://www.loom.com/share/1ac33822301444748133ffe72638ddc4

The two asks in the [original GH
issue](https://github.com/grafana/oncall-private/issues/2947) were:

> 1. Make the error message clearer. We can identify if it's delivering
or updating and being rate-limited. This is possible because Slack sets
limits per API method. Also, this limit is a per-slack channel while we
are posting messages & applying ratelimit per on-call integration, which
confuses customers.
> 2. Debounce update alert group message in Slack

Both of these have been addressed in this PR

## Which issue(s) this PR closes

Closes https://github.com/grafana/oncall-private/issues/2947

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-12-02 14:40:30 -05:00
Joey Orlando
a29e35c25a
refactor SlackMessage.channel_id (CHAR field) to SlackMessage.channel (foreign key relationship) (#5292)
# What this PR does

Related to https://github.com/grafana/oncall-private/issues/2947

**NOTE**

This PR introduces steps 1 and 2 of the 3 part migration proposed
[here](https://raintank-corp.slack.com/archives/C06K1MQ07GS/p1732555465144099).
Step 3, swapping reads to be from the new-column and dropping
dual-writes, will be done in a future PR/release.

---

I’m tackling this work now because _ultimately_ I want to move
`AlertReceiveChannel.rate_limited_in_slack_at` to
`SlackChannel.rate_limited_at` , but first I sorta need to refactor
`SlackMessage.channel_id` from a `CHAR` field to a foreign key
relationship (because in the spots where we touch Slack rate limiting,
like
[here](https://github.com/grafana/oncall/blob/dev/engine/apps/slack/alert_group_slack_service.py#L42-L50)
for example, we only have `slack_message.channel_id`, which means I need
to do extra queries to fetch the appropriate `SlackChannel` to then be
able to get/set `SlackChannel.rate_limited_at`

Other minor stuffs:
- it also prepares us to drop `SlackMessage._slack_team_identity`. We
already have a `@property` of `SlackMessage.slack_team_identity` (which
[previously had some hacky
logic](https://github.com/grafana/oncall/blob/dev/engine/apps/slack/models/slack_message.py#L74-L84)).
I've refactored `SlackMessage.slack_team_identity` to simply point to
`self.organization.slack_team_identity` + updated our code to _stop_
setting `SlackMessage._slack_team_identity` (will drop this column in
future release)

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-11-26 11:03:38 +00:00
Vadim Stepanov
87d7982250
Unified Slack app reinstall (#4682)
# What this PR does

Adds a button to reinstall the Slack app to migrate to Unified Slack
App. Also adds backend support for this.

<img width="1204" alt="Screenshot 2024-07-18 at 18 33 08"
src="https://github.com/user-attachments/assets/a326b4a2-fc65-4b88-98c0-2955e3717e3a">


## Which issue(s) this PR closes

Related to https://github.com/grafana/oncall-gateway/issues/252

<!--
*Note*: if you have more than one GitHub issue that this PR closes, be
sure to preface
each issue link with a [closing
keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue).
This ensures that the issue(s) are auto-closed once the PR has been
merged.
-->

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] Added the relevant release notes label (see labels prefixed w/
`release:`). These labels dictate how your PR will
    show up in the autogenerated release notes.
2024-07-19 11:53:06 +00:00
Linhua Tan
0c7281a255
Fix Slack access token length issue (#3016)
# What this PR does

fix the following error caused by too short varchar length of database
fields `access_token` and `bot_access_token` in table
`slack_slackteamidentity`

```
2023-09-12 18:34:07.448 | django.db.utils.DataError: value too long for type character varying(100) |  
-- | -- | --
  |   | 2023-09-12 18:34:07.448 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.448 | return self.cursor.execute(sql, params) |  
  |   | 2023-09-12 18:34:07.448 | File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute |  
  |   | 2023-09-12 18:34:07.448 | raise dj_exc_value.with_traceback(traceback) from exc_value |  
  |   | 2023-09-12 18:34:07.448 | File "/usr/local/lib/python3.11/site-packages/django/db/utils.py", line 90, in __exit__ |  
  |   | 2023-09-12 18:34:07.448 | with self.db.wrap_database_errors: |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 79, in _execute |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return executor(sql, params, many, context) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 66, in execute |  
  |   | 2023-09-12 18:34:07.447 | cursor.execute(sql, params) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | cursor = super().execute_sql(result_type) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return query.get_compiler(self.db).execute_sql(CURSOR) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/query.py", line 802, in _update |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return filtered._update(values) > 0 |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 912, in _do_update |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | updated = self._do_update(base_qs, using, pk_val, values, update_fields, |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 858, in _save_table |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | updated = self._save_table( |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 776, in save_base |  
  |   | 2023-09-12 18:34:07.447 | self.save_base(using=using, force_insert=force_insert, |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/models/base.py", line 739, in save |  
  |   | 2023-09-12 18:34:07.447 | self.save() |  
  |   | 2023-09-12 18:34:07.447 | File "/etc/app/apps/slack/models/slack_team_identity.py", line 72, in update_oauth_fields |  
  |   | 2023-09-12 18:34:07.447 | slack_team_identity.update_oauth_fields(user, organization, response) |  
  |   | 2023-09-12 18:34:07.447 | File "/etc/app/apps/social_auth/pipeline.py", line 102, in populate_slack_identities |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | result = func(*args, **out) or {} |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/backends/base.py", line 118, in run_pipeline |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | out = self.run_pipeline(pipeline, pipeline_index, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/backends/base.py", line 86, in pipeline |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self.pipeline(pipeline, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/backends/base.py", line 83, in authenticate |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | user = backend.authenticate(request, **credentials) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/contrib/auth/__init__.py", line 76, in authenticate |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return func(*func_args, **func_kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/views/decorators/debug.py", line 42, in sensitive_variables_wrapper |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return authenticate(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_django/strategy.py", line 105, in authenticate |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self.strategy.authenticate(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/etc/app/apps/social_auth/backends.py", line 100, in do_auth |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return func(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/utils.py", line 253, in wrapper |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self.do_auth(access_token, response=response, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/etc/app/apps/social_auth/backends.py", line 88, in auth_complete |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return func(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/utils.py", line 253, in wrapper |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self.auth_complete(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/backends/base.py", line 39, in complete |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | user = backend.complete(user=user, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_core/actions.py", line 49, in do_complete |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | result = do_complete( |  
  |   | 2023-09-12 18:34:07.447 | File "/etc/app/apps/api/views/auth.py", line 52, in overridden_complete_slack_auth |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return func(request, backend, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/social_django/utils.py", line 46, in wrapper |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return view_func(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | response = view_func(request, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return func(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/rest_framework/decorators.py", line 50, in handler |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | response = handler(request, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 506, in dispatch |  
  |   | 2023-09-12 18:34:07.447 | raise exc |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception |  
  |   | 2023-09-12 18:34:07.447 | self.raise_uncaught_exception(exc) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 469, in handle_exception |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | response = self.handle_exception(exc) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/rest_framework/views.py", line 509, in dispatch |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self.dispatch(request, *args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 70, in view |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return view_func(*args, **kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | response = wrapped_callback(request, *callback_args, **callback_kwargs) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 181, in _get_response |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | response = get_response(request) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 47, in inner |  
  |   | 2023-09-12 18:34:07.447 | Traceback (most recent call last): |  
  |   | 2023-09-12 18:34:07.447 |   |  
  |   | 2023-09-12 18:34:07.447 | The above exception was the direct cause of the following exception: |  
  |   | 2023-09-12 18:34:07.447 |   |  
  |   | 2023-09-12 18:34:07.447 |   |  
  |   | 2023-09-12 18:34:07.447 | psycopg2.errors.StringDataRightTruncation: value too long for type character varying(100) |  
  |   | 2023-09-12 18:34:07.447 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |  
  |   | 2023-09-12 18:34:07.447 | return self.cursor.execute(sql, params) |  
  |   | 2023-09-12 18:34:07.447 | File "/usr/local/lib/python3.11/site-packages/django/db/backends/utils.py", line 84, in _execute |  
  |   | 2023-09-12 18:34:07.447 | Traceback (most recent call last): |  
  |   | 2023-09-12 18:34:07.447 | 2023-09-12 10:34:07 source=engine:app google_trace_id=50a15245db9b828e0ab33e8d115dd10a/3838538413005063100 logger=django.request Internal Server Error: /api/internal/v1/complete/slack-install-free/
```

---------

Co-authored-by: Vadim Stepanov <vadimkerr@gmail.com>
2023-09-13 11:53:17 +01:00
Joey Orlando
90e0b21d3e
remove SlackActionRecord model/table (#2201)
# What this PR does

Closes #2169 

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [ ] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
2023-06-13 10:56:06 +00:00
Ildar Iskhakov
1b7ada4315
Add database migrations linter (#1020)
# What this PR does

This PR adds
[django-migration-linter](https://github.com/3YOURMIND/django-migration-linter)
to keep database migrations
 backwards compatible

- we can automatically run migrations and they are zero-downtime, e.g.
old code can work with the migrated database
 - we can run and rollback migrations without worrying about data safety
- OnCall is deployed to the multiple environments core team is not able
to control

See [django-migration-linter
checklist](https://github.com/3YOURMIND/django-migration-linter/blob/main/docs/incompatibilities.md)
for the common mistakes and best practices


## Which issue(s) this PR fixes

## Checklist

- [ ] Tests updated
- [ ] Documentation added
- [ ] `CHANGELOG.md` updated

---------

Co-authored-by: Joey Orlando <joey.orlando@grafana.com>
2023-02-06 16:01:37 +08:00
Matias Bordese
9f89897264 Drop data migrations setting up demo tokens 2022-06-06 12:29:25 -03:00
Michael Derynck
6b40f95033 World, meet OnCall!
Co-authored-by: Eve832 <eve.meelan@grafana.com>
    Co-authored-by: Francisco Montes de Oca <nevermind89x@gmail.com>
    Co-authored-by: Ildar Iskhakov <ildar.iskhakov@grafana.com>
    Co-authored-by: Innokentii Konstantinov <innokenty.konstantinov@grafana.com>
    Co-authored-by: Julia <ferril.darkdiver@gmail.com>
    Co-authored-by: maskin25 <kengurek@gmail.com>
    Co-authored-by: Matias Bordese <mbordese@gmail.com>
    Co-authored-by: Matvey Kukuy <motakuk@gmail.com>
    Co-authored-by: Michael Derynck <michael.derynck@grafana.com>
    Co-authored-by: Richard Hartmann <richih@richih.org>
    Co-authored-by: Robby Milo <robbymilo@fastmail.com>
    Co-authored-by: Timur Olzhabayev <timur.olzhabayev@grafana.com>
    Co-authored-by: Vadim Stepanov <vadimkerr@gmail.com>
    Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>
2022-06-03 08:09:47 -06:00