capistrano-ops 0.2.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +121 -29
  3. data/lib/capistrano/ops/backup/helper.rb +56 -0
  4. data/lib/capistrano/ops/{capistrano/v3/tasks/backup → backup/tasks}/database/create.rake +1 -2
  5. data/lib/capistrano/ops/{capistrano/v3/tasks/backup → backup/tasks}/database/pull.rake +1 -2
  6. data/lib/capistrano/ops/{capistrano/v3/tasks/backup → backup/tasks}/storage/create.rake +1 -2
  7. data/lib/capistrano/ops/{capistrano/v3/tasks/backup → backup/tasks}/storage/pull.rake +1 -2
  8. data/lib/capistrano/ops/backup.rb +14 -4
  9. data/lib/capistrano/ops/capistrano.rb +8 -13
  10. data/lib/capistrano/ops/figaro_yml/helpers.rb +184 -0
  11. data/lib/capistrano/ops/figaro_yml/paths.rb +19 -0
  12. data/lib/capistrano/ops/figaro_yml/tasks/backup.rake +26 -0
  13. data/lib/capistrano/ops/figaro_yml/tasks/check.rake +12 -0
  14. data/lib/capistrano/ops/figaro_yml/tasks/check_config_present.rake +12 -0
  15. data/lib/capistrano/ops/figaro_yml/tasks/check_figaro_file_exists.rake +12 -0
  16. data/lib/capistrano/ops/figaro_yml/tasks/check_git_tracking.rake +12 -0
  17. data/lib/capistrano/ops/{capistrano/v3/tasks/figaro_yml → figaro_yml/tasks}/compare.rake +10 -19
  18. data/lib/capistrano/ops/figaro_yml/tasks/create_local.rake +27 -0
  19. data/lib/capistrano/ops/figaro_yml/tasks/figaro_yml_symlink.rake +10 -0
  20. data/lib/capistrano/ops/figaro_yml/tasks/get.rake +45 -0
  21. data/lib/capistrano/ops/figaro_yml/tasks/get_stage.rake +15 -0
  22. data/lib/capistrano/ops/figaro_yml/tasks/load.rake +10 -0
  23. data/lib/capistrano/ops/figaro_yml/tasks/rollback.rake +22 -0
  24. data/lib/capistrano/ops/figaro_yml/tasks/setup.rake +16 -0
  25. data/lib/capistrano/ops/{capistrano/v3/tasks/figaro_yml → figaro_yml/tasks}/sort_local.rake +2 -4
  26. data/lib/capistrano/ops/figaro_yml.rb +29 -0
  27. data/lib/capistrano/ops/helper.rb +14 -0
  28. data/lib/capistrano/ops/invoke/tasks/invoke.rake +25 -0
  29. data/lib/capistrano/ops/invoke.rb +3 -0
  30. data/lib/capistrano/ops/logrotate/helpers.rb +50 -0
  31. data/lib/capistrano/ops/logrotate/paths.rb +47 -0
  32. data/lib/capistrano/ops/{capistrano/v3/tasks/logrotate → logrotate/tasks}/check.rake +3 -5
  33. data/lib/capistrano/ops/{capistrano/v3/tasks/logrotate → logrotate/tasks}/disable.rake +2 -5
  34. data/lib/capistrano/ops/logrotate/tasks/enable.rake +28 -0
  35. data/lib/capistrano/ops/logrotate/tasks/load.rake +10 -0
  36. data/lib/capistrano/ops/logrotate.rb +19 -0
  37. data/lib/capistrano/ops/logs/helpers.rb +16 -0
  38. data/lib/capistrano/ops/logs/paths.rb +23 -0
  39. data/lib/capistrano/ops/logs/tasks/load.rake +9 -0
  40. data/lib/capistrano/ops/logs/tasks/rails.rake +18 -0
  41. data/lib/capistrano/ops/logs/tasks/sidekiq.rake +42 -0
  42. data/lib/capistrano/ops/logs.rb +18 -0
  43. data/lib/capistrano/ops/{backup → rails/lib/backup}/s3.rb +1 -1
  44. data/lib/capistrano/ops/rails/lib/backup.rb +6 -0
  45. data/lib/capistrano/ops/rails/lib/notification.rb +9 -0
  46. data/lib/capistrano/ops/rails/lib/railtie.rb +17 -0
  47. data/lib/capistrano/ops/{tasks → rails/lib/tasks}/pg/postgres_helper.rb +1 -1
  48. data/lib/capistrano/ops/version.rb +1 -1
  49. data/lib/capistrano/ops/{capistrano/v3/tasks/whenever.rake → whenever/tasks/show_crontab.rake} +1 -3
  50. data/lib/capistrano/ops/whenever.rb +17 -0
  51. data/lib/capistrano/ops/wkhtmltopdf/helpers.rb +50 -0
  52. data/lib/capistrano/ops/wkhtmltopdf/tasks/setup.rake +17 -0
  53. data/lib/capistrano/ops/wkhtmltopdf.rb +17 -1
  54. data/lib/capistrano/ops.rb +4 -3
  55. metadata +60 -36
  56. data/lib/capistrano/ops/capistrano/tasks/wkhtmltopdf.rake +0 -48
  57. data/lib/capistrano/ops/capistrano/v3/tasks/backup/backup_helper.rb +0 -50
  58. data/lib/capistrano/ops/capistrano/v3/tasks/figaro_yml/figaro_yaml_helper.rb +0 -74
  59. data/lib/capistrano/ops/capistrano/v3/tasks/figaro_yml/get.rake +0 -68
  60. data/lib/capistrano/ops/capistrano/v3/tasks/figaro_yml/get_stage.rake +0 -13
  61. data/lib/capistrano/ops/capistrano/v3/tasks/figaro_yml.rb +0 -3
  62. data/lib/capistrano/ops/capistrano/v3/tasks/invoke.rake +0 -23
  63. data/lib/capistrano/ops/capistrano/v3/tasks/logrotate/enable.rake +0 -24
  64. data/lib/capistrano/ops/capistrano/v3/tasks/logrotate/logrotate_helper.rb +0 -68
  65. data/lib/capistrano/ops/capistrano/v3/tasks/logs/rails.rake +0 -16
  66. data/lib/capistrano/ops/notification.rb +0 -9
  67. data/lib/capistrano/ops/railtie.rb +0 -15
  68. /data/lib/capistrano/ops/{capistrano/v3/tasks/logrotate → logrotate/tasks}/templates/logrotate.conf.erb +0 -0
  69. /data/lib/capistrano/ops/{capistrano/v3/tasks/logrotate → logrotate/tasks}/templates/schedule.rb.erb +0 -0
  70. /data/lib/capistrano/ops/{backup → rails/lib/backup}/api.rb +0 -0
  71. /data/lib/capistrano/ops/{backup → rails/lib/backup}/s3_helper.rb +0 -0
  72. /data/lib/capistrano/ops/{notification → rails/lib/notification}/api.rb +0 -0
  73. /data/lib/capistrano/ops/{notification → rails/lib/notification}/slack.rb +0 -0
  74. /data/lib/capistrano/ops/{notification → rails/lib/notification}/webhook.rb +0 -0
  75. /data/lib/capistrano/ops/{tasks → rails/lib/tasks}/pg/dump.rake +0 -0
  76. /data/lib/capistrano/ops/{tasks → rails/lib/tasks}/pg/remove_old_dumps.rake +0 -0
  77. /data/lib/capistrano/ops/{tasks → rails/lib/tasks}/storage/backup.rake +0 -0
  78. /data/lib/capistrano/ops/{tasks → rails/lib/tasks}/storage/remove_old_backups.rake +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72b073b9c2ecb5026ab9f56c3953f9bd664e5537087a07c7a22cd390a69fe7da
