kamal-backup 0.1.0.pre.9 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dffee9d885ca23342a84ac3fc494d09f9f44b323a10ae981df4665f31206b20a
4
- data.tar.gz: 0c6352b4f00008b54b22442f0b192eb54adf7f52c0350ab8cb5c69dd1cff9c4f
3
+ metadata.gz: 7135af9b16454829f69ed19ca84d58045232e5db583cc54cbc1fe623bf80c4f6
4
+ data.tar.gz: 8f70a9143faec5b730e3e9d70a33b4bed4f1f650815f81c97c303766151fd2af
5
5
  SHA512:
6
- metadata.gz: 77f916eec58efe57ad7c1b65b8f93cab39d647b9051dc6d77cbebfa66f830cbc65bfdf9bdfc8aa0016109969a88b68bef8f2ea79a71a97ce4670b6c1028fa8ba
7
- data.tar.gz: 631793de8449a07bf774f91a5bf7aea669b4773da960a27319cf8ecca00c6194a37214f36cc70c49857247406e665292318ad145f9c9e87d15f53751b92bf00a
6
+ metadata.gz: a919c1e57b6061ce588bd73d00b87eeff13e7b312b3da1bf05d8263116eadc119facc2fedadcba62d21a4d0983835bb52b89486eb13beeeffb3673588ec39845
7
+ data.tar.gz: 64739bbaac082b4266d37b2dfbd70d4ad53c7010a825a037126ff4b9cfb828c0968d2dd1045c25cd82fab5371864a2405c10c0edee99152948131f8d8112bf38
data/README.md CHANGED
@@ -59,6 +59,8 @@ For most Rails apps, that is enough. `restore local` and `drill local` can infer
59
59
 
60
60
  Only create `config/kamal-backup.local.yml` if you need to override those local defaults.
61
61
 
62
+ Local restore and drill also require the `restic` binary on your machine. The backup accessory image already includes `restic` for production-side commands.
63
+
62
64
  Then add the backup accessory to `config/deploy.yml`:
63
65
 
64
66
  ```yaml
@@ -193,6 +195,8 @@ You still provide the local secrets yourself in env:
193
195
  - `POSTGRES_PASSWORD` or `MYSQL_PWD` when needed
194
196
  - `RESTIC_REPOSITORY` when it is not visible through `kamal config`
195
197
 
198
+ And you need `restic` installed locally and available on `PATH`.
199
+
196
200
  Example:
197
201
 
198
202
  ```sh
@@ -217,6 +221,8 @@ It prompts locally, then shells out through Kamal to the backup accessory.
217
221
  bundle exec kamal-backup -d production drill local latest --check "bin/rails runner 'puts User.count'"
218
222
  ```
219
223
 
224
+ Like `restore local`, this runs on your machine and requires a local `restic` install.
225
+
220
226
  `drill production` restores into scratch targets on production infrastructure. It does not touch the live production database:
221
227
 
222
228
  ```sh
data/exe/kamal-backup CHANGED
@@ -1,10 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
3
+ root = File.expand_path("..", __dir__)
4
+ gemfile = File.join(root, "Gemfile")
5
+ libdir = File.join(root, "lib")
4
6
 
5
- require "bundler/setup"
7
+ $LOAD_PATH.unshift(libdir) if File.directory?(libdir) && !$LOAD_PATH.include?(libdir)
6
8
 
7
- $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
9
+ if File.exist?(gemfile)
10
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
11
+ require "bundler/setup"
12
+ end
8
13
 
9
14
  require "kamal_backup"
10
15
 
@@ -29,6 +29,7 @@ module KamalBackup
29
29
 
30
30
  def backup
31
31
  config.validate_backup
32
+ require_restic!
32
33
 
33
34
  timestamp = current_timestamp
34
35
  restic.ensure_repository
@@ -48,6 +49,7 @@ module KamalBackup
48
49
 
49
50
  def restore_to_local_machine(snapshot = "latest")
50
51
  validate_local_machine_restore
52
+ require_restic!
51
53
 
52
54
  build_restore_result("local", snapshot) do |result|
53
55
  adapter = database
@@ -63,6 +65,7 @@ module KamalBackup
63
65
 
64
66
  def restore_to_production(snapshot = "latest")
