You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -16,6 +16,8 @@ Slack Bolt for Python -- a framework for building Slack apps in Python.
16
16
17
17
## Environment Setup
18
18
19
+
You can verify the venv is active by checking `echo $VIRTUAL_ENV`. If tools like `black`, `flake8`, `mypy` or `pytest` are not found, ask the user to activate the venv.
20
+
19
21
A python virtual environment (`venv`) should be activated before running any commands.
20
22
21
23
```bash
@@ -29,18 +31,30 @@ source .venv/bin/activate
29
31
./scripts/install.sh
30
32
```
31
33
32
-
You can verify the venv is active by checking `echo $VIRTUAL_ENV`. If tools like `black`, `flake8`, `mypy` or `pytest` are not found, ask the user to activate the venv.
33
-
34
34
## Common Commands
35
35
36
-
### Testing
36
+
### Pre-submission Checklist
37
37
38
-
Always use the project scripts instead of calling `pytest` directly:
38
+
Before considering any work complete, you MUST run these commands in order and confirm they all pass:
39
+
40
+
```bash
41
+
./scripts/format.sh --no-install # 1. Format
42
+
./scripts/lint.sh --no-install # 2. Lint
43
+
./scripts/run_tests.sh <relevant># 3. Run relevant tests (see Testing below)
44
+
./scripts/run_mypy.sh --no-install # 4. Type check
45
+
```
46
+
47
+
To run everything at once (installs deps + formats + lints + tests + typechecks):
39
48
40
49
```bash
41
-
# Install all dependencies and run all tests (formats, lints, tests, typechecks)
42
50
./scripts/install_all_and_run_tests.sh
51
+
```
43
52
53
+
### Testing
54
+
55
+
Always use the project scripts instead of calling `pytest` directly:
# Type check -- mypy, configured in pyproject.toml
61
75
./scripts/run_mypy.sh --no-install
62
76
```
63
77
78
+
## Critical Conventions
79
+
80
+
### Sync/Async Mirroring Rule
81
+
82
+
**When modifying any sync module, you MUST also update the corresponding async module (and vice versa).** This is the most important convention in this codebase.
83
+
84
+
Almost every module has both a sync and async variant. Async files use the `async_` prefix alongside their sync counterpart:
**Adapters are an exception:** Most adapters are sync-only or async-only depending on the framework. Async-native frameworks (FastAPI, Starlette, Sanic, Tornado, ASGI, Socket Mode) have `async_handler.py`. Sync-only frameworks (Flask, Django, Bottle, CherryPy, Falcon, Pyramid, AWS Lambda, Google Cloud Functions, WSGI) have `handler.py`.
107
+
108
+
### Prefer the Middleware Pattern
109
+
110
+
Middleware is the project's preferred approach for cross-cutting concerns. Before adding logic to individual listeners or utility functions, consider whether it belongs as a built-in middleware in the framework.
111
+
112
+
**When to add built-in middleware:**
113
+
114
+
- Cross-cutting concerns that apply to many or all requests (logging, metrics, observability)
115
+
- Request validation, transformation, or enrichment
116
+
- Authorization extensions beyond the built-in `SingleTeamAuthorization`/`MultiTeamsAuthorization`
117
+
- Feature-level request handling (the `Assistant` middleware in `slack_bolt/middleware/assistant/assistant.py` is the canonical example -- it intercepts assistant thread events and dispatches them to registered sub-listeners)
118
+
119
+
**How to add built-in middleware:**
120
+
121
+
1. Subclass `Middleware` (sync) and implement `process(self, *, req, resp, next)`. Call `next()` to continue the chain.
122
+
2. Subclass `AsyncMiddleware` (async) and implement `async_process(self, *, req, resp, next)`. Call `await next()` to continue.
123
+
3. Export from `slack_bolt/middleware/__init__.py` (sync) and `slack_bolt/middleware/async_builtins.py` (async).
124
+
4. Register the middleware in `App.__init__()` (`slack_bolt/app/app.py`) and `AsyncApp.__init__()` (`slack_bolt/app/async_app.py`) where the default middleware chain is assembled.
125
+
126
+
**Canonical example:**`AttachingFunctionToken` (`slack_bolt/middleware/attaching_function_token/`) is a good small middleware to follow -- it has a clean sync/async pair, a focused `process()` method, and is properly exported and registered in the app's middleware chain.
127
+
128
+
### Single Runtime Dependency Rule
129
+
130
+
The core package depends ONLY on `slack_sdk` (defined in `pyproject.toml`). Never add runtime dependencies to `pyproject.toml`. Additional dependencies go in the appropriate `requirements/*.txt` file.
131
+
64
132
## Architecture
65
133
66
134
### Request Processing Pipeline
@@ -90,49 +158,12 @@ Listeners receive arguments by parameter name. The framework inspects function s
90
158
91
159
Each adapter in `slack_bolt/adapter/` converts between a web framework's request/response types and `BoltRequest`/`BoltResponse`. Adapters exist for: Flask, FastAPI, Django, Starlette, Sanic, Bottle, Tornado, CherryPy, Falcon, Pyramid, AWS Lambda, Google Cloud Functions, Socket Mode, WSGI, ASGI, and more.
92
160
93
-
### Sync/Async Mirroring Pattern
94
-
95
-
**This is the most important pattern in this codebase.** Almost every module has both a sync and async variant. When you modify one, you almost always must modify the other.
96
-
97
-
**File naming convention:** Async files use the `async_` prefix alongside their sync counterpart:
**Adapters are an exception:** Most adapters are sync-only or async-only depending on the framework. Async-native frameworks (FastAPI, Starlette, Sanic, Tornado, ASGI, Socket Mode) have `async_handler.py`. Sync-only frameworks (Flask, Django, Bottle, CherryPy, Falcon, Pyramid, AWS Lambda, Google Cloud Functions, WSGI) have `handler.py`.
123
-
124
161
### AI Agents & Assistants
125
162
126
163
`BoltAgent` (`slack_bolt/agent/`) provides `chat_stream()`, `set_status()`, and `set_suggested_prompts()` for AI-powered agents. `Assistant` middleware (`slack_bolt/middleware/assistant/`) handles assistant thread events.
127
164
128
165
## Key Development Patterns
129
166
130
-
### Adding or Modifying Middleware
131
-
132
-
1. Implement the sync version in `slack_bolt/middleware/` (subclass `Middleware`, implement `process()`)
133
-
2. Implement the async version with `async_` prefix (subclass `AsyncMiddleware`, implement `async_process()`)
134
-
3. Export built-in middleware from `slack_bolt/middleware/__init__.py` (sync) and `async_builtins.py` (async)
135
-
136
167
### Adding a Context Utility
137
168
138
169
Each context utility lives in its own subdirectory under `slack_bolt/context/`:
@@ -153,14 +184,21 @@ Then wire it into `BoltContext` (`slack_bolt/context/context.py`) and `AsyncBolt
153
184
2. Add `__init__.py` and `handler.py` (or `async_handler.py` for async frameworks)
154
185
3. The handler converts the framework's request to `BoltRequest`, calls `app.dispatch()`, and converts `BoltResponse` back
155
186
4. Add the framework to `requirements/adapter.txt` with version constraints
156
-
5. Add adapter tests in `tests/adapter_tests/` (or `tests/adapter_tests_async/`)
187
+
5. Add adapter tests in `tests/adapter_tests/` (sync) or `tests/adapter_tests_async/` (async)
157
188
158
189
### Adding a Kwargs-Injectable Argument
159
190
160
191
1. Add the new arg to `slack_bolt/kwargs_injection/args.py` and `async_args.py`
161
192
2. Update the `Args` class with the new property
162
193
3. Populate the arg in the appropriate context or listener setup code
163
194
195
+
## Security Considerations
196
+
197
+
-**Request Verification:** The built-in `RequestVerification` middleware validates `x-slack-signature` and `x-slack-request-timestamp` on every incoming HTTP request. Never disable this in production. It is automatically skipped for `socket_mode` requests.
198
+
-**Tokens & Secrets:**`SLACK_SIGNING_SECRET` and `SLACK_BOT_TOKEN` must come from environment variables. Never hardcode or commit secrets.
199
+
-**Authorization Middleware:**`SingleTeamAuthorization` and `MultiTeamsAuthorization` verify tokens and inject an authorized `WebClient` into the context. Do not bypass these.
200
+
-**Tests:** Always use mock servers (`tests/mock_web_api_server/`) and dummy values. Never use real tokens in tests.
201
+
164
202
## Dependencies
165
203
166
204
The core package has a **single required runtime dependency**: `slack_sdk` (defined in `pyproject.toml`). Do not add runtime dependencies.
@@ -176,7 +214,9 @@ The core package has a **single required runtime dependency**: `slack_sdk` (defi
176
214
177
215
When adding a new dependency: add it to the appropriate `requirements/*.txt` file with version constraints, never to `pyproject.toml``dependencies` (unless it's a core runtime dep, which is very rare).
178
216
179
-
## Test Organization
217
+
## Test Organization and CI
218
+
219
+
### Directory Structure
180
220
181
221
-`tests/scenario_tests/` -- Integration-style tests with realistic Slack payloads
182
222
-`tests/slack_bolt/` -- Unit tests mirroring the source structure
@@ -188,15 +228,19 @@ When adding a new dependency: add it to the appropriate `requirements/*.txt` fil
188
228
189
229
**Mock server:** Many tests use `tests/mock_web_api_server/` to simulate Slack API responses. Look at existing tests for usage patterns rather than making real API calls.
190
230
191
-
## Code Style
231
+
### CI Pipeline
232
+
233
+
GitHub Actions (`.github/workflows/ci-build.yml`) runs on every push to `main` and every PR:
192
234
193
-
-**Black**formatter configured in `pyproject.toml` (line-length=125)
194
-
-**Flake8**linter configured in `.flake8` (line-length=125, ignores: F841,F821,W503,E402)
195
-
-**MyPy**configured in `pyproject.toml`
196
-
-**pytest**configured in `pyproject.toml`
235
+
-**Lint**-- `./scripts/lint.sh` on latest Python
236
+
-**Typecheck**-- `./scripts/run_mypy.sh` on latest Python
237
+
-**Unit tests**-- full test suite across Python 3.7--3.14 matrix
238
+
-**Code coverage**-- uploaded to Codecov
197
239
198
-
## GitHub & CI/CD
240
+
## PR and Commit Guidelines
199
241
200
-
-`.github/` -- GitHub-specific configuration and documentation
201
-
-`.github/workflows/` -- Continuous integration pipeline definitions that run on GitHub Actions
202
-
-`.github/maintainers_guide.md` -- Maintainer workflows and release process
242
+
- PRs target the `main` branch
243
+
- You MUST run `./scripts/install_all_and_run_tests.sh` before submitting
0 commit comments