ops_team 0.1.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fa5c498bf634206ab5ef4e53313731fb1ab8ee71456051d03f0b50d7b98f71ab
4
+ data.tar.gz: 6167a9ec3c12915fe62f3ccc3de1ce2a7f22351d32a7b2c10d8bb2b3c6da291d
5
+ SHA512:
6
+ metadata.gz: 0273b1834ceb76c119328e45574ba27a924bb9ba50334661ad78ffebee8883f6efa0de75f8a97536d351103e36c64accd29ac1ae68892085828600b1c85de2fb
7
+ data.tar.gz: f021f9ea483736c3e13692d58f9284c105117fac4b1b873dd8918b9e5b123b4bd900c8b4735805a1b7f5f149c4ff8fb5c9a5f5efafb5e75644c1c3e9ebbf5001
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ gem "colorize"
8
+ gem "require_all"
9
+
10
+ group :test do
11
+ gem "fuubar"
12
+ gem "rspec"
13
+ end
14
+
15
+ group :development do
16
+ gem "pry"
17
+ gem "pry-byebug"
18
+ gem "rerun"
19
+ gem "rubocop"
20
+ end
data/bin/ops ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../loader"
5
+
6
+ require 'ops'
7
+
8
+ Ops.new(ARGV).run
data/bin/tag ADDED
@@ -0,0 +1,16 @@
1
+ #!/bin/bash
2
+ # tags a commit, asking for input when needed
3
+
4
+ if [ -n "$1" ]; then
5
+ tag="$1"
6
+ else
7
+ tag=$(grep -o "'[0-9.]*'" ops_team.gemspec | sed "s/'//g")
8
+ if [ -z "$tag" ]; then
9
+ read -p "Enter tag value: " tag
10
+ fi
11
+ fi
12
+
13
+ comment="Tagging $tag for release"
14
+ echo "Tagging '$tag' with comment '$comment'..."
15
+ git tag -a "$tag" -m "$comment"
16
+ git push origin "$tag"
@@ -0,0 +1,11 @@
1
+ dependencies:
2
+ # e.g.
3
+ # brew:
4
+ # - docker-compose
5
+ # - docker
6
+ # - curl
7
+ actions:
8
+ start:
9
+ command: docker-compose up -d
10
+ stop:
11
+ command: docker-compose down
@@ -0,0 +1,29 @@
1
+ dependencies:
2
+ gem:
3
+ - bundler
4
+ - rerun
5
+ custom:
6
+ - bundle
7
+ actions:
8
+ start:
9
+ command: echo update me
10
+ stop:
11
+ command: echo update me too
12
+ test:
13
+ command: rspec
14
+ alias: t
15
+ test-watch:
16
+ command: rerun -x ops test
17
+ alias: tw
18
+ lint:
19
+ command: bundle exec rubocop --safe-auto-correct
20
+ alias: l
21
+ build:
22
+ command: gem build *.gemspec
23
+ alias: b
24
+ install:
25
+ command: gem install `ls -t *.gem | head -n1`
26
+ alias: i
27
+ build-and-install:
28
+ command: ops build && ops install
29
+ alias: bi
@@ -0,0 +1,26 @@
1
+ dependencies:
2
+ brew:
3
+ - terraform
4
+ apt:
5
+ - terraform
6
+ custom:
7
+ - terraform init
8
+ actions:
9
+ apply:
10
+ command: terraform apply
11
+ alias: a
12
+ apply-auto-approve:
13
+ command: terraform apply --auto-approve
14
+ alias: aa
15
+ destroy:
16
+ command: terraform destroy
17
+ alias: d
18
+ destroy-auto-approve:
19
+ command: terraform destroy --auto-approve
20
+ alias: dd
21
+ plan:
22
+ command: terraform plan
23
+ alias: p
24
+ graph:
25
+ command: terraform graph
26
+ alias: g
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # represents one action to be performed in the shell
4
+ # can assemble a command line from a command and args
5
+ class Action
6
+ def initialize(command, args)
7
+ @command = command
8
+ @args = args
9
+ end
10
+
11
+ def run
12
+ Kernel.exec(to_s)
13
+ end
14
+
15
+ def to_s
16
+ "#{@command} #{@args.join(' ')}"
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Builtin
4
+ def initialize(args, config)
5
+ @args = args
6
+ @config = config
7
+ end
8
+
9
+ def run
10
+ raise NotImplementedError
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'require_all'
4
+ require_rel "../dependencies"
5
+
6
+ require 'builtin'
7
+ require 'builtins/helpers/dependency_handler'
8
+
9
+ module Builtins
10
+ class Down < Builtin
11
+ def run
12
+ # TODO: return a success/failure status to the caller
13
+ unmeet_dependencies
14
+ end
15
+
16
+ private
17
+
18
+ def dependency_handler
19
+ Helpers::DependencyHandler.new(@config["dependencies"])
20
+ end
21
+
22
+ def unmeet_dependencies
23
+ dependency_handler.dependencies.each do |dependency|
24
+ # don't even output anything for dependencies that shouldn't be considered on this machine
25
+ next unless dependency.should_meet?
26
+
27
+ Output.status("[#{dependency.type}] #{dependency.name}")
28
+
29
+ unmeet_dependency(dependency)
30
+ end
31
+ end
32
+
33
+ def unmeet_dependency(dependency)
34
+ # TODO: make this simpler, and factor in `should_meet?` above, too
35
+ dependency.unmeet if dependency.met? || dependency.always_act?
36
+
37
+ if dependency.success?
38
+ Output.okay
39
+ else
40
+ Output.failed
41
+ Output.error("Error unmeeting #{dependency.type} dependency '#{dependency.name}':")
42
+ puts(dependency.output)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'builtin'
4
+ require 'output'
5
+
6
+ module Builtins
7
+ class Env < Builtin
8
+ def run
9
+ Output.print(environment)
10
+ end
11
+
12
+ private
13
+
14
+ def environment
15
+ ENV['environment'] || 'dev'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'builtin'
4
+ require 'output'
5
+
6
+ require 'require_all'
7
+ require_rel "../../dependencies"
8
+
9
+ module Builtins
10
+ module Helpers
11
+ class DependencyHandler
12
+ def initialize(dependency_set)
13
+ @dependency_set = dependency_set
14
+ end
15
+
16
+ def dependencies
17
+ return [] unless @dependency_set
18
+
19
+ @dependency_set.map do |type, names|
20
+ dependencies_for(type, names)
21
+ end.flatten
22
+ end
23
+
24
+ def dependencies_for(type, names)
25
+ dependency_class = Dependencies.const_get(type.capitalize.to_sym)
26
+
27
+ names.map { |name| dependency_class.new(name) }
28
+ rescue NameError
29
+ Output.error("No way to handle dependencies of type '#{type}'; ignoring.")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ require 'builtin'
6
+ require 'output'
7
+
8
+ module Builtins
9
+ class Init < Builtin
10
+ OPS_YML = "ops.yml"
11
+ TEMPLATE_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "etc"))
12
+ OPS_YML_TEMPLATE = File.join(TEMPLATE_DIR, "%<template_name>s.template.yml")
13
+ DEFAULT_TEMPLATE_NAME = "ops"
14
+
15
+ def run
16
+ if File.exist?(OPS_YML)
17
+ Output.error("File '#{OPS_YML} exists; not initializing.")
18
+ else
19
+ Output.out("Creating '#{OPS_YML} from template...")
20
+ FileUtils.cp(template_path, OPS_YML)
21
+ end
22
+ rescue SystemCallError
23
+ Output.error(template_not_found_message)
24
+ exit 1
25
+ end
26
+
27
+ private
28
+
29
+ def template_name_arg
30
+ @args[0]
31
+ end
32
+
33
+ def template_path
34
+ format(OPS_YML_TEMPLATE, template_name: template_name_arg || DEFAULT_TEMPLATE_NAME)
35
+ end
36
+
37
+ def template_name_list
38
+ @template_name_list ||= Dir.entries(TEMPLATE_DIR).map do |name|
39
+ name.match(/^([^.]*).template.yml/)&.captures&.first
40
+ end.compact
41
+ end
42
+
43
+ def template_not_found_message
44
+ <<~MESSAGE
45
+ Template '#{template_path} does not exist.
46
+ \nValid template names are:
47
+ - #{template_name_list.join("\n - ")}\n
48
+ MESSAGE
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'require_all'
4
+ require_rel "../dependencies"
5
+
6
+ require 'builtin'
7
+ require 'builtins/helpers/dependency_handler'
8
+ require 'output'
9
+
10
+ module Builtins
11
+ class Up < Builtin
12
+ def run
13
+ # TODO: return a success/failure status to the caller
14
+ meet_dependencies
15
+ end
16
+
17
+ private
18
+
19
+ def dependency_handler
20
+ Helpers::DependencyHandler.new(@config["dependencies"])
21
+ end
22
+
23
+ def meet_dependencies
24
+ dependency_handler.dependencies.each do |dependency|
25
+ # don't even output anything for dependencies that shouldn't be considered on this machine
26
+ next unless dependency.should_meet?
27
+
28
+ Output.status("[#{dependency.type}] #{dependency.name}")
29
+
30
+ meet_dependency(dependency)
31
+ end
32
+ end
33
+
34
+ def meet_dependency(dependency)
35
+ # TODO: make this simpler, and factor in `should_meet?` above, too
36
+ dependency.meet if !dependency.met? || dependency.always_act?
37
+
38
+ if dependency.success?
39
+ Output.okay
40
+ else
41
+ Output.failed
42
+ Output.error("Error meeting #{dependency.type} dependency '#{dependency.name}':")
43
+ puts(dependency.output)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'English'
4
+
5
+ require 'dependency'
6
+
7
+ module Dependencies
8
+ class Apk < Dependency
9
+ def met?
10
+ execute("apk info | grep -q #{name}")
11
+ end
12
+
13
+ def meet
14
+ execute("apk add #{name}")
15
+ end
16
+
17
+ def unmeet
18
+ # do nothing; we don't want to uninstall packages and reinstall them every time
19
+ true
20
+ end
21
+
22
+ def should_meet?
23
+ system("which apk")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependency'
4
+
5
+ module Dependencies
6
+ class Apt < Dependency
7
+ def met?
8
+ execute("dpkg-query --show --showformat '${db:Status-Status}\n' #{name} | grep -q ^installed")
9
+ end
10
+
11
+ def meet
12
+ execute("apt-get install -y #{name}")
13
+ end
14
+
15
+ def unmeet
16
+ # do nothing; we don't want to uninstall packages and reinstall them every time
17
+ true
18
+ end
19
+
20
+ def should_meet?
21
+ `uname`.chomp == "Linux"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependency'
4
+
5
+ module Dependencies
6
+ class Brew < Dependency
7
+ def met?
8
+ execute("brew list #{name}")
9
+ end
10
+
11
+ def meet
12
+ execute("brew install #{name}")
13
+ end
14
+
15
+ def unmeet
16
+ # do nothing; we don't want to uninstall packages and reinstall them every time
17
+ true
18
+ end
19
+
20
+ def should_meet?
21
+ `uname`.chomp == "Darwin"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependencies/brew'
4
+
5
+ module Dependencies
6
+ class Cask < Brew
7
+ def met?
8
+ execute("brew cask list #{name}")
9
+ end
10
+
11
+ def meet
12
+ execute("brew cask install #{name}")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependency'
4
+
5
+ module Dependencies
6
+ class Custom < Dependency
7
+ def met?
8
+ # we always want to try to meet this dependency
9
+ false
10
+ end
11
+
12
+ def meet
13
+ # this dependency is just a custom, idempotent command
14
+ execute(name)
15
+ end
16
+
17
+ def unmeet
18
+ true
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependency'
4
+
5
+ module Dependencies
6
+ class Docker < Dependency
7
+ def met?
8
+ execute("cd #{name} && docker-compose ps | grep -q ' Up '")
9
+ end
10
+
11
+ def meet
12
+ execute("cd #{name} && docker-compose up -d")
13
+ end
14
+
15
+ def unmeet
16
+ execute("cd #{name} && docker-compose down")
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependency'
4
+ require 'options'
5
+
6
+ module Dependencies
7
+ class Gem < Dependency
8
+ def met?
9
+ execute("gem list -i '^#{name}$'")
10
+ end
11
+
12
+ def meet
13
+ if Options.get("gem.use_sudo")
14
+ execute("sudo gem install #{name}")
15
+ elsif Options.get("gem.user_install")
16
+ execute("gem install --user-install #{name}")
17
+ else
18
+ execute("gem install #{name}")
19
+ end
20
+ end
21
+
22
+ def unmeet
23
+ # do nothing; we don't want to uninstall packages and reinstall them every time
24
+ true
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dependency'
4
+
5
+ module Dependencies
6
+ class Terraform < Dependency
7
+ def met?
8
+ false
9
+ end
10
+
11
+ def always_act?
12
+ true
13
+ end
14
+
15
+ def meet
16
+ execute("cd #{name} && terraform init && terraform apply -input=false --auto-approve")
17
+ end
18
+
19
+ def unmeet
20
+ execute("cd #{name} && terraform destroy -input=false --auto-approve")
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'English'
5
+
6
+ require 'output'
7
+
8
+ class Dependency
9
+ DESCRIPTION_TYPE_WIDTH = 8
10
+
11
+ attr_reader :name, :output, :exit_code
12
+
13
+ def initialize(name)
14
+ @name = name
15
+ end
16
+
17
+ def met?
18
+ raise NotImplementedError
19
+ end
20
+
21
+ def meet
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def unmeet
26
+ raise NotImplementedError
27
+ end
28
+
29
+ # should_meet? can be used to implement dependencies that should only be met on some platforms,
30
+ # e.g. brew on Macs and apt on Linux
31
+ # it can be used to base a decision on anything else that can be read from the environment at
32
+ # runtime
33
+ def should_meet?
34
+ true
35
+ end
36
+
37
+ # if true, this type of resource must always have `meet` and `unmeet` called;
38
+ # useful for resources that can't easily be checked to see if they're met
39
+ def always_act?
40
+ false
41
+ end
42
+
43
+ def type
44
+ self.class.name.split('::').last
45
+ end
46
+
47
+ def success?
48
+ @exit_code.nil? ? true : @exit_code.zero?
49
+ end
50
+
51
+ private
52
+
53
+ def execute(cmd)
54
+ @output, status = Open3.capture2e(cmd)
55
+ @exit_code = status.exitstatus
56
+
57
+ success?
58
+ end
59
+ end
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'yaml'
5
+ require 'require_all'
6
+
7
+ require 'action'
8
+ require 'output'
9
+ require 'options'
10
+ require_rel "builtins"
11
+
12
+ # executes commands defined in local `ops.yml`
13
+ class Ops
14
+ class UnknownActionError < StandardError; end
15
+
16
+ CONFIG_FILE = "ops.yml"
17
+
18
+ INVALID_SYNTAX_EXIT_CODE = 1
19
+
20
+ def initialize(argv)
21
+ @action_name = argv[0]
22
+ @args = argv[1..-1]
23
+
24
+ Options.set(config["options"] || {})
25
+ end
26
+
27
+ def run
28
+ exit(INVALID_SYNTAX_EXIT_CODE) unless syntax_valid?
29
+
30
+ return builtin.run if builtin
31
+
32
+ Output.warn("Running '#{action}' from #{CONFIG_FILE}...")
33
+ action.run
34
+ rescue UnknownActionError => e
35
+ Output.error("Error: #{e}")
36
+ end
37
+
38
+ private
39
+
40
+ def syntax_valid?
41
+ if @action_name.nil?
42
+ # TODO: output to stderr
43
+ puts "Usage: ops <action>"
44
+ false
45
+ else
46
+ true
47
+ end
48
+ end
49
+
50
+ def builtin
51
+ @builtin ||= Builtins.const_get(builtin_class_name).new(@args, config)
52
+ rescue NameError
53
+ # this means there isn't a builtin with that name in that module
54
+ nil
55
+ end
56
+
57
+ def builtin_class_name
58
+ @action_name.capitalize.to_sym
59
+ end
60
+
61
+ def action
62
+ @action ||= Action.new(command, @args)
63
+ end
64
+
65
+ def command
66
+ @command ||= begin
67
+ return actions[@action_name]["command"] if actions[@action_name]
68
+ return aliases[@action_name]["command"] if aliases[@action_name]
69
+
70
+ raise UnknownActionError, "Unknown action: #{@action_name}"
71
+ end
72
+ end
73
+
74
+ def actions
75
+ config["actions"]
76
+ end
77
+
78
+ def config
79
+ @config ||= begin
80
+ Output.warn("File '#{CONFIG_FILE}' does not exist.") unless File.exist?(CONFIG_FILE)
81
+ YAML.load_file(CONFIG_FILE)
82
+ rescue StandardError
83
+ {}
84
+ end
85
+ end
86
+
87
+ def aliases
88
+ @aliases ||= begin
89
+ actions.each_with_object({}) do |(_name, body), alias_hash|
90
+ alias_hash[body["alias"]] = body if body.include?("alias")
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ Ops.new(ARGV).run if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Options
4
+ class << self
5
+ def get(path)
6
+ @options.dig(*path.split('.'))
7
+ end
8
+
9
+ def set(options)
10
+ @options = options
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'colorize'
4
+
5
+ class Output
6
+ @out = STDOUT
7
+ @err = STDERR
8
+
9
+ STATUS_WIDTH = "50"
10
+
11
+ OKAY = "OK"
12
+ SKIPPED = "SKIPPED"
13
+ FAILED = "FAILED"
14
+
15
+ # used to silence output, e.g. in testing
16
+ class DummyOutput
17
+ def print(*_); end
18
+
19
+ def puts(*_); end
20
+ end
21
+
22
+ class << self
23
+ def status(name)
24
+ @out.print(format("%-#{STATUS_WIDTH}<name>s ", name: name))
25
+ end
26
+
27
+ def okay
28
+ @out.puts(OKAY.green)
29
+ end
30
+
31
+ def skipped
32
+ @out.puts(SKIPPED.yellow)
33
+ end
34
+
35
+ def failed
36
+ @out.puts(FAILED.red)
37
+ end
38
+
39
+ def warn(msg)
40
+ @err.puts(msg.yellow)
41
+ end
42
+
43
+ def error(msg)
44
+ @err.puts(msg.red)
45
+ end
46
+
47
+ def out(msg)
48
+ @out.puts(msg)
49
+ end
50
+
51
+ def print(msg)
52
+ @out.print(msg)
53
+ end
54
+
55
+ def silence
56
+ @out = @err = dummy_output
57
+ end
58
+
59
+ def dummy_output
60
+ @dummy_output ||= DummyOutput.new
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # for convenience, add "lib" to the load path
4
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/lib"))
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ops_team
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - nickthecook@gmail.com
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.8.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.8'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.8.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: require_all
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.1'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.1.6
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.1'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.1.6
53
+ description:
54
+ email:
55
+ executables:
56
+ - ops
57
+ extensions: []
58
+ extra_rdoc_files: []
59
+ files:
60
+ - Gemfile
61
+ - bin/ops
62
+ - bin/tag
63
+ - etc/ops.template.yml
64
+ - etc/ruby.template.yml
65
+ - etc/terraform.template.yml
66
+ - lib/action.rb
67
+ - lib/builtin.rb
68
+ - lib/builtins/down.rb
69
+ - lib/builtins/env.rb
70
+ - lib/builtins/helpers/dependency_handler.rb
71
+ - lib/builtins/init.rb
72
+ - lib/builtins/up.rb
73
+ - lib/dependencies/apk.rb
74
+ - lib/dependencies/apt.rb
75
+ - lib/dependencies/brew.rb
76
+ - lib/dependencies/cask.rb
77
+ - lib/dependencies/custom.rb
78
+ - lib/dependencies/docker.rb
79
+ - lib/dependencies/gem.rb
80
+ - lib/dependencies/terraform.rb
81
+ - lib/dependency.rb
82
+ - lib/ops.rb
83
+ - lib/options.rb
84
+ - lib/output.rb
85
+ - loader.rb
86
+ homepage:
87
+ licenses:
88
+ - GPL-3.0-only
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubygems_version: 3.0.3
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: ops_team handles basic operations tasks for your project, driven by YAML
109
+ config
110
+ test_files: []