65
67
  validate_production_restore
68
+ require_restic!
66
69
 
67
70
  build_restore_result("production", snapshot) do |result|
68
71
  adapter = database
@@ -77,6 +80,7 @@ module KamalBackup
77
80
 
78
81
  def drill_on_local_machine(snapshot = "latest", check_command: nil)
79
82
  validate_local_machine_restore
83
+ require_restic!
80
84
 
81
85
  run_drill("local", snapshot, check_command: check_command) do |result|
82
86
  adapter = database
@@ -92,6 +96,7 @@ module KamalBackup
92
96
 
93
97
  def drill_on_production(snapshot = "latest", database_name: nil, sqlite_path: nil, file_target: "/restore/files", check_command: nil)
94
98
  validate_production_drill(file_target, database_name, sqlite_path)
99
+ require_restic!
95
100
 
96
101
  run_drill("production", snapshot, check_command: check_command) do |result|
97
102
  adapter = database
@@ -113,16 +118,19 @@ module KamalBackup
113
118
 
114
119
  def snapshots
115
120
  config.validate_restic
121
+ require_restic!
116
122
  restic.snapshots.stdout
117
123
  end
118
124
 
119
125
  def check
120
126
  config.validate_restic
127
+ require_restic!
121
128
  restic.check.stdout
122
129
  end
123
130
 
124
131
  def evidence
125
132
  config.validate_restic
133
+ require_restic!
126
134
  @evidence_class.new(config, restic: restic, redactor: redactor).to_json
127
135
  end
128
136
 
@@ -312,6 +320,14 @@ module KamalBackup
312
320
  config.validate_local_database_restore_target(adapter.current_target_identifier)
313
321
  end
314
322
 
323
+ def require_restic!
324
+ return unless using_builtin_restic?
325
+ return if Command.available?("restic")
326
+
327
+ raise ConfigurationError,
328
+ "restic is required on PATH for commands that run on this machine. Install restic locally and try again."
329
+ end
330
+
315
331
  def run_drill_check(command)
316
332
  result = Command.capture(
317
333
  CommandSpec.new(argv: ["sh", "-lc", command]),
@@ -347,6 +363,10 @@ module KamalBackup
347
363
  @restic ||= Restic.new(config, redactor: redactor)
348
364
  end
349
365
 
366
+ def using_builtin_restic?
367
+ @restic.nil? || @restic.is_a?(Restic)
368
+ end
369
+
350
370
  def database
351
371
  @database ||= Databases::Base.build(config, redactor: redactor)
352
372
  end
@@ -329,6 +329,7 @@ module KamalBackup
329
329
  puts deploy_snippet
330
330
  puts
331
331
  puts "For most Rails apps, restore local and drill local can infer the development database, storage path, and tmp state directory."
332
+ puts "Local restore and drill also require the restic binary on your machine."
332
333
  puts "Create config/kamal-backup.local.yml only if you need to override those local defaults."
333
334
  end
334
335
 
@@ -26,6 +26,13 @@ module KamalBackup
26
26
 
27
27
  class Command
28
28
  class << self
29
+ def available?(name)
30
+ ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).any? do |dir|
31
+ path = File.join(dir, name)
32
+ File.executable?(path) && !File.directory?(path)
33
+ end
34
+ end
35
+
29
36
  def capture(spec, input: nil, redactor:)
30
37
  stdout, stderr, status = Open3.capture3(spec.env, *spec.argv, stdin_data: input)
31
38
  result = CommandResult.new(stdout: stdout, stderr: stderr, status: status.exitstatus)
@@ -88,10 +88,7 @@ module KamalBackup
88
88
  end
89
89
 
90
90
  def executable_available?(name)
91
- ENV.fetch("PATH", "").split(File::PATH_SEPARATOR).any? do |dir|
92
- path = File.join(dir, name)
93
- File.executable?(path) && !File.directory?(path)
94
- end
91
+ Command.available?(name)
95
92
  end
96
93
  end
97
94
  end
@@ -1,3 +1,3 @@
1
1
  module KamalBackup
2
- VERSION = "0.1.0.pre.9"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kamal-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - crmne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-04-23 00:00:00.000000000 Z
11
+ date: 2026-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor