deployangel 0.1.21 → 0.1.23
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 +21 -0
- data/README.md +46 -1
- data/lib/deployangel/configuration.rb +8 -1
- data/lib/deployangel/metadata.rb +67 -1
- data/lib/deployangel/rails/metadata.rb +31 -4
- data/lib/deployangel/rails/railtie.rb +11 -1
- data/lib/deployangel/tasks.rb +74 -0
- data/lib/deployangel/version.rb +1 -1
- data/lib/deployangel.rb +10 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2635666118ec2250b5414245e3ea0aa1026d30e4369788e2c82bf6e6b0a52f71
|
|
4
|
+
data.tar.gz: 0fac6aa9bf419e2ad7a93a289902c94fa94a6d0b42c1418d7370afbaf90501cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 41f77d3e77fae4bccf35c82570582e01501246314c540d6bf6d227cdcd15e033237d62d9b0b2769e80766f53293982b4e8fe07e644ced1e99d93ca13a57b93f2
|
|
7
|
+
data.tar.gz: 674cb4c4972c88d861375904572c1048f247f041400c52b8d5380f44b3ff76d8b6f473362b404bedcf2377e1b6811cf96eea39f5cb9934b07271ddd627376afa
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.23 (2026-10-09)
|
|
4
|
+
|
|
5
|
+
- GoodJob's cron (`config.good_job.cron`, or `GOOD_JOB_CRON`) is read from
|
|
6
|
+
the processes that run it, so its jobs are expected on schedule. Entries
|
|
7
|
+
whose schedule or class is a lambda, or that are off by default, are
|
|
8
|
+
left out; schedules without a zone are read in the server's.
|
|
9
|
+
|
|
10
|
+
## 0.1.22 (2026-10-09)
|
|
11
|
+
|
|
12
|
+
- Work scheduled outside the app's own scheduler is watched too.
|
|
13
|
+
`config.recurring_jobs` declares it by the name it runs under (a job
|
|
14
|
+
class, `"rake <task>"`, or a `DeployAngel.task` name) with a cron line
|
|
15
|
+
or Fugit's words, for cron, Heroku Scheduler, or a Kubernetes CronJob.
|
|
16
|
+
- `DeployAngel.task("name") { ... }` records plain code that a scheduler
|
|
17
|
+
starts as a run of that name, with its duration and whether it raised.
|
|
18
|
+
- Rake tasks a schedule names are recorded with no code change, when the
|
|
19
|
+
task loads the app (`:environment`).
|
|
20
|
+
- The whenever gem's `config/schedule.rb` is read with whenever's own
|
|
21
|
+
parser, when whenever is in the bundle: rake tasks and runners that
|
|
22
|
+
perform a job class are expected on schedule, in the server's zone.
|
|
23
|
+
|
|
3
24
|
## 0.1.21 (2026-10-09)
|
|
4
25
|
|
|
5
26
|
- `deployangel exercise` stops requesting a page after its first 404, 405,
|
data/README.md
CHANGED
|
@@ -98,7 +98,8 @@ the dashboard says so.
|
|
|
98
98
|
as it is. If your app's messages might hold personal or health data, [turn
|
|
99
99
|
messages off](#exception-messages).
|
|
100
100
|
- Once per process: the route table, job classes, recurring schedules
|
|
101
|
-
declared for Solid Queue, sidekiq-cron,
|
|
101
|
+
declared for Solid Queue, GoodJob, sidekiq-cron, sidekiq-scheduler, or
|
|
102
|
+
whenever, critical
|
|
102
103
|
flows, and file digests (relative paths and hashes, never file contents) so
|
|
103
104
|
DeployAngel can tell which routes changed in a release.
|
|
104
105
|
Disable digests with `DEPLOYANGEL_FILE_DIGESTS=false`.
|
|
@@ -210,6 +211,50 @@ end
|
|
|
210
211
|
Jobs that exist only in Redis, such as ones created in code or in the
|
|
211
212
|
Sidekiq web UI, aren't read.
|
|
212
213
|
|
|
214
|
+
GoodJob's cron (`config.good_job.cron`, or `GOOD_JOB_CRON`) is read from the
|
|
215
|
+
processes that run it, the ones with cron enabled. Schedules without a zone
|
|
216
|
+
are read in the server's, as GoodJob reads them. An entry whose `cron:` or
|
|
217
|
+
`class:` is a lambda, or that's `enabled_by_default: false`, isn't expected.
|
|
218
|
+
The agent doesn't see entries turned off in GoodJob's dashboard, so one you
|
|
219
|
+
switch off there will look missed after the next deploy.
|
|
220
|
+
|
|
221
|
+
#### Cron, Heroku Scheduler, and whenever
|
|
222
|
+
|
|
223
|
+
Work that something outside the app starts on a schedule, such as cron,
|
|
224
|
+
Heroku Scheduler, or a Kubernetes CronJob, is invisible to those files.
|
|
225
|
+
Declare it by the name it runs under, with a cron line or words like
|
|
226
|
+
`"every day at 4am"`, in the server's time zone unless you add one
|
|
227
|
+
(`"0 3 * * * America/New_York"`):
|
|
228
|
+
|
|
229
|
+
```ruby
|
|
230
|
+
DeployAngel.configure do |config|
|
|
231
|
+
config.recurring_jobs = {
|
|
232
|
+
"NightlyInvoiceJob" => "0 3 * * *", # bin/rails runner "NightlyInvoiceJob.perform_now"
|
|
233
|
+
"rake invoices:send" => "every day at 4am", # bin/rails invoices:send
|
|
234
|
+
"nightly import" => "30 2 * * *" # DeployAngel.task("nightly import") { ... }
|
|
235
|
+
}
|
|
236
|
+
end
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
- **A job class** is recorded wherever it runs, a one-off `rails runner`
|
|
240
|
+
included.
|
|
241
|
+
- **A rake task** named `"rake <task>"` is recorded with no code change, as
|
|
242
|
+
long as it loads the app (depends on `:environment`).
|
|
243
|
+
- **Any other code** is recorded when you wrap it, which returns the block's
|
|
244
|
+
value and re-raises what it raises:
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
DeployAngel.task("nightly import") { Importer.run }
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The [whenever](https://github.com/javan/whenever) gem's `config/schedule.rb`
|
|
251
|
+
is read automatically when whenever is in the app's bundle (it's usually in
|
|
252
|
+
the Gemfile already, for deploys): its `rake` jobs, and `runner` jobs that
|
|
253
|
+
perform a job class (`"NightlyInvoiceJob.perform_later"`), are expected on
|
|
254
|
+
the schedule whenever writes to the crontab. Other `runner` code and
|
|
255
|
+
`command` jobs can't be matched to a run; wrap them in `DeployAngel.task`
|
|
256
|
+
and declare them as above.
|
|
257
|
+
|
|
213
258
|
## Checkpoints
|
|
214
259
|
|
|
215
260
|
Errors and latency don't catch work that silently stops happening. Count the
|
|
@@ -11,7 +11,8 @@ module DeployAngel
|
|
|
11
11
|
|
|
12
12
|
attr_accessor :token, :endpoint, :enabled, :environments, :release_version, :revision,
|
|
13
13
|
:flush_interval, :open_timeout, :read_timeout, :max_queued_payloads, :max_routes, :logger,
|
|
14
|
-
:file_digests, :critical_flows, :ignored_routes, :sidekiq_cron_schedule_file, :exception_messages
|
|
14
|
+
:file_digests, :critical_flows, :ignored_routes, :sidekiq_cron_schedule_file, :exception_messages,
|
|
15
|
+
:recurring_jobs
|
|
15
16
|
|
|
16
17
|
def initialize(env = ENV)
|
|
17
18
|
@token = env["DEPLOYANGEL_TOKEN"]
|
|
@@ -36,6 +37,12 @@ module DeployAngel
|
|
|
36
37
|
# For an app that loads sidekiq-cron's jobs itself (load_from_hash!)
|
|
37
38
|
# from its own file, such as "config/sidekiq_schedule.yml.erb".
|
|
38
39
|
@sidekiq_cron_schedule_file = nil
|
|
40
|
+
# Work scheduled outside the app's own scheduler (cron, Heroku
|
|
41
|
+
# Scheduler, a Kubernetes CronJob), by the name it runs under: a job
|
|
42
|
+
# class, "rake <task>", or a DeployAngel.task name. Each schedule is a
|
|
43
|
+
# cron line or Fugit's words ("every day at 4am"), optionally ending
|
|
44
|
+
# in a time zone.
|
|
45
|
+
@recurring_jobs = {}
|
|
39
46
|
end
|
|
40
47
|
|
|
41
48
|
# Reports only with a token, and by default in every environment but
|
data/lib/deployangel/metadata.rb
CHANGED
|
@@ -63,7 +63,73 @@ module DeployAngel
|
|
|
63
63
|
# Declared recurring jobs. Each source is read on its own, so a file that
|
|
64
64
|
# can't be read leaves the others' schedules in place.
|
|
65
65
|
def schedules
|
|
66
|
-
sidekiq_cron_schedules + sidekiq_scheduler_schedules
|
|
66
|
+
sidekiq_cron_schedules + sidekiq_scheduler_schedules + whenever_schedules + configured_schedules
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# config.recurring_jobs: work scheduled outside the app, by the name it
|
|
70
|
+
# runs under. A schedule without a zone is read in the server's.
|
|
71
|
+
def configured_schedules
|
|
72
|
+
Array(@config.recurring_jobs).filter_map do |name, schedule|
|
|
73
|
+
next if name.to_s.strip.empty? || schedule.to_s.strip.empty?
|
|
74
|
+
|
|
75
|
+
{ "key" => name.to_s, "class" => name.to_s, "schedule" => schedule.to_s, "source" => "config", "time_zone" => local_time_zone }
|
|
76
|
+
end
|
|
77
|
+
rescue StandardError
|
|
78
|
+
[]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
WHENEVER_FILE = "config/schedule.rb"
|
|
82
|
+
WHENEVER_JOB = /\A\s*(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)(?:\.set\(.*?\))?\.(?:perform_now|perform_later|perform_async|perform_inline)\b/m
|
|
83
|
+
|
|
84
|
+
# The whenever gem's config/schedule.rb, which it turns into the server's
|
|
85
|
+
# crontab on deploy. Read with whenever's own parser, so times come out
|
|
86
|
+
# as cron reads them, in the server's zone. Rake tasks are recorded by
|
|
87
|
+
# name (Tasks.install_rake); a runner that performs a job class is
|
|
88
|
+
# matched by that class. Other commands can't be told apart, so they're
|
|
89
|
+
# left to config.recurring_jobs and DeployAngel.task.
|
|
90
|
+
def whenever_schedules
|
|
91
|
+
path = File.join(@root, WHENEVER_FILE)
|
|
92
|
+
return [] unless File.file?(path) && whenever_loaded?
|
|
93
|
+
|
|
94
|
+
list = ::Whenever::JobList.new(file: path)
|
|
95
|
+
chronic = list.instance_variable_get(:@chronic_options) || {}
|
|
96
|
+
by_time = (list.instance_variable_get(:@jobs) || {}).values.flat_map(&:to_a)
|
|
97
|
+
by_time.flat_map do |time, jobs|
|
|
98
|
+
Array(jobs).flat_map { |job| whenever_entries(time, job, chronic) }
|
|
99
|
+
end.uniq { |schedule| schedule["key"] }
|
|
100
|
+
rescue StandardError, ScriptError
|
|
101
|
+
[]
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def whenever_loaded?
|
|
105
|
+
require "whenever"
|
|
106
|
+
true
|
|
107
|
+
rescue LoadError
|
|
108
|
+
false
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def whenever_entries(time, job, chronic)
|
|
112
|
+
name = whenever_job_name(job) or return []
|
|
113
|
+
crons = ::Whenever::Output::Cron.enumerate(time).flat_map do |each|
|
|
114
|
+
::Whenever::Output::Cron.enumerate(job.at, false).map do |at|
|
|
115
|
+
::Whenever::Output::Cron.new(each, nil, at, chronic_options: chronic).time_in_cron_syntax.to_s
|
|
116
|
+
end
|
|
117
|
+
end.uniq.reject { |cron| cron.empty? || cron == "@reboot" }
|
|
118
|
+
crons.map do |cron|
|
|
119
|
+
{ "key" => crons.one? ? name : "#{name} (#{cron})", "class" => name, "schedule" => cron, "source" => "whenever",
|
|
120
|
+
"time_zone" => local_time_zone }
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def whenever_job_name(job)
|
|
125
|
+
template = job.instance_variable_get(:@template).to_s
|
|
126
|
+
task = job.instance_variable_get(:@options)&.dig(:task).to_s.strip
|
|
127
|
+
if template.match?(/\brake :task\b/)
|
|
128
|
+
rake = task.split.first.to_s
|
|
129
|
+
"#{Tasks::RAKE_PREFIX}#{rake}" unless rake.empty?
|
|
130
|
+
elsif template.include?(":runner_command")
|
|
131
|
+
task[WHENEVER_JOB, 1]
|
|
132
|
+
end
|
|
67
133
|
end
|
|
68
134
|
|
|
69
135
|
# sidekiq-cron jobs from its schedule file (config/schedule.yml unless
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module DeployAngel
|
|
4
4
|
module Rails
|
|
5
5
|
# The Rails adapter: the route table from the router, job classes from
|
|
6
|
-
# Active Job, and Solid Queue's recurring tasks. The schedule files
|
|
6
|
+
# Active Job, and Solid Queue's and GoodJob's recurring tasks. The schedule files
|
|
7
7
|
# sidekiq-cron and sidekiq-scheduler read, and the file digests, are
|
|
8
8
|
# gathered in DeployAngel::Metadata.
|
|
9
9
|
class Metadata < ::DeployAngel::Metadata
|
|
@@ -44,10 +44,10 @@ module DeployAngel
|
|
|
44
44
|
[]
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
# Solid Queue's
|
|
48
|
-
# on every framework.
|
|
47
|
+
# Solid Queue's and GoodJob's schedules live in the Rails app; the rest
|
|
48
|
+
# are read the same way on every framework.
|
|
49
49
|
def schedules
|
|
50
|
-
solid_queue_schedules + super
|
|
50
|
+
solid_queue_schedules + good_job_schedules + super
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
# Solid Queue recurring tasks for the current environment.
|
|
@@ -69,6 +69,33 @@ module DeployAngel
|
|
|
69
69
|
[]
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
+
# GoodJob's cron, from a process that runs it. GoodJob turns cron on
|
|
73
|
+
# per process (often only the worker's, with GOOD_JOB_ENABLE_CRON), and
|
|
74
|
+
# its CLI applies --enable-cron after boot, before metadata is first
|
|
75
|
+
# sent. A schedule without a zone is read in the server's, as Fugit
|
|
76
|
+
# reads it. A schedule or class given as a lambda can't be known
|
|
77
|
+
# without running app code, so it's left out.
|
|
78
|
+
def good_job_schedules
|
|
79
|
+
return [] unless defined?(::GoodJob) && ::GoodJob.respond_to?(:configuration)
|
|
80
|
+
|
|
81
|
+
configuration = ::GoodJob.configuration
|
|
82
|
+
return [] unless configuration.enable_cron?
|
|
83
|
+
|
|
84
|
+
configuration.cron.filter_map do |key, entry|
|
|
85
|
+
next unless entry.is_a?(Hash)
|
|
86
|
+
|
|
87
|
+
entry = entry.transform_keys(&:to_sym)
|
|
88
|
+
cron, job_class = entry.values_at(:cron, :class)
|
|
89
|
+
job_class = job_class.name if job_class.is_a?(Module)
|
|
90
|
+
next if entry[:enabled_by_default] == false
|
|
91
|
+
next unless cron.is_a?(String) && !cron.strip.empty? && job_class.is_a?(String) && !job_class.empty?
|
|
92
|
+
|
|
93
|
+
{ "key" => key.to_s, "class" => job_class, "schedule" => cron, "source" => "good_job", "time_zone" => local_time_zone }
|
|
94
|
+
end
|
|
95
|
+
rescue StandardError
|
|
96
|
+
[]
|
|
97
|
+
end
|
|
98
|
+
|
|
72
99
|
# A command task runs as a job of this class, so its runs show up in
|
|
73
100
|
# job telemetry under that name.
|
|
74
101
|
def command_job_class
|
|
@@ -24,14 +24,24 @@ module DeployAngel
|
|
|
24
24
|
DeployAngel::Apartment.install if DeployAngel.configuration.exception_messages
|
|
25
25
|
# The metadata goes in at start, before the reporter thread can run:
|
|
26
26
|
# the code fingerprint is built from its file digests.
|
|
27
|
+
metadata = DeployAngel::Rails::Metadata.new(app: app, config: DeployAngel.configuration, root: ::Rails.root.to_s, environment: ::Rails.env)
|
|
27
28
|
DeployAngel.start(
|
|
28
29
|
environment: ::Rails.env,
|
|
29
30
|
root: ::Rails.root.to_s,
|
|
30
31
|
framework: "rails",
|
|
31
32
|
framework_version: ::Rails.version,
|
|
32
33
|
logger: ::Rails.logger,
|
|
33
|
-
metadata:
|
|
34
|
+
metadata: metadata
|
|
34
35
|
)
|
|
36
|
+
# A rake task cron starts loads the app (its :environment
|
|
37
|
+
# prerequisite) before it runs, so the hook is in place in time.
|
|
38
|
+
DeployAngel::Tasks.install_rake(metadata.schedules) if DeployAngel.recording? && Railtie.rake_process?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.rake_process?
|
|
42
|
+
defined?(::Rake.application) && ::Rake.application.top_level_tasks.any?
|
|
43
|
+
rescue StandardError
|
|
44
|
+
false
|
|
35
45
|
end
|
|
36
46
|
end
|
|
37
47
|
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
|
|
5
|
+
module DeployAngel
|
|
6
|
+
# Work that runs on a schedule but isn't a job, such as a rake task that
|
|
7
|
+
# cron, Heroku Scheduler, or whenever starts. Recorded as a job run under
|
|
8
|
+
# its name, with its duration and whether it raised, so DeployAngel can
|
|
9
|
+
# expect it on schedule like any recurring job.
|
|
10
|
+
module Tasks
|
|
11
|
+
NAME = /\A[[:graph:]][[:print:]]{0,199}\z/
|
|
12
|
+
RAKE_PREFIX = "rake "
|
|
13
|
+
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
def run(name)
|
|
17
|
+
name = name.to_s
|
|
18
|
+
return yield unless DeployAngel.recording? && valid?(name)
|
|
19
|
+
|
|
20
|
+
DeployAngel.add_capability("jobs")
|
|
21
|
+
previous = ExecutionContext.enter(ExecutionContext::JOB)
|
|
22
|
+
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
23
|
+
failed = false
|
|
24
|
+
begin
|
|
25
|
+
yield
|
|
26
|
+
rescue Exception => e # rubocop:disable Lint/RescueException -- recorded, then re-raised untouched
|
|
27
|
+
failed = true
|
|
28
|
+
DeployAngel.record_exception(e, source: "job_class:#{name}")
|
|
29
|
+
raise
|
|
30
|
+
ensure
|
|
31
|
+
ExecutionContext.restore(previous)
|
|
32
|
+
DeployAngel.record_job(job_class: name, duration_ms: (Process.clock_gettime(Process::CLOCK_MONOTONIC) - started) * 1000.0,
|
|
33
|
+
failed: failed)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def valid?(name)
|
|
38
|
+
return true if name.match?(NAME)
|
|
39
|
+
|
|
40
|
+
unless @warned
|
|
41
|
+
DeployAngel.configuration.logger&.warn("DeployAngel didn't record task #{name.inspect}: use a name of up to 200 printable characters")
|
|
42
|
+
@warned = true
|
|
43
|
+
end
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Records the rake tasks a schedule names ("rake invoices:send"), so a
|
|
48
|
+
# task cron starts needs no code change. Only those tasks: others, like
|
|
49
|
+
# db:migrate at deploy time, aren't recurring work.
|
|
50
|
+
def install_rake(schedules)
|
|
51
|
+
return unless defined?(::Rake::Task)
|
|
52
|
+
|
|
53
|
+
names = Array(schedules).filter_map { |schedule| schedule["class"].to_s.delete_prefix(RAKE_PREFIX) if schedule["class"].to_s.start_with?(RAKE_PREFIX) }
|
|
54
|
+
return if names.empty?
|
|
55
|
+
|
|
56
|
+
@rake_tasks = names.to_set
|
|
57
|
+
::Rake::Task.prepend(RakeTask) unless ::Rake::Task <= RakeTask
|
|
58
|
+
rescue StandardError
|
|
59
|
+
nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def scheduled_rake_task?(name)
|
|
63
|
+
@rake_tasks&.include?(name) || false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
module RakeTask
|
|
67
|
+
def execute(args = nil)
|
|
68
|
+
return super unless DeployAngel::Tasks.scheduled_rake_task?(name)
|
|
69
|
+
|
|
70
|
+
DeployAngel::Tasks.run("#{DeployAngel::Tasks::RAKE_PREFIX}#{name}") { super }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/deployangel/version.rb
CHANGED
data/lib/deployangel.rb
CHANGED
|
@@ -61,6 +61,15 @@ module DeployAngel
|
|
|
61
61
|
agent&.record_exception(exception, **options)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
# Records a block as a run of scheduled work, for code that cron or a
|
|
65
|
+
# scheduler outside the app starts and that isn't a job:
|
|
66
|
+
# DeployAngel.task("invoices:send") { Invoice.send_due }
|
|
67
|
+
# It returns the block's value and re-raises what it raises. Declare the
|
|
68
|
+
# schedule in config.recurring_jobs so a missed run is noticed.
|
|
69
|
+
def task(name, &)
|
|
70
|
+
Tasks.run(name, &)
|
|
71
|
+
end
|
|
72
|
+
|
|
64
73
|
CHECKPOINT_NAME = /\A[a-z0-9][a-z0-9_.:-]{0,99}\z/i
|
|
65
74
|
|
|
66
75
|
# Counts a business event, such as DeployAngel.checkpoint("order.fulfilled").
|
|
@@ -116,6 +125,7 @@ require_relative "deployangel/rack/http"
|
|
|
116
125
|
require_relative "deployangel/rails/http"
|
|
117
126
|
require_relative "deployangel/rails/active_job"
|
|
118
127
|
require_relative "deployangel/rails/error_subscriber"
|
|
128
|
+
require_relative "deployangel/tasks"
|
|
119
129
|
require_relative "deployangel/metadata"
|
|
120
130
|
require_relative "deployangel/rails/metadata"
|
|
121
131
|
require_relative "deployangel/sidekiq"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: deployangel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.23
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jordan Owens
|
|
@@ -57,6 +57,7 @@ files:
|
|
|
57
57
|
- lib/deployangel/rails/metadata.rb
|
|
58
58
|
- lib/deployangel/rails/railtie.rb
|
|
59
59
|
- lib/deployangel/sidekiq.rb
|
|
60
|
+
- lib/deployangel/tasks.rb
|
|
60
61
|
- lib/deployangel/verification_waiter.rb
|
|
61
62
|
- lib/deployangel/version.rb
|
|
62
63
|
homepage: https://www.deployangel.com
|
|
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
83
84
|
- !ruby/object:Gem::Version
|
|
84
85
|
version: '0'
|
|
85
86
|
requirements: []
|
|
86
|
-
rubygems_version: 4.0.
|
|
87
|
+
rubygems_version: 4.0.0
|
|
87
88
|
specification_version: 4
|
|
88
89
|
summary: 'DeployAngel agent for Rails: production verification for every deployment.'
|
|
89
90
|
test_files: []
|