deployangel 0.1.37 → 0.1.38
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/lib/deployangel/cli/formatter.rb +28 -5
- data/lib/deployangel/cli.rb +4 -0
- data/lib/deployangel/mcp.rb +5 -0
- 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: 9a0944295d3cbddf9d6ff41ce21ad608b3c9615dc2910bfed6ef9745ffde6e93
|
|
4
|
+
data.tar.gz: 7197967f339bb1af5057528e2b08b9e894379051401d059f02a91ec6cd3083ad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fc73a15daea7553d4a04121c001a49feef7a15195b0313b1115ab572a387cc053bf80196d6c8d79baee8c980df2833c198cdf7a2e0dcdeda18d81235dd3c208
|
|
7
|
+
data.tar.gz: 4d5fe66f67476bd5c0e41137d6f3f38746d31da776ea295526e4becd463da21f61bf4d23a5d0ebfaac61df4c84d0d4692b67e49797d5e05a6cb63fa5e59a706f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.38 (2026-11-04)
|
|
4
|
+
|
|
5
|
+
- `deployangel verify` shows a volume drop (servers from 2026-11-04) as
|
|
6
|
+
what ran against what was expected (`0 requests, about 27 expected`),
|
|
7
|
+
and lists findings a person accepted as an intended change, with who
|
|
8
|
+
and why. A failing finding that could be intended gets the link where a
|
|
9
|
+
person can accept it; the CLI and MCP server can't, so an agent never
|
|
10
|
+
accepts its own failure.
|
|
11
|
+
- The MCP server's instructions, and the block `deployangel install
|
|
12
|
+
agents` writes, tell agents to hand that link to the user with their
|
|
13
|
+
evidence and never report the release as a success.
|
|
14
|
+
|
|
3
15
|
## 0.1.37 (2026-11-03)
|
|
4
16
|
|
|
5
17
|
- An exception raised entirely in gems, with no frame from the app's
|
|
@@ -10,7 +10,7 @@ module DeployAngel
|
|
|
10
10
|
"job_failure_rate" => "Job failure rate", "job_duration" => "Job duration p95", "queue_latency" => "Queue latency p95",
|
|
11
11
|
"new_fingerprint" => "New exception", "fingerprint_amplification" => "Exception amplification",
|
|
12
12
|
"missing_recurring_job" => "Recurring job", "first_use_failure" => "First-use failure", "external_check" => "External check",
|
|
13
|
-
"checkpoint_rate" => "Checkpoint"
|
|
13
|
+
"checkpoint_rate" => "Checkpoint", "volume_drop" => "Volume"
|
|
14
14
|
}.freeze
|
|
15
15
|
DURATIONS = %w[p95_latency job_duration queue_latency].freeze
|
|
16
16
|
# Exercise plan statuses with something worth running now.
|
|
@@ -18,6 +18,9 @@ module DeployAngel
|
|
|
18
18
|
REASONS = { "normally_active" => "normally active", "changed_in_release" => "changed in this release",
|
|
19
19
|
"rarely_used" => "rarely used", "critical_flow" => "critical flow" }.freeze
|
|
20
20
|
COUNTS = %w[new_fingerprint checkpoint_rate].freeze
|
|
21
|
+
# Findings worth listing: problems, and changes a person accepted as
|
|
22
|
+
# intended (servers from 2026-11-04 send "accepted").
|
|
23
|
+
LISTED = %w[failing warning accepted].freeze
|
|
21
24
|
|
|
22
25
|
module_function
|
|
23
26
|
|
|
@@ -26,7 +29,10 @@ module DeployAngel
|
|
|
26
29
|
problems = problems(document)
|
|
27
30
|
if problems.any?
|
|
28
31
|
lines << "Findings:"
|
|
29
|
-
problems.each
|
|
32
|
+
problems.each do |f|
|
|
33
|
+
lines << " #{f["status"].ljust(8)} #{finding_line(f)}"
|
|
34
|
+
acceptance_lines(f).each { |line| lines << " #{line}" }
|
|
35
|
+
end
|
|
30
36
|
end
|
|
31
37
|
if (gathering = gathering_line(document))
|
|
32
38
|
lines << "#{gathering} (--format=json for details)"
|
|
@@ -44,7 +50,7 @@ module DeployAngel
|
|
|
44
50
|
problems = problems(document)
|
|
45
51
|
if problems.any?
|
|
46
52
|
lines.push("", "| Status | Finding |", "| --- | --- |")
|
|
47
|
-
problems.each { |f| lines << "| #{f["status"]} | #{cell(finding_line(f))} |" }
|
|
53
|
+
problems.each { |f| lines << "| #{f["status"]} | #{cell([ finding_line(f), *acceptance_lines(f) ].join(". "))} |" }
|
|
48
54
|
end
|
|
49
55
|
if (gathering = gathering_line(document))
|
|
50
56
|
lines.push("", gathering)
|
|
@@ -85,7 +91,19 @@ module DeployAngel
|
|
|
85
91
|
end
|
|
86
92
|
|
|
87
93
|
def problems(document)
|
|
88
|
-
Array(document["findings"]).select { |f|
|
|
94
|
+
Array(document["findings"]).select { |f| LISTED.include?(f["status"]) }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Who accepted a finding as an intended change, or where a person can.
|
|
98
|
+
# Only a person can, on the release page: the API can't.
|
|
99
|
+
def acceptance_lines(finding)
|
|
100
|
+
if (accepted = finding["accepted_as_intended"])
|
|
101
|
+
[ "Accepted as intended by #{accepted["by"]}: #{accepted["note"]}" ]
|
|
102
|
+
elsif finding["accept_url"]
|
|
103
|
+
[ "If this change was intended, a person can accept it: #{finding["accept_url"]}" ]
|
|
104
|
+
else
|
|
105
|
+
[]
|
|
106
|
+
end
|
|
89
107
|
end
|
|
90
108
|
|
|
91
109
|
def gathering_line(document)
|
|
@@ -216,7 +234,12 @@ module DeployAngel
|
|
|
216
234
|
|
|
217
235
|
def finding_line(finding)
|
|
218
236
|
label = "#{LABELS.fetch(finding["signal"], finding["signal"])} on #{finding["scope"]}"
|
|
219
|
-
if
|
|
237
|
+
if finding["signal"] == "volume_drop"
|
|
238
|
+
# Its baseline value is what the release before predicts for this
|
|
239
|
+
# much traffic.
|
|
240
|
+
unit = finding["scope"].to_s.start_with?("route:") ? "requests" : "runs"
|
|
241
|
+
"#{label}: #{finding["observed_value"].to_i} #{unit}, about #{finding["baseline_value"].to_f.round} expected"
|
|
242
|
+
elsif COUNTS.include?(finding["signal"])
|
|
220
243
|
"#{label}: #{finding["observed_value"].to_i} occurrences"
|
|
221
244
|
elsif finding["signal"] == "missing_recurring_job"
|
|
222
245
|
# Its value is the job's interval in seconds, not a rate.
|
data/lib/deployangel/cli.rb
CHANGED
|
@@ -112,6 +112,10 @@ module DeployAngel
|
|
|
112
112
|
investigate the likely cause, and propose a fix. `next_steps` names the last
|
|
113
113
|
cleared release a rollback would go to. Do not roll back or change
|
|
114
114
|
production without explicit approval.
|
|
115
|
+
- A failed release whose failing finding is a volume or checkpoint drop you
|
|
116
|
+
made on purpose (a route or job you removed): you can't accept it. Tell the
|
|
117
|
+
user why you think it was intended, with your evidence, and give them the
|
|
118
|
+
finding's `accept_url` so a person decides. It stays failed until then.
|
|
115
119
|
- Exit 3: still verifying; run the command again.
|
|
116
120
|
- Not cleared yet: call `get_exercise_plan` (or `bundle exec deployangel plan`).
|
|
117
121
|
If its status is "exercisable" or "waiting_for_activity", run
|
data/lib/deployangel/mcp.rb
CHANGED
|
@@ -31,6 +31,11 @@ module DeployAngel
|
|
|
31
31
|
Only act on status "exercisable" or "waiting_for_activity"; for "warm_up" or
|
|
32
32
|
"no_baseline" nothing you run can clear it. Exercise routes marked mutating only with a test account
|
|
33
33
|
or after asking. Report what you ran with the plan's report_with command (deployangel check).
|
|
34
|
+
A failing volume_drop or checkpoint_rate finding with an accept_url may be an intended change, such as
|
|
35
|
+
a route or job you removed on purpose. You cannot accept it, and must not try: tell the user why you
|
|
36
|
+
think it was intended, with your evidence, and give them the accept_url so a person decides. Until
|
|
37
|
+
someone accepts it, the release is failed: never report it as success. A finding with status
|
|
38
|
+
accepted was accepted as intended by the person in accepted_as_intended.
|
|
34
39
|
TEXT
|
|
35
40
|
|
|
36
41
|
TARGET_PROPERTIES = {
|
data/lib/deployangel/version.rb
CHANGED