deployangel 0.1.18 → 0.1.19
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 +9 -0
- data/README.md +18 -1
- data/lib/deployangel/cli.rb +132 -3
- data/lib/deployangel/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf16d5f1c1214f77e3b72e911693d7e52efd852da3dcaa21308957d8789bbb63
|
|
4
|
+
data.tar.gz: 6957cf6b461965450428d49b7d12631bcd2431e7a71bdfd9d995de9b63bd8f0a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f8eb73de68335aec60421c1e550c4983e1a1ffd0e93e27726ce75028d13245a4cc41ec3ea9193d4dbadb48a30eb6953e1bd41cac7837634cefea05bb9b2820f8
|
|
7
|
+
data.tar.gz: 2c910d0882a1c2bed0b0e4bf24dc8b238121702d1d77ae760d74e207050757795b60d054a7f5fa3a6a0b113ee10d736da344ed49db29dfb3f9f6cf76f1a9f766
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.19 (2026-10-09)
|
|
4
|
+
|
|
5
|
+
- `deployangel install agents` sets up Claude Code, Cursor, and Codex in a
|
|
6
|
+
project: the MCP server in `.mcp.json`, `.cursor/mcp.json`, and
|
|
7
|
+
`.codex/config.toml` (forwarding `DEPLOYANGEL_API_TOKEN`), and instructions
|
|
8
|
+
to wait for a verdict after deploying in `AGENTS.md`, with a `CLAUDE.md`
|
|
9
|
+
that imports it. It never replaces existing entries, and re-running it only
|
|
10
|
+
updates its own instructions.
|
|
11
|
+
|
|
3
12
|
## 0.1.18 (2026-10-08)
|
|
4
13
|
|
|
5
14
|
- In Rails, the agent gets its file digests when it starts, so the reporter
|
data/README.md
CHANGED
|
@@ -413,6 +413,22 @@ choose with `--format=text|json`. Exit codes:
|
|
|
413
413
|
|
|
414
414
|
### MCP server
|
|
415
415
|
|
|
416
|
+
To set up Claude Code, Cursor, and Codex for a project in one step, run this
|
|
417
|
+
in the project:
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
bundle exec deployangel install agents
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
It adds the MCP server to `.mcp.json` (Claude Code), `.cursor/mcp.json`
|
|
424
|
+
(Cursor), and `.codex/config.toml` (Codex, which reads it only in projects you
|
|
425
|
+
trust), and the instructions below to `AGENTS.md`, with a `CLAUDE.md` that
|
|
426
|
+
imports it. It never replaces an existing entry, and running it again updates
|
|
427
|
+
only its own instructions. Commit the files; the token stays in your
|
|
428
|
+
environment.
|
|
429
|
+
|
|
430
|
+
Or add the server yourself:
|
|
431
|
+
|
|
416
432
|
```bash
|
|
417
433
|
claude mcp add deployangel -- bundle exec deployangel mcp # Claude Code
|
|
418
434
|
```
|
|
@@ -450,7 +466,8 @@ so its plan lists nothing.
|
|
|
450
466
|
|
|
451
467
|
### Suggested instructions for your coding agent
|
|
452
468
|
|
|
453
|
-
|
|
469
|
+
`deployangel install agents` adds instructions like these. To add them
|
|
470
|
+
yourself, put this in your `CLAUDE.md` or `AGENTS.md`:
|
|
454
471
|
|
|
455
472
|
```markdown
|
|
456
473
|
## Production verification
|
data/lib/deployangel/cli.rb
CHANGED
|
@@ -33,8 +33,9 @@ module DeployAngel
|
|
|
33
33
|
exception Details for a fingerprint deployangel exception FINGERPRINT
|
|
34
34
|
check Report a smoke test result --name=NAME --status=pass|fail [--covers=a,b]
|
|
35
35
|
[--commit=SHA | --deployment=ID] [--details-url=URL]
|
|
36
|
-
install Add a Kamal deploy hook,
|
|
37
|
-
bake the commit into an image
|
|
36
|
+
install Add a Kamal deploy hook, deployangel install kamal
|
|
37
|
+
bake the commit into an image, deployangel install docker
|
|
38
|
+
or set up coding agents deployangel install agents
|
|
38
39
|
mcp Run the MCP server over stdio (for coding agents)
|
|
39
40
|
|
|
40
41
|
With no target, verify, plan, and check use the current git HEAD commit.
|
|
@@ -71,6 +72,46 @@ module DeployAngel
|
|
|
71
72
|
Kamal apps don't need this: DeployAngel reads Kamal's KAMAL_VERSION.
|
|
72
73
|
HELP
|
|
73
74
|
|
|
75
|
+
# The block `deployangel install agents` keeps in AGENTS.md (and CLAUDE.md
|
|
76
|
+
# when it doesn't import AGENTS.md), replaced whole on each run.
|
|
77
|
+
AGENTS_START = "<!-- deployangel:start -->"
|
|
78
|
+
AGENTS_END = "<!-- deployangel:end -->"
|
|
79
|
+
AGENT_INSTRUCTIONS = <<~MARKDOWN
|
|
80
|
+
#{AGENTS_START}
|
|
81
|
+
## Production verification (DeployAngel)
|
|
82
|
+
|
|
83
|
+
After deploying, or pushing a commit that deploys, wait for DeployAngel's
|
|
84
|
+
verdict: call the `wait_for_verification` MCP tool with the commit and
|
|
85
|
+
`until: "initial"`, calling again while it's in progress, or run
|
|
86
|
+
`bundle exec deployangel verify --commit=<sha> --wait --until=initial`.
|
|
87
|
+
|
|
88
|
+
- Exit 0 / verified: the release is cleared. Report the clearance line and
|
|
89
|
+
anything DeployAngel is still watching, then move on.
|
|
90
|
+
- Exit 6: no problems so far, but NOT cleared. Report "no problems so far, not
|
|
91
|
+
yet cleared" and the expected clearance time. DeployAngel keeps verifying and
|
|
92
|
+
alerts on failure.
|
|
93
|
+
- Exit 7: warnings at the initial check. Report them and review the findings.
|
|
94
|
+
The release is NOT cleared.
|
|
95
|
+
- Exit 2 / inconclusive: the release is NOT verified. Do not claim success.
|
|
96
|
+
- Exit 1 / failed: read the findings and exceptions (`get_exception`),
|
|
97
|
+
investigate the likely cause, and propose a fix. Do not roll back or change
|
|
98
|
+
production without explicit approval.
|
|
99
|
+
- Exit 3: still verifying; run the command again.
|
|
100
|
+
- Not cleared yet: call `get_exercise_plan` (or `bundle exec deployangel plan`).
|
|
101
|
+
If its status is "exercisable" or "waiting_for_activity", say what it lists
|
|
102
|
+
and offer to exercise it: read-only routes freely, routes marked mutating
|
|
103
|
+
only with a test account or after asking. If the status is "warm_up",
|
|
104
|
+
nothing run can clear it.
|
|
105
|
+
#{AGENTS_END}
|
|
106
|
+
MARKDOWN
|
|
107
|
+
|
|
108
|
+
AGENTS_TOKEN_HELP = <<~HELP.chomp
|
|
109
|
+
The MCP server and CLI need DEPLOYANGEL_API_TOKEN, a "CLI & coding agents" token
|
|
110
|
+
from the app's Settings, in the environment your agent runs in (for example in
|
|
111
|
+
an .envrc with direnv). Never put it in these files: they're meant to be committed.
|
|
112
|
+
Codex reads .codex/config.toml only in projects you've marked as trusted.
|
|
113
|
+
HELP
|
|
114
|
+
|
|
74
115
|
DOCKERFILE_LINES = <<~DOCKERFILE
|
|
75
116
|
# The commit this image runs, for DeployAngel. Build with --build-arg GIT_SHA=$(git rev-parse HEAD).
|
|
76
117
|
ARG GIT_SHA
|
|
@@ -230,7 +271,8 @@ module DeployAngel
|
|
|
230
271
|
case (target = @argv.shift)
|
|
231
272
|
when "kamal" then install_kamal
|
|
232
273
|
when "docker" then install_docker
|
|
233
|
-
|
|
274
|
+
when "agents" then install_agents
|
|
275
|
+
else usage_error("install needs a target: deployangel install kamal, docker, or agents")
|
|
234
276
|
end
|
|
235
277
|
end
|
|
236
278
|
|
|
@@ -256,6 +298,93 @@ module DeployAngel
|
|
|
256
298
|
0
|
|
257
299
|
end
|
|
258
300
|
|
|
301
|
+
# Sets up Claude Code, Cursor, and Codex in this project: the MCP server
|
|
302
|
+
# in each one's project config, and instructions to wait for a verdict
|
|
303
|
+
# after deploying. Never overwrites what's there: an existing entry is
|
|
304
|
+
# kept, and a file it can't read is left for you to edit.
|
|
305
|
+
def install_agents
|
|
306
|
+
command = %w[bundle exec deployangel mcp]
|
|
307
|
+
lines = [
|
|
308
|
+
install_json_mcp(".mcp.json", command, "Claude Code"),
|
|
309
|
+
install_json_mcp(File.join(".cursor", "mcp.json"), command, "Cursor"),
|
|
310
|
+
install_codex_mcp(command),
|
|
311
|
+
*install_agent_instructions
|
|
312
|
+
]
|
|
313
|
+
@stdout.puts(*lines, "", AGENTS_TOKEN_HELP)
|
|
314
|
+
0
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def install_json_mcp(relative, command, agent)
|
|
318
|
+
path = File.join(@root, relative)
|
|
319
|
+
config = File.exist?(path) ? JSON.parse(File.read(path)) : {}
|
|
320
|
+
raise JSON::ParserError, "not a JSON object" unless config.is_a?(Hash)
|
|
321
|
+
|
|
322
|
+
servers = (config["mcpServers"] ||= {})
|
|
323
|
+
return "#{relative} already has a deployangel MCP server (#{agent})." if servers.key?("deployangel")
|
|
324
|
+
|
|
325
|
+
created = !File.exist?(path)
|
|
326
|
+
servers["deployangel"] = { "command" => command.first, "args" => command.drop(1) }
|
|
327
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
328
|
+
File.write(path, "#{JSON.pretty_generate(config)}\n")
|
|
329
|
+
"#{created ? "Created" : "Updated"} #{relative}: the DeployAngel MCP server for #{agent}."
|
|
330
|
+
rescue JSON::ParserError
|
|
331
|
+
"Couldn't read #{relative}, so it's unchanged. Add a \"deployangel\" server to its mcpServers: " \
|
|
332
|
+
"command \"#{command.first}\", args #{command.drop(1).to_json}."
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def install_codex_mcp(command)
|
|
336
|
+
relative = File.join(".codex", "config.toml")
|
|
337
|
+
path = File.join(@root, relative)
|
|
338
|
+
existing = File.exist?(path) ? File.read(path) : nil
|
|
339
|
+
return "#{relative} already has a deployangel MCP server (Codex)." if existing&.include?("[mcp_servers.deployangel]")
|
|
340
|
+
|
|
341
|
+
table = <<~TOML
|
|
342
|
+
[mcp_servers.deployangel]
|
|
343
|
+
command = #{command.first.to_json}
|
|
344
|
+
args = #{command.drop(1).to_json.gsub(",", ", ")}
|
|
345
|
+
env_vars = ["DEPLOYANGEL_API_TOKEN", "DEPLOYANGEL_URL"]
|
|
346
|
+
TOML
|
|
347
|
+
FileUtils.mkdir_p(File.dirname(path))
|
|
348
|
+
File.write(path, existing ? "#{existing.sub(/\n*\z/, "\n")}\n#{table}" : table)
|
|
349
|
+
"#{existing ? "Updated" : "Created"} #{relative}: the DeployAngel MCP server for Codex."
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# AGENTS.md serves Codex and Cursor. Claude Code reads CLAUDE.md, so it
|
|
353
|
+
# gets the block too, unless it already imports AGENTS.md; a project
|
|
354
|
+
# without one gets a CLAUDE.md that does.
|
|
355
|
+
def install_agent_instructions
|
|
356
|
+
lines = [ upsert_instructions("AGENTS.md") ]
|
|
357
|
+
claude = File.join(@root, "CLAUDE.md")
|
|
358
|
+
if !File.exist?(claude)
|
|
359
|
+
File.write(claude, "@AGENTS.md\n")
|
|
360
|
+
lines << "Created CLAUDE.md, which imports AGENTS.md for Claude Code."
|
|
361
|
+
elsif !File.read(claude).match?(/^@AGENTS\.md\s*$/)
|
|
362
|
+
lines << upsert_instructions("CLAUDE.md")
|
|
363
|
+
end
|
|
364
|
+
lines
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def upsert_instructions(relative)
|
|
368
|
+
path = File.join(@root, relative)
|
|
369
|
+
unless File.exist?(path)
|
|
370
|
+
File.write(path, AGENT_INSTRUCTIONS)
|
|
371
|
+
return "Created #{relative} with instructions to wait for DeployAngel's verdict after deploying."
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
content = File.read(path)
|
|
375
|
+
block = /#{Regexp.escape(AGENTS_START)}.*?#{Regexp.escape(AGENTS_END)}\n?/m
|
|
376
|
+
if content.match?(block)
|
|
377
|
+
updated = content.sub(block, AGENT_INSTRUCTIONS)
|
|
378
|
+
return "#{relative} already has DeployAngel's instructions." if updated == content
|
|
379
|
+
|
|
380
|
+
File.write(path, updated)
|
|
381
|
+
"Updated DeployAngel's instructions in #{relative}."
|
|
382
|
+
else
|
|
383
|
+
File.write(path, "#{content.sub(/\n*\z/, "\n")}\n#{AGENT_INSTRUCTIONS}")
|
|
384
|
+
"Added instructions to wait for DeployAngel's verdict after deploying to #{relative}."
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
259
388
|
# Adds DEPLOYANGEL_REVISION, from a GIT_SHA build arg, to the Dockerfile.
|
|
260
389
|
# It never edits CI workflows; it says what to pass instead.
|
|
261
390
|
def install_docker
|
data/lib/deployangel/version.rb
CHANGED
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.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jordan Owens
|
|
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
82
82
|
- !ruby/object:Gem::Version
|
|
83
83
|
version: '0'
|
|
84
84
|
requirements: []
|
|
85
|
-
rubygems_version: 4.0.
|
|
85
|
+
rubygems_version: 4.0.10
|
|
86
86
|
specification_version: 4
|
|
87
87
|
summary: 'DeployAngel agent for Rails: production verification for every deployment.'
|
|
88
88
|
test_files: []
|