maintenance_tasks 1.0.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +180 -22
- data/Rakefile +16 -16
- data/app/controllers/maintenance_tasks/application_controller.rb +3 -6
- data/app/controllers/maintenance_tasks/runs_controller.rb +1 -12
- data/app/controllers/maintenance_tasks/tasks_controller.rb +7 -4
- data/app/helpers/maintenance_tasks/application_helper.rb +2 -48
- data/app/helpers/maintenance_tasks/{task_helper.rb → tasks_helper.rb} +26 -18
- data/app/jobs/maintenance_tasks/task_job.rb +49 -6
- data/app/models/maintenance_tasks/application_record.rb +2 -2
- data/app/models/maintenance_tasks/csv_collection.rb +33 -0
- data/app/models/maintenance_tasks/progress.rb +19 -14
- data/app/models/maintenance_tasks/run.rb +39 -1
- data/app/models/maintenance_tasks/runner.rb +20 -5
- data/app/models/maintenance_tasks/runs_page.rb +55 -0
- data/app/models/maintenance_tasks/task_data.rb +9 -5
- data/app/models/maintenance_tasks/ticker.rb +0 -1
- data/app/tasks/maintenance_tasks/task.rb +43 -16
- data/app/validators/maintenance_tasks/run_status_validator.rb +15 -13
- data/app/views/layouts/maintenance_tasks/_navbar.html.erb +0 -6
- data/app/views/maintenance_tasks/runs/_info.html.erb +6 -0
- data/app/views/maintenance_tasks/runs/_run.html.erb +1 -9
- data/app/views/maintenance_tasks/runs/info/_running.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/show.html.erb +31 -4
- data/config/routes.rb +4 -6
- data/db/migrate/20210225152418_remove_index_on_task_name.rb +14 -0
- data/exe/maintenance_tasks +2 -2
- data/lib/generators/maintenance_tasks/install_generator.rb +4 -5
- data/lib/generators/maintenance_tasks/task_generator.rb +15 -9
- data/lib/generators/maintenance_tasks/templates/csv_task.rb.tt +13 -0
- data/lib/generators/maintenance_tasks/templates/task_spec.rb.tt +1 -1
- data/lib/generators/maintenance_tasks/templates/task_test.rb.tt +1 -1
- data/lib/maintenance_tasks.rb +34 -30
- data/lib/maintenance_tasks/cli.rb +18 -4
- data/lib/maintenance_tasks/engine.rb +6 -3
- metadata +9 -31
- data/app/views/maintenance_tasks/runs/index.html.erb +0 -15
- data/app/views/maintenance_tasks/tasks/actions/_cancelled.html.erb +0 -1
- data/app/views/maintenance_tasks/tasks/actions/_cancelling.html.erb +0 -4
- data/app/views/maintenance_tasks/tasks/actions/_enqueued.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_errored.html.erb +0 -1
- data/app/views/maintenance_tasks/tasks/actions/_interrupted.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_new.html.erb +0 -1
- data/app/views/maintenance_tasks/tasks/actions/_paused.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_pausing.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_running.html.erb +0 -2
- data/app/views/maintenance_tasks/tasks/actions/_succeeded.html.erb +0 -1
- data/lib/maintenance_tasks/integrations/bugsnag_handler.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c673afea63371c8c8f69ccda520b66fb1391d17ff6f241eb5610e45c60493561
|
4
|
+
data.tar.gz: a1b914d6fdf7391bda0691444f8af2e263c71313c295bf2fd38e6e655f661a99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d161e823b16c12abd127d725cccf985d0bca50253cb40937d265685d6078730beff127913eea7973ff23211576d5d143508ac61968ebb2460f1c12fc89ff5d82
|
7
|
+
data.tar.gz: 46de8ac9e6819829de191a0fcfaf40c48b2922f1cc3024df58a41a7e6763658149f3f32baa168045bae6c00790da1b789647d36bad880714bdf63e75d67aeb32
|
data/README.md
CHANGED
@@ -3,11 +3,16 @@
|
|
3
3
|
A Rails engine for queuing and managing maintenance tasks.
|
4
4
|
|
5
5
|
## Table of Contents
|
6
|
+
|
7
|
+
* [Demo](#demo)
|
6
8
|
* [Installation](#installation)
|
9
|
+
* [Active Job Dependency](#active-job-dependency)
|
7
10
|
* [Usage](#usage)
|
8
11
|
* [Creating a Task](#creating-a-task)
|
9
|
-
|
12
|
+
* [Creating a CSV Task](#creating-a-csv-task)
|
13
|
+
* [Considerations when writing Tasks](#considerations-when-writing-tasks)
|
10
14
|
* [Writing tests for a Task](#writing-tests-for-a-task)
|
15
|
+
* [Writing tests for a CSV Task](#writing-tests-for-a-csv-task)
|
11
16
|
* [Running a Task](#running-a-task)
|
12
17
|
* [Monitoring your Task's status](#monitoring-your-tasks-status)
|
13
18
|
* [How Maintenance Tasks runs a Task](#how-maintenance-tasks-runs-a-task)
|
@@ -17,22 +22,23 @@ A Rails engine for queuing and managing maintenance tasks.
|
|
17
22
|
* [Customizing the maintenance tasks module](#customizing-the-maintenance-tasks-module)
|
18
23
|
* [Customizing the underlying job class](#customizing-the-underlying-job-class)
|
19
24
|
* [Customizing the rate at which task progress gets updated](#customizing-the-rate-at-which-task-progress-gets-updated)
|
25
|
+
* [Customizing which Active Storage service to use](#customizing-which-active-storage-service-to-use)
|
20
26
|
* [Upgrading](#upgrading)
|
21
27
|
* [Contributing](#contributing)
|
22
28
|
* [Releasing new versions](#releasing-new-versions)
|
23
29
|
|
24
|
-
##
|
30
|
+
## Demo
|
25
31
|
|
26
|
-
|
32
|
+
Watch this demo video to see the gem in action:
|
27
33
|
|
28
|
-
|
29
|
-
gem 'maintenance_tasks'
|
30
|
-
```
|
34
|
+
[![Link to demo video](static/demo.png)](https://www.youtube.com/watch?v=BTuvTQxlFzs)
|
31
35
|
|
32
|
-
|
36
|
+
## Installation
|
37
|
+
|
38
|
+
To install the gem and run the install generator, execute:
|
33
39
|
|
34
40
|
```bash
|
35
|
-
$ bundle
|
41
|
+
$ bundle add maintenance_tasks
|
36
42
|
$ rails generate maintenance_tasks:install
|
37
43
|
```
|
38
44
|
|
@@ -40,6 +46,22 @@ The generator creates and runs a migration to add the necessary table to your
|
|
40
46
|
database. It also mounts Maintenance Tasks in your `config/routes.rb`. By
|
41
47
|
default the web UI can be accessed in the new `/maintenance_tasks` path.
|
42
48
|
|
49
|
+
In case you use an exception reporting service (e.g. Bugsnag) you might want to
|
50
|
+
define an error handler. See [Customizing the error
|
51
|
+
handler](#customizing-the-error-handler) for more information.
|
52
|
+
|
53
|
+
### Active Job Dependency
|
54
|
+
|
55
|
+
The Maintenance Tasks framework relies on ActiveJob behind the scenes to run
|
56
|
+
Tasks. The default queuing backend for ActiveJob is
|
57
|
+
[asynchronous][async-adapter]. It is **strongly recommended** to change this to
|
58
|
+
a persistent backend so that Task progress is not lost during code or
|
59
|
+
infrastructure changes. For more information on configuring a queuing backend,
|
60
|
+
take a look at the [ActiveJob documentation][active-job-docs].
|
61
|
+
|
62
|
+
[async-adapter]: https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html
|
63
|
+
[active-job-docs]: https://guides.rubyonrails.org/active_job_basics.html#setting-the-backend
|
64
|
+
|
43
65
|
## Usage
|
44
66
|
|
45
67
|
### Creating a Task
|
@@ -81,7 +103,45 @@ module Maintenance
|
|
81
103
|
end
|
82
104
|
```
|
83
105
|
|
84
|
-
|
106
|
+
### Creating a CSV Task
|
107
|
+
|
108
|
+
You can also write a Task that iterates on a CSV file. Note that writing CSV
|
109
|
+
Tasks **requires ActiveStorage to be configured**. Ensure that the dependency
|
110
|
+
is specified in your application's Gemfile, and that you've followed the
|
111
|
+
[setup instuctions][setup].
|
112
|
+
|
113
|
+
[setup]: https://edgeguides.rubyonrails.org/active_storage_overview.html#setup
|
114
|
+
|
115
|
+
Generate a CSV Task by running:
|
116
|
+
|
117
|
+
```bash
|
118
|
+
$ rails generate maintenance_tasks:task import_posts --csv
|
119
|
+
```
|
120
|
+
|
121
|
+
The generated task is a subclass of `MaintenanceTasks::Task` that implements:
|
122
|
+
|
123
|
+
* `process`: do the work of your maintenance task on a `CSV::Row`
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
# app/tasks/maintenance/import_posts_task.rb
|
127
|
+
module Maintenance
|
128
|
+
class ImportPostsTask < MaintenanceTasks::Task
|
129
|
+
csv_collection
|
130
|
+
|
131
|
+
def process(row)
|
132
|
+
Post.create!(title: row["title"], content: row["content"])
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
```csv
|
139
|
+
# posts.csv
|
140
|
+
title,content
|
141
|
+
My Title,Hello World!
|
142
|
+
```
|
143
|
+
|
144
|
+
### Considerations when writing Tasks
|
85
145
|
|
86
146
|
MaintenanceTasks relies on the queue adapter configured for your application to
|
87
147
|
run the job which is processing your Task. The guidelines for writing Task may
|
@@ -120,7 +180,7 @@ module Maintenance
|
|
120
180
|
test "#process performs a task iteration" do
|
121
181
|
post = Post.new
|
122
182
|
|
123
|
-
Maintenance::UpdatePostsTask.
|
183
|
+
Maintenance::UpdatePostsTask.process(post)
|
124
184
|
|
125
185
|
assert_equal 'New content!', post.content
|
126
186
|
end
|
@@ -128,6 +188,32 @@ module Maintenance
|
|
128
188
|
end
|
129
189
|
```
|
130
190
|
|
191
|
+
### Writing tests for a CSV Task
|
192
|
+
|
193
|
+
You should write tests for your `#process` method in a CSV Task as well. It
|
194
|
+
takes a `CSV::Row` as an argument. You can pass a row, or a hash with string
|
195
|
+
keys to `#process` from your test.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
# app/tasks/maintenance/import_posts_task_test.rb
|
199
|
+
module Maintenance
|
200
|
+
class ImportPostsTaskTest < ActiveSupport::TestCase
|
201
|
+
test "#process performs a task iteration" do
|
202
|
+
assert_difference -> { Post.count } do
|
203
|
+
Maintenance::UpdatePostsTask.process({
|
204
|
+
'title' => 'My Title',
|
205
|
+
'content' => 'Hello World!',
|
206
|
+
})
|
207
|
+
end
|
208
|
+
|
209
|
+
post = Post.last
|
210
|
+
assert_equal 'My Title', post.title
|
211
|
+
assert_equal 'Hello World!', post.content
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
```
|
216
|
+
|
131
217
|
### Running a Task
|
132
218
|
|
133
219
|
You can run your new Task by accessing the Web UI and clicking on "Run".
|
@@ -138,11 +224,26 @@ Alternatively, you can run your Task in the command line:
|
|
138
224
|
$ bundle exec maintenance_tasks perform Maintenance::UpdatePostsTask
|
139
225
|
```
|
140
226
|
|
141
|
-
|
142
|
-
|
227
|
+
To run a Task that processes CSVs from the command line, use the --csv option:
|
228
|
+
|
229
|
+
```bash
|
230
|
+
$ bundle exec maintenance_tasks perform Maintenance::ImportPostsTask --csv 'path/to/my_csv.csv'
|
231
|
+
```
|
232
|
+
|
233
|
+
You can also run a Task in Ruby by sending `run` with a Task name to Runner:
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
MaintenanceTasks::Runner.run(name: 'Maintenance::UpdatePostsTask')
|
237
|
+
```
|
238
|
+
|
239
|
+
To run a Task that processes CSVs using the Runner, provide a Hash containing an
|
240
|
+
open IO object and a filename to `run`:
|
143
241
|
|
144
242
|
```ruby
|
145
|
-
MaintenanceTasks::Runner.
|
243
|
+
MaintenanceTasks::Runner.run(
|
244
|
+
name: 'Maintenance::ImportPostsTask'
|
245
|
+
csv_file: { io: File.open('path/to/my_csv.csv'), filename: 'my_csv.csv' }
|
246
|
+
)
|
146
247
|
```
|
147
248
|
|
148
249
|
### Monitoring your Task's status
|
@@ -224,17 +325,39 @@ be placed in a `maintenance_tasks.rb` initializer.
|
|
224
325
|
Exceptions raised while a Task is performing are rescued and information about
|
225
326
|
the error is persisted and visible in the UI.
|
226
327
|
|
227
|
-
If
|
228
|
-
|
229
|
-
|
230
|
-
If you want to integrate with another exception monitoring service or customize
|
231
|
-
error handling, a callback can be defined:
|
328
|
+
If you want to integrate with an exception monitoring service (e.g. Bugsnag),
|
329
|
+
you can define an error handler:
|
232
330
|
|
233
331
|
```ruby
|
234
332
|
# config/initializers/maintenance_tasks.rb
|
235
|
-
MaintenanceTasks.error_handler = ->(error
|
333
|
+
MaintenanceTasks.error_handler = ->(error, task_context, _errored_element) do
|
334
|
+
Bugsnag.notify(error) do |notification|
|
335
|
+
notification.add_tab(:task, task_context)
|
336
|
+
end
|
337
|
+
end
|
236
338
|
```
|
237
339
|
|
340
|
+
The error handler should be a lambda that accepts three arguments:
|
341
|
+
|
342
|
+
* `error`: The exception that was raised.
|
343
|
+
* `task_context`: A hash with additional information about the Task and the
|
344
|
+
error:
|
345
|
+
* `task_name`: The name of the Task that errored
|
346
|
+
* `started_at`: The time the Task started
|
347
|
+
* `ended_at`: The time the Task errored
|
348
|
+
Note that `task_context` may be empty if the Task produced an error before any
|
349
|
+
context could be gathered (for example, if deserializing the job to process
|
350
|
+
your Task failed).
|
351
|
+
* `errored_element`: The element, if any, that was being processed when the
|
352
|
+
Task raised an exception. If you would like to pass this object to your
|
353
|
+
exception monitoring service, make sure you **sanitize the object** to avoid
|
354
|
+
leaking sensitive data and **convert it to a format** that is compatible with
|
355
|
+
your bug tracker. For example, Bugsnag only sends the id and class name of
|
356
|
+
ActiveRecord objects in order to protect sensitive data. CSV rows, on the
|
357
|
+
other hand, are converted to strings and passed raw to Bugsnag, so make sure
|
358
|
+
to filter any personal data from these objects before adding them to a
|
359
|
+
report.
|
360
|
+
|
238
361
|
#### Customizing the maintenance tasks module
|
239
362
|
|
240
363
|
`MaintenanceTasks.tasks_module` can be configured to define the module in which
|
@@ -281,6 +404,36 @@ MaintenanceTasks.ticker_delay = 2.seconds
|
|
281
404
|
|
282
405
|
If no value is specified, it will default to 1 second.
|
283
406
|
|
407
|
+
#### Customizing which Active Storage service to use
|
408
|
+
|
409
|
+
The Active Storage framework in Rails 6.1 and up supports multiple storage
|
410
|
+
services per environment. To specify which service to use,
|
411
|
+
`MaintenanceTasks.active_storage_service` can be configured with the service's
|
412
|
+
key, as specified in your application's `config/storage.yml`:
|
413
|
+
|
414
|
+
```yaml
|
415
|
+
# config/storage.yml
|
416
|
+
user_data:
|
417
|
+
service: GCS
|
418
|
+
credentials: <%= Rails.root.join("path/to/user/data/keyfile.json") %>
|
419
|
+
project: "my-project"
|
420
|
+
bucket: "user-data-bucket"
|
421
|
+
|
422
|
+
internal:
|
423
|
+
service: GCS
|
424
|
+
credentials: <%= Rails.root.join("path/to/internal/keyfile.json") %>
|
425
|
+
project: "my-project"
|
426
|
+
bucket: "internal-bucket"
|
427
|
+
```
|
428
|
+
|
429
|
+
```ruby
|
430
|
+
# config/initializers/maintenance_tasks.rb
|
431
|
+
MaintenanceTasks.active_storage_service = :internal
|
432
|
+
```
|
433
|
+
|
434
|
+
There is no need to configure this option if your application uses only one
|
435
|
+
storage service per environment.
|
436
|
+
|
284
437
|
## Upgrading
|
285
438
|
|
286
439
|
Use bundler to check for and upgrade to newer versions. After installing a new
|
@@ -302,15 +455,20 @@ pull requests. You can find the contribution guidelines on
|
|
302
455
|
|
303
456
|
## Releasing new versions
|
304
457
|
|
305
|
-
|
458
|
+
Updates should be added to the latest draft release on GitHub as Pull Requests
|
459
|
+
are merged.
|
460
|
+
|
461
|
+
Once a release is ready, follow these steps:
|
306
462
|
|
307
463
|
* Update `spec.version` in `maintenance_tasks.gemspec`.
|
308
464
|
* Run `bundle install` to bump the `Gemfile.lock` version of the gem.
|
309
465
|
* Open a PR and merge on approval.
|
310
|
-
* Create a [release on GitHub][release] with a version number that matches the
|
311
|
-
version defined in the gemspec.
|
312
466
|
* Deploy via [Shipit][shipit] and see the new version on
|
313
467
|
<https://rubygems.org/gems/maintenance_tasks>.
|
468
|
+
* Ensure the release has documented all changes and publish it.
|
469
|
+
* Create a new [draft release on GitHub][release] with the title
|
470
|
+
'Upcoming Release'. The tag version can be left blank. This will be the
|
471
|
+
starting point for documenting changes related to the next release.
|
314
472
|
|
315
473
|
[release]: https://help.github.com/articles/creating-releases/
|
316
474
|
[shipit]: https://shipit.shopify.io/shopify/maintenance_tasks/rubygems
|
data/Rakefile
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
begin
|
3
|
-
require
|
3
|
+
require "bundler/setup"
|
4
4
|
rescue LoadError
|
5
|
-
puts
|
5
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
6
6
|
end
|
7
7
|
|
8
|
-
require
|
8
|
+
require "rdoc/task"
|
9
9
|
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
-
rdoc.rdoc_dir =
|
11
|
-
rdoc.title =
|
12
|
-
rdoc.options <<
|
13
|
-
rdoc.rdoc_files.include(
|
14
|
-
rdoc.rdoc_files.include(
|
10
|
+
rdoc.rdoc_dir = "rdoc"
|
11
|
+
rdoc.title = "MaintenanceTasks"
|
12
|
+
rdoc.options << "--line-numbers"
|
13
|
+
rdoc.rdoc_files.include("README.md")
|
14
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
15
15
|
end
|
16
16
|
|
17
|
-
APP_RAKEFILE = File.expand_path(
|
18
|
-
load(
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load("rails/tasks/engine.rake")
|
19
19
|
|
20
|
-
load(
|
20
|
+
load("rails/tasks/statistics.rake")
|
21
21
|
|
22
|
-
require
|
22
|
+
require "bundler/gem_tasks"
|
23
23
|
|
24
|
-
require
|
24
|
+
require "rubocop/rake_task"
|
25
25
|
RuboCop::RakeTask.new
|
26
26
|
|
27
|
-
task(test:
|
28
|
-
task(
|
29
|
-
task(default: [
|
27
|
+
task(test: "app:test")
|
28
|
+
task("test:system" => "app:test:system")
|
29
|
+
task(default: ["db:test:prepare", "test", "test:system", "rubocop"])
|
@@ -3,11 +3,9 @@
|
|
3
3
|
module MaintenanceTasks
|
4
4
|
# Base class for all controllers used by this engine.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# Can be extended to add different authentication and authorization code.
|
7
7
|
class ApplicationController < ActionController::Base
|
8
|
-
|
9
|
-
|
10
|
-
BULMA_CDN = 'https://cdn.jsdelivr.net'
|
8
|
+
BULMA_CDN = "https://cdn.jsdelivr.net"
|
11
9
|
|
12
10
|
content_security_policy do |policy|
|
13
11
|
policy.style_src(BULMA_CDN)
|
@@ -17,10 +15,9 @@ module MaintenanceTasks
|
|
17
15
|
before_action do
|
18
16
|
request.content_security_policy_nonce_generator ||=
|
19
17
|
->(_request) { SecureRandom.base64(16) }
|
20
|
-
request.content_security_policy_nonce_directives = [
|
18
|
+
request.content_security_policy_nonce_directives = ["style-src"]
|
21
19
|
end
|
22
20
|
|
23
21
|
protect_from_forgery with: :exception
|
24
22
|
end
|
25
|
-
private_constant :ApplicationController
|
26
23
|
end
|
@@ -6,17 +6,7 @@ module MaintenanceTasks
|
|
6
6
|
#
|
7
7
|
# @api private
|
8
8
|
class RunsController < ApplicationController
|
9
|
-
before_action :set_run
|
10
|
-
|
11
|
-
# Shows a full list of Runs.
|
12
|
-
def index
|
13
|
-
query = Run.all.order(id: :desc)
|
14
|
-
if params[:task_name].present?
|
15
|
-
task_name = Run.sanitize_sql_like(params[:task_name])
|
16
|
-
query = query.where('task_name LIKE ?', "%#{task_name}%")
|
17
|
-
end
|
18
|
-
@pagy, @runs = pagy(query)
|
19
|
-
end
|
9
|
+
before_action :set_run
|
20
10
|
|
21
11
|
# Updates a Run status to paused.
|
22
12
|
def pause
|
@@ -40,5 +30,4 @@ module MaintenanceTasks
|
|
40
30
|
@run = Run.find(params.fetch(:id))
|
41
31
|
end
|
42
32
|
end
|
43
|
-
private_constant :RunsController
|
44
33
|
end
|
@@ -7,7 +7,7 @@ module MaintenanceTasks
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
class TasksController < ApplicationController
|
10
|
-
before_action :set_refresh, only: [:index
|
10
|
+
before_action :set_refresh, only: [:index]
|
11
11
|
|
12
12
|
# Renders the maintenance_tasks/tasks page, displaying
|
13
13
|
# available tasks to users, grouped by category.
|
@@ -19,12 +19,16 @@ module MaintenanceTasks
|
|
19
19
|
# Shows running and completed instances of the Task.
|
20
20
|
def show
|
21
21
|
@task = TaskData.find(params.fetch(:id))
|
22
|
-
|
22
|
+
set_refresh if @task.last_run&.active?
|
23
|
+
@runs_page = RunsPage.new(@task.previous_runs, params[:cursor])
|
23
24
|
end
|
24
25
|
|
25
26
|
# Runs a given Task and redirects to the Task page.
|
26
27
|
def run
|
27
|
-
task = Runner.
|
28
|
+
task = Runner.run(
|
29
|
+
name: params.fetch(:id),
|
30
|
+
csv_file: params[:csv_file]
|
31
|
+
)
|
28
32
|
redirect_to(task_path(task))
|
29
33
|
rescue ActiveRecord::RecordInvalid => error
|
30
34
|
redirect_to(task_path(error.record.task_name), alert: error.message)
|
@@ -38,5 +42,4 @@ module MaintenanceTasks
|
|
38
42
|
@refresh = 3
|
39
43
|
end
|
40
44
|
end
|
41
|
-
private_constant :TasksController
|
42
45
|
end
|
@@ -4,17 +4,6 @@ module MaintenanceTasks
|
|
4
4
|
#
|
5
5
|
# @api private
|
6
6
|
module ApplicationHelper
|
7
|
-
include Pagy::Frontend
|
8
|
-
|
9
|
-
# Renders pagination for the page, if there is more than one page present.
|
10
|
-
#
|
11
|
-
# @param pagy [Pagy] the pagy instance containing pagination details,
|
12
|
-
# including the number of pages the results are spread across.
|
13
|
-
# @return [String] the HTML to render for pagination.
|
14
|
-
def pagination(pagy)
|
15
|
-
raw(pagy_bulma_nav(pagy)) if pagy.pages > 1
|
16
|
-
end
|
17
|
-
|
18
7
|
# Renders a time element with the given datetime, worded as relative to the
|
19
8
|
# current time.
|
20
9
|
#
|
@@ -24,44 +13,9 @@ module MaintenanceTasks
|
|
24
13
|
# @param datetime [ActiveSupport::TimeWithZone] the time to be presented.
|
25
14
|
# @return [String] the HTML to render with the relative datetime in words.
|
26
15
|
def time_ago(datetime)
|
27
|
-
time_tag(datetime, title: datetime.utc.iso8601, class:
|
28
|
-
time_ago_in_words(datetime) +
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# Fix stylesheet_link_tag to handle integrity when preloading.
|
33
|
-
# To be reverted once fixed upstream in Rails.
|
34
|
-
def stylesheet_link_tag(*sources)
|
35
|
-
return super unless respond_to?(:send_preload_links_header, true)
|
36
|
-
options = sources.extract_options!.stringify_keys
|
37
|
-
path_options = options.extract!('protocol', 'host', 'skip_pipeline')
|
38
|
-
.symbolize_keys
|
39
|
-
preload_links = []
|
40
|
-
crossorigin = options.delete('crossorigin')
|
41
|
-
crossorigin = 'anonymous' if crossorigin == true
|
42
|
-
nopush = options['nopush'].nil? ? true : options.delete('nopush')
|
43
|
-
integrity = options['integrity']
|
44
|
-
|
45
|
-
sources_tags = sources.uniq.map do |source|
|
46
|
-
href = path_to_stylesheet(source, path_options)
|
47
|
-
preload_link = "<#{href}>; rel=preload; as=style"
|
48
|
-
preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
|
49
|
-
preload_link += "; integrity=#{integrity}" unless integrity.nil?
|
50
|
-
preload_link += '; nopush' if nopush
|
51
|
-
preload_links << preload_link
|
52
|
-
tag_options = {
|
53
|
-
'rel' => 'stylesheet',
|
54
|
-
'media' => 'screen',
|
55
|
-
'crossorigin' => crossorigin,
|
56
|
-
'href' => href,
|
57
|
-
}.merge!(options)
|
58
|
-
tag(:link, tag_options)
|
16
|
+
time_tag(datetime, title: datetime.utc.iso8601, class: "is-clickable") do
|
17
|
+
time_ago_in_words(datetime) + " ago"
|
59
18
|
end
|
60
|
-
|
61
|
-
send_preload_links_header(preload_links)
|
62
|
-
|
63
|
-
safe_join(sources_tags)
|
64
19
|
end
|
65
20
|
end
|
66
|
-
private_constant :ApplicationHelper
|
67
21
|
end
|