sensible-cli 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.idea/.gitignore +8 -0
- data/.idea/material_theme_project_new.xml +10 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/sensible-ruby.iml +47 -0
- data/.idea/vcs.xml +6 -0
- data/README.md +6 -0
- data/exe/sensible +37 -36
- data/lib/sensible/log.rb +16 -1
- data/lib/sensible/package.rb +40 -29
- data/lib/sensible/parse.rb +1 -1
- data/lib/sensible/requirement.rb +71 -1
- data/lib/sensible/shell.rb +106 -0
- data/lib/sensible/task.rb +72 -40
- data/lib/sensible/version.rb +1 -1
- data/lib/sensible.rb +108 -116
- data/new-sensible-spec.md +140 -0
- data/sensible.yml +11 -21
- metadata +47 -7
- data/.sensible/tasks/another.yml +0 -7
- data/.sensible/tasks/test.yml +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac1a27c2c7bb7b0b94e321c73538dc2c86acd7fff5a1f08df6c8c8c4457d3312
|
4
|
+
data.tar.gz: 6c09a5676d85d4a19985f9f84a88e9b49f5f00ed760b034f60b7c642a49d47df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 471fd3d26546e3c722a550f4f164502ef7ec71a23dada9cb67fd882d8f84388478ed1120f59b3a5ae9f2e543cc7941b39270d2ddba4472e25951f78576ccec2a
|
7
|
+
data.tar.gz: ec7ee80deebbce2917b4f6801e885dd3802f9e90d3e2d1c841ea651b5f34c6f4f48791cd8658f046205a2ddbc8a26d159f4686dd6460cb5e16fb0a9ffe1893f1
|
data/.idea/.gitignore
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<project version="4">
|
3
|
+
<component name="MaterialThemeProjectNewConfig">
|
4
|
+
<option name="metadata">
|
5
|
+
<MTProjectMetadataState>
|
6
|
+
<option name="userId" value="-7c4bb857:19787ef65ab:-7fff" />
|
7
|
+
</MTProjectMetadataState>
|
8
|
+
</option>
|
9
|
+
</component>
|
10
|
+
</project>
|
data/.idea/misc.xml
ADDED
data/.idea/modules.xml
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<project version="4">
|
3
|
+
<component name="ProjectModuleManager">
|
4
|
+
<modules>
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/sensible-ruby.iml" filepath="$PROJECT_DIR$/.idea/sensible-ruby.iml" />
|
6
|
+
</modules>
|
7
|
+
</component>
|
8
|
+
</project>
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
3
|
+
<component name="ModuleRunConfigurationManager">
|
4
|
+
<shared />
|
5
|
+
</component>
|
6
|
+
<component name="NewModuleRootManager">
|
7
|
+
<content url="file://$MODULE_DIR$">
|
8
|
+
<sourceFolder url="file://$MODULE_DIR$/features" isTestSource="true" />
|
9
|
+
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
|
10
|
+
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
11
|
+
</content>
|
12
|
+
<orderEntry type="inheritedJdk" />
|
13
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
14
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v2.6.9, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
15
|
+
<orderEntry type="library" scope="PROVIDED" name="constrain (v0.10.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
16
|
+
<orderEntry type="library" scope="PROVIDED" name="date (v3.4.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
17
|
+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.6.2, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
18
|
+
<orderEntry type="library" scope="PROVIDED" name="erb (v5.0.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="forward_to (v0.3.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
20
|
+
<orderEntry type="library" scope="PROVIDED" name="indented_io (v0.9.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
21
|
+
<orderEntry type="library" scope="PROVIDED" name="io-console (v0.8.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
22
|
+
<orderEntry type="library" scope="PROVIDED" name="irb (v1.15.2, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
23
|
+
<orderEntry type="library" scope="PROVIDED" name="pastel (v0.8.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
24
|
+
<orderEntry type="library" scope="PROVIDED" name="pp (v0.6.2, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="prettyprint (v0.2.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
26
|
+
<orderEntry type="library" scope="PROVIDED" name="psych (v5.2.6, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
27
|
+
<orderEntry type="library" scope="PROVIDED" name="rake (v13.3.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
28
|
+
<orderEntry type="library" scope="PROVIDED" name="rdoc (v6.14.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
29
|
+
<orderEntry type="library" scope="PROVIDED" name="reline (v0.6.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
30
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.13.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
31
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.13.4, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
32
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.13.5, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
33
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.13.5, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
34
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.13.4, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
35
|
+
<orderEntry type="library" scope="PROVIDED" name="shellopts (v2.6.2, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
36
|
+
<orderEntry type="library" scope="PROVIDED" name="stringio (v3.1.7, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
37
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-color (v0.6.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
38
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-command (v0.10.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
39
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-cursor (v0.7.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
40
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-prompt (v0.23.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
41
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-reader (v0.9.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
42
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-screen (v0.8.2, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
43
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-spinner (v0.9.3, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
44
|
+
<orderEntry type="library" scope="PROVIDED" name="tty-which (v0.5.0, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
45
|
+
<orderEntry type="library" scope="PROVIDED" name="wisper (v2.0.1, RVM: ruby-3.4.2 [global]) [gem]" level="application" />
|
46
|
+
</component>
|
47
|
+
</module>
|
data/.idea/vcs.xml
ADDED
data/README.md
CHANGED
@@ -208,3 +208,9 @@ An example of a command that sets the environment to `prod`:
|
|
208
208
|
sensible check --env prod # Check the project for missing dependencies in the prod environment
|
209
209
|
sensible install --env stage # Install missing dependencies and requirements in the staging environment
|
210
210
|
```
|
211
|
+
|
212
|
+
|
213
|
+
# Todo
|
214
|
+
[ ] Add --host support, to run it agains another machine using ssh
|
215
|
+
[ ] Variables for tasks
|
216
|
+
[ ] Include other tasks?
|
data/exe/sensible
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
1
|
+
#!/usr/bin/env -S ruby --yjit
|
2
2
|
|
3
3
|
SPEC = %(
|
4
|
-
@ A small tool to manage and deploy projects
|
4
|
+
@ A small tool to manage and deploy projects/machines
|
5
5
|
|
6
6
|
Install and update systems much like ansible but using shell scripts. It uses
|
7
7
|
a sensible.yml configuration file to control the process
|
@@ -10,14 +10,19 @@ SPEC = %(
|
|
10
10
|
-e,env,environment=ENV
|
11
11
|
Sets the environment (dev/prod/etc),
|
12
12
|
|
13
|
-
-f,file=
|
13
|
+
-f,file=CONF:EFILE
|
14
14
|
Path to sensible configuration file
|
15
15
|
|
16
|
-
-d,dir,directory=
|
16
|
+
-d,dir,directory=EDIR
|
17
17
|
Path to sensible directory. Default '.sensible'
|
18
18
|
|
19
|
+
--host=HOST
|
20
|
+
Run tasks agains a remote machine over ssh. Requires ssh keys added to machine.
|
21
|
+
|
19
22
|
-v,verbose
|
20
|
-
Verbose
|
23
|
+
Verbose
|
24
|
+
|
25
|
+
-a=EFILE
|
21
26
|
|
22
27
|
COMMANDS
|
23
28
|
check!
|
@@ -41,17 +46,9 @@ SPEC = %(
|
|
41
46
|
|
42
47
|
require_relative '../lib/sensible.rb'
|
43
48
|
require 'shellopts'
|
49
|
+
require_relative '../lib/sensible/log'
|
44
50
|
|
45
|
-
|
46
|
-
module ShellOpts
|
47
|
-
class ShellOpts
|
48
|
-
def version_number
|
49
|
-
Sensible::VERSION
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
opts, args = ShellOpts::process(SPEC, ARGV)
|
51
|
+
opts, args = ShellOpts::process(SPEC, ARGV, version_number: Sensible::VERSION)
|
55
52
|
cmd = opts.subcommand!
|
56
53
|
#cmd == :task! or args.expect(0) # Ensure no arguments except for task
|
57
54
|
|
@@ -60,31 +57,35 @@ if opts.verbose
|
|
60
57
|
puts " env: #{opts.env}"
|
61
58
|
puts " file: #{opts.file}"
|
62
59
|
puts " dir: #{opts.dir}"
|
60
|
+
puts " a: #{opts.a}"
|
63
61
|
puts " args: #{args}"
|
64
|
-
# puts "Command: #{cmd.to_s.sub(/!$/, "")}"
|
65
62
|
end
|
66
63
|
|
64
|
+
if opts.subcommand == :init!
|
65
|
+
Sensible::Sensible.init(opts)
|
66
|
+
exit
|
67
|
+
end
|
68
|
+
|
69
|
+
sensible = Sensible::Sensible.new("sensible.yml", opts, args)
|
67
70
|
case opts.subcommand
|
68
|
-
when :
|
69
|
-
|
70
|
-
|
71
|
-
sensible
|
72
|
-
|
73
|
-
case opts.subcommand
|
74
|
-
when
|
75
|
-
|
76
|
-
when :
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
sensible.task_run(arg)
|
84
|
-
when :create!
|
85
|
-
arg = args.expect(1) # Expect a single argument to sensible task
|
86
|
-
sensible.task_create(arg)
|
87
|
-
end
|
71
|
+
when :check!
|
72
|
+
sensible.check
|
73
|
+
when :install!
|
74
|
+
sensible.install
|
75
|
+
when :task!
|
76
|
+
case opts.subcommand!.subcommand
|
77
|
+
when nil
|
78
|
+
Sensible::Logger::error "Missing subcommand"
|
79
|
+
when :list!; sensible.task_list
|
80
|
+
when :run!
|
81
|
+
arg = args.expect(1) # Expect a single argument to sensible task
|
82
|
+
sensible.task_run(arg)
|
83
|
+
when :create!
|
84
|
+
arg = args.expect(1) # Expect a single argument to sensible task
|
85
|
+
sensible.task_create(arg)
|
88
86
|
end
|
87
|
+
else
|
88
|
+
ShellOpts::error "Missing command"
|
89
89
|
end
|
90
90
|
|
91
|
+
|
data/lib/sensible/log.rb
CHANGED
@@ -7,7 +7,14 @@ module Sensible
|
|
7
7
|
|
8
8
|
class Logger
|
9
9
|
def self.log(message, indent = 0, use_print: false)
|
10
|
-
|
10
|
+
spaceIndent = ""
|
11
|
+
indent.times { |i| spaceIndent << " " }
|
12
|
+
|
13
|
+
if use_print
|
14
|
+
print "#{spaceIndent}#{message}"
|
15
|
+
else
|
16
|
+
puts "#{spaceIndent}#{message}"
|
17
|
+
end
|
11
18
|
end
|
12
19
|
|
13
20
|
def self.success(message, indent = 0, use_print: false)
|
@@ -64,5 +71,13 @@ module Sensible
|
|
64
71
|
|
65
72
|
prompt.yes?("#{spaceIndent}#{message}")
|
66
73
|
end
|
74
|
+
|
75
|
+
def self.clear_line()
|
76
|
+
print "\r\e[K"
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.flush
|
80
|
+
$stdout.flush
|
81
|
+
end
|
67
82
|
end
|
68
83
|
end
|
data/lib/sensible/package.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'log'
|
2
|
+
require_relative 'shell'
|
2
3
|
require 'tty-prompt'
|
3
4
|
require 'pastel'
|
4
5
|
|
@@ -6,47 +7,57 @@ module Sensible
|
|
6
7
|
class Package
|
7
8
|
attr_reader :sensible
|
8
9
|
attr_reader :name
|
9
|
-
attr_reader :
|
10
|
-
attr_reader :install
|
11
|
-
attr_reader :env
|
12
|
-
|
13
|
-
def initialize(packageHash, sensible)
|
14
|
-
@name = packageHash['name']
|
15
|
-
@check = packageHash['check']
|
16
|
-
@install = packageHash['install']
|
17
|
-
@env = packageHash['env'] || []
|
10
|
+
attr_reader :distro
|
18
11
|
|
12
|
+
def initialize(packageName, distro, sensible)
|
13
|
+
@name = packageName
|
14
|
+
@distro = distro
|
19
15
|
@sensible = sensible
|
20
16
|
end
|
21
17
|
|
22
|
-
|
23
18
|
# Check if the package is installed
|
24
19
|
def do_check
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
check_command = nil
|
21
|
+
|
22
|
+
case @distro
|
23
|
+
when "rpm"
|
24
|
+
check_command = "rpm -q #{name}"
|
25
|
+
when "deb"
|
26
|
+
check_command = "dpkg-query -W #{name}"
|
27
|
+
when "aur"
|
28
|
+
check_command = "pacman -Qi #{name}"
|
29
|
+
end
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
return true
|
36
|
-
end
|
31
|
+
if check_command == nil
|
32
|
+
Logger.error("Unknown check command")
|
33
|
+
exit(1)
|
37
34
|
end
|
38
|
-
|
35
|
+
|
36
|
+
# Run the shell command
|
37
|
+
shell = Shell.new(@sensible)
|
38
|
+
return shell.run_command(check_command)
|
39
39
|
end
|
40
40
|
|
41
41
|
# Install the package
|
42
42
|
def do_install
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
install_command = nil
|
44
|
+
|
45
|
+
case @distro
|
46
|
+
when "rpm"
|
47
|
+
install_command = "sudo dnf install -y #{name}"
|
48
|
+
when "deb"
|
49
|
+
install_command = "sudo apt get install -y #{name}"
|
50
|
+
when "aur"
|
51
|
+
install_command = "pacman -Syu #{name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
if install_command == nil
|
55
|
+
Logger.error("Unknown install command")
|
56
|
+
exit(1)
|
49
57
|
end
|
50
|
-
|
58
|
+
|
59
|
+
shell = Shell.new(@sensible)
|
60
|
+
return shell.run_command(install_command)
|
61
|
+
end
|
51
62
|
end
|
52
63
|
end
|
data/lib/sensible/parse.rb
CHANGED
data/lib/sensible/requirement.rb
CHANGED
@@ -1,7 +1,77 @@
|
|
1
1
|
require_relative 'package'
|
2
|
+
require_relative 'parse'
|
2
3
|
|
3
4
|
module Sensible
|
4
|
-
class Requirement
|
5
|
+
class Requirement
|
6
|
+
attr_reader :sensible
|
7
|
+
attr_reader :name
|
8
|
+
attr_reader :check
|
9
|
+
attr_reader :install
|
10
|
+
attr_reader :env
|
11
|
+
attr_reader :description
|
12
|
+
attr_reader :packages
|
5
13
|
# Pretty much the same as package right now
|
14
|
+
|
15
|
+
def initialize(requirement_file_name, sensible)
|
16
|
+
requirement_file_path = "#{sensible.sensible_folder}/#{sensible.requirements_folder}/#{requirement_file_name}.yml"
|
17
|
+
|
18
|
+
# If requirement is not found, exit!
|
19
|
+
if not File.exist?(requirement_file_path)
|
20
|
+
pastel = Pastel.new
|
21
|
+
Logger.error("Requirement: #{pastel.bold(requirement_file_name)} does not exist!")
|
22
|
+
exit(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Load the data
|
26
|
+
requirement_data = YAML.load_file(requirement_file_path)
|
27
|
+
|
28
|
+
@sensible = sensible
|
29
|
+
@name = requirement_data["name"]
|
30
|
+
@check = requirement_data["check"]
|
31
|
+
@install = requirement_data["install"]
|
32
|
+
@env = requirement_data["env"]
|
33
|
+
@description = requirement_data["description"]
|
34
|
+
|
35
|
+
# Parse packages
|
36
|
+
@packages = Parse::parse_sensible_packages(requirement_data['packages'], sensible)
|
37
|
+
end
|
38
|
+
|
39
|
+
def do_check
|
40
|
+
# If check is not set, always run the task
|
41
|
+
if @check == nil
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
|
45
|
+
# If there is no check, default to false, to force task to install every time
|
46
|
+
system(@check, out: File::NULL)
|
47
|
+
return $?.success?
|
48
|
+
end
|
49
|
+
|
50
|
+
def do_install
|
51
|
+
# TODO: Handle the show output property!
|
52
|
+
|
53
|
+
if @install.include?("\n")
|
54
|
+
temp_path = "/tmp/sensible"
|
55
|
+
temp_file_name = "install.sh"
|
56
|
+
temp_file_path = "#{temp_path}/#{temp_file_name}"
|
57
|
+
|
58
|
+
# Make sure we have the tmp folder created
|
59
|
+
FileUtils.mkdir_p(temp_path)
|
60
|
+
|
61
|
+
File.open(temp_file_path, "w") do |f|
|
62
|
+
f.puts "#!/usr/bin/env bash\n\n"
|
63
|
+
f.write(@install)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Make it executable
|
67
|
+
File.chmod(0700, temp_file_path)
|
68
|
+
|
69
|
+
system("#{temp_file_path}", out: File::NULL, err: File::NULL)
|
70
|
+
return $?.success?
|
71
|
+
else
|
72
|
+
system(@install, out: File::NULL, err: File::NULL)
|
73
|
+
return $?.success?
|
74
|
+
end
|
75
|
+
end
|
6
76
|
end
|
7
77
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
|
3
|
+
module Sensible
|
4
|
+
class Shell
|
5
|
+
attr_reader :sensible
|
6
|
+
|
7
|
+
def initialize(sensible)
|
8
|
+
@sensible = sensible
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_command(command, user = nil, show_output: false)
|
12
|
+
show_output = @sensible.opts.verbose
|
13
|
+
|
14
|
+
if (@sensible.opts.host != nil)
|
15
|
+
# Run command on remote machine
|
16
|
+
Net::SSH.start(@sensible.opts.host, 'root') do |ssh|
|
17
|
+
out, err, code = exec_user_with_status(ssh, command, as_user: user)
|
18
|
+
|
19
|
+
if @sensible.opts.verbose
|
20
|
+
puts "STDOUT: #{out}"
|
21
|
+
puts "STDERR: #{err}"
|
22
|
+
puts "EXIT CODE: #{code}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Show a warning if the user does not exist!
|
26
|
+
if err.include?("does not exist or the user entry does not contain all the required fields")
|
27
|
+
Logger.error("User: '#{user}' does not exist!")
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
if code == 0
|
32
|
+
return true
|
33
|
+
else
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
else
|
38
|
+
# Standard local shell command
|
39
|
+
# If command contains new lines, use a temporary file
|
40
|
+
if command.include?("\n")
|
41
|
+
system("bash", "-c", command, out: (show_output ? $stdout : File::NULL), err: (show_output ? $stderr : File::NULL))
|
42
|
+
return $?.success?
|
43
|
+
else
|
44
|
+
if user != nil
|
45
|
+
system("sudo -u #{user} #{command}", out: (show_output ? $stdout : File::NULL), err: (show_output ? $stderr : File::NULL))
|
46
|
+
else
|
47
|
+
system(command, out: (show_output ? $stdout : File::NULL), err: (show_output ? $stderr : File::NULL))
|
48
|
+
end
|
49
|
+
return $?.success?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def exec_with_status(ssh, command)
|
55
|
+
stdout = stderr = ""
|
56
|
+
exit_code = nil
|
57
|
+
|
58
|
+
ssh.open_channel do |ch|
|
59
|
+
ch.exec(command) do |ch, success|
|
60
|
+
raise "could not exec #{command}" unless success
|
61
|
+
|
62
|
+
ch.on_data { |c, d| stdout << d }
|
63
|
+
ch.on_extended_data { |c, t, d| stderr << d }
|
64
|
+
ch.on_request("exit-status") { |c, data| exit_code = data.read_long }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
ssh.loop
|
68
|
+
[stdout, stderr, exit_code]
|
69
|
+
end
|
70
|
+
|
71
|
+
def exec_user_with_status(ssh, command, as_user: nil)
|
72
|
+
stdout = ''
|
73
|
+
stderr = ''
|
74
|
+
exit_code = nil
|
75
|
+
|
76
|
+
ssh.open_channel do |ch|
|
77
|
+
|
78
|
+
if as_user
|
79
|
+
ch.exec("su - #{as_user}") do |ch_exec, success|
|
80
|
+
raise "could not exec sudo" unless success
|
81
|
+
ch.send_data("#{command}\n")
|
82
|
+
|
83
|
+
ch.on_data { |_, data| stdout << data }
|
84
|
+
ch.on_extended_data { |_, _, data| stderr << data }
|
85
|
+
ch.on_request("exit-status") { |_, data| exit_code = data.read_long }
|
86
|
+
|
87
|
+
# when done:
|
88
|
+
ch.send_data("exit\n")
|
89
|
+
end
|
90
|
+
else
|
91
|
+
ch.exec(command) do |ch_exec, success|
|
92
|
+
raise "Could not exec #{cmd}" unless success
|
93
|
+
|
94
|
+
ch.on_data { |_, data| stdout << data }
|
95
|
+
ch.on_extended_data { |_, _, data| stderr << data }
|
96
|
+
ch.on_request("exit-status") { |_, data| exit_code = data.read_long }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
ssh.loop
|
102
|
+
[stdout, stderr, exit_code]
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
data/lib/sensible/task.rb
CHANGED
@@ -1,66 +1,98 @@
|
|
1
1
|
require_relative 'package'
|
2
|
+
require_relative 'shell'
|
2
3
|
|
3
4
|
module Sensible
|
4
|
-
class Task
|
5
|
+
class Task
|
6
|
+
attr_reader :sensible
|
7
|
+
attr_reader :name
|
8
|
+
attr_reader :packages
|
9
|
+
attr_reader :check
|
10
|
+
attr_reader :script
|
11
|
+
attr_reader :require
|
12
|
+
attr_reader :env
|
5
13
|
attr_reader :file_name
|
14
|
+
attr_reader :user
|
6
15
|
attr_reader :description
|
7
16
|
attr_accessor :show_output
|
8
17
|
|
9
|
-
def initialize(taskHash, file_name, sensible)
|
10
|
-
|
18
|
+
def initialize(taskHash, file_name, user = nil, sensible)
|
19
|
+
@name = taskHash['name']
|
20
|
+
@check = taskHash['check']
|
21
|
+
@script = taskHash['script']
|
22
|
+
@require = taskHash['require']
|
23
|
+
@env = taskHash['env'] || []
|
11
24
|
@file_name = file_name
|
12
25
|
@description = taskHash['description']
|
13
26
|
@show_output = taskHash['showOutput']
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
27
|
+
|
28
|
+
# If task is initalized with user, force use of that
|
29
|
+
if user != nil
|
30
|
+
@user = user
|
31
|
+
end
|
32
|
+
|
33
|
+
# Always use the user from the task
|
34
|
+
if taskHash['user'] != nil
|
35
|
+
@user = taskHash['user']
|
22
36
|
end
|
23
37
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
38
|
+
@sensible = sensible
|
39
|
+
|
40
|
+
@packages = []
|
41
|
+
if taskHash['packages']
|
42
|
+
taskHash['packages'].each do |distro, packages|
|
43
|
+
packages.each do |packageName|
|
44
|
+
@packages << Package.new(packageName, distro, sensible)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
31
49
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
temp_file_path = "#{temp_path}/#{temp_file_name}"
|
50
|
+
# Check if the packages in this task is installed
|
51
|
+
def do_packages_check
|
52
|
+
has_all_packages_install = true
|
36
53
|
|
37
|
-
|
38
|
-
|
54
|
+
@packages.each do |package|
|
55
|
+
package.name
|
39
56
|
|
40
|
-
|
41
|
-
|
42
|
-
f.write(@install)
|
57
|
+
if !package.do_check
|
58
|
+
has_all_packages_install = false
|
43
59
|
end
|
60
|
+
end
|
61
|
+
|
62
|
+
return has_all_packages_install
|
63
|
+
end
|
44
64
|
|
45
|
-
|
46
|
-
|
65
|
+
# Install the packages in this task
|
66
|
+
def do_packages_install
|
67
|
+
has_all_packages_install = true
|
47
68
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
return $?.success?
|
69
|
+
@packages.each do |package|
|
70
|
+
if !package.do_install
|
71
|
+
has_all_packages_install = false
|
72
|
+
end
|
53
73
|
end
|
54
|
-
end
|
55
74
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
75
|
+
return has_all_packages_install
|
76
|
+
end
|
77
|
+
|
78
|
+
def do_check
|
79
|
+
# If check is not set, always run the task
|
80
|
+
if @check == nil
|
61
81
|
return false
|
62
82
|
end
|
63
83
|
|
84
|
+
# If there is no check, default to false, to force task to script every time
|
85
|
+
shell = Shell.new(@sensible)
|
86
|
+
return shell.run_command(@check, @user)
|
87
|
+
end
|
88
|
+
|
89
|
+
def do_script
|
90
|
+
# TODO: Handle the show output property!
|
91
|
+
shell = Shell.new(@sensible)
|
92
|
+
return shell.run_command(@script, @user)
|
93
|
+
end
|
94
|
+
|
95
|
+
def do_verify
|
64
96
|
return true
|
65
97
|
end
|
66
98
|
end
|
data/lib/sensible/version.rb
CHANGED
data/lib/sensible.rb
CHANGED
@@ -12,21 +12,13 @@ module Sensible
|
|
12
12
|
attr_reader :opts
|
13
13
|
attr_reader :args
|
14
14
|
|
15
|
-
attr_reader :
|
16
|
-
attr_reader :packages
|
17
|
-
attr_reader :requirements
|
18
|
-
attr_reader :postTasks
|
19
|
-
|
20
|
-
attr_reader :sensible_folder
|
21
|
-
attr_reader :tasks_folder
|
15
|
+
attr_reader :tasks
|
22
16
|
|
23
17
|
|
24
18
|
def initialize(sensibleFileName, opts, args)
|
25
19
|
@opts = opts
|
26
20
|
@args = args
|
27
21
|
|
28
|
-
@sensible_folder = '.sensible'
|
29
|
-
@tasks_folder = 'tasks'
|
30
22
|
|
31
23
|
file_name = opts.file || sensibleFileName
|
32
24
|
unless File.exist?(file_name)
|
@@ -37,66 +29,85 @@ module Sensible
|
|
37
29
|
# Load the Sensile file
|
38
30
|
sensible_file_data = YAML.load_file(file_name)
|
39
31
|
|
40
|
-
# Parse packages
|
41
|
-
if sensible_file_data['packages']
|
42
|
-
@packages = Parse.parse_sensible_packages(sensible_file_data['packages'], self)
|
43
|
-
end
|
44
32
|
|
45
|
-
#
|
46
|
-
|
47
|
-
|
48
|
-
|
33
|
+
# Recursively go through all the tasks inside the sensible file
|
34
|
+
# Add them to a list, that we will go through later
|
35
|
+
@tasks = []
|
36
|
+
def process_task(task_line, task_user = nil)
|
37
|
+
task = nil
|
38
|
+
|
39
|
+
# Handle inline tasks inside root sensible file
|
40
|
+
if task_line.class == Hash
|
41
|
+
task = Task.new(task_line, task_line, task_user, self)
|
42
|
+
end
|
49
43
|
|
50
|
-
|
51
|
-
|
52
|
-
|
44
|
+
if task_line.is_a?(String)
|
45
|
+
task_yaml = YAML.load_file(task_line + '.yml')
|
46
|
+
task = Task.new(task_yaml, task_line, task_user, self)
|
47
|
+
end
|
53
48
|
|
54
|
-
|
55
|
-
|
49
|
+
if task.require != nil
|
50
|
+
task.require.each do |path|
|
51
|
+
process_task(path, task.user)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
@tasks << task
|
56
|
+
end
|
57
|
+
|
58
|
+
sensible_file_data.each do |key, value|
|
59
|
+
case key
|
60
|
+
when "require"
|
61
|
+
value.each do |path|
|
62
|
+
process_task(path)
|
63
|
+
end
|
64
|
+
when "tasks"
|
65
|
+
value.each do |path|
|
66
|
+
process_task(path)
|
67
|
+
end
|
68
|
+
end
|
56
69
|
end
|
57
70
|
end
|
58
71
|
|
59
72
|
|
60
73
|
# Run all the checks for packages and requirements
|
61
74
|
def check
|
62
|
-
|
75
|
+
# Prewarm sudo, to prevent asking too much
|
76
|
+
shell = Shell.new(self)
|
77
|
+
shell.run_command('sudo -v', show_output: true)
|
63
78
|
|
64
|
-
|
65
|
-
|
66
|
-
if
|
67
|
-
|
68
|
-
# If user has defined an environment, skip if the set environment isn't in the package enviroment list
|
69
|
-
next if pkg.env.any? && !pkg.env.include?(@opts.env)
|
70
|
-
else
|
71
|
-
# If env contains anything, when env is not defined in opts, skip it, as this is not the correct env
|
72
|
-
next if pkg.env.any?
|
79
|
+
@tasks.each_with_index do |task, index|
|
80
|
+
user = nil
|
81
|
+
if task.user
|
82
|
+
user = "(User: #{task.user})"
|
73
83
|
end
|
74
84
|
|
75
|
-
|
76
|
-
|
85
|
+
pastel = Pastel.new
|
86
|
+
if index > 0
|
87
|
+
Logger.log("\n#{pastel.bold(task.name)} #{user}")
|
77
88
|
else
|
78
|
-
Logger.
|
89
|
+
Logger.log("#{pastel.bold(task.name)} #{user}")
|
79
90
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
next if requirement.env.any? && !requirement.env.include?(@opts.env)
|
91
|
+
|
92
|
+
# Do an environment test
|
93
|
+
# if @opts.env
|
94
|
+
# # If requirement env is not define, we expect it should always be installed regardless of environment
|
95
|
+
# # If user has defined an environment, skip if the set environment isn't in the package enviroment list
|
96
|
+
# next if requirement.env.any? && !requirement.env.include?(@opts.env)
|
97
|
+
# end
|
98
|
+
if task.packages.length > 0
|
99
|
+
if task.do_packages_check
|
100
|
+
Logger.success("Packages installed!")
|
91
101
|
else
|
92
|
-
|
93
|
-
next if pkg.env.any?
|
102
|
+
Logger.danger("Packages NOT installed!")
|
94
103
|
end
|
104
|
+
end
|
95
105
|
|
96
|
-
|
97
|
-
|
106
|
+
if task.check
|
107
|
+
if task.do_check
|
108
|
+
Logger.success("Is installed!")
|
98
109
|
else
|
99
|
-
Logger.danger("
|
110
|
+
Logger.danger("Is NOT installed!")
|
100
111
|
end
|
101
112
|
end
|
102
113
|
end
|
@@ -104,85 +115,66 @@ module Sensible
|
|
104
115
|
|
105
116
|
def install
|
106
117
|
# Prewarm sudo, to prevent asking too much
|
107
|
-
|
118
|
+
shell = Shell.new(self)
|
119
|
+
shell.run_command('sudo -v', show_output: true)
|
108
120
|
|
109
|
-
|
110
|
-
|
111
|
-
|
121
|
+
|
122
|
+
@tasks.each_with_index do |task, index|
|
123
|
+
user = nil
|
124
|
+
if task.user
|
125
|
+
user = "(#{task.user})"
|
126
|
+
end
|
112
127
|
|
113
|
-
|
114
|
-
|
128
|
+
pastel = Pastel.new
|
129
|
+
if index > 0
|
130
|
+
Logger.log("\n#{pastel.bold(task.name)} #{user}")
|
131
|
+
else
|
132
|
+
Logger.log("#{pastel.bold(task.name)} #{user}")
|
115
133
|
end
|
116
|
-
Logger.log("")
|
117
|
-
end
|
118
|
-
|
119
|
-
# Install packages
|
120
|
-
if @packages != nil
|
121
|
-
Logger.log("Installing packages...")
|
122
|
-
for pkg in @packages
|
123
|
-
# Do an environment test
|
124
|
-
if @opts.env
|
125
|
-
# If package env is not defined, we expect it should always be installed regardless of environment
|
126
|
-
# If user has defined an environment, skip if the set environment isn't in the package enviroment list
|
127
|
-
next if pkg.env.any? && !pkg.env.include?(@opts.env)
|
128
|
-
else
|
129
|
-
# If env contains anything, when env is not defined in opts, skip it, as this is not the correct env
|
130
|
-
next if pkg.env.any?
|
131
|
-
end
|
132
134
|
|
133
|
-
|
134
|
-
|
135
|
+
|
136
|
+
# Do an environment test
|
137
|
+
# if @opts.env
|
138
|
+
# # If requirement env is not define, we expect it should always be installed regardless of environment
|
139
|
+
# # If user has defined an environment, skip if the set environment isn't in the package enviroment list
|
140
|
+
# next if requirement.env.any? && !requirement.env.include?(@opts.env)
|
141
|
+
# end
|
142
|
+
if task.packages.length > 0
|
143
|
+
if task.do_packages_check
|
144
|
+
Logger.success("Packages installed!")
|
135
145
|
else
|
136
|
-
Logger.info("Installing
|
137
|
-
if
|
138
|
-
Logger.
|
139
|
-
|
146
|
+
Logger.info("Installing packages...\r", use_print: true)
|
147
|
+
if task.do_packages_install
|
148
|
+
Logger.clear_line
|
149
|
+
Logger.success("Packages installed!")
|
140
150
|
else
|
141
|
-
Logger.
|
142
|
-
|
151
|
+
Logger.clear_line
|
152
|
+
Logger.danger("Packages NOT installed!")
|
143
153
|
end
|
154
|
+
|
155
|
+
Logger.flush
|
144
156
|
end
|
145
|
-
end
|
146
|
-
Logger.log("")
|
147
|
-
end
|
148
|
-
|
149
|
-
# Handle requirements
|
150
|
-
if @requirements != nil
|
151
|
-
Logger.log("Handling requirements...")
|
152
|
-
for requirement in @requirements
|
153
|
-
# Do an environment test
|
154
|
-
if @opts.env
|
155
|
-
# If package env is not defined, we expect it should always be installed regardless of environment
|
156
|
-
# If user has defined an environment, skip if the set environment isn't in the package enviroment list
|
157
|
-
next if requirement.env.any? && !requirement.env.include?(@opts.env)
|
158
|
-
else
|
159
|
-
# If env contains anything, when env is not defined in opts, skip it, as this is not the correct env
|
160
|
-
next if requirement.env.any?
|
161
|
-
end
|
157
|
+
end
|
162
158
|
|
163
|
-
|
164
|
-
|
159
|
+
if task.check
|
160
|
+
if task.do_check
|
161
|
+
Logger.success("Is installed!")
|
165
162
|
else
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
163
|
+
if task.script
|
164
|
+
Logger.info("Running task...\r", use_print: true)
|
165
|
+
if task.do_script
|
166
|
+
Logger.clear_line
|
167
|
+
Logger.success("Is installed!")
|
168
|
+
else
|
169
|
+
Logger.clear_line
|
170
|
+
Logger.danger("Is NOT installed!")
|
171
|
+
end
|
172
|
+
Logger.flush
|
170
173
|
else
|
171
|
-
Logger.danger("
|
172
|
-
$stdout.flush
|
174
|
+
Logger.danger("Is NOT installed!")
|
173
175
|
end
|
174
176
|
end
|
175
177
|
end
|
176
|
-
Logger.log("")
|
177
|
-
end
|
178
|
-
|
179
|
-
# Run post tasks
|
180
|
-
if @postTasks != nil
|
181
|
-
Logger.log("Running post tasks...")
|
182
|
-
|
183
|
-
for task in @postTasks
|
184
|
-
task_run(task)
|
185
|
-
end
|
186
178
|
end
|
187
179
|
|
188
180
|
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# New sensible specification
|
2
|
+
|
3
|
+
To structure everything better, and making it efficient for setting up machines or projects, i've come up with a new specification.
|
4
|
+
|
5
|
+
You are now able to completely able to define your own structure,
|
6
|
+
|
7
|
+
sensible.yml inside a project for folder:
|
8
|
+
|
9
|
+
```yaml
|
10
|
+
packages:
|
11
|
+
- rpm: [btop]
|
12
|
+
|
13
|
+
require:
|
14
|
+
- .sensible/requirements/postgres17 # Path to the task
|
15
|
+
- .sensible/requirements/httpd
|
16
|
+
|
17
|
+
tasks:
|
18
|
+
- .sensible/tasks/test
|
19
|
+
|
20
|
+
options:
|
21
|
+
# Possible future options
|
22
|
+
```
|
23
|
+
|
24
|
+
The nice thing here is, that the order of where you place the packages, require and tasks property matters. It parses the file from top-to-bottom, so in this example, it install packages first, handle requirements, and run tasks at the end. You could do it in complete reverse order if you wanted.
|
25
|
+
|
26
|
+
The same thing with the require and tasks property, the list in there, will be handled in that order..
|
27
|
+
|
28
|
+
When you add an requirement, it's the relative path from where you execute sensible from.
|
29
|
+
|
30
|
+
## Folder structure example
|
31
|
+
|
32
|
+
```
|
33
|
+
.sensible/
|
34
|
+
requirements/
|
35
|
+
httpd.yml
|
36
|
+
postgresql17.yml
|
37
|
+
tasks/
|
38
|
+
another.yml
|
39
|
+
test.yml
|
40
|
+
sensible.yml
|
41
|
+
```
|
42
|
+
|
43
|
+
You could also structure it like this:
|
44
|
+
|
45
|
+
```
|
46
|
+
services/
|
47
|
+
httpd.yml
|
48
|
+
postgresql17.yml
|
49
|
+
tasks/
|
50
|
+
another.yml
|
51
|
+
test.yml
|
52
|
+
hosts/
|
53
|
+
server1.yml
|
54
|
+
server2.yml
|
55
|
+
```
|
56
|
+
|
57
|
+
Then you run the command: `sensible -f check hosts/server1.yml` or `sensible -f install hosts/server1.yml`
|
58
|
+
|
59
|
+
If you want to have a hosts folder, I recommend using the `-f` option.
|
60
|
+
|
61
|
+
By default sensible will look for a sensible.yml in the folder you are executing sensible from.
|
62
|
+
|
63
|
+
## Tasks
|
64
|
+
Everything is basically a task, it manages packages, and the script to check and install the task.
|
65
|
+
|
66
|
+
### Properties
|
67
|
+
|
68
|
+
#### name
|
69
|
+
This is name of the task, should be short and simple
|
70
|
+
|
71
|
+
#### description
|
72
|
+
This a longer description to help explain it in more detail what it does.
|
73
|
+
|
74
|
+
#### require
|
75
|
+
A task can require other things. Lets say you have a task that installs a frontend project, that can then require that you have a apache server installed to run.
|
76
|
+
|
77
|
+
**This property is optional**
|
78
|
+
|
79
|
+
#### packages
|
80
|
+
Here you can definethe packages a task should install. You define which type of package via the property name: `rpm`, `deb` or `aur`
|
81
|
+
|
82
|
+
Example:
|
83
|
+
|
84
|
+
```
|
85
|
+
packages:
|
86
|
+
rpm: [btop] # RHEL based
|
87
|
+
deb: [btop] # Debian based
|
88
|
+
aur: [btop] # Arch linux based
|
89
|
+
```
|
90
|
+
|
91
|
+
**This property is optional**
|
92
|
+
|
93
|
+
#### check
|
94
|
+
This is the script you can use to check if the task was installed succesfully.
|
95
|
+
|
96
|
+
You will most likely use this, if you are going to use the `script` property.
|
97
|
+
|
98
|
+
**This property is optional**
|
99
|
+
|
100
|
+
#### script
|
101
|
+
This the install script for the task. Let's say you need to do a git clone, create a user, switch to that user etc.
|
102
|
+
|
103
|
+
If this script exits with 0, it completed successfully
|
104
|
+
|
105
|
+
**This property is optional**
|
106
|
+
|
107
|
+
|
108
|
+
### Full example
|
109
|
+
|
110
|
+
```yaml
|
111
|
+
# .sensible/task/test.yml
|
112
|
+
---
|
113
|
+
name: Task example
|
114
|
+
description: This installs an apache httpd server, shellopts gem
|
115
|
+
require:
|
116
|
+
- .sensible/requirements/httpd # Remember, it's relative from execution path
|
117
|
+
packages: # Optional if task does not require packages
|
118
|
+
deb: # Debian packages
|
119
|
+
aur: # Aur packages (Arch linux)
|
120
|
+
rpm: [httpd]
|
121
|
+
check: |
|
122
|
+
# This is for a more complex check, like if you need to check a service is running, files exist, etc...
|
123
|
+
script: |
|
124
|
+
# Script is optional, as it's intended for tasks that require more than just installing various packages.
|
125
|
+
# Maybe you require things being installed in a certain order
|
126
|
+
```
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
### Future ideas
|
135
|
+
|
136
|
+
#### Allow for ruby files
|
137
|
+
I'm planning on allowing .rb-files too, for even more flexibility.
|
138
|
+
|
139
|
+
#### Include other files
|
140
|
+
It might be a nice feature to be able to include other files.
|
data/sensible.yml
CHANGED
@@ -1,23 +1,13 @@
|
|
1
|
-
preTasks:
|
2
|
-
- test
|
3
|
-
|
4
1
|
packages:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
check:
|
2
|
+
rpm: [btop]
|
3
|
+
|
4
|
+
|
5
|
+
tasks:
|
6
|
+
- name: Check whoami
|
7
|
+
user: sample
|
8
|
+
check: whoami
|
9
|
+
script: whoami
|
12
10
|
|
13
|
-
|
14
|
-
-
|
15
|
-
|
16
|
-
install: echo "install"
|
17
|
-
|
18
|
-
- name: Test requirement that fails
|
19
|
-
check: exit 1
|
20
|
-
install: exit 1
|
21
|
-
|
22
|
-
postTasks:
|
23
|
-
- another
|
11
|
+
- .sensible/apps/project-frontend
|
12
|
+
- .sensible/apps/project-frontend-2
|
13
|
+
- .sensible/tasks/test
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sensible-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mikkel Jensen
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: shellopts
|
@@ -15,14 +15,20 @@ dependencies:
|
|
15
15
|
requirements:
|
16
16
|
- - ">="
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version:
|
18
|
+
version: 2.6.1
|
19
|
+
- - "<"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3'
|
19
22
|
type: :runtime
|
20
23
|
prerelease: false
|
21
24
|
version_requirements: !ruby/object:Gem::Requirement
|
22
25
|
requirements:
|
23
26
|
- - ">="
|
24
27
|
- !ruby/object:Gem::Version
|
25
|
-
version:
|
28
|
+
version: 2.6.1
|
29
|
+
- - "<"
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '3'
|
26
32
|
- !ruby/object:Gem::Dependency
|
27
33
|
name: tty-which
|
28
34
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,6 +99,34 @@ dependencies:
|
|
93
99
|
- - ">="
|
94
100
|
- !ruby/object:Gem::Version
|
95
101
|
version: '0'
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: net-ssh
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
type: :runtime
|
110
|
+
prerelease: false
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: logger
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.6.0
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 1.6.0
|
96
130
|
description: A small tool to manage projects, making shell scripts easier to manage,
|
97
131
|
and faster to setup projects!
|
98
132
|
email:
|
@@ -102,9 +136,13 @@ executables:
|
|
102
136
|
extensions: []
|
103
137
|
extra_rdoc_files: []
|
104
138
|
files:
|
139
|
+
- ".idea/.gitignore"
|
140
|
+
- ".idea/material_theme_project_new.xml"
|
141
|
+
- ".idea/misc.xml"
|
142
|
+
- ".idea/modules.xml"
|
143
|
+
- ".idea/sensible-ruby.iml"
|
144
|
+
- ".idea/vcs.xml"
|
105
145
|
- ".rspec"
|
106
|
-
- ".sensible/tasks/another.yml"
|
107
|
-
- ".sensible/tasks/test.yml"
|
108
146
|
- README.md
|
109
147
|
- Rakefile
|
110
148
|
- exe/sensible
|
@@ -113,8 +151,10 @@ files:
|
|
113
151
|
- lib/sensible/package.rb
|
114
152
|
- lib/sensible/parse.rb
|
115
153
|
- lib/sensible/requirement.rb
|
154
|
+
- lib/sensible/shell.rb
|
116
155
|
- lib/sensible/task.rb
|
117
156
|
- lib/sensible/version.rb
|
157
|
+
- new-sensible-spec.md
|
118
158
|
- sensible.yml
|
119
159
|
- sig/sensible.rbs
|
120
160
|
homepage: https://github.com/dasmikko/sensible-ruby
|
@@ -135,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
175
|
- !ruby/object:Gem::Version
|
136
176
|
version: '0'
|
137
177
|
requirements: []
|
138
|
-
rubygems_version: 3.6.
|
178
|
+
rubygems_version: 3.6.9
|
139
179
|
specification_version: 4
|
140
180
|
summary: A small tool to manage projects.
|
141
181
|
test_files: []
|
data/.sensible/tasks/another.yml
DELETED
data/.sensible/tasks/test.yml
DELETED