Class: WideEvent::Kamal::DeployEditor
- Inherits:
-
Object
- Object
- WideEvent::Kamal::DeployEditor
- Defined in:
- lib/wide_event/kamal/deploy_editor.rb
Overview
Applies the wide_events Kamal accessory to a host application's config/deploy.yml without disturbing unrelated comments, ordering, or sections. Detection of structure and conflicts uses Psych.safe_load; every actual mutation is a targeted line insertion/replacement on the original text so byte-identical content survives everywhere we did not intentionally touch it.
Anything the line-based patcher cannot safely reason about (ERB, YAML aliases/merge keys, tabs, duplicate root keys, non-mapping env/ accessories/aliases, an existing non-owned wide_events accessory, conflicting WIDE_EVENTS_* values, or any other shape this editor was not built to understand) causes a refusal: the original content is returned completely unchanged, alongside a complete mergeable snippet the caller can hand to a human or an agent.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- MINIMUM_VERSION =
"2.10.0"- BEGIN_MARKER =
"# BEGIN wide_events store"- END_MARKER =
"# END wide_events store"- CLEAR_VARS =
%w[WIDE_EVENTS_URL WIDE_EVENTS_SERVICE WIDE_EVENTS_ENVIRONMENT].freeze
- SECRET_VARS =
%w[WIDE_EVENTS_INGEST_TOKEN WIDE_EVENTS_QUERY_TOKEN].freeze
- ALIAS_TELEMETRY_KEY =
"telemetry"- ALIAS_TELEMETRY_LINE =
'telemetry: app exec -i --reuse "bin/rails wide_events:sql"'- ALIAS_BACKUP_KEY =
"wide-events-backup"- ALIAS_BACKUP_LINE =
--reuse is load-bearing: without it Kamal's
accessory execstarts a new container from the store image, where (a) the image entrypoint already is /usr/local/bin/wide-events, so the appended command becomes argv and main exits 2 with usage, and (b) there is no running server holding /run/wide-events/admin.sock to take the backup through. With --reuse this is adocker execinto the live accessory container, which is the only place an on-demand backup can be requested. 'wide-events-backup: accessory exec wide_events --reuse "wide-events admin backup"'- ACCESSORY_TEMPLATE_PATH =
File.( "../../generators/wide_events/store/templates/accessory.yml.erb", __dir__ )
- ROOT_KEY_RE =
/\A([A-Za-z_][A-Za-z0-9_.-]*):(.*)\n?\z/- Refusal =
Raised internally to unwind straight to a refusal; never escapes #apply.
Class.new(StandardError)
Instance Method Summary collapse
- #apply ⇒ Object
-
#initialize(content, service:, host:, hostname:, environment: "production", retention_days: 30, image: nil) ⇒ DeployEditor
constructor
A new instance of DeployEditor.
Constructor Details
#initialize(content, service:, host:, hostname:, environment: "production", retention_days: 30, image: nil) ⇒ DeployEditor
Returns a new instance of DeployEditor.
55 56 57 58 59 60 61 62 63 |
# File 'lib/wide_event/kamal/deploy_editor.rb', line 55 def initialize(content, service:, host:, hostname:, environment: "production", retention_days: 30, image: nil) @original = content.to_s @service = service @host = host @hostname = hostname @environment = environment @retention_days = retention_days @image = image || "ghcr.io/adammiribyan/wide-events-store:#{WideEvent::VERSION}" end |
Instance Method Details
#apply ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/wide_event/kamal/deploy_editor.rb', line 65 def apply parsed = preflight! lines = @original.lines changed = false changed |= apply_minimum_version(lines) env_range = root_block_range(lines, "env") changed |= apply_env_in_place(lines, env_range) if env_range aliases_range = root_block_range(lines, "aliases") changed |= apply_aliases_in_place(lines, aliases_range, parsed["aliases"] || {}) if aliases_range accessories_range = root_block_range(lines, "accessories") changed |= apply_accessories_in_place(lines, accessories_range) if accessories_range changed |= append_env_section(lines) unless env_range changed |= append_aliases_section(lines) unless aliases_range changed |= append_accessories_section(lines) unless accessories_range new_content = lines.join verify_parseable!(new_content) Result.new(content: new_content, changed: changed, snippet: nil, conflicts: []) rescue Refusal => e Result.new(content: @original, changed: false, snippet: build_snippet, conflicts: [ e. ]) end |