capistrano-nomad 0.14.1 → 0.15.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/capistrano-nomad.gemspec +1 -1
- data/lib/capistrano/nomad/helpers/nomad.rb +48 -2
- 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: 3d733a824e5d9c7403669bbf958bbd8ee0583fe9a054d45065fd1b71eec0941d
|
|
4
|
+
data.tar.gz: b5a12159f7bf4c6fa241732c21a732a60953dc548fcf2139b97f94348566a584
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7c97291b411d604e7308ed135548d4f3d092158b2ddec7a8675e5e4d1af29a1d66f8e7e9e181d4753dd5042d0ebf2c0ac609e9f03c4341a077b163e0b582835e
|
|
7
|
+
data.tar.gz: 6819e434bdde1b26b7c7f80d18ccdc23422f6fedb30c4b37f54657ba452b9bcc4309c34b744e9faab0e88df47a8b221e69fee9149a354a02dc956544b1a163e4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.15.0]
|
|
4
|
+
|
|
5
|
+
- Fix command escaping for console task to support complex commands with special characters using base64 encoding
|
|
6
|
+
|
|
3
7
|
## [0.14.1]
|
|
4
8
|
|
|
5
9
|
- Support for `IS_DETACHED` environment variable to run jobs in detached mode (e.g. `IS_DETACHED=true cap production nomad:app:deploy`)
|
data/Gemfile.lock
CHANGED
data/capistrano-nomad.gemspec
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require "active_support/core_ext/string"
|
|
2
|
+
require "base64"
|
|
2
3
|
require "sshkit/interactive"
|
|
3
4
|
|
|
4
5
|
class CapistranoNomadErbNamespace
|
|
@@ -29,6 +30,48 @@ def capistrano_nomad_ensure_absolute_path(path)
|
|
|
29
30
|
path[0] == "/" ? path : "/#{path}"
|
|
30
31
|
end
|
|
31
32
|
|
|
33
|
+
# Escapes a command string for use with sshkit-interactive.
|
|
34
|
+
#
|
|
35
|
+
# sshkit-interactive wraps commands in '$SHELL -l -c "..."' and naively
|
|
36
|
+
# replaces all single quotes with \". This breaks commands that have
|
|
37
|
+
# content inside single quotes (e.g., bin/rails runner 'puts "hello"').
|
|
38
|
+
#
|
|
39
|
+
# This function pre-processes the command to handle single-quoted sections
|
|
40
|
+
# properly by:
|
|
41
|
+
# 1. Converting single quotes to escaped double quotes (\")
|
|
42
|
+
# 2. Escaping content inside those sections for double-quote context
|
|
43
|
+
# (backslashes become \\, double quotes become \\\")
|
|
44
|
+
#
|
|
45
|
+
# After this transformation, sshkit-interactive's gsub("'", '\\"') becomes
|
|
46
|
+
# a no-op since there are no single quotes left.
|
|
47
|
+
def capistrano_nomad_escape_command(command)
|
|
48
|
+
# Process single-quoted sections: 'content' -> \"escaped_content\"
|
|
49
|
+
command.gsub(/'([^']*)'/) do |_match|
|
|
50
|
+
content = Regexp.last_match(1)
|
|
51
|
+
|
|
52
|
+
# Escape for double-quote shell context:
|
|
53
|
+
# - Backslashes need to be doubled (\ -> \\)
|
|
54
|
+
# - Double quotes need to become \\\" to survive shell parsing
|
|
55
|
+
escaped_content = content
|
|
56
|
+
.gsub("\\", "\\\\\\\\")
|
|
57
|
+
.gsub('"', '\\\\\\\\\\\"')
|
|
58
|
+
|
|
59
|
+
'\"' + escaped_content + '\"'
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Escapes a command string for use with sshkit-interactive by base64 encoding.
|
|
64
|
+
#
|
|
65
|
+
# sshkit-interactive wraps commands in '$SHELL -l -c "..."' and naively
|
|
66
|
+
# replaces all single quotes with \". Base64 avoids all quoting issues by
|
|
67
|
+
# decoding the command inside the Nomad task and executing it with /bin/sh.
|
|
68
|
+
def capistrano_nomad_escape_command(command)
|
|
69
|
+
encoded_command = Base64.strict_encode64(command)
|
|
70
|
+
decoded_command = "printf\\ %s\\ #{encoded_command}\\ \\|\\ base64\\ -d\\ \\|\\ /bin/sh"
|
|
71
|
+
|
|
72
|
+
"/bin/sh -lc #{decoded_command}"
|
|
73
|
+
end
|
|
74
|
+
|
|
32
75
|
def capistrano_nomad_build_file_path(parent_path, basename, kind: nil, **options)
|
|
33
76
|
capistrano_nomad_ensure_options!(options)
|
|
34
77
|
namespace = options[:namespace]
|
|
@@ -189,6 +232,9 @@ end
|
|
|
189
232
|
def capistrano_nomad_exec_within_job(name, command, task: nil, **options)
|
|
190
233
|
capistrano_nomad_ensure_options!(options)
|
|
191
234
|
|
|
235
|
+
# Escape command for SSH transport via sshkit-interactive
|
|
236
|
+
escaped_command = capistrano_nomad_escape_command(command)
|
|
237
|
+
|
|
192
238
|
capistrano_nomad_run_remotely do
|
|
193
239
|
if (task_details = capistrano_nomad_find_job_task_details(name, task: task, **options))
|
|
194
240
|
capistrano_nomad_execute_nomad_command(
|
|
@@ -196,7 +242,7 @@ def capistrano_nomad_exec_within_job(name, command, task: nil, **options)
|
|
|
196
242
|
:exec,
|
|
197
243
|
options.merge(task: task_details[:name]),
|
|
198
244
|
task_details[:alloc_id],
|
|
199
|
-
|
|
245
|
+
escaped_command,
|
|
200
246
|
)
|
|
201
247
|
else
|
|
202
248
|
# If alloc can't be determined then choose at random
|
|
@@ -205,7 +251,7 @@ def capistrano_nomad_exec_within_job(name, command, task: nil, **options)
|
|
|
205
251
|
:exec,
|
|
206
252
|
options.merge(job: true),
|
|
207
253
|
task,
|
|
208
|
-
|
|
254
|
+
escaped_command,
|
|
209
255
|
)
|
|
210
256
|
end
|
|
211
257
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capistrano-nomad
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.15.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Hu
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|