4
- data.tar.gz: 60e5b8b52641c59bd1c6c3ec1b99aef79e90269a2ca11deb23b39283348b00e1
3
+ metadata.gz: '03096171fc878362361e6d4f5c525db4e28fc2acfe10f7b2dcb15852ed8e6b99'
4
+ data.tar.gz: f50d51428cf175cff22f739373f5ce81e79982cfcb1e484323586fc181834aa8
5
5
  SHA512:
6
- metadata.gz: 6bff0e67cad4a819dd93400b7de6b8acbec6642df2bc15e569cfd3a3a2ae6ec38a70f38eb09483f90b335cc423da5ef3ef9e2a912b036fe576911b35f26f1bfa
7
- data.tar.gz: eb67fd7c492534f4e4086327631ea52c391802f76f3ac17b17525313483eff0ec8e54441a08f045a78d75714ab4fc9691a71de47706ffa7a03ce56786b85900d
6
+ metadata.gz: 0d32c02dfc012ed82cdbe2adf0a968d19eca1332661a1765158a1be92b12bd45e63755a0533a52b814b7d383a6124d436fd3d10b85907d262deb9207437d177e
7
+ data.tar.gz: 404850e368cddef350bf54ea6b3e681fa123029fa2a0bc7dfb74786ebc16e5c948e8fec1d0e182bc5c99d83fa073d4c26e5b3a7d61d63a3cd272f5b4ea8ee474
data/README.md CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  The capistrano-ops gem is a valuable library, tailor-made for Rails DevOps professionals, offering an array of beneficial scripts to streamline and enhance operations with Capistrano. The focus is on seamless integration with Capistrano version 3 and above.
4
4
 
