capistrano-nomad 0.16.0 → 0.16.2
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 +10 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +3 -1
- data/README.md +3 -1
- data/Rakefile +8 -1
- data/capistrano-nomad.gemspec +2 -2
- data/lib/capistrano/nomad/helpers/nomad.rb +33 -8
- data/test/upload_plan_test.rb +77 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 408063f04626ace5215b232901a72869fb5aabfe336017ce0e33aa1f1b53b02c
|
|
4
|
+
data.tar.gz: 4f3019490d7fa5042f1efe94ba7bedf1725fe3f25d391c19ae87fd45b051d79e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae43c669814a9ba3ccd7462d4cd862b97cc79bdeefed86966fa251fbe45fa184cb8ac570b35bfd811907f1e276af4c6c6c6e3d57823c4fdea6922f891822b2c1
|
|
7
|
+
data.tar.gz: bb552095171a362745db10f63a45c3ca24ee9f7fb715d52738fa18802472798b695090a55a5d79bb5a7457dbad84d44e1b03b5112a132f7cdda1b0d1c8ca8051
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.16.2]
|
|
4
|
+
|
|
5
|
+
- Fail `upload_plan` and other plan operations when Nomad rejects a job or cannot determine the plan
|
|
6
|
+
- Keep successful plans with allocation changes successful despite Nomad's exit code 1
|
|
7
|
+
- Include CLI regression tests in the gem
|
|
8
|
+
|
|
9
|
+
## [0.16.1]
|
|
10
|
+
|
|
11
|
+
- Pass every configured variable file to `nomad plan` and `nomad run`
|
|
12
|
+
|
|
3
13
|
## [0.16.0]
|
|
4
14
|
|
|
5
15
|
- Add `:redeploy` task that stops job before performing a full deploy to ensure fresh allocations
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
capistrano-nomad (0.16.
|
|
4
|
+
capistrano-nomad (0.16.2)
|
|
5
5
|
activesupport (<= 7.0.8)
|
|
6
6
|
byebug
|
|
7
7
|
capistrano (~> 3.0)
|
|
@@ -52,9 +52,11 @@ GEM
|
|
|
52
52
|
PLATFORMS
|
|
53
53
|
arm64-darwin-21
|
|
54
54
|
arm64-darwin-23
|
|
55
|
+
x86_64-linux-gnu
|
|
55
56
|
|
|
56
57
|
DEPENDENCIES
|
|
57
58
|
capistrano-nomad!
|
|
59
|
+
minitest (~> 5.0)
|
|
58
60
|
|
|
59
61
|
BUNDLED WITH
|
|
60
62
|
2.4.20
|
data/README.md
CHANGED
|
@@ -213,7 +213,9 @@ cap production nomad:version
|
|
|
213
213
|
|
|
214
214
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
Run `bundle exec rake test` to test the generated Capistrano `upload_plan` task through the CLI. The tests use local transport and controlled Nomad exit codes. To also check rejection of invalid HCL with a real Nomad binary, run `NOMAD_REAL_BINARY=/path/to/nomad bundle exec rake test`.
|
|
217
|
+
|
|
218
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version in `capistrano-nomad.gemspec`, run `bundle install`, and update `CHANGELOG.md`. Run `bundle exec rake test` and commit the release changes. Then run `bundle exec rake release`, which creates the version tag, pushes the release commit and tag, and publishes the gem to [RubyGems](https://rubygems.org).
|
|
217
219
|
|
|
218
220
|
## Contributing
|
|
219
221
|
|
data/Rakefile
CHANGED
data/capistrano-nomad.gemspec
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = "capistrano-nomad"
|
|
5
|
-
spec.version = "0.16.
|
|
5
|
+
spec.version = "0.16.2"
|
|
6
6
|
spec.authors = ["James Hu"]
|
|
7
7
|
|
|
8
8
|
spec.summary = "Capistrano plugin for deploying and managing Nomad jobs"
|
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
# Specify which files should be added to the gem when it is released. The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
19
19
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
20
20
|
%x(git ls-files -z).split("\x0").reject do |f|
|
|
21
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|
|
|
21
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:bin|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
spec.bindir = "exe"
|
|
@@ -138,6 +138,10 @@ def capistrano_nomad_build_release_var_file_path(name, **options)
|
|
|
138
138
|
"#{release_path}#{capistrano_nomad_ensure_absolute_path(capistrano_nomad_build_base_var_file_path(name, **options))}"
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
+
def capistrano_nomad_plan_command?(args)
|
|
142
|
+
args.first.to_s == "plan" || args.take(2).map(&:to_s) == ["job", "plan"]
|
|
143
|
+
end
|
|
144
|
+
|
|
141
145
|
def capistrano_nomad_run_nomad_command(kind, *args)
|
|
142
146
|
converted_args = args.each_with_object([]) do |arg, collection|
|
|
143
147
|
# If hash then convert it as options
|
|
@@ -165,15 +169,25 @@ def capistrano_nomad_run_nomad_command(kind, *args)
|
|
|
165
169
|
end
|
|
166
170
|
|
|
167
171
|
with(env_vars) do
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
if capistrano_nomad_plan_command?(args)
|
|
173
|
+
# Nomad returns 1 for a successful plan with changes; all other nonzero exits are errors
|
|
174
|
+
public_send(kind, :nomad, *converted_args, '; status=$?; if [ "$status" -eq 1 ]; then exit 0; else exit "$status"; fi', raise_on_non_zero_exit: true)
|
|
175
|
+
else
|
|
176
|
+
# Ignore errors for commands other than plans
|
|
177
|
+
public_send(kind, :nomad, *converted_args, raise_on_non_zero_exit: false)
|
|
178
|
+
end
|
|
170
179
|
end
|
|
171
180
|
end
|
|
172
181
|
|
|
173
182
|
def capistrano_nomad_execute_nomad_command(*args, **options)
|
|
174
183
|
capistrano_nomad_run_remotely do |host|
|
|
175
|
-
|
|
184
|
+
if capistrano_nomad_plan_command?(args)
|
|
185
|
+
# Use SSHKit's checked execution because the interactive backend does not raise on failure
|
|
176
186
|
capistrano_nomad_run_nomad_command(:execute, *args, **options)
|
|
187
|
+
else
|
|
188
|
+
run_interactively(host) do
|
|
189
|
+
capistrano_nomad_run_nomad_command(:execute, *args, **options)
|
|
190
|
+
end
|
|
177
191
|
end
|
|
178
192
|
end
|
|
179
193
|
end
|
|
@@ -328,6 +342,15 @@ def capistrano_nomad_fetch_job_var_files(name, **options)
|
|
|
328
342
|
capistrano_nomad_fetch_job_options(name, :var_files, **options) || []
|
|
329
343
|
end
|
|
330
344
|
|
|
345
|
+
# Build one command option per configured variable file so Nomad receives every file in order
|
|
346
|
+
def capistrano_nomad_build_job_var_file_options(name, **options)
|
|
347
|
+
capistrano_nomad_fetch_job_var_files(name, **options).map do |var_file|
|
|
348
|
+
{
|
|
349
|
+
var_file: capistrano_nomad_build_release_var_file_path(var_file, **options),
|
|
350
|
+
}
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
331
354
|
def capistrano_nomad_fetch_jobs_names_by_namespace(**options)
|
|
332
355
|
capistrano_nomad_ensure_options!(options)
|
|
333
356
|
namespace = options[:namespace]
|
|
@@ -521,14 +544,19 @@ def capistrano_nomad_upload_jobs(names, **options)
|
|
|
521
544
|
end
|
|
522
545
|
end
|
|
523
546
|
|
|
547
|
+
# Plan each job with every configured variable file before the uploaded job path
|
|
524
548
|
def capistrano_nomad_plan_jobs(names, **options)
|
|
525
549
|
names.each do |name|
|
|
526
|
-
args = [
|
|
550
|
+
args = [
|
|
551
|
+
*capistrano_nomad_build_job_var_file_options(name, **options),
|
|
552
|
+
capistrano_nomad_build_release_job_path(name, **options),
|
|
553
|
+
]
|
|
527
554
|
|
|
528
555
|
capistrano_nomad_execute_nomad_command(:plan, *args)
|
|
529
556
|
end
|
|
530
557
|
end
|
|
531
558
|
|
|
559
|
+
# Run each job with all configured variable files while preserving the existing command options
|
|
532
560
|
def capistrano_nomad_run_jobs(names, is_detached: true, **options)
|
|
533
561
|
capistrano_nomad_ensure_options!(options)
|
|
534
562
|
|
|
@@ -541,13 +569,10 @@ def capistrano_nomad_run_jobs(names, is_detached: true, **options)
|
|
|
541
569
|
preserve_counts: true,
|
|
542
570
|
}
|
|
543
571
|
|
|
544
|
-
capistrano_nomad_fetch_job_var_files(name, **options).each do |var_file|
|
|
545
|
-
run_options[:var_file] = capistrano_nomad_build_release_var_file_path(var_file, **options)
|
|
546
|
-
end
|
|
547
|
-
|
|
548
572
|
capistrano_nomad_execute_nomad_command(
|
|
549
573
|
:run,
|
|
550
574
|
run_options,
|
|
575
|
+
*capistrano_nomad_build_job_var_file_options(name, **options),
|
|
551
576
|
capistrano_nomad_build_release_job_path(name, **options),
|
|
552
577
|
)
|
|
553
578
|
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "minitest/autorun"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "open3"
|
|
6
|
+
require "tmpdir"
|
|
7
|
+
|
|
8
|
+
class UploadPlanTest < Minitest::Test
|
|
9
|
+
def test_upload_plan_succeeds_for_accepted_plans_and_fails_for_rejected_plans
|
|
10
|
+
Dir.mktmpdir("capistrano-nomad") do |root|
|
|
11
|
+
FileUtils.mkdir_p(["#{root}/config/deploy", "#{root}/nomad/jobs", "#{root}/bin"])
|
|
12
|
+
File.write("#{root}/Capfile", <<~RUBY)
|
|
13
|
+
require "capistrano/setup"
|
|
14
|
+
require "capistrano/deploy"
|
|
15
|
+
require "capistrano/nomad"
|
|
16
|
+
install_plugin Capistrano::Nomad
|
|
17
|
+
RUBY
|
|
18
|
+
File.write("#{root}/config/deploy.rb", <<~RUBY)
|
|
19
|
+
set :application, "plan-test"
|
|
20
|
+
set :deploy_to, #{"#{root}/remote".inspect}
|
|
21
|
+
set :root, #{root.inspect}
|
|
22
|
+
set :current_revision, "test"
|
|
23
|
+
set :nomad_docker_image_types, {}
|
|
24
|
+
SSHKit.config.command_map[:nomad] = #{"#{root}/bin/nomad".inspect}
|
|
25
|
+
nomad_job :example
|
|
26
|
+
RUBY
|
|
27
|
+
File.write("#{root}/config/deploy/test.rb", <<~RUBY)
|
|
28
|
+
server "localhost", roles: [:manager]
|
|
29
|
+
set :sshkit_backend, SSHKit::Backend::Local
|
|
30
|
+
RUBY
|
|
31
|
+
File.write("#{root}/bin/ssh", <<~SH)
|
|
32
|
+
#!/bin/sh
|
|
33
|
+
for argument do command="$argument"; done
|
|
34
|
+
exec /bin/sh -c "$command"
|
|
35
|
+
SH
|
|
36
|
+
FileUtils.chmod(0755, "#{root}/bin/ssh")
|
|
37
|
+
File.write("#{root}/bin/nomad", <<~SH)
|
|
38
|
+
#!/bin/sh
|
|
39
|
+
[ "$1" = plan ] || exit 99
|
|
40
|
+
cat "$2"
|
|
41
|
+
case "$NOMAD_TEST_EXIT" in
|
|
42
|
+
0|1) echo 'Scheduler dry-run: accepted';;
|
|
43
|
+
*) echo 'Error determining plan results' >&2;;
|
|
44
|
+
esac
|
|
45
|
+
exit "$NOMAD_TEST_EXIT"
|
|
46
|
+
SH
|
|
47
|
+
FileUtils.chmod(0755, "#{root}/bin/nomad")
|
|
48
|
+
|
|
49
|
+
[0, 1, 255, 2].each do |exit_code|
|
|
50
|
+
job = exit_code < 2 ? 'job "example" {}' : 'job "example" {'
|
|
51
|
+
File.write("#{root}/nomad/jobs/example.hcl", job)
|
|
52
|
+
output, status = Open3.capture2e(
|
|
53
|
+
{ "NOMAD_TEST_EXIT" => exit_code.to_s, "PATH" => "#{root}/bin:#{ENV.fetch("PATH")}" },
|
|
54
|
+
"bundle", "exec", "cap", "test", "nomad:example:upload_plan",
|
|
55
|
+
chdir: root,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
assert_includes(output, job, output)
|
|
59
|
+
if exit_code < 2
|
|
60
|
+
assert(status.success?, output)
|
|
61
|
+
assert_includes(output, "Scheduler dry-run: accepted")
|
|
62
|
+
else
|
|
63
|
+
refute(status.success?, output)
|
|
64
|
+
assert_includes(output, "Error determining plan results")
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if ENV["NOMAD_REAL_BINARY"]
|
|
69
|
+
FileUtils.cp(ENV.fetch("NOMAD_REAL_BINARY"), "#{root}/bin/nomad")
|
|
70
|
+
output, status = Open3.capture2e("bundle", "exec", "cap", "test", "nomad:example:upload_plan", chdir: root)
|
|
71
|
+
|
|
72
|
+
refute(status.success?, output)
|
|
73
|
+
assert_includes(output, "Error parsing job file")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
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.16.
|
|
4
|
+
version: 0.16.2
|
|
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-
|
|
11
|
+
date: 2026-10-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
@@ -130,6 +130,7 @@ files:
|
|
|
130
130
|
- lib/capistrano/nomad/helpers/nomad.rb
|
|
131
131
|
- lib/capistrano/nomad/scm/git_local.rb
|
|
132
132
|
- lib/capistrano/nomad/tasks/nomad.rake
|
|
133
|
+
- test/upload_plan_test.rb
|
|
133
134
|
homepage: https://github.com/axsuul/capistrano-nomad
|
|
134
135
|
licenses:
|
|
135
136
|
- MIT
|
|
@@ -152,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
152
153
|
- !ruby/object:Gem::Version
|
|
153
154
|
version: '0'
|
|
154
155
|
requirements: []
|
|
155
|
-
rubygems_version: 3.
|
|
156
|
+
rubygems_version: 3.4.19
|
|
156
157
|
signing_key:
|
|
157
158
|
specification_version: 4
|
|
158
159
|
summary: Capistrano plugin for deploying and managing Nomad jobs
|