heathrow 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +58 -0
- data/README.md +205 -0
- data/bin/heathrow +42 -0
- data/bin/heathrowd +283 -0
- data/docs/ARCHITECTURE.md +1172 -0
- data/docs/DATABASE_SCHEMA.md +685 -0
- data/docs/DEVELOPMENT_WORKFLOW.md +867 -0
- data/docs/DISCORD_SETUP.md +142 -0
- data/docs/GMAIL_OAUTH_SETUP.md +120 -0
- data/docs/PLUGIN_SYSTEM.md +1370 -0
- data/docs/PROJECT_PLAN.md +1022 -0
- data/docs/README.md +417 -0
- data/docs/REDDIT_SETUP.md +174 -0
- data/docs/REPLY_FORWARD.md +182 -0
- data/docs/WHATSAPP_TELEGRAM_SETUP.md +306 -0
- data/heathrow.gemspec +34 -0
- data/heathrowd.service +21 -0
- data/img/heathrow.svg +95 -0
- data/img/rss_threaded.png +0 -0
- data/img/sources.png +0 -0
- data/lib/heathrow/address_book.rb +42 -0
- data/lib/heathrow/config.rb +332 -0
- data/lib/heathrow/database.rb +731 -0
- data/lib/heathrow/database_new.rb +392 -0
- data/lib/heathrow/event_bus.rb +175 -0
- data/lib/heathrow/logger.rb +122 -0
- data/lib/heathrow/message.rb +176 -0
- data/lib/heathrow/message_composer.rb +399 -0
- data/lib/heathrow/message_organizer.rb +774 -0
- data/lib/heathrow/migrations/001_initial_schema.rb +248 -0
- data/lib/heathrow/notmuch.rb +45 -0
- data/lib/heathrow/oauth2_smtp.rb +254 -0
- data/lib/heathrow/plugin/base.rb +212 -0
- data/lib/heathrow/plugin_manager.rb +141 -0
- data/lib/heathrow/poller.rb +93 -0
- data/lib/heathrow/smtp_sender.rb +204 -0
- data/lib/heathrow/source.rb +39 -0
- data/lib/heathrow/sources/base.rb +74 -0
- data/lib/heathrow/sources/discord.rb +357 -0
- data/lib/heathrow/sources/gmail.rb +294 -0
- data/lib/heathrow/sources/imap.rb +198 -0
- data/lib/heathrow/sources/instagram.rb +307 -0
- data/lib/heathrow/sources/instagram_fetch.py +101 -0
- data/lib/heathrow/sources/instagram_send.py +55 -0
- data/lib/heathrow/sources/instagram_send_marionette.py +104 -0
- data/lib/heathrow/sources/maildir.rb +606 -0
- data/lib/heathrow/sources/messenger.rb +212 -0
- data/lib/heathrow/sources/messenger_fetch.js +297 -0
- data/lib/heathrow/sources/messenger_fetch_marionette.py +138 -0
- data/lib/heathrow/sources/messenger_send.js +32 -0
- data/lib/heathrow/sources/messenger_send.py +100 -0
- data/lib/heathrow/sources/reddit.rb +461 -0
- data/lib/heathrow/sources/rss.rb +299 -0
- data/lib/heathrow/sources/slack.rb +375 -0
- data/lib/heathrow/sources/source_manager.rb +328 -0
- data/lib/heathrow/sources/telegram.rb +498 -0
- data/lib/heathrow/sources/webpage.rb +207 -0
- data/lib/heathrow/sources/weechat.rb +479 -0
- data/lib/heathrow/sources/whatsapp.rb +474 -0
- data/lib/heathrow/ui/application.rb +8098 -0
- data/lib/heathrow/ui/navigation.rb +8 -0
- data/lib/heathrow/ui/panes.rb +8 -0
- data/lib/heathrow/ui/source_wizard.rb +567 -0
- data/lib/heathrow/ui/threaded_view.rb +780 -0
- data/lib/heathrow/ui/views.rb +8 -0
- data/lib/heathrow/version.rb +3 -0
- data/lib/heathrow/wizards/discord_wizard.rb +193 -0
- data/lib/heathrow/wizards/slack_wizard.rb +140 -0
- data/lib/heathrow.rb +55 -0
- metadata +147 -0
|
@@ -0,0 +1,867 @@
|
|
|
1
|
+
# Heathrow Development Workflow
|
|
2
|
+
|
|
3
|
+
**Goal:** Ensure consistent, safe, and efficient development process.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Development Environment Setup](#development-environment-setup)
|
|
10
|
+
2. [Git Workflow](#git-workflow)
|
|
11
|
+
3. [Coding Standards](#coding-standards)
|
|
12
|
+
4. [Testing Workflow](#testing-workflow)
|
|
13
|
+
5. [Documentation Workflow](#documentation-workflow)
|
|
14
|
+
6. [Review Process](#review-process)
|
|
15
|
+
7. [Release Process](#release-process)
|
|
16
|
+
8. [Troubleshooting](#troubleshooting)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Development Environment Setup
|
|
21
|
+
|
|
22
|
+
### Prerequisites
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Ruby 3.0+
|
|
26
|
+
ruby --version
|
|
27
|
+
|
|
28
|
+
# SQLite 3
|
|
29
|
+
sqlite3 --version
|
|
30
|
+
|
|
31
|
+
# Git
|
|
32
|
+
git --version
|
|
33
|
+
|
|
34
|
+
# Optional: w3m for HTML email rendering
|
|
35
|
+
w3m -version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Initial Setup
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Clone repository
|
|
42
|
+
git clone https://github.com/yourusername/heathrow.git
|
|
43
|
+
cd heathrow
|
|
44
|
+
|
|
45
|
+
# Install dependencies
|
|
46
|
+
gem install sqlite3 minitest rcurses
|
|
47
|
+
|
|
48
|
+
# Create config directories
|
|
49
|
+
mkdir -p ~/.heathrow/{plugins,attachments,backups}
|
|
50
|
+
|
|
51
|
+
# Initialize database
|
|
52
|
+
ruby -Ilib -e "require 'heathrow/database'; Heathrow::Database.new.migrate_to_latest"
|
|
53
|
+
|
|
54
|
+
# Run tests to verify setup
|
|
55
|
+
ruby test/test_all.rb
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### IDE/Editor Configuration
|
|
59
|
+
|
|
60
|
+
**VS Code:**
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"ruby.format": "rubocop",
|
|
65
|
+
"ruby.lint": {
|
|
66
|
+
"rubocop": true
|
|
67
|
+
},
|
|
68
|
+
"files.associations": {
|
|
69
|
+
"*.rb": "ruby"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Vim:**
|
|
75
|
+
|
|
76
|
+
```vim
|
|
77
|
+
" .vimrc
|
|
78
|
+
autocmd FileType ruby setlocal expandtab shiftwidth=2 tabstop=2
|
|
79
|
+
autocmd FileType ruby setlocal colorcolumn=100
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Git Workflow
|
|
85
|
+
|
|
86
|
+
### Branch Strategy
|
|
87
|
+
|
|
88
|
+
**Main Branches:**
|
|
89
|
+
- `main` - Production-ready code
|
|
90
|
+
- `develop` - Integration branch for next release
|
|
91
|
+
|
|
92
|
+
**Supporting Branches:**
|
|
93
|
+
- `feature/*` - New features
|
|
94
|
+
- `bugfix/*` - Bug fixes
|
|
95
|
+
- `hotfix/*` - Emergency production fixes
|
|
96
|
+
- `refactor/*` - Code improvements
|
|
97
|
+
- `docs/*` - Documentation updates
|
|
98
|
+
|
|
99
|
+
### Branch Naming
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Features
|
|
103
|
+
git checkout -b feature/gmail-plugin
|
|
104
|
+
git checkout -b feature/search-engine
|
|
105
|
+
|
|
106
|
+
# Bug fixes
|
|
107
|
+
git checkout -b bugfix/fix-slack-auth
|
|
108
|
+
git checkout -b bugfix/memory-leak-in-ui
|
|
109
|
+
|
|
110
|
+
# Refactoring
|
|
111
|
+
git checkout -b refactor/simplify-filter-engine
|
|
112
|
+
|
|
113
|
+
# Documentation
|
|
114
|
+
git checkout -b docs/update-plugin-guide
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Commit Messages
|
|
118
|
+
|
|
119
|
+
**Format:**
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
<type>(<scope>): <subject>
|
|
123
|
+
|
|
124
|
+
<body>
|
|
125
|
+
|
|
126
|
+
<footer>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Types:**
|
|
130
|
+
- `feat` - New feature
|
|
131
|
+
- `fix` - Bug fix
|
|
132
|
+
- `refactor` - Code refactoring
|
|
133
|
+
- `docs` - Documentation
|
|
134
|
+
- `test` - Test additions/changes
|
|
135
|
+
- `chore` - Maintenance tasks
|
|
136
|
+
|
|
137
|
+
**Examples:**
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Good
|
|
141
|
+
git commit -m "feat(plugins): add Gmail OAuth2 authentication"
|
|
142
|
+
|
|
143
|
+
git commit -m "fix(ui): prevent crash when terminal too small
|
|
144
|
+
|
|
145
|
+
Terminal width < 80 caused division by zero in pane calculation.
|
|
146
|
+
Added minimum width check and display warning message.
|
|
147
|
+
|
|
148
|
+
Fixes #123"
|
|
149
|
+
|
|
150
|
+
git commit -m "refactor(database): extract query builder to separate class
|
|
151
|
+
|
|
152
|
+
Improves testability and readability of database queries.
|
|
153
|
+
No functional changes."
|
|
154
|
+
|
|
155
|
+
# Bad
|
|
156
|
+
git commit -m "fixed stuff"
|
|
157
|
+
git commit -m "WIP"
|
|
158
|
+
git commit -m "asdfasdf"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Workflow Steps
|
|
162
|
+
|
|
163
|
+
#### 1. Start New Feature
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Update develop branch
|
|
167
|
+
git checkout develop
|
|
168
|
+
git pull origin develop
|
|
169
|
+
|
|
170
|
+
# Create feature branch
|
|
171
|
+
git checkout -b feature/my-feature
|
|
172
|
+
|
|
173
|
+
# Make changes...
|
|
174
|
+
|
|
175
|
+
# Commit frequently
|
|
176
|
+
git add lib/heathrow/my_feature.rb
|
|
177
|
+
git commit -m "feat(my-feature): implement core logic"
|
|
178
|
+
|
|
179
|
+
# Push to remote
|
|
180
|
+
git push -u origin feature/my-feature
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### 2. Keep Branch Updated
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Rebase on develop regularly
|
|
187
|
+
git fetch origin
|
|
188
|
+
git rebase origin/develop
|
|
189
|
+
|
|
190
|
+
# Resolve conflicts if any
|
|
191
|
+
git add <resolved-files>
|
|
192
|
+
git rebase --continue
|
|
193
|
+
|
|
194
|
+
# Force push (only on feature branches!)
|
|
195
|
+
git push --force-with-lease
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### 3. Submit Pull Request
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Ensure all tests pass
|
|
202
|
+
ruby test/test_all.rb
|
|
203
|
+
|
|
204
|
+
# Push final version
|
|
205
|
+
git push origin feature/my-feature
|
|
206
|
+
|
|
207
|
+
# Create PR via GitHub CLI or web interface
|
|
208
|
+
gh pr create --base develop --title "Add My Feature" --body "Description..."
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### 4. After PR Merged
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
# Delete local branch
|
|
215
|
+
git checkout develop
|
|
216
|
+
git pull origin develop
|
|
217
|
+
git branch -d feature/my-feature
|
|
218
|
+
|
|
219
|
+
# Delete remote branch (if not auto-deleted)
|
|
220
|
+
git push origin --delete feature/my-feature
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Hotfix Workflow
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Create hotfix from main
|
|
227
|
+
git checkout main
|
|
228
|
+
git checkout -b hotfix/critical-bug
|
|
229
|
+
|
|
230
|
+
# Fix the issue
|
|
231
|
+
git commit -m "fix(critical): resolve security vulnerability"
|
|
232
|
+
|
|
233
|
+
# Merge to main
|
|
234
|
+
git checkout main
|
|
235
|
+
git merge hotfix/critical-bug
|
|
236
|
+
git tag v1.2.3
|
|
237
|
+
git push origin main --tags
|
|
238
|
+
|
|
239
|
+
# Merge to develop
|
|
240
|
+
git checkout develop
|
|
241
|
+
git merge hotfix/critical-bug
|
|
242
|
+
git push origin develop
|
|
243
|
+
|
|
244
|
+
# Delete hotfix branch
|
|
245
|
+
git branch -d hotfix/critical-bug
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Coding Standards
|
|
251
|
+
|
|
252
|
+
### Ruby Style Guide
|
|
253
|
+
|
|
254
|
+
**Follow:** [Ruby Style Guide](https://rubystyle.guide/)
|
|
255
|
+
|
|
256
|
+
**Key Points:**
|
|
257
|
+
|
|
258
|
+
1. **Indentation:** 2 spaces, no tabs
|
|
259
|
+
2. **Line Length:** 100 characters max
|
|
260
|
+
3. **Method Length:** 15 lines max (guideline, not strict)
|
|
261
|
+
4. **Class Length:** 200 lines max (consider splitting)
|
|
262
|
+
5. **Naming:**
|
|
263
|
+
- Classes: `CamelCase`
|
|
264
|
+
- Methods: `snake_case`
|
|
265
|
+
- Constants: `SCREAMING_SNAKE_CASE`
|
|
266
|
+
- Private methods: prefix with `private`
|
|
267
|
+
|
|
268
|
+
**Example:**
|
|
269
|
+
|
|
270
|
+
```ruby
|
|
271
|
+
module Heathrow
|
|
272
|
+
class MessageRouter
|
|
273
|
+
MAX_RETRIES = 3
|
|
274
|
+
|
|
275
|
+
def initialize(filter_engine, view_manager, db)
|
|
276
|
+
@filter_engine = filter_engine
|
|
277
|
+
@view_manager = view_manager
|
|
278
|
+
@db = db
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def route_message(message)
|
|
282
|
+
validate_message(message)
|
|
283
|
+
|
|
284
|
+
views = matching_views(message)
|
|
285
|
+
views.each { |view| add_to_view(message, view) }
|
|
286
|
+
|
|
287
|
+
log_routing(message, views)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
private
|
|
291
|
+
|
|
292
|
+
def validate_message(message)
|
|
293
|
+
raise ArgumentError, "Message cannot be nil" unless message
|
|
294
|
+
raise ArgumentError, "Message must have sender" unless message.sender
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def matching_views(message)
|
|
298
|
+
@view_manager.all_views.select do |view|
|
|
299
|
+
@filter_engine.matches?(message, view.filters)
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def add_to_view(message, view)
|
|
304
|
+
# Implementation...
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def log_routing(message, views)
|
|
308
|
+
# Implementation...
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### File Organization
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
lib/heathrow/
|
|
318
|
+
├── heathrow.rb # Main entry point
|
|
319
|
+
├── version.rb # Version constant
|
|
320
|
+
├── config.rb # Configuration
|
|
321
|
+
├── database.rb # Database layer
|
|
322
|
+
├── event_bus.rb # Event system
|
|
323
|
+
├── logger.rb # Logging
|
|
324
|
+
├── cache.rb # Caching
|
|
325
|
+
├── message.rb # Message model
|
|
326
|
+
├── message_router.rb # Message routing
|
|
327
|
+
├── view_manager.rb # View management
|
|
328
|
+
├── filter_engine.rb # Filter evaluation
|
|
329
|
+
├── search_engine.rb # Search
|
|
330
|
+
├── plugin_manager.rb # Plugin management
|
|
331
|
+
├── stream_manager.rb # Real-time streaming
|
|
332
|
+
├── plugin/
|
|
333
|
+
│ ├── base.rb # Plugin base class
|
|
334
|
+
│ ├── errors.rb # Plugin errors
|
|
335
|
+
│ └── registry.rb # Plugin registry
|
|
336
|
+
├── plugins/
|
|
337
|
+
│ ├── gmail.rb
|
|
338
|
+
│ ├── slack.rb
|
|
339
|
+
│ └── ...
|
|
340
|
+
├── ui/
|
|
341
|
+
│ ├── application.rb # Main UI
|
|
342
|
+
│ ├── pane_manager.rb # Pane management
|
|
343
|
+
│ ├── input_handler.rb # Input handling
|
|
344
|
+
│ ├── renderer.rb # Rendering
|
|
345
|
+
│ ├── composer.rb # Message composer
|
|
346
|
+
│ └── thread_view.rb # Thread view
|
|
347
|
+
└── migrations/
|
|
348
|
+
├── 001_initial.rb
|
|
349
|
+
└── ...
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### Documentation Comments
|
|
353
|
+
|
|
354
|
+
**Use YARD format:**
|
|
355
|
+
|
|
356
|
+
```ruby
|
|
357
|
+
# Fetch messages from the plugin
|
|
358
|
+
#
|
|
359
|
+
# @param since [Integer, nil] Unix timestamp to fetch from (nil for all)
|
|
360
|
+
# @return [Array<Heathrow::Message>] Array of normalized messages
|
|
361
|
+
# @raise [Plugin::ConnectionError] If connection fails
|
|
362
|
+
# @raise [Plugin::AuthenticationError] If authentication fails
|
|
363
|
+
#
|
|
364
|
+
# @example Fetch recent messages
|
|
365
|
+
# messages = plugin.fetch_messages(since: Time.now.to_i - 3600)
|
|
366
|
+
#
|
|
367
|
+
def fetch_messages(since: nil)
|
|
368
|
+
# Implementation...
|
|
369
|
+
end
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Testing Workflow
|
|
375
|
+
|
|
376
|
+
### Running Tests
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Run all tests
|
|
380
|
+
ruby test/test_all.rb
|
|
381
|
+
|
|
382
|
+
# Run specific test file
|
|
383
|
+
ruby test/test_filter_engine.rb
|
|
384
|
+
|
|
385
|
+
# Run specific test
|
|
386
|
+
ruby test/test_filter_engine.rb -n test_simple_equality_filter
|
|
387
|
+
|
|
388
|
+
# Run with verbose output
|
|
389
|
+
ruby test/test_all.rb -v
|
|
390
|
+
|
|
391
|
+
# Run with code coverage (if using SimpleCov)
|
|
392
|
+
COVERAGE=1 ruby test/test_all.rb
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Writing Tests
|
|
396
|
+
|
|
397
|
+
**Test File Naming:**
|
|
398
|
+
- Unit tests: `test/test_<component>.rb`
|
|
399
|
+
- Integration tests: `test/integration/test_<feature>.rb`
|
|
400
|
+
- E2E tests: `test/e2e/test_<workflow>.rb`
|
|
401
|
+
|
|
402
|
+
**Test Structure:**
|
|
403
|
+
|
|
404
|
+
```ruby
|
|
405
|
+
require 'minitest/autorun'
|
|
406
|
+
require_relative 'test_helper'
|
|
407
|
+
|
|
408
|
+
class TestMessageRouter < Minitest::Test
|
|
409
|
+
# Setup runs before each test
|
|
410
|
+
def setup
|
|
411
|
+
@db = Database.new(":memory:")
|
|
412
|
+
@filter_engine = FilterEngine.new
|
|
413
|
+
@view_manager = ViewManager.new(@db, @filter_engine)
|
|
414
|
+
@router = MessageRouter.new(@filter_engine, @view_manager, @db)
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# Teardown runs after each test (optional)
|
|
418
|
+
def teardown
|
|
419
|
+
@db.close
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Test methods must start with "test_"
|
|
423
|
+
def test_routes_message_to_matching_view
|
|
424
|
+
# Arrange
|
|
425
|
+
view = @view_manager.create_view("Test", {field: "sender", op: "=", value: "test@example.com"})
|
|
426
|
+
message = create_test_message(sender: "test@example.com")
|
|
427
|
+
|
|
428
|
+
# Act
|
|
429
|
+
@router.route_message(message)
|
|
430
|
+
|
|
431
|
+
# Assert
|
|
432
|
+
messages = @router.messages_for_view(view.id)
|
|
433
|
+
assert_equal 1, messages.count
|
|
434
|
+
assert_equal message.external_id, messages.first.external_id
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def test_raises_error_on_invalid_message
|
|
438
|
+
assert_raises(ArgumentError) do
|
|
439
|
+
@router.route_message(nil)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
private
|
|
444
|
+
|
|
445
|
+
def create_test_message(overrides = {})
|
|
446
|
+
TestHelper.create_test_message(overrides)
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Test Coverage Goals
|
|
452
|
+
|
|
453
|
+
| Component Type | Target Coverage |
|
|
454
|
+
|-------------------|-----------------|
|
|
455
|
+
| Core Layer | 95%+ |
|
|
456
|
+
| Application Layer | 85%+ |
|
|
457
|
+
| UI Layer | 60%+ |
|
|
458
|
+
| Plugins | 75%+ |
|
|
459
|
+
| Overall | 80%+ |
|
|
460
|
+
|
|
461
|
+
### Continuous Integration
|
|
462
|
+
|
|
463
|
+
**GitHub Actions Workflow:**
|
|
464
|
+
|
|
465
|
+
```yaml
|
|
466
|
+
# .github/workflows/test.yml
|
|
467
|
+
name: Test
|
|
468
|
+
|
|
469
|
+
on: [push, pull_request]
|
|
470
|
+
|
|
471
|
+
jobs:
|
|
472
|
+
test:
|
|
473
|
+
runs-on: ubuntu-latest
|
|
474
|
+
|
|
475
|
+
steps:
|
|
476
|
+
- uses: actions/checkout@v2
|
|
477
|
+
|
|
478
|
+
- name: Set up Ruby
|
|
479
|
+
uses: ruby/setup-ruby@v1
|
|
480
|
+
with:
|
|
481
|
+
ruby-version: 3.2
|
|
482
|
+
|
|
483
|
+
- name: Install dependencies
|
|
484
|
+
run: gem install sqlite3 minitest rcurses
|
|
485
|
+
|
|
486
|
+
- name: Run tests
|
|
487
|
+
run: ruby test/test_all.rb
|
|
488
|
+
|
|
489
|
+
- name: Run rubocop
|
|
490
|
+
run: gem install rubocop && rubocop
|
|
491
|
+
|
|
492
|
+
- name: Check coverage
|
|
493
|
+
run: |
|
|
494
|
+
COVERAGE=1 ruby test/test_all.rb
|
|
495
|
+
# Fail if coverage < 80%
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## Documentation Workflow
|
|
501
|
+
|
|
502
|
+
### Documentation Types
|
|
503
|
+
|
|
504
|
+
1. **Code Comments** - YARD format for methods/classes
|
|
505
|
+
2. **README.md** - Project overview and quickstart
|
|
506
|
+
3. **docs/** - Detailed guides
|
|
507
|
+
4. **CHANGELOG.md** - Version history
|
|
508
|
+
5. **API.md** - API reference (auto-generated from YARD)
|
|
509
|
+
|
|
510
|
+
### Documentation Standards
|
|
511
|
+
|
|
512
|
+
**Keep documentation:**
|
|
513
|
+
- Up-to-date with code
|
|
514
|
+
- Clear and concise
|
|
515
|
+
- Example-driven
|
|
516
|
+
- Beginner-friendly
|
|
517
|
+
|
|
518
|
+
**Update documentation when:**
|
|
519
|
+
- Adding new feature
|
|
520
|
+
- Changing API
|
|
521
|
+
- Fixing bug that affects usage
|
|
522
|
+
- Deprecating functionality
|
|
523
|
+
|
|
524
|
+
### Generating API Docs
|
|
525
|
+
|
|
526
|
+
```bash
|
|
527
|
+
# Install YARD
|
|
528
|
+
gem install yard
|
|
529
|
+
|
|
530
|
+
# Generate docs
|
|
531
|
+
yard doc
|
|
532
|
+
|
|
533
|
+
# View docs
|
|
534
|
+
yard server
|
|
535
|
+
# Open http://localhost:8808
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## Review Process
|
|
541
|
+
|
|
542
|
+
### Pre-Review Checklist
|
|
543
|
+
|
|
544
|
+
Before submitting PR, verify:
|
|
545
|
+
|
|
546
|
+
- [ ] All tests pass
|
|
547
|
+
- [ ] No rubocop violations
|
|
548
|
+
- [ ] Documentation updated
|
|
549
|
+
- [ ] CHANGELOG.md updated
|
|
550
|
+
- [ ] Commit messages follow convention
|
|
551
|
+
- [ ] No commented-out code
|
|
552
|
+
- [ ] No debug print statements
|
|
553
|
+
- [ ] Branch rebased on latest develop
|
|
554
|
+
|
|
555
|
+
### Code Review Guidelines
|
|
556
|
+
|
|
557
|
+
**For Reviewers:**
|
|
558
|
+
|
|
559
|
+
1. **Functionality** - Does it work as intended?
|
|
560
|
+
2. **Tests** - Are there sufficient tests?
|
|
561
|
+
3. **Readability** - Is the code clear?
|
|
562
|
+
4. **Performance** - Are there obvious bottlenecks?
|
|
563
|
+
5. **Security** - Any vulnerabilities?
|
|
564
|
+
6. **Architecture** - Does it fit the design?
|
|
565
|
+
|
|
566
|
+
**Review Comments:**
|
|
567
|
+
|
|
568
|
+
```
|
|
569
|
+
# Good
|
|
570
|
+
"Consider extracting this to a separate method for better testability."
|
|
571
|
+
"This could cause a race condition if called from multiple threads."
|
|
572
|
+
"Nice solution! One suggestion: use `find` instead of `select.first` for clarity."
|
|
573
|
+
|
|
574
|
+
# Bad
|
|
575
|
+
"This is wrong."
|
|
576
|
+
"Why did you do it this way?"
|
|
577
|
+
"Just rewrite this."
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
**Approval Criteria:**
|
|
581
|
+
- At least 1 approval from maintainer
|
|
582
|
+
- All CI checks pass
|
|
583
|
+
- No unresolved discussions
|
|
584
|
+
|
|
585
|
+
---
|
|
586
|
+
|
|
587
|
+
## Release Process
|
|
588
|
+
|
|
589
|
+
### Versioning
|
|
590
|
+
|
|
591
|
+
**Semantic Versioning:** `MAJOR.MINOR.PATCH`
|
|
592
|
+
|
|
593
|
+
- `MAJOR` - Breaking changes
|
|
594
|
+
- `MINOR` - New features (backward compatible)
|
|
595
|
+
- `PATCH` - Bug fixes
|
|
596
|
+
|
|
597
|
+
**Examples:**
|
|
598
|
+
- `1.0.0` - Initial stable release
|
|
599
|
+
- `1.1.0` - Added Slack plugin
|
|
600
|
+
- `1.1.1` - Fixed Slack authentication bug
|
|
601
|
+
- `2.0.0` - Changed config file format (breaking)
|
|
602
|
+
|
|
603
|
+
### Release Steps
|
|
604
|
+
|
|
605
|
+
#### 1. Prepare Release
|
|
606
|
+
|
|
607
|
+
```bash
|
|
608
|
+
# Create release branch
|
|
609
|
+
git checkout develop
|
|
610
|
+
git checkout -b release/v1.2.0
|
|
611
|
+
|
|
612
|
+
# Update version
|
|
613
|
+
# Edit lib/heathrow/version.rb
|
|
614
|
+
module Heathrow
|
|
615
|
+
VERSION = "1.2.0"
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
# Update CHANGELOG.md
|
|
619
|
+
# Add release notes under "## [1.2.0] - 2024-01-15"
|
|
620
|
+
|
|
621
|
+
# Commit changes
|
|
622
|
+
git commit -am "chore: prepare v1.2.0 release"
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
#### 2. Test Release
|
|
626
|
+
|
|
627
|
+
```bash
|
|
628
|
+
# Run full test suite
|
|
629
|
+
ruby test/test_all.rb
|
|
630
|
+
|
|
631
|
+
# Manual testing
|
|
632
|
+
./bin/heathrow
|
|
633
|
+
|
|
634
|
+
# Integration testing with real services (if possible)
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
#### 3. Merge and Tag
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
# Merge to main
|
|
641
|
+
git checkout main
|
|
642
|
+
git merge release/v1.2.0
|
|
643
|
+
|
|
644
|
+
# Tag release
|
|
645
|
+
git tag -a v1.2.0 -m "Release v1.2.0"
|
|
646
|
+
git push origin main --tags
|
|
647
|
+
|
|
648
|
+
# Merge to develop
|
|
649
|
+
git checkout develop
|
|
650
|
+
git merge release/v1.2.0
|
|
651
|
+
git push origin develop
|
|
652
|
+
|
|
653
|
+
# Delete release branch
|
|
654
|
+
git branch -d release/v1.2.0
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
#### 4. Publish
|
|
658
|
+
|
|
659
|
+
```bash
|
|
660
|
+
# Build gem
|
|
661
|
+
gem build heathrow.gemspec
|
|
662
|
+
|
|
663
|
+
# Publish to RubyGems
|
|
664
|
+
gem push heathrow-1.2.0.gem
|
|
665
|
+
|
|
666
|
+
# Create GitHub release
|
|
667
|
+
gh release create v1.2.0 --title "v1.2.0" --notes "See CHANGELOG.md"
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
#### 5. Announce
|
|
671
|
+
|
|
672
|
+
- Post to project blog/website
|
|
673
|
+
- Update documentation site
|
|
674
|
+
- Notify users (mailing list, Discord, etc.)
|
|
675
|
+
|
|
676
|
+
### CHANGELOG Format
|
|
677
|
+
|
|
678
|
+
```markdown
|
|
679
|
+
# Changelog
|
|
680
|
+
|
|
681
|
+
All notable changes to this project will be documented in this file.
|
|
682
|
+
|
|
683
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
684
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
685
|
+
|
|
686
|
+
## [Unreleased]
|
|
687
|
+
|
|
688
|
+
### Added
|
|
689
|
+
- Feature X that does Y
|
|
690
|
+
|
|
691
|
+
### Changed
|
|
692
|
+
- Improved performance of Z
|
|
693
|
+
|
|
694
|
+
### Fixed
|
|
695
|
+
- Bug in A that caused B
|
|
696
|
+
|
|
697
|
+
## [1.2.0] - 2024-01-15
|
|
698
|
+
|
|
699
|
+
### Added
|
|
700
|
+
- Gmail plugin with OAuth2 support
|
|
701
|
+
- Full-text search across all messages
|
|
702
|
+
- Message threading support
|
|
703
|
+
|
|
704
|
+
### Changed
|
|
705
|
+
- Improved UI rendering performance by 50%
|
|
706
|
+
- Updated dependencies to latest versions
|
|
707
|
+
|
|
708
|
+
### Fixed
|
|
709
|
+
- Crash when terminal width < 80
|
|
710
|
+
- Memory leak in real-time stream manager
|
|
711
|
+
|
|
712
|
+
### Security
|
|
713
|
+
- Fixed XSS vulnerability in HTML email rendering
|
|
714
|
+
|
|
715
|
+
## [1.1.0] - 2023-12-01
|
|
716
|
+
|
|
717
|
+
...
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
---
|
|
721
|
+
|
|
722
|
+
## Troubleshooting
|
|
723
|
+
|
|
724
|
+
### Common Issues
|
|
725
|
+
|
|
726
|
+
#### Tests Failing Locally
|
|
727
|
+
|
|
728
|
+
```bash
|
|
729
|
+
# Ensure clean database
|
|
730
|
+
rm ~/.heathrow/heathrow.db
|
|
731
|
+
ruby -Ilib -e "require 'heathrow/database'; Heathrow::Database.new.migrate_to_latest"
|
|
732
|
+
|
|
733
|
+
# Clear cache
|
|
734
|
+
rm -rf /tmp/heathrow_test_*
|
|
735
|
+
|
|
736
|
+
# Reinstall dependencies
|
|
737
|
+
gem uninstall sqlite3 minitest rcurses
|
|
738
|
+
gem install sqlite3 minitest rcurses
|
|
739
|
+
|
|
740
|
+
# Run tests again
|
|
741
|
+
ruby test/test_all.rb
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
#### Rubocop Violations
|
|
745
|
+
|
|
746
|
+
```bash
|
|
747
|
+
# Auto-fix simple violations
|
|
748
|
+
rubocop -a
|
|
749
|
+
|
|
750
|
+
# Auto-fix unsafe violations (be careful!)
|
|
751
|
+
rubocop -A
|
|
752
|
+
|
|
753
|
+
# Ignore specific violations (last resort)
|
|
754
|
+
# Add to .rubocop.yml:
|
|
755
|
+
# Style/StringLiterals:
|
|
756
|
+
# Enabled: false
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
#### Git Conflicts
|
|
760
|
+
|
|
761
|
+
```bash
|
|
762
|
+
# Abort rebase and start fresh
|
|
763
|
+
git rebase --abort
|
|
764
|
+
git fetch origin
|
|
765
|
+
git rebase origin/develop
|
|
766
|
+
|
|
767
|
+
# Use merge instead (not recommended)
|
|
768
|
+
git merge origin/develop
|
|
769
|
+
|
|
770
|
+
# Resolve conflicts manually
|
|
771
|
+
# Edit conflicted files
|
|
772
|
+
git add <resolved-files>
|
|
773
|
+
git rebase --continue
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
#### Performance Issues
|
|
777
|
+
|
|
778
|
+
```bash
|
|
779
|
+
# Profile code
|
|
780
|
+
ruby -r profile test/test_all.rb
|
|
781
|
+
|
|
782
|
+
# Memory profiling
|
|
783
|
+
gem install memory_profiler
|
|
784
|
+
ruby -r memory_profiler -e "MemoryProfiler.report { require 'heathrow' }.pretty_print"
|
|
785
|
+
|
|
786
|
+
# Database performance
|
|
787
|
+
# Add logging to database.rb
|
|
788
|
+
def query(sql, params = [])
|
|
789
|
+
start = Time.now
|
|
790
|
+
result = @db.execute(sql, params)
|
|
791
|
+
puts "Query took #{Time.now - start}s: #{sql}"
|
|
792
|
+
result
|
|
793
|
+
end
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
### Getting Help
|
|
797
|
+
|
|
798
|
+
1. **Check documentation:** `docs/`
|
|
799
|
+
2. **Search issues:** GitHub issues
|
|
800
|
+
3. **Ask in discussions:** GitHub discussions
|
|
801
|
+
4. **IRC/Discord:** Project chat
|
|
802
|
+
5. **Email:** maintainers
|
|
803
|
+
|
|
804
|
+
---
|
|
805
|
+
|
|
806
|
+
## Development Tips
|
|
807
|
+
|
|
808
|
+
### Productivity
|
|
809
|
+
|
|
810
|
+
1. **Use aliases:**
|
|
811
|
+
|
|
812
|
+
```bash
|
|
813
|
+
# .bashrc or .zshrc
|
|
814
|
+
alias ht='./bin/heathrow'
|
|
815
|
+
alias htt='ruby test/test_all.rb'
|
|
816
|
+
alias htl='tail -f ~/.heathrow/heathrow.log'
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
2. **Quick iterations:**
|
|
820
|
+
|
|
821
|
+
```bash
|
|
822
|
+
# Watch files and auto-run tests
|
|
823
|
+
gem install watchr
|
|
824
|
+
# Create Watchfile with test runner
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
3. **Debugging:**
|
|
828
|
+
|
|
829
|
+
```ruby
|
|
830
|
+
# Use pry for debugging
|
|
831
|
+
gem install pry
|
|
832
|
+
# In code:
|
|
833
|
+
require 'pry'
|
|
834
|
+
binding.pry
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### Best Practices
|
|
838
|
+
|
|
839
|
+
1. **Test-driven development** - Write test first, then implementation
|
|
840
|
+
2. **Commit often** - Small commits are easier to review and revert
|
|
841
|
+
3. **Document as you go** - Don't leave it for later
|
|
842
|
+
4. **Ask for help early** - Don't waste time stuck
|
|
843
|
+
5. **Review your own code** - Read diff before committing
|
|
844
|
+
|
|
845
|
+
### Code Review Checklist
|
|
846
|
+
|
|
847
|
+
Before submitting PR:
|
|
848
|
+
|
|
849
|
+
```markdown
|
|
850
|
+
## PR Checklist
|
|
851
|
+
|
|
852
|
+
- [ ] Tests pass locally
|
|
853
|
+
- [ ] Added tests for new functionality
|
|
854
|
+
- [ ] Updated documentation
|
|
855
|
+
- [ ] Updated CHANGELOG.md
|
|
856
|
+
- [ ] No rubocop violations
|
|
857
|
+
- [ ] No breaking changes (or clearly documented)
|
|
858
|
+
- [ ] Reviewed my own code in diff view
|
|
859
|
+
- [ ] Tested manually in terminal
|
|
860
|
+
- [ ] Considered edge cases
|
|
861
|
+
- [ ] Checked for security issues
|
|
862
|
+
- [ ] Ensured backward compatibility
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
---
|
|
866
|
+
|
|
867
|
+
This workflow ensures consistent, high-quality development across the entire Heathrow project.
|