deployangel 0.1.7 → 0.1.8
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 +12 -0
- data/README.md +87 -4
- data/lib/deployangel/configuration.rb +4 -1
- data/lib/deployangel/rails/http.rb +14 -1
- data/lib/deployangel/rails/metadata.rb +6 -3
- data/lib/deployangel/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 26338624984d9d36012cf0e66b2448ddf31985ae9b629c4ca211e467c5e39e6c
|
|
4
|
+
data.tar.gz: bbbb651d96b7091563b263e20df94bc8471bf132bbf8a0511297176c111a74ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5846a9913395c0defeeb41b1e5f5ad20a924439ee92ca899b09ae76dcbf935748432cf2c02e01b81772029796f39f5cc221c690313b30ea73a2831aac11825d0
|
|
7
|
+
data.tar.gz: 534d6218818cb03b8be1f4144d21d129484b112acdb08a18c53300f62c67dd7198d9dc48a66284ada08069ea08a0795f9cce705d8c6baa11f4fc371d5edf88e5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.8 (2026-10-04)
|
|
4
|
+
|
|
5
|
+
- Health checks served by a lambda or a mounted Rack app at a conventional
|
|
6
|
+
path (`/up`, `/health`, `/healthz`, `/healthcheck`, `/health_check`,
|
|
7
|
+
`/livez`, `/readyz`, `/statusz`, `/ping`) are left out, like the health-check
|
|
8
|
+
gems'. A controller at one of these paths is still recorded, since it may be
|
|
9
|
+
a real page.
|
|
10
|
+
- `config.sidekiq_cron_schedule_file` reads sidekiq-cron jobs from the file an
|
|
11
|
+
app loads them from itself, such as `config/sidekiq_schedule.yml.erb` passed
|
|
12
|
+
to `Sidekiq::Cron::Job.load_from_hash!`. ERB is rendered, as in the default
|
|
13
|
+
file.
|
|
14
|
+
|
|
3
15
|
## 0.1.7 (2026-10-04)
|
|
4
16
|
|
|
5
17
|
- Health checks from OkComputer, health_check, and rails-healthcheck are left
|
data/README.md
CHANGED
|
@@ -45,8 +45,10 @@ ENV DEPLOYANGEL_REVISION=$GIT_SHA
|
|
|
45
45
|
|
|
46
46
|
and build with `docker build --build-arg GIT_SHA=$(git rev-parse HEAD) .`. On
|
|
47
47
|
DigitalOcean App Platform, set `DEPLOYANGEL_REVISION: ${_self.COMMIT_HASH}` in
|
|
48
|
-
the app spec.
|
|
49
|
-
|
|
48
|
+
the app spec. On Elastic Beanstalk, see
|
|
49
|
+
[Deploying to Elastic Beanstalk](#deploying-to-elastic-beanstalk). If the agent
|
|
50
|
+
finds none of these, its telemetry can't be tied to a deploy, and the dashboard
|
|
51
|
+
says so.
|
|
50
52
|
|
|
51
53
|
## What it sends
|
|
52
54
|
|
|
@@ -73,6 +75,17 @@ deploy, and the dashboard says so.
|
|
|
73
75
|
It does not send request bodies, parameters, headers, cookies, SQL, logs, or
|
|
74
76
|
user data.
|
|
75
77
|
|
|
78
|
+
## Data and pricing
|
|
79
|
+
|
|
80
|
+
- Everything goes to DeployAngel's hosted service, which runs on DigitalOcean
|
|
81
|
+
in the United States. There's no self-hosted version, and no choice of
|
|
82
|
+
region.
|
|
83
|
+
- Telemetry is kept for 21 days, and release history for 7, 30, or 90 days
|
|
84
|
+
depending on the plan. The [privacy policy](https://deployangel.com/privacy)
|
|
85
|
+
has the details and the services DeployAngel uses.
|
|
86
|
+
- DeployAngel is free during the beta, with notice before paid plans start.
|
|
87
|
+
See [pricing](https://deployangel.com/pricing).
|
|
88
|
+
|
|
76
89
|
## Safety
|
|
77
90
|
|
|
78
91
|
- Nothing runs on the network during a request. Requests only update
|
|
@@ -115,8 +128,11 @@ Health checks aren't recorded: load balancers and uptime monitors call them
|
|
|
115
128
|
all the time and they always answer fast, so they would make your app look
|
|
116
129
|
busier and healthier than its real pages. The agent recognizes Rails' own
|
|
117
130
|
(`/up`), OkComputer, health_check, and rails-healthcheck, wherever they're
|
|
118
|
-
mounted
|
|
119
|
-
|
|
131
|
+
mounted, and a lambda or Rack app at a conventional path (`/up`, `/health`,
|
|
132
|
+
`/healthz`, `/healthcheck`, `/health_check`, `/livez`, `/readyz`, `/statusz`,
|
|
133
|
+
`/ping`), such as `get "healthz", to: ->(_) { [200, {}, ["ok"]] }`. If your
|
|
134
|
+
health check is your own controller, list its route the way the dashboard
|
|
135
|
+
shows it. HEAD requests to it are left out too:
|
|
120
136
|
|
|
121
137
|
```ruby
|
|
122
138
|
DeployAngel.configure do |config|
|
|
@@ -124,6 +140,22 @@ DeployAngel.configure do |config|
|
|
|
124
140
|
end
|
|
125
141
|
```
|
|
126
142
|
|
|
143
|
+
DeployAngel expects declared recurring jobs on schedule. It reads Solid Queue's
|
|
144
|
+
`config/recurring.yml`, sidekiq-scheduler's section of Sidekiq's config, and
|
|
145
|
+
sidekiq-cron's schedule file (`config/schedule.yml` unless sidekiq-cron is
|
|
146
|
+
configured otherwise), rendering ERB in each. If your app loads sidekiq-cron
|
|
147
|
+
jobs itself from another file, for example with `Sidekiq::Cron::Job.load_from_hash!`,
|
|
148
|
+
point the agent at that file:
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
DeployAngel.configure do |config|
|
|
152
|
+
config.sidekiq_cron_schedule_file = "config/sidekiq_schedule.yml.erb"
|
|
153
|
+
end
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Jobs that exist only in Redis, such as ones created in code or in the
|
|
157
|
+
Sidekiq web UI, aren't read.
|
|
158
|
+
|
|
127
159
|
`DEPLOYANGEL_ENABLED=true|false` forces reporting on or off in any environment.
|
|
128
160
|
`DEPLOYANGEL_URL` overrides the API endpoint (default `https://api.deployangel.com`).
|
|
129
161
|
|
|
@@ -182,6 +214,28 @@ to the run. Explicit options still win.
|
|
|
182
214
|
DEPLOYANGEL_API_TOKEN: ${{ secrets.DEPLOYANGEL_API_TOKEN }}
|
|
183
215
|
```
|
|
184
216
|
|
|
217
|
+
### When a release never reports
|
|
218
|
+
|
|
219
|
+
A registered release must start reporting within 15 minutes of being
|
|
220
|
+
registered. If no instance reports it by then, the verdict is
|
|
221
|
+
**inconclusive** with reason `no_release_telemetry`, and the dashboard says
|
|
222
|
+
"Not cleared: this release never reported". The usual causes are a release
|
|
223
|
+
that never booted (a failed migration or a crash on start), an agent with no
|
|
224
|
+
token, or a release identity the agent can't find. If the app kept reporting
|
|
225
|
+
an earlier release instead, the verdict names it ("while v41 kept running").
|
|
226
|
+
`deployangel verify --wait` exits 2, so the CI step above fails the job.
|
|
227
|
+
|
|
228
|
+
If the release does start reporting within 24 hours, as after a slow rolling
|
|
229
|
+
deploy, DeployAngel withdraws that verdict and verifies the release from then,
|
|
230
|
+
unless a newer release has rolled out first. A CI job that already failed stays
|
|
231
|
+
failed; run `deployangel verify --wait` again to wait for the new verdict.
|
|
232
|
+
|
|
233
|
+
Only registered releases are caught this way. DeployAngel learns about an
|
|
234
|
+
unregistered release when the agent first reports it, so a release that never
|
|
235
|
+
boots is never seen. If a release that dies on boot is a risk for you, register
|
|
236
|
+
deploys from CI. The 15 minutes count from registration, so register when the
|
|
237
|
+
deploy finishes, not when it starts.
|
|
238
|
+
|
|
185
239
|
### Deploying with Kamal
|
|
186
240
|
|
|
187
241
|
The agent reads `KAMAL_VERSION`, so it knows its release with no setup. Pass
|
|
@@ -234,6 +288,35 @@ set :deployangel_register, false # turn it off, e.g. for a stage without De
|
|
|
234
288
|
With `:deployangel_wait`, `cap` exits with an error if the release fails
|
|
235
289
|
verification, which CI can act on. It never rolls anything back.
|
|
236
290
|
|
|
291
|
+
### Deploying to Elastic Beanstalk
|
|
292
|
+
|
|
293
|
+
Elastic Beanstalk doesn't tell the app which commit it's running. Set
|
|
294
|
+
`DEPLOYANGEL_REVISION` in the same `update-environment` call that deploys the
|
|
295
|
+
new version, so the two always change together. This works on every platform,
|
|
296
|
+
Docker included, with no build args. Then wait for the environment and register
|
|
297
|
+
the release:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
aws elasticbeanstalk update-environment \
|
|
301
|
+
--environment-name "$EB_ENV" \
|
|
302
|
+
--version-label "$VERSION_LABEL" \
|
|
303
|
+
--option-settings "Namespace=aws:elasticbeanstalk:application:environment,OptionName=DEPLOYANGEL_REVISION,Value=$GITHUB_SHA"
|
|
304
|
+
aws elasticbeanstalk wait environment-updated --environment-names "$EB_ENV"
|
|
305
|
+
|
|
306
|
+
bundle exec deployangel release --commit="$GITHUB_SHA" --version="$VERSION_LABEL"
|
|
307
|
+
bundle exec deployangel verify --wait --until=initial
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
`update-environment` returns as soon as the deploy starts, so don't skip the
|
|
311
|
+
wait: registering early starts the
|
|
312
|
+
[15-minute clock](#when-a-release-never-reports) before the new version is
|
|
313
|
+
running. If the deploy fails and Beanstalk rolls back, the environment still
|
|
314
|
+
returns to Ready, but the new commit never reports, so `verify` exits 2.
|
|
315
|
+
|
|
316
|
+
Leave `DEPLOYANGEL_RELEASE_VERSION` unset here. When the agent reports a
|
|
317
|
+
version, the release is matched by it, so it would have to equal `--version`
|
|
318
|
+
exactly. Matching by commit avoids that.
|
|
319
|
+
|
|
237
320
|
## CLI and coding agents
|
|
238
321
|
|
|
239
322
|
The gem ships a `deployangel` command. It doesn't boot Rails. Give it a token
|
|
@@ -11,7 +11,7 @@ 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
|
|
14
|
+
:file_digests, :critical_flows, :ignored_routes, :sidekiq_cron_schedule_file
|
|
15
15
|
|
|
16
16
|
def initialize(env = ENV)
|
|
17
17
|
@token = env["DEPLOYANGEL_TOKEN"]
|
|
@@ -30,6 +30,9 @@ module DeployAngel
|
|
|
30
30
|
@critical_flows = {}
|
|
31
31
|
# Route keys as the dashboard shows them, such as "GET /healthz".
|
|
32
32
|
@ignored_routes = []
|
|
33
|
+
# For an app that loads sidekiq-cron's jobs itself (load_from_hash!)
|
|
34
|
+
# from its own file, such as "config/sidekiq_schedule.yml.erb".
|
|
35
|
+
@sidekiq_cron_schedule_file = nil
|
|
33
36
|
end
|
|
34
37
|
|
|
35
38
|
# Reports only with a token. By default only in the listed
|
|
@@ -13,6 +13,9 @@ module DeployAngel
|
|
|
13
13
|
# counting them would make any app look busy and healthy. Others can
|
|
14
14
|
# be left out with config.ignored_routes.
|
|
15
15
|
HEALTH_CHECK_CONTROLLERS = %w[rails/health ok_computer/ok_computer health_check/health_check healthcheck/healthchecks].freeze
|
|
16
|
+
# Health checks served by a lambda or a mounted Rack app rather than a
|
|
17
|
+
# controller, at a conventional path such as /healthz.
|
|
18
|
+
HEALTH_CHECK_PATHS = %w[up health healthz healthcheck health_check livez readyz statusz ping].freeze
|
|
16
19
|
|
|
17
20
|
def initialize(app)
|
|
18
21
|
@app = app
|
|
@@ -37,7 +40,7 @@ module DeployAngel
|
|
|
37
40
|
|
|
38
41
|
private
|
|
39
42
|
def record(env, status, started, unhandled:, exception: nil)
|
|
40
|
-
return if
|
|
43
|
+
return if health_check?(env)
|
|
41
44
|
|
|
42
45
|
route = route_key(env)
|
|
43
46
|
return if route && DeployAngel.configuration.ignored_route?(route)
|
|
@@ -57,6 +60,16 @@ module DeployAngel
|
|
|
57
60
|
nil
|
|
58
61
|
end
|
|
59
62
|
|
|
63
|
+
# A controller at a health-check path may be a real page, so only
|
|
64
|
+
# controllerless routes are judged by their path.
|
|
65
|
+
def health_check?(env)
|
|
66
|
+
controller = env["action_dispatch.request.path_parameters"]&.dig(:controller)
|
|
67
|
+
return HEALTH_CHECK_CONTROLLERS.include?(controller) if controller
|
|
68
|
+
|
|
69
|
+
pattern = route_pattern(env) or return false
|
|
70
|
+
HEALTH_CHECK_PATHS.include?(pattern.delete_suffix(FORMAT_SUFFIX).split("/").last)
|
|
71
|
+
end
|
|
72
|
+
|
|
60
73
|
def route_key(env)
|
|
61
74
|
method = env["REQUEST_METHOD"]
|
|
62
75
|
if (pattern = route_pattern(env))
|
|
@@ -86,8 +86,10 @@ module DeployAngel
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# sidekiq-cron jobs from its schedule file (config/schedule.yml unless
|
|
89
|
-
# configured otherwise), which it loads when Sidekiq starts
|
|
90
|
-
#
|
|
89
|
+
# configured otherwise), which it loads when Sidekiq starts, or from
|
|
90
|
+
# the file in config.sidekiq_cron_schedule_file for an app that loads
|
|
91
|
+
# them itself. Jobs created in code live only in Redis, which the agent
|
|
92
|
+
# doesn't read.
|
|
91
93
|
def sidekiq_cron_schedules
|
|
92
94
|
return [] unless defined?(::Sidekiq::Cron)
|
|
93
95
|
|
|
@@ -105,7 +107,8 @@ module DeployAngel
|
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
def sidekiq_cron_schedule_file
|
|
108
|
-
configured =
|
|
110
|
+
configured = @config.sidekiq_cron_schedule_file
|
|
111
|
+
configured ||= ::Sidekiq::Cron.configuration.cron_schedule_file if ::Sidekiq::Cron.respond_to?(:configuration)
|
|
109
112
|
File.expand_path(configured || "config/schedule.yml", @root)
|
|
110
113
|
rescue StandardError
|
|
111
114
|
File.join(@root, "config", "schedule.yml")
|
data/lib/deployangel/version.rb
CHANGED