Skip to content

Commit

Permalink
Use upload_files_v2 Slack SDK method by default in Slack Operators
Browse files Browse the repository at this point in the history
  • Loading branch information
Taragolis committed May 1, 2024
1 parent 242a169 commit cc25d71
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 30 deletions.
17 changes: 17 additions & 0 deletions airflow/providers/slack/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@
Changelog
---------

.. note::
Due to future discontinue of `files.upload <https://api.slack.com/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay>`__
Slack API method the default value of ``SlackAPIFileOperator.method_version`` and ``SqlToSlackApiFileOperator.slack_method_version``
changed from ``v1`` to ``v2``

If you previously use ``v1`` you should check that your application has appropriate scopes:

* **files:write** - for write files.
* **files:read** - for read files (not required if you use Slack SDK >= 3.23.0).
* **channels:read** - get list of public channels, for convert Channel Name to Channel ID.
* **groups:read** - get list of private channels, for convert Channel Name to Channel ID
* **mpim:read** - additional permission for API method **conversations.list**
* **im:read** - additional permission for API method **conversations.list**

If you use ``SlackHook.send_file`` please consider switch to ``SlackHook.send_file_v2``
or ``SlackHook.send_file_v1_to_v2`` methods.

8.6.2
.....

Expand Down
11 changes: 10 additions & 1 deletion airflow/providers/slack/hooks/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@
from pathlib import Path
from typing import TYPE_CHECKING, Any, Sequence, TypedDict

from deprecated import deprecated
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
from typing_extensions import NotRequired