5
+ ## Table of Contents
6
+
7
+ <details>
8
+ <summary>Click to expand</summary>
9
+
10
+ - [Main Features](#main-features)
11
+ - [Requirements](#requirements)
12
+ - [Installation](#installation)
13
+ - [Script overview](#script-overview)
14
+ - [Usage](#usage)
15
+ - [Optional Settings for backup task](#optional-settings-for-backup-task)
16
+ - [use with whenever/capistrano](#use-with-whenevercapistrano)
17
+ - [Configuration](#configuration)
18
+ - [Slack integration](#slack-integration)
19
+ - [Webhook integration](#webhook-integration)
20
+ - [Notification level](#notification-level)
21
+ - [Backups](#backups)
22
+ - [Backup provider](#backup-provider)
23
+ - [Logrotate](#logrotate)
24
+ - [Configuration](#configuration-1)
25
+ - [Usage](#usage-1)
26
+ - [Wkhtmltopdf Setup](#wkhtmltopdf-setup)
27
+ - [Contributing](#contributing)
28
+ - [License](#license)
29
+
30
+ </details>
31
+
5
32
  ## Main Features:
6
33
 
7
34
  🗃️ **Database and Storage Backups:**
@@ -11,12 +38,16 @@ The capistrano-ops gem is a valuable library, tailor-made for Rails DevOps profe
11
38
 
12
39
  🛠️ **Configuration Management:**
13
40
 
14
- - Compare application.yml files between local and server environments using figaro_yml:compare.
15
- - Fetch server environment variables set via Figaro with figaro_yml:get.
41
+ - Compare `application.yml` files between local and server environments using `figaro_yml:compare`.
42
+ - Fetch server environment variables set via Figaro with `figaro_yml:get`.
43
+ - Copy local `application.yml` to the server with `figaro_yml:setup`. This task automatically triggers `figaro_yml:backup` before proceeding.
44
+ - Create a backup of the server's `application.yml` with `figaro_yml:backup`. This is automatically executed before `figaro_yml:setup` to ensure a recovery point is available.
45
+ - Roll back to the previous `application.yml` on the server using `figaro_yml:rollback`. This can be used to quickly revert changes made by `figaro_yml:setup` if needed.
16
46
 
17
47
  📜 **Logging and Task Management:**
18
48
 
19
49
  - Real-time viewing of Rails server logs.
50
+ - Real-time viewing of sidekiq logs.
20
51
  - Showcase the server app's crontab generated with the 'whenever' gem.
21
52
  - Ability to invoke server-specific rake tasks.
22
53
 
@@ -43,16 +74,20 @@ The capistrano-ops gem is a valuable library, tailor-made for Rails DevOps profe
43
74
 
44
75
  - S3 and other S3-compatible services are supported to ensure your data remains secure and accessible.
45
76
 
77
+ [↑](#)
78
+
46
79
  ## Requirements
47
80
 
48
81
  ```ruby
49
82
  'capistrano', '~> 3.0'
50
- 'whenever'
51
- 'capistrano-figaro-yml'
83
+ 'whenever' # for scheduling tasks
84
+ 'figaro' # for environment variables if you use figaro_yml tasks
52
85
 
53
86
  # hint: if you use other aws-sdk gems, its possible that you have to update them too
54
87
  ```
55
88
 
89
+ [↑](#)
90
+
56
91
  ## Installation
57
92
 
58
93
  Add the gem to your `Gemfile` after setting up Capistrano
@@ -74,35 +109,64 @@ Then `bundle` and add it to your `Capfile`
74
109
  require 'capistrano/ops'
75
110
  ```
76
111
 
112
+ or if you want to use only specific tasks one or more of the following:
113
+
114
+ ```ruby
115
+ # Capfile
116
+
117
+
118
+ require 'capistrano/ops/backup' # backup:database:create, backup:database:pull, backup:storage:create, backup:storage:pull
119
+ require 'capistrano/ops/figaro_yml' # figaro_yml:compare, figaro_yml:get, figaro_yml:setup, figaro_yml:backup, figaro_yml:rollback
120
+ require 'capistrano/ops/invoke' # invoke:rake
121
+ require 'capistrano/ops/logrotate' # logrotate:enable, logrotate:disable, logrotate:check
122
+ require 'capistrano/ops/logs' # logs:rails, logs:sidekiq, logs:sidekiq:info, logs:sidekiq:error
123
+ require 'capistrano/ops/whenever' # whenever:show_crontab
124
+
125
+ # optionally and not included in require 'capistrano/ops'
126
+ require 'capistrano/ops/wkhtmltopdf' # setup wkhtmltopdf-binary on server
127
+ ```
128
+
77
129
  and `initializers`
78
130
 
79
131
  ```ruby
80
132
  # initializers/capistrano_ops.rb
133
+
134
+ # needed for the backup tasks
81
135
  require 'capistrano/ops'
82
136
  ```
83
137
 
138
+ [↑](#)
139
+
84
140
  ## Script overview
85
141
 
86
- | Script | Description |
87
- | ------------------------------------------------ | ----------------------------------------------------------------- |
88
- | `cap <environment> backup:create` | creates backup of postgres database on the server (deprecated) |
89
- | `cap <environment> backup:pull` | download latest postgres backup from server (deprecated) |
90
- | `cap <environment> backup:database:create` | creates backup of postgres database on the server |
91
- | `cap <environment> backup:database:pull` | download latest postgres backup from server |
92
- | `cap <environment> backup:storage:create` | creates backup of storage on the server |
93
- | `cap <environment> backup:storage:pull` | download latest storage backup from server |
94
- | `cap <environment> figaro_yml:compare` | compare local application.yml with server application.yml |
95
- | `cap <environment> figaro_yml:get` | shows env vars from server application.yml configured thru figaro |
96
- | `cap <environment> logs:rails` | display server log live |
97
- | `cap <environment> whenever:show_crontab` | display server app crontab generated with whenever |
98
- | `cap <environment> invoke:rake TASK=<your:task>` | invoke rake task on server |
99
- | `cap <environment> logrotate:enable` | enable logrotate for logfiles on server |
100
- | `cap <environment> logrotate:disable` | disable logrotate for logfiles on server |
101
- | `cap <environment> logrotate:check` | show logrotate status for logfiles on server |
102
- | `rake pg:dump` | creates postgres database backup |
103
- | `rake pg:remove_old_dumps` | remove old postgres backups |
104
- | `rake storage:backup` | creates backup of storage |
105
- | `rake storage:remove_old_backups` | remove old storage backups |
142
+ | Script | Description |
143
+ | ------------------------------------------------ | ------------------------------------------------------------------------ |
144
+ | `cap <environment> backup:create` | creates backup of postgres database on the server (removed since v1.0.0) |
145
+ | `cap <environment> backup:pull` | download latest postgres backup from server (removed since v1.0.0) |
146
+ | `cap <environment> backup:database:create` | creates backup of postgres database on the server |
147
+ | `cap <environment> backup:database:pull` | download latest postgres backup from server |
148
+ | `cap <environment> backup:storage:create` | creates backup of storage on the server |
149
+ | `cap <environment> backup:storage:pull` | download latest storage backup from server |
150
+ | `cap <environment> figaro_yml:setup` | copy local application.yml to server application.yml |
151
+ | `cap <environment> figaro_yml:compare` | compare local application.yml with server application.yml |
152
+ | `cap <environment> figaro_yml:get` | shows env vars from server application.yml configured thru figaro |
153
+ | `cap <environment> figaro_yml:backup` | creates backup of server application.yml (keeps last 5 versions) |
154
+ | `cap <environment> figaro_yml:rollback` | rollback server application.yml to previous version |
155
+ | `cap <environment> logs:rails` | display server log live |
156
+ | `cap <environment> logs:sidekiq` | display sidekiq log live |
157
+ | `cap <environment> logs:sidekiq:info` | display sidekiq info log live |
158
+ | `cap <environment> logs:sidekiq:error` | display sidekiq error log live |
159
+ | `cap <environment> whenever:show_crontab` | display server app crontab generated with whenever |
160
+ | `cap <environment> invoke:rake TASK=<your:task>` | invoke rake task on server |
161
+ | `cap <environment> logrotate:enable` | enable logrotate for logfiles on server |
162
+ | `cap <environment> logrotate:disable` | disable logrotate for logfiles on server |
163
+ | `cap <environment> logrotate:check` | show logrotate status for logfiles on server |
164
+ | `rake pg:dump` | creates postgres database backup |
165
+ | `rake pg:remove_old_dumps` | remove old postgres backups |
166
+ | `rake storage:backup` | creates backup of storage |
167
+ | `rake storage:remove_old_backups` | remove old storage backups |
168
+
169
+ [↑](#)
106
170
 
107
171
  ## Usage
108
172
 
@@ -118,6 +182,8 @@ production:
118
182
  port: database_port
119
183
  ```
120
184
 
185
+ [↑](#)
186
+
121
187
  ### Optional Settings for backup task
122
188
 
123
189
  | env | description | type/options |
@@ -127,7 +193,7 @@ production:
127
193
  | NUMBER_OF_EXTERNAL_BACKUPS | number of backups to keep externally (default: nil) | `number` |
128
194
  | BACKUPS_ENABLED | enable/disable backup task (default: Rails.env == 'production') | `boolean` |
129
195
  | EXTERNAL_BACKUP_ENABLED | enable/disable external backup (default: false) (only if 'BACKUPS_ENABLED', needs additional setup) | `boolean` |
130
- | KEEP_LOCAL_STORAGE_BACKUPS | keep local storage backups (default: Rails.env == 'production') | `boolean` |
196
+ | KEEP_LOCAL_STORAGE_BACKUPS | keep local storage backups (default: true) | `boolean` |
131
197
  | DEFAULT_URL | notification message title (default: "#{database} Backup") | `string` |
132
198
  | NOTIFICATION_TYPE | for notification (default: nil) | `string` (`webhook`/`slack`) |
133
199
  | NOTIFICATION_LEVEL | for notification (default: nil) | `string` (`info`/`error`) |
@@ -142,6 +208,8 @@ production:
142
208
  | S3_BACKUP_SECRET | S3 secret key for backups | `string` |
143
209
  | S3_BACKUP_ENDPOINT | S3 endpoint for backups (optional, used for other S3 compatible services) | `string` |
144
210
 
211
+ [↑](#)
212
+
145
213
  ### use with whenever/capistrano
146
214
 
147
215
  install whenever gem and add this to your schedule.rb
@@ -170,6 +238,8 @@ add this to your capfile
170
238
  require 'whenever/capistrano'
171
239
  ```
172
240
 
241
+ [↑](#)
242
+
173
243
  ## Configuration
174
244
 
175
245
  You can optionally specify the capistrano roles for the rake task (Defaults to `:app`):
@@ -179,6 +249,8 @@ You can optionally specify the capistrano roles for the rake task (Defaults to `
179
249
  set :rake_roles, %i[db app]
180
250
  ```
181
251
 
252
+ [↑](#)
253
+
182
254
  ## Slack integration
183
255
 
184
256
  if you want to use slack integration you have to add this to your `application.yml`
@@ -189,6 +261,8 @@ SLACK_SECRET: '<your-slack-secret>'
189
261
  SLACK_CHANNEL: '<your-slack-channel>'
190
262
  ```
191
263
 
264
+ [↑](#)
265
+
192
266
  ## Webhook integration
193
267
 
194
268
  if you want to use webhook integration you have to add this to your `application.yml`
@@ -199,6 +273,8 @@ WEBHOOK_URL: '<your-webhook-url>'
199
273
  WEBHOOK_SECRET: '<your-webhook-secret>'
200
274
  ```
201
275
 
276
+ [↑](#)
277
+
202
278
  ## Notification level
203
279
 
204
280
  if you want to use notification level you have to add this to your `application.yml`
@@ -207,6 +283,8 @@ if you want to use notification level you have to add this to your `application.
207
283
  NOTIFICATION_LEVEL: 'info' # default is 'error'
208
284
  ```
209
285
 
286
+ [↑](#)
287
+
210
288
  ## Backups
211
289
 
212
290
  if you want to configure the number of backups you have to add this to your `application.yml`
@@ -222,6 +300,8 @@ NUMBER_OF_LOCAL_BACKUPS: 7 # default is nil (local)
222
300
  NUMBER_OF_EXTERNAL_BACKUPS: 7 # default is nil (local)
223
301
  ```
224
302
 
303
+ [↑](#)
304
+
225
305
  ### Backup provider
226
306
 
227
307
  if you want to use an external backup provider you have to add this to your `application.yml`
@@ -235,6 +315,8 @@ S3_BACKUP_SECRET: '<your-s3-secret>'
235
315
  S3_BACKUP_ENDPOINT: '<your-s3-endpoint>' # optional, used for other S3 compatible services
236
316
  ```
237
317
 
318
+ [↑](#)
319
+
238
320
  ## Logrotate
239
321
 
240
322
  Logrotate is a utility designed for administrators who manage servers producing a high volume of log files to help them save some disk space as well as to avoid a potential risk making a system unresponsive due to the lack of disk space.
@@ -244,6 +326,7 @@ The capistrano-ops gem provides a set of tasks to manage logrotate on your serve
244
326
  - `cap <environment> logrotate:enable` - This task enables logrotate for logfiles on the server.
245
327
  - `cap <environment> logrotate:disable` - This task disables logrotate for logfiles on the server.
246
328
  - `cap <environment> logrotate:check` - This task shows the logrotate status for logfiles on the server.
329
+ [↑](#)
247
330
 
248
331
  ### Configuration
249
332
 
@@ -254,6 +337,8 @@ You can optionally specify the logrotate configuration file path (Defaults to `/
254
337
  set :logrotate_path, '/path/to/your/logrotate.conf'
255
338
  ```
256
339
 
340
+ [↑](#)
341
+
257
342
  ### Usage
258
343
 
259
344
  To use logrotate, you need to have it installed on your server. If it's not installed, you can install it using the package manager of your system. For example, on Ubuntu, you can install it using apt:
@@ -263,6 +348,7 @@ sudo apt-get install logrotate
263
348
  ```
264
349
 
265
350
  Once logrotate is installed, you can use the capistrano-ops tasks to manage it.
351
+ [↑](#)
266
352
 
267
353
  ## Wkhtmltopdf Setup
268
354
 
@@ -292,6 +378,8 @@ To use this script, include it in your Capistrano tasks and it will automaticall
292
378
  require 'capistrano/ops/wkhtmltopdf'
293
379
  ```
294
380
 
381
+ [↑](#)
382
+
295
383
  ## Contributing
296
384
 
297
385
  1. Fork it ( https://github.com/zauberware/capistrano-ops/fork )
@@ -300,14 +388,18 @@ require 'capistrano/ops/wkhtmltopdf'
300
388
  4. Push to the branch (`git push origin my-new-feature`)
301
389
  5. Create a new Pull Request
302
390
 
391
+ [↑](#)
392
+
303
393
  ## License
304
394
 
305
395
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
306
396
 
307
- ```
397
+ This gem contains code/snippets from the following sources:
308
398
 
309
- ```
399
+ - [capistrano-figaro-yml](https://github.com/ChouAndy/capistrano-figaro-yml) by Andy Chou under the [MIT License](https://github.com/chouandy/capistrano-figaro-yml/blob/master/LICENSE.md)
400
+ - [capistranorb documentation](https://capistranorb.com/documentation/tasks/rails/)
310
401
 
311
- ```
402
+ props to the original authors 🎉
403
+ check out their work too!
312
404
 
313
- ```
405
+ [↑](#)
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module Ops
5
+ module Backup
6
+ module Helper
7
+ def backup_file_name(type)
8
+ regex = type == 'storage' ? "'.{0,}\.tar.gz'" : "'.{0,}\.dump'"
9
+ @backup_file_name ||= capture "cd #{shared_path}/backups && ls -lt | grep -E -i #{regex} | head -n 1 | awk '{print $9}'"
10
+ end
11
+
12
+ def backup_file_size
13
+ @backup_file_size ||= capture "cd #{shared_path}/backups && wc -c #{@backup_file_name} | awk '{print $1}'"
14
+ end
15
+
16
+ def download_backup(backup_file, type)
17
+ puts "Downloading #{type} backup"
18
+ download! "#{shared_path}/backups/#{backup_file}", backup_file
19
+ puts "Download finished\nDeleting temporary backup..."
20
+ cleanup_backup(backup_file, "Download finished\nDeleting temporary backup...")
21
+ end
22
+
23
+ def cleanup_backup(backup_file, message)
24
+ puts message
25
+ execute "cd #{shared_path}/backups && rm #{backup_file}"
26
+ puts 'Temporary backup deleted'
27
+ end
28
+
29
+ def question(question, default = 'n', &block)
30
+ print "#{question} #{default.downcase == 'n' ? '(y/N)' : '(Y/n)'}: "
31
+ input = $stdin.gets.strip.downcase
32
+ answer = (input.empty? ? default : input).downcase.to_s
33
+
34
+ if %w[y n].include?(answer)
35
+ yield(answer == 'y')
36
+ else
37
+ question(question, default, &block)
38
+ end
39
+ end
40
+
41
+ def prepare_env
42
+ @env = "RAILS_ENV=#{fetch(:stage)}"
43
+ @path_cmd = "PATH=$HOME/.rbenv/versions/#{RUBY_VERSION}/bin:$PATH"
44
+ @test_command = "cd #{release_path} && #{@path_cmd} && #{@env}"
45
+ end
46
+
47
+ def size_str(size)
48
+ units = %w[B KB MB GB TB]
49
+ e = (Math.log(size) / Math.log(1024)).floor
50
+ s = format('%.2f', size.to_f / 1024**e)
51
+ s.sub(/\.?0*$/, units[e])
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../backup_helper'
4
3
  namespace :backup do
5
4
  namespace :database do
6
- include BackupHelper
5
+ include Capistrano::Ops::Backup::Helper
7
6
  # Default to :app role
8
7
  rake_roles = fetch(:rake_roles, :app)
9
8
 
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../backup_helper'
4
3
  namespace :backup do
5
4
  namespace :database do
6
- include BackupHelper
5
+ include Capistrano::Ops::Backup::Helper
7
6
  # Default to :app role
8
7
  rake_roles = fetch(:rake_roles, :app)
9
8
 
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../backup_helper'
4
3
  namespace :backup do
5
4
  namespace :storage do
6
- include BackupHelper
5
+ include Capistrano::Ops::Backup::Helper
7
6
  # Default to :app role
8
7
  rake_roles = fetch(:rake_roles, :app)
9
8
 
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../backup_helper'
4
3
  namespace :backup do
5
4
  namespace :storage do
6
- include BackupHelper
5
+ include Capistrano::Ops::Backup::Helper
7
6
  # Default to :app role
8
7
  rake_roles = fetch(:rake_roles, :app)
9
8
  desc 'pull latest storage dump from server to local'
@@ -1,8 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'capistrano/ops/backup/api'
4
- require 'capistrano/ops/backup/s3'
3
+ require 'capistrano/ops/helper'
4
+ require 'capistrano/ops/backup/helper'
5
5
 
6
- module Backup
7
- class Error < StandardError; end
6
+ module TaskLoader
7
+ extend Capistrano::Ops::Helper
8
+
9
+ def self.load_tasks_if_gem_present(gem_name, task_path, warning_message)
10
+ if gem_in_gemfile?(gem_name)
11
+ Dir.glob("#{File.expand_path(__dir__)}/#{task_path}/**/*.rake").each { |f| load f }
12
+ else
13
+ puts warning_message
14
+ end
15
+ end
8
16
  end
17
+
18
+ TaskLoader.load_tasks_if_gem_present('rails', 'backup/tasks', 'WARNING: Gemfile does not include rails gem which is required for backup tasks')
@@ -1,18 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'capistrano/version'
4
-
5
- if defined?(Capistrano::VERSION) && Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new('3.0.0')
6
- load File.expand_path('capistrano/v3/tasks/whenever.rake', __dir__)
7
- load File.expand_path('capistrano/v3/tasks/backup.rake', __dir__)
8
- load File.expand_path('capistrano/v3/tasks/figaro_yml.rb', __dir__)
9
-
10
- load File.expand_path('capistrano/v3/tasks/invoke.rake', __dir__)
11
- path = File.expand_path(__dir__)
12
- Dir.glob("#{path}/capistrano/v3/tasks/backup/**/*.rake").each { |f| load f }
13
- Dir.glob("#{path}/capistrano/v3/tasks/logrotate/**/*.rake").each { |f| load f }
14
- Dir.glob("#{path}/capistrano/v3/tasks/logs/**/*.rake").each { |f| load f }
15
-
16
- else
4
+ require 'capistrano/ops/whenever'
5
+ require 'capistrano/ops/figaro_yml'
6
+ require 'capistrano/ops/logrotate'
7
+ require 'capistrano/ops/logs'
8
+ require 'capistrano/ops/invoke'
9
+ require 'capistrano/ops/backup'
10
+
11
+ unless defined?(Capistrano::VERSION) && Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new('3.0.0')
17
12
  puts 'Capistrano 3 is required to use this gem'
18
13
  end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ # rubocop:disable Metrics/ModuleLength
6
+ module Capistrano
7
+ module Ops
8
+ module FigaroYml
9
+ module Helpers
10
+ def remote_file_exists?
11
+ test("[ -f #{figaro_yml_remote_path} ]")
12
+ end
13
+
14
+ def remote_backup_exists?
15
+ count_remote_files.positive?
16
+ end
17
+
18
+ def rollback_remote_backup
19
+ latest_backup = latest_remote_backup
20
+ puts "mv #{figaro_yml_remote_path.parent.join(latest_backup)} #{figaro_yml_remote_path}"
21
+ execute :mv, figaro_yml_remote_path.parent.join(latest_backup), figaro_yml_remote_path
22
+ execute :ls, '-l', figaro_yml_remote_path.parent
23
+ end
24
+
25
+ def latest_remote_backup
26
+ command = "ls -1t #{figaro_yml_remote_path.parent} | grep -E '#{backup_regex}' | head -n 1"
27
+ capture(command).strip
28
+ end
29
+
30
+ def backup_regex
31
+ # filename we are looking for "#{figaro_yml_remote_path.basename}-yyyy-mm-dd-HH-MM-SS.bak"
32
+ "#{figaro_yml_remote_path.basename}-[0-9]{4}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}.bak"
33
+ end
34
+
35
+ def count_remote_files
36
+ command = "ls -1 #{figaro_yml_remote_path.parent} | grep -E '#{backup_regex}' | wc -l"
37
+ capture(command).to_i
38
+ end
39
+
40
+ def create_remote_backup
41
+ backup_file = "#{figaro_yml_remote_path.basename}-#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}.bak"
42
+ # puts "cp #{figaro_yml_remote_path} #{figaro_yml_remote_path.parent.join(backup_file)}"
43
+ execute :cp, figaro_yml_remote_path, figaro_yml_remote_path.parent.join(backup_file)
44
+ end
45
+
46
+ def cleanup_remote_backups
47
+ number_of_backups = count_remote_files
48
+ return unless number_of_backups > 5
49
+
50
+ diff = number_of_backups - 5
51
+ # remove older backups and keep the latest 5
52
+ command = "ls -1t #{figaro_yml_remote_path.parent} | grep -E '#{backup_regex}' | tail -n #{diff}"
53
+
54
+ capture(command).split("\n").each do |file|
55
+ execute "rm #{figaro_yml_remote_path.parent.join(file)}"
56
+ end
57
+ end
58
+
59
+ def local_figaro_yml(env)
60
+ @local_figaro_yml ||= YAML.load(ERB.new(File.read(figaro_yml_local_path)).result)
61
+ local_figaro = {}
62
+ deployment_env = fetch(:rails_env, env).to_s
63
+
64
+ @local_figaro_yml.each do |key, value|
65
+ if key == env
66
+ local_figaro[deployment_env] = @local_figaro_yml[key]
67
+ elsif !value.is_a?(Hash)
68
+ local_figaro[key] = @local_figaro_yml[key]
69
+ end
70
+ end
71
+
72
+ local_figaro
73
+ end
74
+
75
+ def local_yaml
76
+ YAML.safe_load(File.read(figaro_yml_local_path)) || {}
77
+ end
78
+
79
+ def figaro_yml_env
80
+ fetch(:figaro_yml_env).to_s
81
+ end
82
+
83
+ def figaro_yml_content
84
+ local_figaro_yml(figaro_yml_env).to_yaml
85
+ end
86
+
87
+ def configs(yaml, env)
88
+ stage_yml = yaml[env.to_s]&.sort.to_h
89
+ global_yml = remove_nested(yaml)&.sort.to_h
90
+ [global_yml, stage_yml]
91
+ end
92
+
93
+ def remove_nested(hash)
94
+ hash.each_with_object({}) do |(key, value), new_hash|
95
+ new_hash[key] = value unless value.is_a?(Hash)
96
+ end
97
+ end
98
+
99
+ def sort_with_nested(hash)
100
+ hash.each_with_object({}) do |(key, value), new_hash|
101
+ new_hash[key] = value.is_a?(Hash) ? sort_with_nested(value) : value
102
+ end.sort.to_h
103
+ end
104
+
105
+ def compare_hashes(hash1, hash2)
106
+ all_keys = hash1.keys | hash2.keys # Union of all keys from both hashes
107
+ all_keys.each_with_object({}) do |key, changes_hash|
108
+ old_value = hash2[key].nil? ? 'nil' : hash2[key].to_s
109
+ new_value = hash1[key].nil? ? 'nil' : hash1[key].to_s
110
+
111
+ changes_hash[key] = { old: old_value, new: new_value } if old_value != new_value
112
+ end.tap { |changes| return changes.empty? ? nil : changes }
113
+ end
114
+
115
+ # selection helpers
116
+ def ask_to_overwrite(question)
117
+ answer = ''
118
+ until %w[y n].include?(answer)
119
+ print "#{question}? (y/N): "
120
+ answer = $stdin.gets.strip.downcase
121
+ end
122
+ answer == 'y'
123
+ end
124
+
125
+ # info helpers
126
+
127
+ def print_changes(changes, message)
128
+ return unless changes
129
+
130
+ puts "#{message}:\n\n"
131
+ changes.each do |key, diff|
132
+ puts "#{key}: #{diff[:old]} => #{diff[:new]}"
133
+ end
134
+ puts "\n"
135
+ end
136
+
137
+ # error helpers
138
+
139
+ def check_git_tracking_error
140
+ puts
141
+ puts "Error - please remove '#{fetch(:figaro_yml_local_path)}' from git:"
142
+ puts
143
+ puts " $ git rm --cached #{fetch(:figaro_yml_local_path)}"
144
+ puts
145
+ puts 'and gitignore it:'
146
+ puts
147
+ puts " $ echo '#{fetch(:figaro_yml_local_path)}' >> .gitignore"
148
+ puts
149
+ end
150
+
151
+ def check_config_present_error
152
+ puts
153
+ puts "Error - '#{figaro_yml_env}' config not present in '#{fetch(:figaro_yml_local_path)}'."
154
+ puts 'Please populate it.'
155
+ puts
156
+ end
157
+
158
+ def check_figaro_file_exists_error
159
+ puts
160
+ puts "Error - '#{fetch(:figaro_yml_local_path)}' file does not exists, and it's required."
161
+ puts
162
+ end
163
+
164
+ # file helpers
165
+ def write_to_file(file, content)
166
+ File.open(file, 'w') do |f|
167
+ f.write(content)
168
+ end
169
+ end
170
+
171
+ def write_combined_yaml(yamls_combined)
172
+ if yamls_combined.empty?
173
+ info 'No data to write.'
174
+ else
175
+ # write to new file
176
+ info 'writing to config/application.yml'
177
+ write_to_file(figaro_yml_local_path, yamls_combined.to_yaml)
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
184
+ # rubocop:enable Metrics/ModuleLength