rails_maint 0.1.1 → 0.2.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 +4 -4
- data/CHANGELOG.md +68 -3
- data/README.md +202 -91
- data/lib/generators/rails_maint/install/install_generator.rb +57 -0
- data/lib/generators/rails_maint/install/templates/initializer.rb.tt +31 -0
- data/lib/generators/rails_maint/install/templates/rails_maint.yml.tt +32 -0
- data/lib/rails_maint/assets/locales/en.yml +2 -1
- data/lib/rails_maint/assets/locales/tr.yml +2 -1
- data/lib/rails_maint/cli/status_printer.rb +52 -0
- data/lib/rails_maint/cli.rb +70 -29
- data/lib/rails_maint/config_loader.rb +16 -0
- data/lib/rails_maint/configuration.rb +73 -0
- data/lib/rails_maint/errors.rb +10 -0
- data/lib/rails_maint/helpers/maintenance_page_helper.rb +34 -29
- data/lib/rails_maint/instrumentation.rb +11 -0
- data/lib/rails_maint/middleware.rb +97 -18
- data/lib/rails_maint/path_matcher.rb +18 -0
- data/lib/rails_maint/railtie.rb +13 -0
- data/lib/rails_maint/schedule.rb +60 -0
- data/lib/rails_maint/version.rb +3 -1
- data/lib/rails_maint/webhook.rb +37 -0
- data/lib/rails_maint.rb +24 -3
- metadata +26 -86
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 644b76b9127a7f3d676d57ac465b5d4a0e51c182ed7e688255521c525c04b8ff
|
|
4
|
+
data.tar.gz: 93a468bdd47373347f2b4da22b471fb3b3792b403e394a24aa7fb3106d5f9767
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d9f1558562c106f2acb1e6cdcce18bbd2d4c7d12af5e199d985f313f488e375562aaf086433c0d4faa33e9dca946c6c65e2913424284b31248bddcf5f32c5171
|
|
7
|
+
data.tar.gz: a1e1ff3f2d802c22d37c41306f0e0fe41b4c0a5c9983852c08f7284563753f0155851407f78df86cd817d022cc9df0a03881dd34695f4287449b3316212460e4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-02-28
|
|
9
|
+
|
|
2
10
|
### Added
|
|
3
|
-
-
|
|
11
|
+
- **Configuration DSL** — `RailsMaint.configure { |c| c.retry_after = 1800 }` for programmatic configuration
|
|
12
|
+
- **Railtie** — Middleware is now auto-registered in Rails apps (no manual `config.middleware.use` needed)
|
|
13
|
+
- **Rails Generator** — `rails generate rails_maint:install` creates config, locale, and initializer files
|
|
14
|
+
- **Retry-After header** — 503 responses include a `Retry-After` header (default: 3600s, configurable)
|
|
15
|
+
- **Route-based maintenance** — `bypass_paths` (always accessible) and `maintenance_paths` (only these paths show maintenance)
|
|
16
|
+
- **Custom maintenance page** — Serve a custom HTML file instead of the default template
|
|
17
|
+
- **Scheduled maintenance** — `rails_maint enable --start="..." --end="..."` for time-windowed maintenance
|
|
18
|
+
- **CLI `status` command** — `rails_maint status` shows current maintenance state and configuration
|
|
19
|
+
- **Webhook notifications** — POST JSON to a configured URL on enable/disable events
|
|
20
|
+
- **ConfigLoader module** — Shared YAML config loading extracted from middleware and CLI
|
|
21
|
+
- **Rails.logger integration** — All log output goes through `RailsMaint.logger` (auto-wired to `Rails.logger` via Railtie)
|
|
22
|
+
- **ActiveSupport::Notifications** — Instrumentation events: `request_blocked.rails_maint`, `enabled.rails_maint`, `disabled.rails_maint`
|
|
23
|
+
- **Custom error classes** — `InvalidConfigurationError`, `InvalidLocaleError`, `ScheduleError`, `WebhookError`
|
|
24
|
+
- **Configuration validation** — `validate!` checks locale format, retry_after, and webhook_url on `RailsMaint.configure`
|
|
25
|
+
- **SimpleCov code coverage** — 99%+ line coverage with branch coverage tracking
|
|
26
|
+
- **README badges** — Gem version, CI status, Codecov, RuboCop style, MIT license
|
|
27
|
+
- **Schedule module** — Parses scheduled maintenance windows with backward-compatible flag file format
|
|
28
|
+
- `remaining_time` translation key added to en.yml and tr.yml
|
|
29
|
+
|
|
30
|
+
### Security
|
|
31
|
+
- Fix IP spoofing vulnerability via X-Forwarded-For header
|
|
32
|
+
- Fix XSS vulnerability in maintenance page template
|
|
33
|
+
- Fix YAML deserialization vulnerability (switched to safe_load)
|
|
34
|
+
- Fix path traversal vulnerability in locale handling
|
|
35
|
+
- Path traversal protection for custom maintenance page
|
|
36
|
+
|
|
4
37
|
### Fixed
|
|
5
|
-
-
|
|
38
|
+
- Remove debug puts statement from production code path
|
|
39
|
+
- Add missing require statements in middleware
|
|
40
|
+
- Fix uninstall command to dynamically find locale files
|
|
41
|
+
- Add locale validation for install command
|
|
42
|
+
- Ensure tmp/ directory exists before writing maintenance file
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
- Minimum Ruby version updated to 3.0+
|
|
46
|
+
- Migrated CI from Travis CI to GitHub Actions
|
|
47
|
+
- Improved error handling throughout
|
|
48
|
+
- Installation reduced from 4 steps to 2 steps (`bundle add` + `rails generate`)
|
|
49
|
+
- Middleware refactored to use Configuration DSL with YAML precedence
|
|
50
|
+
- CLI `uninstall` now also removes the initializer file
|
|
51
|
+
|
|
52
|
+
### Removed
|
|
53
|
+
- Remove unused create_maintenance_page method
|
|
54
|
+
- Remove obsolete .travis.yml
|
|
55
|
+
|
|
56
|
+
## [0.1.1] - 2024-03-28
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
- Multi-language support (English, Turkish)
|
|
60
|
+
- IP whitelist support with proxy header detection
|
|
61
|
+
- CLI commands (install, enable, disable, uninstall)
|
|
62
|
+
- Rack middleware integration
|
|
63
|
+
- Customizable maintenance page with modern design
|
|
64
|
+
|
|
65
|
+
## [0.1.0] - 2024-03-20
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
- Initial release
|
|
69
|
+
- Basic maintenance mode functionality
|
|
70
|
+
- Simple CLI interface
|
data/README.md
CHANGED
|
@@ -1,129 +1,259 @@
|
|
|
1
1
|
# RailsMaint
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/rb/rails_maint)
|
|
4
|
+
[](https://github.com/codescaptain/rails_maint/actions)
|
|
5
|
+
[](https://codecov.io/gh/codescaptain/rails_maint)
|
|
6
|
+
[](https://github.com/rubocop/rubocop)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
<img src="https://github.com/user-attachments/assets/4daa45fe-833b-48c5-9f69-457424769804" width="500" height="500" alt="rails_maint">
|
|
10
|
+
|
|
11
|
+
|
|
3
12
|
RailsMaint is a simple and customizable maintenance mode gem for Rails applications. It allows you to display a sleek maintenance page to your users during maintenance work.
|
|
4
13
|
|
|
5
14
|
## Features
|
|
6
15
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
16
|
+
- Easy setup — just 2 commands to install
|
|
17
|
+
- Automatic middleware registration via Railtie
|
|
18
|
+
- Configuration DSL and YAML config support
|
|
19
|
+
- Retry-After HTTP header for SEO-friendly 503 responses
|
|
20
|
+
- Route-based maintenance with bypass paths
|
|
21
|
+
- Scheduled maintenance windows with auto-deactivation
|
|
22
|
+
- Custom maintenance page support
|
|
23
|
+
- Multi-language support (English and Turkish)
|
|
24
|
+
- IP whitelist support
|
|
25
|
+
- CLI commands (install, enable, disable, status, uninstall)
|
|
26
|
+
- Webhook notifications on enable/disable events
|
|
27
|
+
- Rails Generator for quick setup
|
|
13
28
|
|
|
14
29
|
## Installation
|
|
15
30
|
|
|
16
|
-
|
|
31
|
+
### Rails Apps (Recommended)
|
|
17
32
|
|
|
33
|
+
```bash
|
|
34
|
+
bundle add rails_maint
|
|
35
|
+
rails generate rails_maint:install
|
|
18
36
|
```
|
|
37
|
+
|
|
38
|
+
That's it! The Railtie automatically registers the middleware. The generator creates:
|
|
39
|
+
- `config/rails_maint.yml` — Configuration file
|
|
40
|
+
- `config/locales/rails_maint.en.yml` — Language file
|
|
41
|
+
- `config/initializers/rails_maint.rb` — Initializer with DSL configuration
|
|
42
|
+
|
|
43
|
+
### Manual Setup
|
|
44
|
+
|
|
45
|
+
1. Add to your Gemfile:
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
19
48
|
gem 'rails_maint'
|
|
20
49
|
```
|
|
21
50
|
|
|
22
|
-
2.
|
|
51
|
+
2. Run:
|
|
23
52
|
|
|
24
|
-
```
|
|
53
|
+
```bash
|
|
25
54
|
bundle install
|
|
55
|
+
rails_maint install
|
|
26
56
|
```
|
|
27
57
|
|
|
28
|
-
3.
|
|
58
|
+
3. If you need manual middleware registration (the Railtie handles this automatically):
|
|
29
59
|
|
|
30
|
-
```
|
|
60
|
+
```ruby
|
|
61
|
+
# config/application.rb
|
|
31
62
|
config.middleware.use RailsMaint::Middleware
|
|
32
63
|
```
|
|
33
64
|
|
|
34
65
|
## Usage
|
|
35
66
|
|
|
36
|
-
### Installing the Gem
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
# For English (default)
|
|
40
|
-
rails_maint install
|
|
41
|
-
|
|
42
|
-
# For Turkish
|
|
43
|
-
rails_maint install --locale=tr
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
This command creates the following files:
|
|
47
|
-
- `config/rails_maint.yml` - Configuration file
|
|
48
|
-
- `config/locales/rails_maint.{locale}.yml` - Language file
|
|
49
|
-
|
|
50
67
|
### Managing Maintenance Mode
|
|
51
68
|
|
|
52
|
-
```
|
|
53
|
-
#
|
|
69
|
+
```bash
|
|
70
|
+
# Enable maintenance mode
|
|
54
71
|
rails_maint enable
|
|
55
72
|
|
|
56
|
-
#
|
|
73
|
+
# Enable with scheduled window
|
|
74
|
+
rails_maint enable --start="2024-06-01 10:00" --end="2024-06-01 12:00"
|
|
75
|
+
|
|
76
|
+
# Disable maintenance mode
|
|
57
77
|
rails_maint disable
|
|
58
78
|
|
|
59
|
-
#
|
|
79
|
+
# Check current status
|
|
80
|
+
rails_maint status
|
|
81
|
+
|
|
82
|
+
# Remove all RailsMaint files
|
|
60
83
|
rails_maint uninstall
|
|
61
84
|
```
|
|
62
85
|
|
|
86
|
+
### Status Command
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
$ rails_maint status
|
|
90
|
+
Status: ENABLED
|
|
91
|
+
Enabled at: 2024-06-01 10:00:00 +0000
|
|
92
|
+
Start time: 2024-06-01 10:00:00 +0000
|
|
93
|
+
End time: 2024-06-01 12:00:00 +0000
|
|
94
|
+
Remaining: 3542s
|
|
95
|
+
|
|
96
|
+
Locale: en
|
|
97
|
+
Whitelisted IPs: 127.0.0.1, ::1
|
|
98
|
+
Bypass paths: /health, /up
|
|
99
|
+
Retry-After: 3600s
|
|
100
|
+
Custom page: none
|
|
101
|
+
Webhook URL: none
|
|
102
|
+
```
|
|
103
|
+
|
|
63
104
|
## Configuration
|
|
64
105
|
|
|
65
|
-
|
|
106
|
+
### YAML Configuration
|
|
66
107
|
|
|
67
|
-
|
|
108
|
+
Customize your settings in `config/rails_maint.yml`:
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
68
111
|
# Default language setting
|
|
69
112
|
locale: en
|
|
70
113
|
|
|
71
|
-
# IP addresses allowed to access
|
|
114
|
+
# IP addresses allowed to access during maintenance
|
|
72
115
|
white_listed_ips:
|
|
73
|
-
- 127.0.0.1
|
|
74
|
-
- ::1
|
|
75
|
-
|
|
76
|
-
# -
|
|
116
|
+
- 127.0.0.1
|
|
117
|
+
- "::1"
|
|
118
|
+
|
|
119
|
+
# Retry-After header value in seconds (default: 3600)
|
|
120
|
+
retry_after: 3600
|
|
121
|
+
|
|
122
|
+
# Paths that bypass maintenance mode (always accessible)
|
|
123
|
+
bypass_paths:
|
|
124
|
+
- /health
|
|
125
|
+
- /up
|
|
126
|
+
- /api/status
|
|
127
|
+
|
|
128
|
+
# Only apply maintenance to specific paths (empty = all paths)
|
|
129
|
+
# maintenance_paths:
|
|
130
|
+
# - /api/*
|
|
131
|
+
|
|
132
|
+
# Custom maintenance page (relative to app root)
|
|
133
|
+
# custom_page: public/maintenance.html
|
|
134
|
+
|
|
135
|
+
# Webhook URL for maintenance notifications
|
|
136
|
+
# webhook_url: https://hooks.slack.com/services/...
|
|
77
137
|
```
|
|
78
138
|
|
|
79
|
-
|
|
139
|
+
### DSL Configuration
|
|
80
140
|
|
|
81
|
-
|
|
141
|
+
Configure programmatically in `config/initializers/rails_maint.rb`:
|
|
82
142
|
|
|
143
|
+
```ruby
|
|
144
|
+
RailsMaint.configure do |config|
|
|
145
|
+
config.locale = 'en'
|
|
146
|
+
config.white_listed_ips = ['127.0.0.1', '::1']
|
|
147
|
+
config.retry_after = 3600
|
|
148
|
+
config.bypass_paths = ['/health', '/up']
|
|
149
|
+
config.maintenance_paths = []
|
|
150
|
+
config.custom_page_path = 'public/maintenance.html'
|
|
151
|
+
config.webhook_url = 'https://hooks.slack.com/services/...'
|
|
152
|
+
end
|
|
83
153
|
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
154
|
+
|
|
155
|
+
**Precedence:** YAML config > DSL config > defaults
|
|
156
|
+
|
|
157
|
+
## Route-Based Maintenance
|
|
158
|
+
|
|
159
|
+
### Bypass Paths
|
|
160
|
+
|
|
161
|
+
Keep certain endpoints accessible during maintenance:
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
bypass_paths:
|
|
165
|
+
- /health
|
|
166
|
+
- /up
|
|
167
|
+
- /api/status
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Maintenance Paths
|
|
171
|
+
|
|
172
|
+
Only show maintenance for specific paths (all others pass through):
|
|
173
|
+
|
|
174
|
+
```yaml
|
|
175
|
+
maintenance_paths:
|
|
176
|
+
- /api/*
|
|
90
177
|
```
|
|
91
178
|
|
|
179
|
+
Wildcard matching is supported with `/*` suffix for prefix matching. When both are configured, `bypass_paths` takes precedence.
|
|
180
|
+
|
|
181
|
+
## Scheduled Maintenance
|
|
182
|
+
|
|
183
|
+
Schedule a maintenance window that auto-deactivates:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
rails_maint enable --start="2024-06-01 10:00" --end="2024-06-01 12:00"
|
|
92
187
|
```
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
188
|
+
|
|
189
|
+
- Before `start_time`: requests pass through normally
|
|
190
|
+
- Between `start_time` and `end_time`: maintenance page is shown
|
|
191
|
+
- After `end_time`: requests pass through again
|
|
192
|
+
- The `Retry-After` header is automatically computed from the remaining time
|
|
193
|
+
|
|
194
|
+
## Custom Maintenance Page
|
|
195
|
+
|
|
196
|
+
Serve your own HTML file instead of the default template:
|
|
197
|
+
|
|
198
|
+
```yaml
|
|
199
|
+
custom_page: public/maintenance.html
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The file path is validated against path traversal attacks. If the file doesn't exist, the default template is used as a fallback.
|
|
203
|
+
|
|
204
|
+
## Webhook Notifications
|
|
205
|
+
|
|
206
|
+
Get notified when maintenance mode changes:
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
webhook_url: https://hooks.slack.com/services/T00/B00/xxx
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
The gem sends a POST request with a JSON payload:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"event": "maintenance.enabled",
|
|
217
|
+
"timestamp": "2024-06-01T10:00:00+00:00",
|
|
218
|
+
"gem": "rails_maint",
|
|
219
|
+
"version": "0.1.1"
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Events: `maintenance.enabled`, `maintenance.disabled`
|
|
224
|
+
|
|
225
|
+
## Language Support
|
|
226
|
+
|
|
227
|
+
Language files are stored in the `config/locales` directory. You can customize existing translations or add new languages:
|
|
228
|
+
|
|
229
|
+
```yaml
|
|
230
|
+
# config/locales/rails_maint.en.yml
|
|
231
|
+
en:
|
|
232
|
+
rails_maint:
|
|
233
|
+
title: "System Maintenance"
|
|
234
|
+
description: "Our system is currently being updated..."
|
|
235
|
+
estimated_time: "Estimated time: 1 hour"
|
|
236
|
+
remaining_time: "Estimated remaining time: %{time}"
|
|
99
237
|
```
|
|
100
238
|
|
|
101
239
|
## How IP Whitelist Works
|
|
102
240
|
|
|
103
241
|
- When maintenance mode is active, IPs in the whitelist can access the site normally
|
|
104
242
|
- All other IPs will see the maintenance page
|
|
105
|
-
-
|
|
106
|
-
-
|
|
243
|
+
- The gem uses `REMOTE_ADDR` for IP checking (not `X-Forwarded-For`, to prevent spoofing)
|
|
244
|
+
- IPs can be configured via both YAML and DSL (merged from both sources)
|
|
245
|
+
|
|
246
|
+
## Requirements
|
|
247
|
+
|
|
248
|
+
- Rails 6.0 or higher
|
|
249
|
+
- Ruby 3.0 or higher
|
|
107
250
|
|
|
108
251
|
## Development
|
|
109
252
|
|
|
110
253
|
1. Clone the repository
|
|
111
254
|
2. Install dependencies: `bundle install`
|
|
112
255
|
3. Run tests: `bundle exec rspec`
|
|
113
|
-
|
|
114
|
-
## Customizing the Maintenance Page
|
|
115
|
-
|
|
116
|
-
The maintenance page template can be customized by creating your own version in `public/maintenance.html`. The default template includes:
|
|
117
|
-
|
|
118
|
-
- Responsive design
|
|
119
|
-
- Animated maintenance icon
|
|
120
|
-
- Clean and modern layout
|
|
121
|
-
- Estimated time display
|
|
122
|
-
|
|
123
|
-
## Rails Version Support
|
|
124
|
-
|
|
125
|
-
- Rails 6.0 or higher
|
|
126
|
-
- Ruby 2.6 or higher
|
|
256
|
+
4. Run linter: `bundle exec rubocop`
|
|
127
257
|
|
|
128
258
|
## Contributing
|
|
129
259
|
|
|
@@ -133,32 +263,13 @@ The maintenance page template can be customized by creating your own version in
|
|
|
133
263
|
4. Push to the branch (`git push origin feature/amazing_feature`)
|
|
134
264
|
5. Create a Pull Request
|
|
135
265
|
|
|
136
|
-
## Best Practices
|
|
137
|
-
|
|
138
|
-
- Always test your changes
|
|
139
|
-
- Follow the Ruby Style Guide
|
|
140
|
-
- Write meaningful commit messages
|
|
141
|
-
- Add tests for new features
|
|
142
|
-
- Update documentation when needed
|
|
143
|
-
|
|
144
|
-
## Common Issues
|
|
145
|
-
|
|
146
|
-
### IP Whitelist Not Working
|
|
147
|
-
|
|
148
|
-
Make sure your IP is correctly added to the configuration file and you're not behind an unexpected proxy.
|
|
149
|
-
|
|
150
|
-
### Language Not Changing
|
|
151
|
-
|
|
152
|
-
Verify that:
|
|
153
|
-
1. The locale file exists
|
|
154
|
-
2. The locale is correctly set in the configuration
|
|
155
|
-
3. The Rails server was restarted after changes
|
|
156
|
-
|
|
157
266
|
## Security
|
|
158
267
|
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
268
|
+
- Uses `REMOTE_ADDR` for IP validation (prevents spoofing via `X-Forwarded-For`)
|
|
269
|
+
- HTML-escapes all translation values to prevent XSS
|
|
270
|
+
- Uses `YAML.safe_load_file` for safe deserialization
|
|
271
|
+
- Validates locale format with strict regex pattern
|
|
272
|
+
- Path traversal protection for custom maintenance pages and locale files
|
|
162
273
|
|
|
163
274
|
## License
|
|
164
275
|
|
|
@@ -175,4 +286,4 @@ Developed and maintained by [CodesCaptain](https://github.com/codescaptain)
|
|
|
175
286
|
|
|
176
287
|
## Changelog
|
|
177
288
|
|
|
178
|
-
See [CHANGELOG.md](CHANGELOG.md) for a list of changes.
|
|
289
|
+
See [CHANGELOG.md](CHANGELOG.md) for a list of changes.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module RailsMaint
|
|
6
|
+
module Generators
|
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
|
9
|
+
|
|
10
|
+
class_option :locale, type: :string, default: 'en',
|
|
11
|
+
desc: 'Set the language for maintenance page (e.g., en, tr)'
|
|
12
|
+
|
|
13
|
+
desc 'Installs RailsMaint configuration, locale, and initializer files'
|
|
14
|
+
|
|
15
|
+
def create_config_file
|
|
16
|
+
template 'rails_maint.yml.tt', 'config/rails_maint.yml'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def copy_locale_file
|
|
20
|
+
locale = options[:locale]
|
|
21
|
+
source = gem_locale_path(locale)
|
|
22
|
+
|
|
23
|
+
unless File.exist?(source)
|
|
24
|
+
say "Locale '#{locale}' is not supported. Falling back to 'en'.", :red
|
|
25
|
+
locale = 'en'
|
|
26
|
+
source = gem_locale_path(locale)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
create_file "config/locales/rails_maint.#{locale}.yml", File.read(source)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def create_initializer
|
|
33
|
+
template 'initializer.rb.tt', 'config/initializers/rails_maint.rb'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def show_post_install_message
|
|
37
|
+
say ''
|
|
38
|
+
say 'RailsMaint installed successfully!', :green
|
|
39
|
+
say ''
|
|
40
|
+
say 'Usage:'
|
|
41
|
+
say ' rails_maint enable # Enable maintenance mode'
|
|
42
|
+
say ' rails_maint disable # Disable maintenance mode'
|
|
43
|
+
say ' rails_maint status # Show maintenance status'
|
|
44
|
+
say ''
|
|
45
|
+
say 'Configuration: config/rails_maint.yml'
|
|
46
|
+
say 'Initializer: config/initializers/rails_maint.rb'
|
|
47
|
+
say ''
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def gem_locale_path(locale)
|
|
53
|
+
File.expand_path("../../../rails_maint/assets/locales/#{locale}.yml", __dir__)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# RailsMaint Configuration
|
|
4
|
+
# Middleware is automatically registered via Railtie.
|
|
5
|
+
# Settings here override defaults; YAML config (config/rails_maint.yml) takes precedence.
|
|
6
|
+
|
|
7
|
+
RailsMaint.configure do |config|
|
|
8
|
+
# Locale for the maintenance page (default: 'en')
|
|
9
|
+
# config.locale = '<%= options[:locale] %>'
|
|
10
|
+
|
|
11
|
+
# IP addresses that bypass maintenance mode
|
|
12
|
+
# config.white_listed_ips = ['127.0.0.1', '::1']
|
|
13
|
+
|
|
14
|
+
# Path to the maintenance flag file
|
|
15
|
+
# config.maintenance_file_path = 'tmp/maintenance_mode.txt'
|
|
16
|
+
|
|
17
|
+
# Retry-After header value in seconds
|
|
18
|
+
# config.retry_after = 3600
|
|
19
|
+
|
|
20
|
+
# Paths that always bypass maintenance mode
|
|
21
|
+
# config.bypass_paths = ['/health', '/up']
|
|
22
|
+
|
|
23
|
+
# Only apply maintenance to specific paths (empty = all paths)
|
|
24
|
+
# config.maintenance_paths = []
|
|
25
|
+
|
|
26
|
+
# Custom maintenance page path (relative to app root)
|
|
27
|
+
# config.custom_page_path = 'public/maintenance.html'
|
|
28
|
+
|
|
29
|
+
# Webhook URL for maintenance event notifications
|
|
30
|
+
# config.webhook_url = 'https://hooks.slack.com/services/...'
|
|
31
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# RailsMaint Configuration
|
|
2
|
+
# -----------------------
|
|
3
|
+
|
|
4
|
+
# Default locale for maintenance page
|
|
5
|
+
locale: <%= options[:locale] %>
|
|
6
|
+
|
|
7
|
+
# IP addresses that can access the application during maintenance
|
|
8
|
+
white_listed_ips:
|
|
9
|
+
- 127.0.0.1
|
|
10
|
+
- "::1"
|
|
11
|
+
# Add more IPs below
|
|
12
|
+
# - 192.168.1.1
|
|
13
|
+
|
|
14
|
+
# Retry-After header value in seconds (default: 3600)
|
|
15
|
+
# retry_after: 3600
|
|
16
|
+
|
|
17
|
+
# Paths that bypass maintenance mode (always accessible)
|
|
18
|
+
# bypass_paths:
|
|
19
|
+
# - /health
|
|
20
|
+
# - /up
|
|
21
|
+
# - /api/status
|
|
22
|
+
|
|
23
|
+
# Paths that are affected by maintenance mode (all others pass through)
|
|
24
|
+
# When empty, all paths are affected
|
|
25
|
+
# maintenance_paths:
|
|
26
|
+
# - /api/*
|
|
27
|
+
|
|
28
|
+
# Custom maintenance page (relative to app root)
|
|
29
|
+
# custom_page: public/maintenance.html
|
|
30
|
+
|
|
31
|
+
# Webhook URL for maintenance notifications (e.g., Slack incoming webhook)
|
|
32
|
+
# webhook_url: https://hooks.slack.com/services/...
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsMaint
|
|
4
|
+
class StatusPrinter
|
|
5
|
+
def print
|
|
6
|
+
config = ConfigLoader.load
|
|
7
|
+
print_maintenance_status
|
|
8
|
+
puts ''
|
|
9
|
+
print_config_status(config)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def print_maintenance_status
|
|
15
|
+
maintenance_file = 'tmp/maintenance_mode.txt'
|
|
16
|
+
|
|
17
|
+
unless File.exist?(maintenance_file)
|
|
18
|
+
puts 'Status: DISABLED'
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
schedule = RailsMaint::Schedule.load(maintenance_file)
|
|
23
|
+
puts schedule.active? ? 'Status: ENABLED' : 'Status: ENABLED (not currently active — outside scheduled window)'
|
|
24
|
+
print_schedule_details(schedule)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def print_schedule_details(schedule)
|
|
28
|
+
puts " Enabled at: #{schedule.enabled_at}" if schedule.enabled_at
|
|
29
|
+
puts " Start time: #{schedule.start_time}" if schedule.start_time
|
|
30
|
+
puts " End time: #{schedule.end_time}" if schedule.end_time
|
|
31
|
+
|
|
32
|
+
return unless schedule.end_time
|
|
33
|
+
|
|
34
|
+
remaining = schedule.seconds_until_end
|
|
35
|
+
puts " Remaining: #{remaining}s" if remaining
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def print_config_status(config)
|
|
39
|
+
puts "Locale: #{config['locale'] || 'en'}"
|
|
40
|
+
print_list('Whitelisted IPs', config['white_listed_ips'])
|
|
41
|
+
print_list('Bypass paths', config['bypass_paths'])
|
|
42
|
+
puts "Retry-After: #{config['retry_after'] || 3600}s"
|
|
43
|
+
puts "Custom page: #{config['custom_page'] || 'none'}"
|
|
44
|
+
puts "Webhook URL: #{config['webhook_url'] || 'none'}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def print_list(label, items)
|
|
48
|
+
items ||= []
|
|
49
|
+
puts "#{label}: #{items.empty? ? 'none' : items.join(', ')}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|