from airflow.exceptions import AirflowNotFoundException
from airflow.exceptions import AirflowNotFoundException, AirflowProviderDeprecationWarning
from airflow.hooks.base import BaseHook
from airflow.providers.slack.utils import ConnectionExtraConfig
from airflow.utils.helpers import exactly_one
Expand Down Expand Up @@ -184,6 +185,14 @@ def call(self, api_method: str, **kwargs) -> SlackResponse:
"""
return self.client.api_call(api_method, **kwargs)

@deprecated(
reason=(
"This method utilise `files.upload` Slack API method which is being sunset on March 11, 2025. "
"Beginning May 8, 2024, newly-created apps will be unable to 'files.upload' Slack API. "
"Please use `send_file_v2` or `send_file_v1_to_v2` instead."
),
category=AirflowProviderDeprecationWarning,
)
def send_file(
self,
*,
Expand Down
2 changes: 1 addition & 1 deletion airflow/providers/slack/transfers/sql_to_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def __init__(
slack_initial_comment: str | None = None,
slack_title: str | None = None,
slack_base_url: str | None = None,
slack_method_version: Literal["v1", "v2"] = "v1",
slack_method_version: Literal["v1", "v2"] = "v2",
df_kwargs: dict | None = None,
action_on_empty_df: Literal["send", "skip", "error"] = "send",
**kwargs,
Expand Down
10 changes: 7 additions & 3 deletions docs/apache-airflow-providers-slack/operators/slack_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ Using the Operator

.. note::
Operator supports two methods for upload files, which controlled by ``method_version``,
by default it use Slack SDK method ``upload_files`` however this might impact a performance and cause random API errors.
It is recommended to switch to Slack SDK method ``upload_files_v2`` by set ``v2`` to ``method_version``,
however this action required to add additional scope to your application:
by default it use Slack SDK method ``upload_files_v2`` it is possible to use legacy ``upload_files``
method by set ``v1`` to ``method_version`` however this not recommended because it
might impact a performance, cause random API errors and is being sunset on March 11, 2025 in addition
beginning May 8, 2024, newly-created apps will be unable to use this API method.

If you previously use ``v1`` you should check that your application has appropriate scopes:

* **files:write** - for write files.
* **files:read** - for read files (not required if you use Slack SDK >= 3.23.0).
Expand All @@ -74,6 +77,7 @@ Using the Operator
.. seealso::
- `Slack SDK 3.19.0 Release Notes <https://github.com/slackapi/python-slack-sdk/releases/tag/v3.19.0>`_
- `conversations.list API <https://api.slack.com/methods/conversations.list>`_
- `files.upload retires in March 2025 <https://api.slack.com/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay>`_

You could send file attachment by specifying file path

Expand Down
11 changes: 7 additions & 4 deletions docs/apache-airflow-providers-slack/operators/sql_to_slack.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ Using the Operator

.. note::
Operator supports two methods for upload files, which controlled by ``slack_method_version``,
by default it use Slack SDK method ``upload_files`` however this might impact a performance and cause random API errors.
It is recommended to switch to Slack SDK method ``upload_files_v2`` by set ``v2`` to ``slack_method_version``,
however this action required to add additional scope to your application:
by default it use Slack SDK method ``upload_files_v2`` it is possible to use legacy ``upload_files``
method by set ``v1`` to ``slack_method_version`` however this not recommended because it
might impact a performance, cause random API errors and is being sunset on March 11, 2025 in addition
beginning May 8, 2024, newly-created apps will be unable to use this API method.

If you previously use ``v1`` you should check that your application has appropriate scopes:

* **files:write** - for write files.
* **files:read** - for read files (not required if you use Slack SDK >= 3.23.0).
Expand All @@ -42,7 +45,7 @@ Using the Operator
.. seealso::
- `Slack SDK 3.19.0 Release Notes <https://github.com/slackapi/python-slack-sdk/releases/tag/v3.19.0>`_
- `conversations.list API <https://api.slack.com/methods/conversations.list>`_

- `files.upload retires in March 2025 <https://api.slack.com/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay>`_

This operator will execute a custom query in the provided SQL connection and publish a file to Slack channel(s).

Expand Down
48 changes: 28 additions & 20 deletions tests/providers/slack/hooks/test_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from slack_sdk.http_retry.builtin_handlers import ConnectionErrorRetryHandler, RateLimitErrorRetryHandler
from slack_sdk.web.slack_response import SlackResponse

from airflow.exceptions import AirflowNotFoundException
from airflow.exceptions import AirflowNotFoundException, AirflowProviderDeprecationWarning
from airflow.models.connection import Connection
from airflow.providers.slack.hooks.slack import SlackHook

Expand Down Expand Up @@ -307,9 +307,11 @@ def test_hook_connection_failed(self, mocked_client, response_data):
)
def test_send_file_wrong_parameters(self, file, content):
hook = SlackHook(slack_conn_id=SLACK_API_DEFAULT_CONN_ID)
warning_message = "use `send_file_v2` or `send_file_v1_to_v2"
error_message = r"Either `file` or `content` must be provided, not both\."
with pytest.raises(ValueError, match=error_message):
hook.send_file(file=file, content=content)
with pytest.warns(AirflowProviderDeprecationWarning, match=warning_message):
with pytest.raises(ValueError, match=error_message):
hook.send_file(file=file, content=content)

@pytest.mark.parametrize("initial_comment", [None, "test comment"])
@pytest.mark.parametrize("title", [None, "test title"])
Expand All @@ -324,14 +326,16 @@ def test_send_file_path(
file.write_text('{"foo": "bar"}')

hook = SlackHook(slack_conn_id=SLACK_API_DEFAULT_CONN_ID)
hook.send_file(
channels=channels,
file=file,
filename="filename.mock",
initial_comment=initial_comment,
title=title,
filetype=filetype,
)
warning_message = "use `send_file_v2` or `send_file_v1_to_v2"
with pytest.warns(AirflowProviderDeprecationWarning, match=warning_message):
hook.send_file(
channels=channels,
file=file,
filename="filename.mock",
initial_comment=initial_comment,
title=title,
filetype=filetype,
)

mocked_client.files_upload.assert_called_once_with(
channels=channels,
Expand All @@ -355,7 +359,9 @@ def test_send_file_path_set_filename(self, mocked_client, tmp_path_factory, file
file.write_text('{"foo": "bar"}')

hook = SlackHook(slack_conn_id=SLACK_API_DEFAULT_CONN_ID)
hook.send_file(file=file)
warning_message = "use `send_file_v2` or `send_file_v1_to_v2"
with pytest.warns(AirflowProviderDeprecationWarning, match=warning_message):
hook.send_file(file=file)

assert mocked_client.files_upload.call_count == 1
call_args = mocked_client.files_upload.call_args.kwargs
Expand All @@ -370,14 +376,16 @@ def test_send_file_path_set_filename(self, mocked_client, tmp_path_factory, file
def test_send_file_content(self, mocked_client, initial_comment, title, filetype, channels, filename):
"""Test send file by providing content."""
hook = SlackHook(slack_conn_id=SLACK_API_DEFAULT_CONN_ID)
hook.send_file(
channels=channels,
content='{"foo": "bar"}',
filename=filename,
initial_comment=initial_comment,
title=title,
filetype=filetype,
)
warning_message = "use `send_file_v2` or `send_file_v1_to_v2"
with pytest.warns(AirflowProviderDeprecationWarning, match=warning_message):
hook.send_file(
channels=channels,
content='{"foo": "bar"}',
filename=filename,
initial_comment=initial_comment,
title=title,
filetype=filetype,
)
mocked_client.files_upload.assert_called_once_with(
channels=channels,
content='{"foo": "bar"}',
Expand Down
1 change: 0 additions & 1 deletion tests/system/providers/slack/example_slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@
task_id="slack_file_upload_2",
channels=SLACK_CHANNEL,
content="file content in txt",
method_version="v2",
)
# [END slack_api_file_operator_content_howto_guide]

Expand Down

0 comments on commit cc25d71

Please sign in to comment.