ops_team 0.10.2 → 0.11.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: d9a12cfab8e68251d5651fdb580efaf961d21333a083df1bc7a8bc14ca08e498
4
- data.tar.gz: 0ddea0179d89116a9ed85c8c6f18dd24e9420cff0d3ae1c1a39aa2b983d0e7e3
3
+ metadata.gz: 952f4e8174c60f623b0768fc6a35eb62524c1f574ea8d887c07023d423365d8e
4
+ data.tar.gz: 9e8421e67c77535683fd7aae10d90c8a671ea3e58c37656a975f303092c8df06
5
5
  SHA512:
6
- metadata.gz: 3b17c7f2bfb516da3ffa82acc5b1ac754a41f2b1a762e460c881a83561b874a925ed8cbdc555c53b5a9500681d77a46551086685936c58a4a1b35c9634614f56
7
- data.tar.gz: 3ddde96d1009c84725c2312e6df25a39e2743b12792e55e300a5dce8b61aac8453527f78c632a573c2507678c948a924d16d96155c9fac7fc5b28de1753a5c1a
6
+ metadata.gz: 8e3c9bb627b2f8570cca8a3dd60f8e176138dcf01b9417889bcf50e2a24cc25759f5cf0492784bbc28e779fe6d201f570e0992fcb1a8261cab9d09f2f4d54e40
7
+ data.tar.gz: 4c89388eb2bf7669cb7d4ddc588424911f56d04a5f6c72921e9fb2729caa0c95aa7cd2efac3b7040842d8976c367364eb881e0e4e672583b3c923d97b291d297
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class AppConfig
4
+ class ParsingError < StandardError; end
5
+
4
6
  class << self
5
7
  def load
6
8
  new(app_config_path).load
@@ -36,8 +38,7 @@ class AppConfig
36
38
  def config
37
39
  @config ||= file_contents ? YAML.safe_load(file_contents) : {}
38
40
  rescue YAML::SyntaxError => e
39
- Output.error("Error parsing config data: #{e}")
40
- {}
41
+ raise ParsingError, "Error parsing config data: #{e}"
41
42
  end
42
43
 
43
44
  def file_contents
@@ -32,12 +32,18 @@ module Builtins
32
32
 
33
33
  private
34
34
 
35
- def template_name_arg
35
+ def template_name
36
36
  @args[0]
37
37
  end
38
38
 
39
39
  def template_path
40
- format(OPS_YML_TEMPLATE, template_name: template_name_arg || DEFAULT_TEMPLATE_NAME)
40
+ return template_name if template_name && File.exist?(template_name)
41
+
42
+ builtin_template_path
43
+ end
44
+
45
+ def builtin_template_path
46
+ format(OPS_YML_TEMPLATE, template_name: template_name || DEFAULT_TEMPLATE_NAME)
41
47
  end
42
48
 
43
49
  def template_name_list
@@ -4,11 +4,12 @@ require 'open3'
4
4
  require 'English'
5
5
 
6
6
  require 'output'
7
+ require 'executor'
7
8
 
8
9
  class Dependency
9
10
  DESCRIPTION_TYPE_WIDTH = 8
10
11
 
11
- attr_reader :name, :output, :exit_code
12
+ attr_reader :name
12
13
 
13
14
  def initialize(name)
14
15
  @name = name
@@ -45,15 +46,23 @@ class Dependency
45
46
  end
46
47
 
47
48
  def success?
48
- @exit_code.nil? ? true : @exit_code.zero?
49
+ @executor.nil? ? true : @executor.success?
50
+ end
51
+
52
+ def output
53
+ @executor&.output
54
+ end
55
+
56
+ def exit_code
57
+ @executor&.exit_code
49
58
  end
50
59
 
51
60
  private
52
61
 
53
62
  def execute(cmd)
54
- @output, status = Open3.capture2e(cmd)
55
- @exit_code = status.exitstatus
63
+ @executor = Executor.new(cmd)
64
+ @executor.execute
56
65
 
57
- success?
66
+ @executor.success?
58
67
  end
