ops_team 1.0.0 → 1.3.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/Gemfile +1 -0
- data/bin/ops +25 -2
- data/lib/action.rb +13 -1
- data/lib/builtins/countdown.rb +74 -0
- data/lib/dependencies/cask.rb +2 -2
- data/lib/environment.rb +3 -2
- data/lib/ops.rb +41 -108
- data/lib/runner.rb +95 -0
- data/ops_team.gemspec +1 -1
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 284cb7b523fa92a233a477d63adf73ca4257a460968fa135e722af70d7782e33
|
4
|
+
data.tar.gz: e9ec66dfe05a1411b5a3180cbffe5545ec23dfc193d06150c80a2cb96147bcd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4f399f48ff25956007f5ee9f7ff043b01c06639d1c58ba6d2dbffbaac5705b33b6c0d94a8a323279b7781aa8a199b8076c3f98e645b9e1a27c1e418cffd4c876
|
7
|
+
data.tar.gz: 0abe327dc2b32a4a82124a1de5f83e71f2d2674b2d3d102cd96db47a4dbed316d094d9041c9f2a2d729176c0cd2cc4ee1c393726f659d4a8d1460e2a1ac03ec6
|
data/Gemfile
CHANGED
data/bin/ops
CHANGED
@@ -1,8 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
|
7
|
+
def usage
|
8
|
+
puts "Usage: ops [-f|--file <ops_yml>] action [<action args>"
|
9
|
+
puts " ops_yml: the config file to load instead of './ops.yml'"
|
10
|
+
puts " action_args: arguments to the action loaded from the config file; depends on the action"
|
11
|
+
|
12
|
+
exit(1)
|
13
|
+
end
|
5
14
|
|
15
|
+
options = {}
|
16
|
+
while ARGV[0]&.match(/^-/)
|
17
|
+
opt = ARGV.shift
|
18
|
+
case opt
|
19
|
+
when '-f', '--file'
|
20
|
+
usage unless ARGV.length >= 1
|
21
|
+
|
22
|
+
options[:file] = ARGV.shift
|
23
|
+
else
|
24
|
+
usage
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
require_relative "../loader"
|
6
29
|
require 'ops'
|
7
30
|
|
8
|
-
Ops.new(ARGV).run
|
31
|
+
Ops.new(ARGV, config_file: options[:file]).run
|
data/lib/action.rb
CHANGED
@@ -17,7 +17,11 @@ class Action
|
|
17
17
|
raise NotAllowedInEnvError, "Action not allowed in #{Environment.environment} environment."
|
18
18
|
end
|
19
19
|
|
20
|
-
|
20
|
+
if perform_shell_expansion?
|
21
|
+
Kernel.exec(to_s)
|
22
|
+
else
|
23
|
+
Kernel.exec(*to_a)
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
23
27
|
def to_s
|
@@ -60,6 +64,10 @@ class Action
|
|
60
64
|
|
61
65
|
private
|
62
66
|
|
67
|
+
def to_a
|
68
|
+
command.split(" ").reject(&:nil?) | @args
|
69
|
+
end
|
70
|
+
|
63
71
|
def not_in_envs
|
64
72
|
@config["not_in_envs"] || []
|
65
73
|
end
|
@@ -75,4 +83,8 @@ class Action
|
|
75
83
|
|
76
84
|
true
|
77
85
|
end
|
86
|
+
|
87
|
+
def perform_shell_expansion?
|
88
|
+
@config["shell_expansion"].nil? ? true : @config["shell_expansion"]
|
89
|
+
end
|
78
90
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'concurrent'
|
4
|
+
|
5
|
+
require 'builtin'
|
6
|
+
require 'output'
|
7
|
+
|
8
|
+
module Builtins
|
9
|
+
class Countdown < Builtin
|
10
|
+
USAGE_STRING = "Usage: ops countdown <seconds>"
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def description
|
14
|
+
"Like `sleep`, but displays time remaining in terminal."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
check_args
|
20
|
+
|
21
|
+
timer_task.execute
|
22
|
+
|
23
|
+
while timer_task.running?
|
24
|
+
sleep(1)
|
25
|
+
timer_task.shutdown if task_complete?
|
26
|
+
end
|
27
|
+
Output.out("\rCountdown complete after #{sleep_seconds}s.")
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def check_args
|
33
|
+
check_arg_count
|
34
|
+
check_arg_is_positive_int
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_arg_count
|
38
|
+
raise Builtin::ArgumentError, USAGE_STRING unless args.length == 1
|
39
|
+
end
|
40
|
+
|
41
|
+
def check_arg_is_positive_int
|
42
|
+
raise Builtin::ArgumentError, USAGE_STRING unless sleep_seconds.positive?
|
43
|
+
# raised when the arg is not an int
|
44
|
+
rescue ::ArgumentError
|
45
|
+
raise Builtin::ArgumentError, USAGE_STRING
|
46
|
+
end
|
47
|
+
|
48
|
+
def timer_task
|
49
|
+
@timer_task ||= Concurrent::TimerTask.new(run_now: true, execution_interval: 1) do
|
50
|
+
Output.print("\r#{seconds_left}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def sleep_seconds
|
55
|
+
Integer(args.first)
|
56
|
+
end
|
57
|
+
|
58
|
+
def task_start_time
|
59
|
+
@task_start_time ||= Time.now
|
60
|
+
end
|
61
|
+
|
62
|
+
def task_end_time
|
63
|
+
@task_end_time ||= task_start_time + sleep_seconds
|
64
|
+
end
|
65
|
+
|
66
|
+
def task_complete?
|
67
|
+
Time.now > task_end_time
|
68
|
+
end
|
69
|
+
|
70
|
+
def seconds_left
|
71
|
+
Integer(task_end_time - Time.now + 1)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/dependencies/cask.rb
CHANGED
@@ -5,11 +5,11 @@ require 'dependencies/brew'
|
|
5
5
|
module Dependencies
|
6
6
|
class Cask < Brew
|
7
7
|
def met?
|
8
|
-
execute("brew cask
|
8
|
+
execute("brew list --cask #{name}")
|
9
9
|
end
|
10
10
|
|
11
11
|
def meet
|
12
|
-
execute("brew cask
|
12
|
+
execute("brew install --cask #{name}")
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
data/lib/environment.rb
CHANGED
@@ -13,8 +13,9 @@ class Environment
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
def initialize(env_hash)
|
16
|
+
def initialize(env_hash, config_path)
|
17
17
|
@env_hash = env_hash
|
18
|
+
@config_path = config_path
|
18
19
|
end
|
19
20
|
|
20
21
|
def set_variables
|
@@ -26,7 +27,7 @@ class Environment
|
|
26
27
|
private
|
27
28
|
|
28
29
|
def set_ops_variables
|
29
|
-
ENV["OPS_YML_DIR"] =
|
30
|
+
ENV["OPS_YML_DIR"] = File.dirname(@config_path)
|
30
31
|
ENV["OPS_VERSION"] = Version.version.to_s
|
31
32
|
ENV["OPS_SECRETS_FILE"] = Secrets.config_path_for(Environment.environment)
|
32
33
|
ENV["OPS_CONFIG_FILE"] = AppConfig.config_path_for(Environment.environment)
|
data/lib/ops.rb
CHANGED
@@ -5,25 +5,15 @@ require 'yaml'
|
|
5
5
|
require 'require_all'
|
6
6
|
require "rubygems"
|
7
7
|
|
8
|
-
require 'hook_handler'
|
9
|
-
require 'action'
|
10
8
|
require 'output'
|
11
9
|
require 'options'
|
12
|
-
require 'environment'
|
13
10
|
require 'version'
|
14
|
-
require '
|
15
|
-
require 'action_suggester'
|
16
|
-
require 'forwards'
|
11
|
+
require 'runner'
|
17
12
|
|
18
13
|
require_rel "builtins"
|
19
14
|
|
20
15
|
# executes commands based on local `ops.yml`
|
21
16
|
class Ops
|
22
|
-
class UnknownActionError < StandardError; end
|
23
|
-
class ActionConfigError < StandardError; end
|
24
|
-
|
25
|
-
CONFIG_FILE = "ops.yml"
|
26
|
-
|
27
17
|
INVALID_SYNTAX_EXIT_CODE = 64
|
28
18
|
UNKNOWN_ACTION_EXIT_CODE = 65
|
29
19
|
ERROR_LOADING_APP_CONFIG_EXIT_CODE = 66
|
@@ -40,50 +30,55 @@ class Ops
|
|
40
30
|
end
|
41
31
|
end
|
42
32
|
|
43
|
-
def initialize(argv)
|
33
|
+
def initialize(argv, config_file: nil)
|
44
34
|
@action_name = argv[0]
|
45
35
|
@args = argv[1..-1]
|
36
|
+
@config_file = config_file || "ops.yml"
|
46
37
|
|
47
38
|
Options.set(config["options"] || {})
|
48
39
|
end
|
49
40
|
|
41
|
+
# rubocop:disable Metrics/MethodLength
|
42
|
+
# better to have all the rescues in one place
|
50
43
|
def run
|
51
44
|
# "return" is here to allow specs to stub "exit" without executing everything after it
|
52
45
|
return exit(INVALID_SYNTAX_EXIT_CODE) unless syntax_valid?
|
53
46
|
return exit(MIN_VERSION_NOT_MET_EXIT_CODE) unless min_version_met?
|
54
47
|
|
55
|
-
|
56
|
-
rescue UnknownActionError => e
|
48
|
+
runner.run
|
49
|
+
rescue Runner::UnknownActionError => e
|
57
50
|
Output.error(e.to_s)
|
58
51
|
Output.out(RECOMMEND_HELP_TEXT) unless print_did_you_mean
|
59
52
|
exit(UNKNOWN_ACTION_EXIT_CODE)
|
60
|
-
rescue ActionConfigError => e
|
53
|
+
rescue Runner::ActionConfigError => e
|
61
54
|
Output.error("Error(s) running action '#{@action_name}': #{e}")
|
62
55
|
exit(ACTION_CONFIG_ERROR_EXIT_CODE)
|
56
|
+
rescue Builtin::ArgumentError => e
|
57
|
+
Output.error("Error running builtin '#{@action_name}': #{e}")
|
58
|
+
exit(BUILTIN_SYNTAX_ERROR_EXIT_CODE)
|
59
|
+
rescue AppConfig::ParsingError => e
|
60
|
+
Output.error("Error parsing app config: #{e}")
|
61
|
+
exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
|
62
|
+
rescue Action::NotAllowedInEnvError => e
|
63
|
+
Output.error("Error running action #{@action_name}: #{e}")
|
64
|
+
exit(ACTION_NOT_ALLOWED_IN_ENV_EXIT_CODE)
|
63
65
|
end
|
66
|
+
# rubocop:enable Metrics/MethodLength
|
64
67
|
|
65
68
|
private
|
66
69
|
|
67
70
|
def syntax_valid?
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
true
|
74
|
-
end
|
71
|
+
return true unless @action_name.nil?
|
72
|
+
|
73
|
+
Output.error("Usage: ops <action>")
|
74
|
+
Output.out(RECOMMEND_HELP_TEXT)
|
75
|
+
false
|
75
76
|
end
|
76
77
|
|
77
78
|
def print_did_you_mean
|
78
|
-
|
79
|
+
Output.out("Did you mean '#{runner.suggestions.join(", ")}'?") if runner.suggestions.any?
|
79
80
|
|
80
|
-
|
81
|
-
|
82
|
-
suggestions.any?
|
83
|
-
end
|
84
|
-
|
85
|
-
def did_you_mean
|
86
|
-
ActionSuggester.new(action_list.names + action_list.aliases + builtin_names)
|
81
|
+
runner.suggestions.any?
|
87
82
|
end
|
88
83
|
|
89
84
|
def min_version_met?
|
@@ -101,96 +96,34 @@ class Ops
|
|
101
96
|
config["min_version"]
|
102
97
|
end
|
103
98
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
do_before_all
|
108
|
-
|
109
|
-
return builtin.run if builtin
|
110
|
-
|
111
|
-
raise UnknownActionError, "Unknown action: #{@action_name}" unless action
|
112
|
-
raise ActionConfigError, action.config_errors.join("; ") unless action.config_valid?
|
113
|
-
|
114
|
-
do_before_action
|
115
|
-
Output.notice("Running '#{action}' from #{CONFIG_FILE} in environment '#{ENV['environment']}'...")
|
116
|
-
action.run
|
117
|
-
rescue Builtin::ArgumentError => e
|
118
|
-
Output.error("Error running builtin '#{@action_name}': #{e}")
|
119
|
-
exit(BUILTIN_SYNTAX_ERROR_EXIT_CODE)
|
120
|
-
rescue AppConfig::ParsingError => e
|
121
|
-
Output.error("Error parsing app config: #{e}")
|
122
|
-
exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
|
123
|
-
rescue Action::NotAllowedInEnvError => e
|
124
|
-
Output.error("Error running action #{@action_name}: #{e}")
|
125
|
-
exit(ACTION_NOT_ALLOWED_IN_ENV_EXIT_CODE)
|
126
|
-
end
|
127
|
-
|
128
|
-
def do_before_all
|
129
|
-
AppConfig.load
|
130
|
-
Secrets.load if action && action.load_secrets?
|
131
|
-
environment.set_variables
|
132
|
-
end
|
133
|
-
|
134
|
-
def do_before_action
|
135
|
-
return if ENV["OPS_RUNNING"] || action.skip_hooks?("before")
|
136
|
-
|
137
|
-
# this prevents before hooks from running in ops executed by ops
|
138
|
-
ENV["OPS_RUNNING"] = "1"
|
139
|
-
hook_handler.do_hooks("before")
|
140
|
-
end
|
141
|
-
|
142
|
-
def hook_handler
|
143
|
-
@hook_handler ||= HookHandler.new(config)
|
144
|
-
end
|
145
|
-
|
146
|
-
def builtin
|
147
|
-
@builtin ||= Builtin.class_for(name: @action_name).new(@args, config)
|
148
|
-
rescue NameError
|
149
|
-
# this means there isn't a builtin with that name in that module
|
150
|
-
nil
|
151
|
-
end
|
152
|
-
|
153
|
-
def builtin_names
|
154
|
-
Builtins.constants.select { |c| Builtins.const_get(c).is_a? Class }.map(&:downcase)
|
155
|
-
end
|
156
|
-
|
157
|
-
def forward
|
158
|
-
@forward ||= Forwards.new(@config, @args).get(@action_name)
|
159
|
-
end
|
160
|
-
|
161
|
-
def action
|
162
|
-
return action_list.get(@action_name) if action_list.get(@action_name)
|
163
|
-
return action_list.get_by_alias(@action_name) if action_list.get_by_alias(@action_name)
|
164
|
-
end
|
165
|
-
|
166
|
-
def action_list
|
167
|
-
@action_list ||= begin
|
168
|
-
Output.warn("'ops.yml' has no 'actions' defined.") if config.any? && config["actions"].nil?
|
169
|
-
|
170
|
-
ActionList.new(config["actions"], @args)
|
171
|
-
end
|
99
|
+
def runner
|
100
|
+
@runner ||= Runner.new(@action_name, @args, config, config_file_absolute_path)
|
172
101
|
end
|
173
102
|
|
174
103
|
def config
|
175
104
|
@config ||= begin
|
176
|
-
if
|
177
|
-
|
105
|
+
if config_file_exists?
|
106
|
+
parsed_config_contents
|
178
107
|
else
|
179
|
-
Output.warn("File '#{
|
108
|
+
Output.warn("File '#{@config_file}' does not exist.") unless @action_name == "init"
|
180
109
|
{}
|
181
110
|
end
|
182
|
-
rescue StandardError => e
|
183
|
-
Output.warn("Error parsing '#{CONFIG_FILE}': #{e}")
|
184
|
-
{}
|
185
111
|
end
|
186
112
|
end
|
187
113
|
|
188
|
-
def
|
189
|
-
|
114
|
+
def parsed_config_contents
|
115
|
+
YAML.load_file(@config_file)
|
116
|
+
rescue StandardError => e
|
117
|
+
Output.warn("Error parsing '#{@config_file}': #{e}")
|
118
|
+
{}
|
119
|
+
end
|
120
|
+
|
121
|
+
def config_file_exists?
|
122
|
+
File.exist?(@config_file)
|
190
123
|
end
|
191
124
|
|
192
|
-
def
|
193
|
-
|
125
|
+
def config_file_absolute_path
|
126
|
+
File.expand_path(@config_file)
|
194
127
|
end
|
195
128
|
end
|
196
129
|
|
data/lib/runner.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'hook_handler'
|
4
|
+
require 'action'
|
5
|
+
require 'action_list'
|
6
|
+
require 'action_suggester'
|
7
|
+
require 'forwards'
|
8
|
+
require 'environment'
|
9
|
+
|
10
|
+
class Runner
|
11
|
+
class UnknownActionError < StandardError; end
|
12
|
+
class ActionConfigError < StandardError; end
|
13
|
+
|
14
|
+
def initialize(action_name, args, config, config_path)
|
15
|
+
@action_name = action_name
|
16
|
+
@args = args
|
17
|
+
@config = config
|
18
|
+
@config_path = config_path
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
return forward.run if forward
|
23
|
+
|
24
|
+
do_before_all
|
25
|
+
|
26
|
+
return builtin.run if builtin
|
27
|
+
|
28
|
+
raise UnknownActionError, "Unknown action: #{@action_name}" unless action
|
29
|
+
raise ActionConfigError, action.config_errors.join("; ") unless action.config_valid?
|
30
|
+
|
31
|
+
do_before_action
|
32
|
+
Output.notice("Running '#{action}' in environment '#{ENV['environment']}'...")
|
33
|
+
action.run
|
34
|
+
end
|
35
|
+
|
36
|
+
def suggestions
|
37
|
+
@suggestions ||= ActionSuggester.new(action_list.names + action_list.aliases + builtin_names).check(@action_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def do_before_all
|
43
|
+
AppConfig.load
|
44
|
+
Secrets.load if action&.load_secrets?
|
45
|
+
environment.set_variables
|
46
|
+
end
|
47
|
+
|
48
|
+
def do_before_action
|
49
|
+
return if ENV["OPS_RUNNING"] || action.skip_hooks?("before")
|
50
|
+
|
51
|
+
# this prevents before hooks from running in ops executed by ops
|
52
|
+
ENV["OPS_RUNNING"] = "1"
|
53
|
+
hook_handler.do_hooks("before")
|
54
|
+
end
|
55
|
+
|
56
|
+
def hook_handler
|
57
|
+
@hook_handler ||= HookHandler.new(@config)
|
58
|
+
end
|
59
|
+
|
60
|
+
def builtin
|
61
|
+
@builtin ||= Builtin.class_for(name: @action_name).new(@args, @config)
|
62
|
+
rescue NameError
|
63
|
+
# this means there isn't a builtin with that name in that module
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def builtin_names
|
68
|
+
Builtins.constants.select { |c| Builtins.const_get(c).is_a? Class }.map(&:downcase)
|
69
|
+
end
|
70
|
+
|
71
|
+
def forward
|
72
|
+
@forward ||= Forwards.new(@config, @args).get(@action_name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def action
|
76
|
+
return action_list.get(@action_name) if action_list.get(@action_name)
|
77
|
+
return action_list.get_by_alias(@action_name) if action_list.get_by_alias(@action_name)
|
78
|
+
end
|
79
|
+
|
80
|
+
def action_list
|
81
|
+
@action_list ||= begin
|
82
|
+
Output.warn("'ops.yml' has no 'actions' defined.") if @config.any? && @config["actions"].nil?
|
83
|
+
|
84
|
+
ActionList.new(@config["actions"], @args)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def env_vars
|
89
|
+
@config.dig("options", "environment") || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
def environment
|
93
|
+
@environment ||= Environment.new(env_vars, @config_path)
|
94
|
+
end
|
95
|
+
end
|
data/ops_team.gemspec
CHANGED
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: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nickthecook@gmail.com
|
@@ -94,22 +94,22 @@ dependencies:
|
|
94
94
|
name: net-ssh
|
95
95
|
requirement: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
|
-
- - ">="
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: 6.1.0
|
100
97
|
- - "~>"
|
101
98
|
- !ruby/object:Gem::Version
|
102
99
|
version: '6.1'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 6.1.0
|
103
103
|
type: :runtime
|
104
104
|
prerelease: false
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 6.1.0
|
110
107
|
- - "~>"
|
111
108
|
- !ruby/object:Gem::Version
|
112
109
|
version: '6.1'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 6.1.0
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: require_all
|
115
115
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- lib/builtin.rb
|
153
153
|
- lib/builtins/background.rb
|
154
154
|
- lib/builtins/background_log.rb
|
155
|
+
- lib/builtins/countdown.rb
|
155
156
|
- lib/builtins/down.rb
|
156
157
|
- lib/builtins/env.rb
|
157
158
|
- lib/builtins/envdiff.rb
|
@@ -181,6 +182,7 @@ files:
|
|
181
182
|
- lib/ops.rb
|
182
183
|
- lib/options.rb
|
183
184
|
- lib/output.rb
|
185
|
+
- lib/runner.rb
|
184
186
|
- lib/secrets.rb
|
185
187
|
- lib/version.rb
|
186
188
|
- loader.rb
|
@@ -204,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
206
|
- !ruby/object:Gem::Version
|
205
207
|
version: '0'
|
206
208
|
requirements: []
|
207
|
-
rubygems_version: 3.
|
209
|
+
rubygems_version: 3.1.2
|
208
210
|
signing_key:
|
209
211
|
specification_version: 4
|
210
212
|
summary: ops_team handles basic operations tasks for your project, driven by YAML
|