maintenance_tasks 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60d043a961d97e4db5e822b86bf17a29fd409cf14e3951c581ecfb92abc7e2af
4
- data.tar.gz: 5170cb9e4bb82c82fe31f07f0dba93ca28caeacffe2b68ec592a092623d6aafd
3
+ metadata.gz: 2dcb5b54d6f3fd47db28a3f57a487c201e2109b3eb8f78efbe3c972a374999e8
4
+ data.tar.gz: eeb95960a0cac8de08aa3af7d12d47f6cfbee4d875ab74f8989f4d17ef545f6c
5
5
  SHA512:
6
- metadata.gz: be30600ed5e353ef1fba3bc484d5349be4567249b0cbb808503e73e0f42af76ae0befe6403fc4bdead3fb3ce0a5cd36e920f427eb013ac5215900571ddbb976a
7
- data.tar.gz: 1242c76047b52eae2463ea562c0ac48d09d773f9d4b069a781a140e49c39c9175e25b1eb7d21db5dce6ee96d43844323337761575909db396ccf4bc044a8355b
6
+ metadata.gz: e99ebde772755c6f3d88d48e65df883805b2ceb4798334f00175bc8e4c83d093bef79931bf0c0c86b303c3d94d2e0b44b3b506b1813ea6e01597ccf47f2c8182
7
+ data.tar.gz: 58d11ad3fa36721e9f29a49cecf586d2f362aaf155667ce6b7702b7acd7bb43f1defa2a2a4ed1fa259d563876b9cec5d5f7b66f4d5dcf43747009e64552fa804
data/README.md CHANGED
@@ -33,12 +33,13 @@ take a look at the [Active Job documentation][active-job-docs].
33
33
  [async-adapter]: https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html
34
34
  [active-job-docs]: https://guides.rubyonrails.org/active_job_basics.html#setting-the-backend
35
35
 
36
-
37
36
  ### Autoloading
38
37
 
39
38
  The Maintenance Tasks framework does not support autoloading in `:classic` mode.