59
68
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Executor
4
+ attr_reader :output, :exit_code
5
+
6
+ class << self
7
+ def execute(command)
8
+ @output, status = Open3.capture2e(command)
9
+ @exit_code = status.exitstatus
10
+
11
+ [@output, @exit_code]
12
+ end
13
+ end
14
+
15
+ def initialize(command)
16
+ @command = command
17
+ end
18
+
19
+ def execute
20
+ @output, status = Open3.capture2e(@command)
21
+ @exit_code = status.exitstatus
22
+
23
+ success?
24
+ end
25
+
26
+ def success?
27
+ @exit_code.nil? ? true : @exit_code.zero?
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HookHandler
4
+ class HookConfigError < StandardError; end
5
+ class HookExecError < StandardError; end
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def do_hooks(name)
12
+ raise HookConfigError, "'hooks.#{name}' must be a list" unless hooks(name).is_a?(Array)
13
+
14
+ execute_hooks(name)
15
+ end
16
+
17
+ private
18
+
19
+ def hooks(name)
20
+ @config.dig("hooks", name) || []
21
+ end
22
+
23
+ def execute_hooks(name)
24
+ hooks(name).each do |hook|
25
+ output, exit_code = Executor.execute(hook)
26
+
27
+ next if exit_code.zero?
28
+
29
+ raise HookExecError, "#{name} hook '#{hook}' failed with exit code #{exit_code}:\n#{output}"
30
+ end
31
+ end
32
+ end
data/lib/ops.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  require 'yaml'
5
5
  require 'require_all'
6
6
 
7
+ require 'hook_handler'
7
8
  require 'action'
8
9
  require 'output'
9
10
  require 'options'
@@ -18,6 +19,7 @@ class Ops
18
19
 
19
20
  INVALID_SYNTAX_EXIT_CODE = 64
20
21
  UNKNOWN_ACTION_EXIT_CODE = 65
22
+ ERROR_LOADING_APP_CONFIG_EXIT_CODE = 66
21
23
 
22
24
  class << self
23
25
  def project_name
@@ -53,13 +55,25 @@ class Ops
53
55
  end
54
56
 
55
57
  def run_action
56
- environment.set_variables
57
- AppConfig.load
58
+ do_before_run_action
58
59
 
59
60
  return builtin.run if builtin
60
61
 
61
62
  Output.notice("Running '#{action}' from #{CONFIG_FILE} in environment '#{ENV['environment']}'...")
62
63
  action.run
64
+ rescue AppConfig::ParsingError => e
65
+ Output.error("Error parsing app config: #{e}")
66
+ exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
67
+ end
68
+
69
+ def do_before_run_action
70
+ environment.set_variables
71
+ AppConfig.load
72
+ hook_handler.do_hooks("before")
73
+ end
74
+
75
+ def hook_handler
76
+ @hook_handler ||= HookHandler.new(config)
63
77
  end
64
78
 
65
79
  def builtin
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'open3'
4
5
 
5
6
  require 'output'
6
7
  require 'app_config'
@@ -38,6 +39,19 @@ class Secrets < AppConfig
38
39
  end
39
40
 
40
41
  def file_contents
41
- @file_contents ||= @filename.match(/\.ejson$/) ? `ejson decrypt #{@filename}` : super
42
+ @file_contents ||= begin
43
+ @filename.match(/\.ejson$/) ? ejson_contents : super
44
+ end
45
+ end
46
+
47
+ def ejson_contents
48
+ @ejson_contents ||= begin
49
+ out, err, _status = Open3.capture3("ejson decrypt #{@filename}")
50
+
51
+ # TODO: err is only nil in testing, but I can't figure out why the stubbing isn't working
52
+ raise ParsingError, "Error decrypting EJSON file: #{err}" unless err.nil? || err.empty?
53
+
54
+ out
55
+ end
42
56
  end
43
57
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'ops_team'
5
- s.version = '0.10.2'
5
+ s.version = '0.11.0'
6
6
  s.authors = [
7
7
  'nickthecook@gmail.com'
8
8
  ]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ops_team
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - nickthecook@gmail.com
@@ -170,6 +170,8 @@ files:
170
170
  - lib/dependencies/sshkey.rb
171
171
  - lib/dependency.rb
172
172
  - lib/environment.rb
173
+ - lib/executor.rb
174
+ - lib/hook_handler.rb
173
175
  - lib/ops.rb
174
176
  - lib/options.rb
175
177
  - lib/output.rb