40
- Please ensure your application is using [Zeitwerk](https://github.com/fxn/zeitwerk) to load your code.
41
- For more information, please consult the [Rails guides on autoloading and reloading constants](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html).
39
+ Please ensure your application is using
40
+ [Zeitwerk](https://github.com/fxn/zeitwerk) to load your code. For more
41
+ information, please consult the [Rails guides on autoloading and reloading
42
+ constants](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html).
42
43
 
43
44
  ## Usage
44
45
 
@@ -51,7 +52,7 @@ The typical Maintenance Tasks workflow is as follows:
51
52
  - or by [using Ruby](#running-a-task-from-ruby).
52
53
  3. [Monitor the Task](#monitoring-your-tasks-status)
53
54
  - either by using the included web UI,
54
- - or by manually checking your task's run's status in your database.
55
+ - or by manually checking your tasks runs status in your database.
55
56
  4. Optionally, delete the Task code if you no longer need it.
56
57
 
57
58
  ### Creating a Task
@@ -70,11 +71,12 @@ The generated task is a subclass of `MaintenanceTasks::Task` that implements:
70
71
  over.
71
72
  * `process`: do the work of your maintenance task on a single record
72
73
 
73
- Optionally, tasks can also implement a custom `#count` method, defining the number
74
- of elements that will be iterated over. Your task's `tick_total` will be calculated
75
- automatically based on the collection size, but this value may be overriden if desired
76
- using the `#count` method (this might be done, for example, to avoid the query that would
77
- be produced to determine the size of your collection).
74
+ Optionally, tasks can also implement a custom `#count` method, defining the
75
+ number of elements that will be iterated over. Your tasks `tick_total` will be
76
+ calculated automatically based on the collection size, but this value may be
77
+ overridden if desired using the `#count` method (this might be done, for
78
+ example, to avoid the query that would be produced to determine the size of your
79
+ collection).
78
80
 
79
81
  Example:
80
82
 
@@ -98,10 +100,12 @@ end
98
100
 
99
101
  You can also write a Task that iterates on a CSV file. Note that writing CSV
100
102
  Tasks **requires Active Storage to be configured**. Ensure that the dependency
101
- is specified in your application's Gemfile, and that you've followed the [setup
102
- instuctions][setup].
103
+ is specified in your applications Gemfile, and that youve followed the [setup
104
+ instructions][storage-setup]. See also [Customizing which Active Storage service
105
+ to use][storage-customizing].
103
106
 
104
- [setup]: https://edgeguides.rubyonrails.org/active_storage_overview.html#setup
107
+ [storage-setup]: https://edgeguides.rubyonrails.org/active_storage_overview.html#setup
108
+ [storage-customizing]: #customizing-which-active-storage-service-to-use
105
109
 
106
110
  Generate a CSV Task by running:
107
111
 
@@ -134,12 +138,12 @@ My Title,Hello World!
134
138
  ```
135
139
 
136
140
  The files uploaded to your Active Storage service provider will be renamed
137
- to include an ISO8601 timestamp and the Task name in snake case format.
141
+ to include an ISO 8601 timestamp and the Task name in snake case format.
138
142
  The CSV is expected to have a trailing newline at the end of the file.
139
143
 
140
144
  #### Batch CSV Tasks
141
145
 
142
- Tasks can process CSVs in batches. Add the `in_batches` option to your task's
146
+ Tasks can process CSVs in batches. Add the `in_batches` option to your tasks
143
147
  `csv_collection` macro:
144
148
 
145
149
  ```ruby
@@ -156,12 +160,12 @@ module Maintenance
156
160
  end
157
161
  ```
158
162
 
159
- As with a regular CSV task, ensure you've implemented the following method:
163
+ As with a regular CSV task, ensure youve implemented the following method:
160
164
 
161
165
  * `process`: do the work of your Task on a batch (array of `CSV::Row` objects).
162
166
 
163
167
  Note that `#count` is calculated automatically based on the number of batches in
164
- your collection, and your Task's progress will be displayed in terms of batches
168
+ your collection, and your Tasks progress will be displayed in terms of batches
165
169
  (not the total number of rows in your CSV).
166
170
 
167
171
  ### Processing Batch Collections
@@ -188,13 +192,13 @@ module Maintenance
188
192
  end
189
193
  ```
190
194
 
191
- Ensure that you've implemented the following methods:
195
+ Ensure that youve implemented the following methods:
192
196
 
193
197
  * `collection`: return an `ActiveRecord::Batches::BatchEnumerator`.
194
198
  * `process`: do the work of your Task on a batch (`ActiveRecord::Relation`).
195
199
 
196
200
  Note that `#count` is calculated automatically based on the number of batches in
197
- your collection, and your Task's progress will be displayed in terms of batches
201
+ your collection, and your Tasks progress will be displayed in terms of batches
198
202
  (not the number of records in the relation).
199
203
 
200
204
  **Important!** Batches should only be used if `#process` is performing a batch
@@ -206,7 +210,7 @@ primary keys of the records of the batch first, and then perform an additional
206
210
  query to load the records when calling `each` (or any `Enumerable` method)
207
211
  inside `#process`.
208
212
 
209
- ### Tasks that don't need a Collection
213
+ ### Tasks that dont need a Collection
210
214
 
211
215
  Sometimes, you might want to run a Task that performs a single operation, such
212
216
  as enqueuing another background job or hitting an external API. The gem supports
@@ -264,7 +268,7 @@ module Maintenance
264
268
  end
265
269
  ```
266
270
 
267
- Note that it's up to you to define a throttling condition that makes sense for
271
+ Note that its up to you to define a throttling condition that makes sense for
268
272
  your app. Shopify implements `DatabaseStatus.healthy?` to check various MySQL
269
273
  metrics such as replication lag, DB threads, whether DB writes are available,
270
274
  etc.
@@ -273,7 +277,7 @@ Tasks can define multiple throttle conditions. Throttle conditions are inherited
273
277
  by descendants, and new conditions will be appended without impacting existing
274
278
  conditions.
275
279
 
276
- The backoff can also be specified as a proc:
280
+ The backoff can also be specified as a Proc:
277
281
 
278
282
  ```ruby
279
283
  # app/tasks/maintenance/update_posts_throttled_task.rb
@@ -287,11 +291,12 @@ module Maintenance
287
291
  end
288
292
  end
289
293
  ```
294
+
290
295
  ### Custom Task Parameters
291
296
 
292
297
  Tasks may need additional information, supplied via parameters, to run.
293
298
  Parameters can be defined as Active Model Attributes in a Task, and then become
294
- accessible to any of Task's methods: `#collection`, `#count`, or `#process`.
299
+ accessible to any of Tasks methods: `#collection`, `#count`, or `#process`.
295
300
 
296
301
  ```ruby
297
302
  # app/tasks/maintenance/update_posts_via_params_task.rb
@@ -315,7 +320,7 @@ end
315
320
  Tasks can leverage Active Model Validations when defining parameters. Arguments
316
321
  supplied to a Task accepting parameters will be validated before the Task starts
317
322
  to run. Since arguments are specified in the user interface via text area
318
- inputs, it's important to check that they conform to the format your Task
323
+ inputs, its important to check that they conform to the format your Task
319
324
  expects, and to sanitize any inputs if necessary.
320
325
 
321
326
  ### Using Task Callbacks
@@ -348,7 +353,7 @@ end
348
353
  Note: The `after_error` callback is guaranteed to complete,
349
354
  so any exceptions raised in your callback code are ignored.
350
355
  If your `after_error` callback code can raise an exception,
351
- you'll need to rescue it and handle it appropriately
356
+ youll need to rescue it and handle it appropriately
352
357
  within the callback.
353
358
 
354
359
  ```ruby
@@ -397,7 +402,7 @@ depend on the queue adapter but in general, you should follow these rules:
397
402
  safely interrupted and resumed.
398
403
  * Idempotency of `Task#process`: it should be safe to run `process` multiple
399
404
  times for the same element of the collection. Read more in [this Sidekiq best
400
- practice][sidekiq-idempotent]. It's important if the Task errors and you run
405
+ practice][sidekiq-idempotent]. Its important if the Task errors and you run
401
406
  it again, because the same element that errored the Task may well be processed
402
407
  again. It especially matters in the situation described above, when the
403
408
  iteration duration exceeds the timeout: if the job is re-enqueued, multiple
@@ -422,7 +427,7 @@ callbacks](#using-task-callbacks) to persist or log a report for example.
422
427
  ### Writing tests for a Task
423
428
 
424
429
  The task generator will also create a test file for your task in the folder
425
- `test/tasks/maintenance/`. At a minimum, it's recommended that the `#process`
430
+ `test/tasks/maintenance/`. At a minimum, its recommended that the `#process`
426
431
  method in your task be tested. You may also want to test the `#collection` and
427
432
  `#count` methods for your task if they are sufficiently complex.
428
433
 
@@ -477,7 +482,7 @@ end
477
482
 
478
483
  ### Writing tests for a Task with parameters
479
484
 
480
- Tests for tasks with parameters need to instatiate the task class in order to
485
+ Tests for tasks with parameters need to instantiate the task class in order to
481
486
  assign attributes. Once the task instance is setup, you may test `#process`
482
487
  normally.
483
488
 
@@ -525,7 +530,8 @@ bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv "path/t
525
530
  The `--csv` option also works with CSV content coming from the standard input:
526
531
 
527
532
  ```sh-session
528
- curl "some/remote/csv" | bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv
533
+ curl "some/remote/csv" |
534
+ bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv
529
535
  ```
530
536
 
531
537
  To run a Task that takes arguments from the command line, use the `--arguments`
@@ -564,7 +570,7 @@ MaintenanceTasks::Runner.run(
564
570
  )
565
571
  ```
566
572
 
567
- ### Monitoring your Task's status
573
+ ### Monitoring your Tasks status
568
574
 
569
575
  The web UI will provide updates on the status of your Task. Here are the states
570
576
  a Task can be in:
@@ -620,11 +626,11 @@ When Sidekiq is stopping, it will give workers 25 seconds to finish before
620
626
  forcefully terminating them (this is the default but can be configured with the
621
627
  `--timeout` option). Before the worker threads are terminated, Sidekiq will try
622
628
  to re-enqueue the job so your Task will be resumed. However, the position in
623
- the collection won't be persisted so at least one iteration may run again.
629
+ the collection wont be persisted so at least one iteration may run again.
624
630
 
625
631
  #### Help! My Task is stuck
626
632
 
627
- Finally, if the queue adapter configured for your application doesn't have this
633
+ Finally, if the queue adapter configured for your application doesnt have this
628
634
  property, or if Sidekiq crashes, is forcefully terminated, or is unable to
629
635
  re-enqueue the jobs that were in progress, the Task may be in a seemingly stuck
630
636
  situation where it appears to be running but is not. In that situation, pausing
@@ -699,7 +705,7 @@ maintenance tasks in your application.
699
705
  ```ruby
700
706
  # config/initializers/maintenance_tasks.rb
701
707
 
702
- MaintenanceTasks.job = 'CustomTaskJob'
708
+ MaintenanceTasks.job = "CustomTaskJob"
703
709
 
704
710
  # app/jobs/custom_task_job.rb
705
711
 
@@ -730,9 +736,9 @@ If no value is specified, it will default to 1 second.
730
736
  #### Customizing which Active Storage service to use
731
737
 
732
738
  The Active Storage framework in Rails 6.1 and up supports multiple storage
733
- services per environment. To specify which service to use,
734
- `MaintenanceTasks.active_storage_service` can be configured with the service's
735
- key, as specified in your application's `config/storage.yml`:
739
+ services. To specify which service to use,
740
+ `MaintenanceTasks.active_storage_service` can be configured with the services
741
+ key, as specified in your applications `config/storage.yml`:
736
742
 
737
743
  ```yaml
738
744
  # config/storage.yml
@@ -757,7 +763,8 @@ MaintenanceTasks.active_storage_service = :internal
757
763
  ```
758
764
 
759
765
  There is no need to configure this option if your application uses only one
760
- storage service per environment.
766
+ storage service. `Rails.configuration.active_storage.service` is used by
767
+ default.
761
768
 
762
769
  #### Customizing the backtrace cleaner
763
770
 
@@ -788,11 +795,11 @@ bin/rails generate maintenance_tasks:install
788
795
 
789
796
  This ensures that new migrations are installed and run as well.
790
797
 
791
- **What if I've deleted my previous Maintenance Task migrations?**
798
+ **What if Ive deleted my previous Maintenance Task migrations?**
792
799
 
793
800
  The install command will attempt to reinstall these old migrations and migrating
794
801
  the database will cause problems. Use `bin/rails
795
- maintenance_tasks:install:migrations` to copy the gem's migrations to your
802
+ maintenance_tasks:install:migrations` to copy the gems migrations to your
796
803
  `db/migrate` folder. Check the release notes to see if any new migrations were
797
804
  added since your last gem upgrade. Ensure that these are kept, but remove any
798
805
  migrations that already ran.
@@ -820,8 +827,8 @@ Once a release is ready, follow these steps:
820
827
  * Deploy via [Shipit][shipit] and see the new version on
821
828
  <https://rubygems.org/gems/maintenance_tasks>.
822
829
  * Ensure the release has documented all changes and publish it.
823
- * Create a new [draft release on GitHub][release] with the title 'Upcoming
824
- Release'. The tag version can be left blank. This will be the starting point
830
+ * Create a new [draft release on GitHub][release] with the title Upcoming
831
+ Release”. The tag version can be left blank. This will be the starting point
825
832
  for documenting changes related to the next release.
826
833
 
827
834
  [release]: https://help.github.com/articles/creating-releases/
@@ -18,10 +18,14 @@ module MaintenanceTasks
18
18
  # Renders the page responsible for providing Task actions to users.
19
19
  # Shows running and completed instances of the Task.
20
20
  def show
21
- @task = TaskDataShow.find(params.fetch(:id))
22
- @active_runs = @task.active_runs
23
- set_refresh if @active_runs.any?
21
+ task_name = params.fetch(:id)
22
+ @task = TaskDataShow.new(task_name)
23
+ @task.active_runs.load
24
+ set_refresh if @task.active_runs.any?
24
25
  @runs_page = RunsPage.new(@task.completed_runs, params[:cursor])
26
+ if @task.active_runs.none? && @runs_page.records.none?
27
+ Task.named(task_name)
28
+ end
25
29
  end
26
30
 
27
31
  private
@@ -104,9 +104,10 @@ module MaintenanceTasks
104
104
  # Return the appropriate field tag for the parameter
105
105
  def parameter_field(form_builder, parameter_name)
106
106
  case form_builder.object.class.attribute_types[parameter_name]
107
- when ActiveModel::Type::Integer, ActiveModel::Type::Decimal,
108
- ActiveModel::Type::Float
107
+ when ActiveModel::Type::Integer
109
108
  form_builder.number_field(parameter_name)
109
+ when ActiveModel::Type::Decimal, ActiveModel::Type::Float
110
+ form_builder.number_field(parameter_name, { step: "any" })
110
111
  when ActiveModel::Type::DateTime
111
112
  form_builder.datetime_field(parameter_name)
112
113
  when ActiveModel::Type::Date
@@ -37,17 +37,22 @@ module MaintenanceTasks
37
37
 
38
38
  enum status: STATUSES.to_h { |status| [status, status.to_s] }
39
39
 
40
- validates :task_name, on: :create, inclusion: { in: ->(_) {
41
- Task.available_tasks.map(&:to_s)
42
- } }
40
+ validates :task_name, on: :create, inclusion: {
41
+ in: ->(_) { Task.available_tasks.map(&:to_s) },
42
+ }
43
43
  validate :csv_attachment_presence, on: :create
44
44
  validate :csv_content_type, on: :create
45
45
  validate :validate_task_arguments, on: :create
46
46
 
47
47
  attr_readonly :task_name
48
48
 
49
- serialize :backtrace
50
- serialize :arguments, JSON
49
+ if Rails.gem_version >= Gem::Version.new("7.1.alpha")
50
+ serialize :backtrace, coder: YAML
51
+ serialize :arguments, coder: JSON
52
+ else
53
+ serialize :backtrace
54
+ serialize :arguments, JSON
55
+ end
51
56
 
52
57
  scope :active, -> { where(status: ACTIVE_STATUSES) }
53
58
  scope :completed, -> { where(status: COMPLETED_STATUSES) }
@@ -11,26 +11,6 @@ module MaintenanceTasks
11
11
  #
12
12
  # @api private
13
13
  class TaskDataShow
14
- class << self
15
- # Initializes a Task Data by name, raising if the Task does not exist.
16
- #
17
- # For the purpose of this method, a Task does not exist if it's deleted
18
- # and doesn't have a Run. While technically, it could have existed and
19
- # been deleted since, if it never had a Run we may as well consider it
20
- # non-existent since we don't have interesting data to show.
21
- #
22
- # @param name [String] the name of the Task subclass.
23
- # @return [TaskDataShow] a Task Data instance.
24
- # @raise [Task::NotFoundError] if the Task does not exist and doesn't have
25
- # a Run.
26
- def find(name)
27
- task_data = new(name)
28
- task_data.active_runs.load
29
- task_data.has_any_run? || Task.named(name)
30
- task_data
31
- end
32
- end
33
-
34
14
  # Initializes a Task Data with a name and optionally a related run.
35
15
  #
36
16
  # @param name [String] the name of the Task subclass.
@@ -107,12 +87,6 @@ module MaintenanceTasks
107
87
  MaintenanceTasks::Task.named(name).new
108
88
  end
109
89
 
110
- # @return [Boolean] whether the Task has any Run.
111
- # @api private
112
- def has_any_run?
113
- active_runs.any? || completed_runs.any?
114
- end
115
-
116
90
  private
117
91
 
118
92
  def runs
@@ -15,9 +15,9 @@
15
15
  <%= csrf_meta_tags %>
16
16
 
17
17
  <%=
18
- stylesheet_link_tag(URI.join(controller.class::BULMA_CDN, 'npm/bulma@0.9.3/css/bulma.css'),
18
+ stylesheet_link_tag(URI.join(controller.class::BULMA_CDN, 'npm/bulma@0.9.4/css/bulma.css'),
19
19
  media: :all,
20
- integrity: 'sha384-Zkr9rpl37lclZu6AwYQZZm0CxiMqLZFiibodW+UXLnAWPBr6qgIzPpcmHkpwnyWD',
20
+ integrity: 'sha384-qQlNh1kc0FyhUqUDXKkl5wpiiSm8PXQw2ZWhAVfU46tmdMDfq2vXG2CXWYT+Dls3',
21
21
  crossorigin: 'anonymous') unless request.xhr?
22
22
  %>
23
23
 
@@ -38,12 +38,12 @@
38
38
  <pre><code><%= highlight_code(code) %></code></pre>
39
39
  <% end %>
40
40
 
41
- <% if @active_runs.any? %>
41
+ <% if @task.active_runs.any? %>
42
42
  <hr/>
43
43
 
44
44
  <h4 class="title is-4">Active Runs</h4>
45
45
 
46
- <%= render @active_runs %>
46
+ <%= render @task.active_runs %>
47
47
  <% end %>
48
48
 
49
49
  <% if @runs_page.records.present? %>
@@ -2,7 +2,12 @@
2
2
 
3
3
  class AddLockVersionToMaintenanceTasksRuns < ActiveRecord::Migration[6.0]
4
4
  def change
5
- add_column(:maintenance_tasks_runs, :lock_version, :integer,
6
- default: 0, null: false)
5
+ add_column(
6
+ :maintenance_tasks_runs,
7
+ :lock_version,
8
+ :integer,
9
+ default: 0,
10
+ null: false,
11
+ )
7
12
  end
8
13
  end
@@ -2,12 +2,18 @@
2
2
 
3
3
  class AddIndexOnTaskNameAndStatusToRuns < ActiveRecord::Migration[6.0]
4
4
  def change
5
- remove_index(:maintenance_tasks_runs,
6
- column: [:task_name, :created_at], order: { created_at: :desc },
7
- name: :index_maintenance_tasks_runs_on_task_name_and_created_at)
5
+ remove_index(
6
+ :maintenance_tasks_runs,
7
+ column: [:task_name, :created_at],
8
+ order: { created_at: :desc },
9
+ name: :index_maintenance_tasks_runs_on_task_name_and_created_at,
10
+ )
8
11
 
9
- add_index(:maintenance_tasks_runs, [:task_name, :status, :created_at],
12
+ add_index(
13
+ :maintenance_tasks_runs,
14
+ [:task_name, :status, :created_at],
10
15
  name: :index_maintenance_tasks_runs,
11
- order: { created_at: :desc })
16
+ order: { created_at: :desc },
17
+ )
12
18
  end
13
19
  end
@@ -9,10 +9,14 @@ module MaintenanceTasks
9
9
  desc "This generator creates a task file at app/tasks and a corresponding "\
10
10
  "test."
11
11
 
12
- class_option :csv, type: :boolean, default: false,
12
+ class_option :csv,
13
+ type: :boolean,
14
+ default: false,
13
15
  desc: "Generate a CSV Task."
14
16
 
15
- class_option :no_collection, type: :boolean, default: false,
17
+ class_option :no_collection,
18
+ type: :boolean,
19
+ default: false,
16
20
  desc: "Generate a collection-less Task."
17
21
 
18
22
  check_class_collision suffix: "Task"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: maintenance_tasks
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify Engineering
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-26 00:00:00.000000000 Z
11
+ date: 2023-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionpack
@@ -154,7 +154,7 @@ homepage: https://github.com/Shopify/maintenance_tasks
154
154
  licenses:
155
155
  - MIT
156
156
  metadata:
157
- source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v2.0.0
157
+ source_code_uri: https://github.com/Shopify/maintenance_tasks/tree/v2.1.0
158
158
  allowed_push_host: https://rubygems.org
159
159
  post_install_message:
160
160
  rdoc_options: []