jive 0.1.0 → 0.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/README.md +14 -18
- data/exe/jive +4 -1
- data/jive.gemspec +26 -19
- data/jive.sh +87 -0
- data/lib/jive.rb +14 -130
- data/lib/jive/batch_runner.rb +70 -0
- data/lib/jive/cli.rb +100 -0
- data/lib/jive/docker.rb +45 -0
- data/lib/jive/git.rb +40 -0
- data/lib/jive/popen.rb +37 -0
- data/lib/jive/project.rb +33 -0
- data/lib/jive/runner.rb +43 -0
- data/lib/jive/shell.rb +45 -0
- data/lib/jive/version.rb +3 -1
- metadata +72 -30
- data/.github/workflows/test.yml +0 -17
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.travis.yml +0 -7
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -35
- data/Rakefile +0 -6
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/bin/test +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb4eb9f7fb9d9ff62d257c2ed146acd462cb2c4db1b07a4a3cc0a43399ce1073
|
4
|
+
data.tar.gz: bb87b75d4635bc12169def9878ab89c7822df1497cd2a39a7aa209c8d8e01489
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d72ccd8285b0726e1465f6caec69dfddec99b0a9b60594da5de94e4dc898356e009d4e924ec9ae863396e2f4fa2cefa2b912793ae69424c345443de16406ed2
|
7
|
+
data.tar.gz: 625c5dc105d2b53c9d9d7a6173761523439ea506dee48dc895252e4392b399a1c5b7d274a5f4bac1cffbdf72661f8c663f561c3ab4b5790f82d3c2b5df81b10c
|
data/README.md
CHANGED
@@ -1,38 +1,34 @@
|
|
1
1
|
# Jive
|
2
2
|
|
3
|
-
|
3
|
+
[](https://github.com/xlgmokha/jive/actions)
|
4
4
|
|
5
|
-
|
5
|
+
Hi!
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
9
|
-
Add this line to your application's Gemfile:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
gem 'jive'
|
13
|
-
```
|
14
|
-
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle
|
18
|
-
|
19
|
-
Or install it yourself as:
|
20
|
-
|
21
9
|
$ gem install jive
|
22
10
|
|
23
11
|
## Usage
|
24
12
|
|
25
|
-
|
13
|
+
$ jive --help
|
14
|
+
|
26
15
|
|
27
16
|
## Development
|
28
17
|
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies.
|
18
|
+
After checking out the repo, run `bin/setup` to install dependencies.
|
19
|
+
Then, run `./bin/test` to run the tests.
|
20
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
21
|
|
31
|
-
To install this gem onto your local machine, run `bundle exec rake install`.
|
22
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
23
|
+
To release a new version, update the version number in `version.rb`,
|
24
|
+
and then run `bundle exec rake release`,
|
25
|
+
which will create a git tag for the version,
|
26
|
+
push git commits and tags, and push the `.gem`
|
27
|
+
file to [rubygems.org](https://rubygems.org).
|
32
28
|
|
33
29
|
## Contributing
|
34
30
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
31
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/xlgmokha/jive.
|
36
32
|
|
37
33
|
## License
|
38
34
|
|
data/exe/jive
CHANGED
data/jive.gemspec
CHANGED
@@ -1,32 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/jive/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "jive"
|
7
7
|
spec.version = Jive::VERSION
|
8
8
|
spec.authors = ["mo khan"]
|
9
|
-
spec.email = ["mo
|
9
|
+
spec.email = ["mo@mokhan.ca"]
|
10
10
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage = "https://
|
11
|
+
spec.summary = "The art just comes."
|
12
|
+
spec.description = "The art just comes."
|
13
|
+
spec.homepage = "https://rubygems.org/gems/jive"
|
14
14
|
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
15
16
|
|
16
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
-
spec.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
-
end
|
18
|
+
spec.files = Dir["lib/**/*.rb"] + Dir["exe/*"] + [
|
19
|
+
"LICENSE.txt",
|
20
|
+
"README.md",
|
21
|
+
"jive.gemspec",
|
22
|
+
"jive.sh"
|
23
|
+
]
|
25
24
|
spec.bindir = "exe"
|
26
|
-
spec.executables = spec.files.grep(%r{
|
25
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
27
26
|
spec.require_paths = ["lib"]
|
27
|
+
spec.post_install_message = <<~MESSAGE
|
28
|
+
Run the following command for setup instructions:
|
29
|
+
|
30
|
+
$ jive setup
|
31
|
+
MESSAGE
|
28
32
|
|
29
|
-
spec.
|
30
|
-
spec.add_development_dependency "
|
31
|
-
spec.add_development_dependency "
|
33
|
+
spec.add_dependency "thor", "~> 1.1"
|
34
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
35
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
36
|
+
spec.add_development_dependency "rubocop", "~> 1.7"
|
37
|
+
spec.add_development_dependency "rubocop-minitest", "~> 0.1"
|
38
|
+
spec.add_development_dependency "rubocop-rake", "~> 0.5"
|
32
39
|
end
|
data/jive.sh
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# shellcheck disable=1001,1012,2039,1090
|
3
|
+
# 1001,1012 stop complaints about '\awk' syntax to bypass aliases.
|
4
|
+
# 2039 stops complaints about array references not being POSIX.
|
5
|
+
# 1090 stops complaints about sourcing non-constant paths.
|
6
|
+
|
7
|
+
__shell="$(\ps -p $$ | \awk 'NR > 1 { sub(/^-/, "", $4); print $4 }')"
|
8
|
+
__shellname="$(basename "${__shell}")"
|
9
|
+
|
10
|
+
case "${__shellname}" in
|
11
|
+
bash)
|
12
|
+
__jive_root_dir="$(builtin cd "$(\dirname "${BASH_SOURCE[0]}")" && \pwd)"
|
13
|
+
;;
|
14
|
+
zsh)
|
15
|
+
__jive_root_dir="$(\dirname "$0:A")"
|
16
|
+
;;
|
17
|
+
*)
|
18
|
+
>&2 \echo "jive is not compatible with your shell (${__shell})"
|
19
|
+
\return 1
|
20
|
+
;;
|
21
|
+
esac
|
22
|
+
|
23
|
+
__jive_exe_dir="${__jive_root_dir}/exe"
|
24
|
+
__jive_lib_dir="${__jive_root_dir}/lib"
|
25
|
+
__jive_script="${__jive_root_dir}/jive.sh"
|
26
|
+
|
27
|
+
__mtime_of_jive_script="$(\date -r "${__jive_script}" +%s)"
|
28
|
+
__jive_auto_reload() {
|
29
|
+
local current_mtime
|
30
|
+
current_mtime="$(\date -r "${__jive_script}" +%s)"
|
31
|
+
|
32
|
+
if [[ "${current_mtime}" != "${__mtime_of_jive_script}" ]]; then
|
33
|
+
echo "Reloading... ${__jive_script}"
|
34
|
+
. "${__jive_script}"
|
35
|
+
fi
|
36
|
+
}
|
37
|
+
|
38
|
+
__jive_exec() {
|
39
|
+
/usr/bin/env -S ruby -I "${__jive_lib_dir}" "${__jive_exe_dir}/jive" "$@"
|
40
|
+
}
|
41
|
+
|
42
|
+
__jive_open_pipe() {
|
43
|
+
local tmpfile
|
44
|
+
tmpfile="$(\mktemp -u)"
|
45
|
+
|
46
|
+
exec 42>"${tmpfile}" # Open the tempfile for writing on FD 42.
|
47
|
+
exec 8<"${tmpfile}" # Open the tempfile for reading on FD 8.
|
48
|
+
\rm -f "${tmpfile}" # Unlink the tempfile. (we've already opened it).
|
49
|
+
}
|
50
|
+
|
51
|
+
__jive_execute_task() {
|
52
|
+
local task=$1
|
53
|
+
|
54
|
+
case "${task}" in
|
55
|
+
cd:*)
|
56
|
+
# shellcheck disable=SC2164
|
57
|
+
cd "${task//cd:/}"
|
58
|
+
;;
|
59
|
+
setenv:*)
|
60
|
+
export "${task//setenv:/}"
|
61
|
+
;;
|
62
|
+
*)
|
63
|
+
echo "Woof! ${task}"
|
64
|
+
;;
|
65
|
+
esac
|
66
|
+
}
|
67
|
+
|
68
|
+
__jive_flush_tasks() {
|
69
|
+
local task
|
70
|
+
while \read -r task; do
|
71
|
+
__jive_execute_task "${task}"
|
72
|
+
done <&8
|
73
|
+
|
74
|
+
__jive_close_pipe
|
75
|
+
}
|
76
|
+
|
77
|
+
__jive_close_pipe() {
|
78
|
+
exec 8<&- # close FD 8.
|
79
|
+
exec 42<&- # close FD 42.
|
80
|
+
}
|
81
|
+
|
82
|
+
jive() {
|
83
|
+
__jive_auto_reload
|
84
|
+
__jive_open_pipe
|
85
|
+
__jive_exec "$@"
|
86
|
+
__jive_flush_tasks
|
87
|
+
}
|
data/lib/jive.rb
CHANGED
@@ -1,144 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "fileutils"
|
4
|
-
require "jive/version"
|
5
4
|
require "open3"
|
6
5
|
|
6
|
+
require "jive/batch_runner"
|
7
|
+
require "jive/git"
|
8
|
+
require "jive/popen"
|
9
|
+
require "jive/project"
|
10
|
+
require "jive/runner"
|
11
|
+
require "jive/shell"
|
12
|
+
require "jive/version"
|
13
|
+
|
7
14
|
module Jive
|
8
15
|
class Error < StandardError; end
|
9
16
|
|
10
|
-
def self.
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
module Popen
|
15
|
-
Result = Struct.new(:command, :stdout, :stderr, :status, :duration)
|
16
|
-
|
17
|
-
def self.popen(command, path = nil, env = {}, &block)
|
18
|
-
result = popen_with_detail(command, path, env, &block)
|
19
|
-
|
20
|
-
["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.popen_with_detail(command, path = Dir.pwd, env = {})
|
24
|
-
FileUtils.mkdir_p(path) unless File.directory?(path)
|
25
|
-
|
26
|
-
captured_stdout = ''
|
27
|
-
captured_stderr = ''
|
28
|
-
exit_status = nil
|
29
|
-
start = Time.now
|
30
|
-
|
31
|
-
Open3.popen3(env.merge('PWD' => path), *Array(command), { chdir: path }) do |stdin, stdout, stderr, wait_thr|
|
32
|
-
out_reader = Thread.new { stdout.read }
|
33
|
-
err_reader = Thread.new { stderr.read }
|
34
|
-
|
35
|
-
yield(stdin) if block_given?
|
36
|
-
|
37
|
-
stdin.close
|
38
|
-
captured_stdout = out_reader.value
|
39
|
-
captured_stderr = err_reader.value
|
40
|
-
exit_status = wait_thr.value
|
41
|
-
end
|
42
|
-
Result.new(command, captured_stdout, captured_stderr, exit_status, Time.now - start)
|
43
|
-
end
|
17
|
+
def self.root
|
18
|
+
@root ||= Pathname.new(__FILE__).parent.parent
|
44
19
|
end
|
45
20
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
def initialize(runner: Runner.new, stdout: STDOUT)
|
50
|
-
@runner = runner
|
51
|
-
@stdout = stdout
|
52
|
-
end
|
53
|
-
|
54
|
-
def run(tasks, verbose: true)
|
55
|
-
runner.run(tasks) do |command, &run|
|
56
|
-
stdout.puts
|
57
|
-
stdout.puts "$ #{command.join(' ')}"
|
58
|
-
result = run.call
|
59
|
-
stdout.print result.stdout if verbose
|
60
|
-
stdout.print result.stderr if verbose
|
61
|
-
stdout.puts "==> Finished in #{result.duration} seconds"
|
62
|
-
stdout.puts
|
63
|
-
end
|
64
|
-
stdout.puts '==================================================='
|
65
|
-
if runner.all_success_and_clean?
|
66
|
-
stdout.puts 'Passed successfully.'
|
67
|
-
return 0
|
68
|
-
elsif runner.all_success?
|
69
|
-
stdout.puts 'Passed successfully, but we have warnings:'
|
70
|
-
stdout.puts
|
71
|
-
emit_warnings
|
72
|
-
return 2
|
73
|
-
else
|
74
|
-
stdout.puts 'Something failed:'
|
75
|
-
emit_warnings
|
76
|
-
emit_errors
|
77
|
-
return 1
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def emit_warnings
|
84
|
-
runner.warned_results.each do |result|
|
85
|
-
stdout.puts
|
86
|
-
stdout.puts "**** #{result.command.join(' ')} had the following warning(s):"
|
87
|
-
stdout.puts
|
88
|
-
stdout.puts result.stderr
|
89
|
-
stdout.puts
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def emit_errors
|
94
|
-
runner.failed_results.each do |result|
|
95
|
-
stdout.puts
|
96
|
-
stdout.puts "**** #{result.command.join(' ')} failed with the following error(s):"
|
97
|
-
stdout.puts
|
98
|
-
stdout.puts result.stdout
|
99
|
-
stdout.puts result.stderr
|
100
|
-
stdout.puts
|
101
|
-
end
|
102
|
-
end
|
21
|
+
def self.run(tasks)
|
22
|
+
Jive::BatchRunner.new.run(tasks)
|
103
23
|
end
|
104
24
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
def initialize
|
109
|
-
@results = []
|
110
|
-
end
|
111
|
-
|
112
|
-
def run(commands, &block)
|
113
|
-
commands.each do |command|
|
114
|
-
block.call(command) do
|
115
|
-
cmd_result = Popen.popen_with_detail(command)
|
116
|
-
results << cmd_result
|
117
|
-
cmd_result
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def all_success_and_clean?
|
123
|
-
all_success? && all_stderr_empty?
|
124
|
-
end
|
125
|
-
|
126
|
-
def all_success?
|
127
|
-
results.all? { |result| result.status.success? }
|
128
|
-
end
|
129
|
-
|
130
|
-
def all_stderr_empty?
|
131
|
-
results.all? { |result| result.stderr.empty? }
|
132
|
-
end
|
133
|
-
|
134
|
-
def failed_results
|
135
|
-
results.reject { |result| result.status.success? }
|
136
|
-
end
|
137
|
-
|
138
|
-
def warned_results
|
139
|
-
results.select do |result|
|
140
|
-
result.status.success? && !result.stderr.empty?
|
141
|
-
end
|
142
|
-
end
|
25
|
+
def self.shell
|
26
|
+
@shell ||= ::Jive::Shell.new
|
143
27
|
end
|
144
28
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
class BatchRunner
|
5
|
+
attr_reader :runner, :stdout
|
6
|
+
|
7
|
+
def initialize(runner: Runner.new, stdout: $stdout)
|
8
|
+
@runner = runner
|
9
|
+
@stdout = stdout
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(tasks)
|
13
|
+
stream_output_for(runner, tasks)
|
14
|
+
stdout.puts "==================================================="
|
15
|
+
print_result_for(runner)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def stream_output_for(runner, tasks)
|
21
|
+
runner.run(tasks) do |command, &run|
|
22
|
+
stdout.puts
|
23
|
+
stdout.puts "$ #{command.join(" ")}"
|
24
|
+
result = run.call
|
25
|
+
stdout.print result.stdout
|
26
|
+
stdout.print result.stderr
|
27
|
+
stdout.puts "==> Finished in #{result.duration} seconds"
|
28
|
+
stdout.puts
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def print_result_for(runner)
|
33
|
+
if runner.all_success_and_clean?
|
34
|
+
stdout.puts "Passed successfully."
|
35
|
+
0
|
36
|
+
elsif runner.all_success?
|
37
|
+
stdout.puts "Passed successfully, but we have warnings:"
|
38
|
+
stdout.puts
|
39
|
+
emit_warnings_for(runner)
|
40
|
+
2
|
41
|
+
else
|
42
|
+
stdout.puts "Something failed:"
|
43
|
+
emit_warnings_for(runner)
|
44
|
+
emit_errors_for(runner)
|
45
|
+
1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def emit_warnings_for(runner)
|
50
|
+
runner.warned_results.each do |result|
|
51
|
+
stdout.puts
|
52
|
+
stdout.puts "**** #{result.command.join(" ")} had the following warning(s):"
|
53
|
+
stdout.puts
|
54
|
+
stdout.puts result.stderr
|
55
|
+
stdout.puts
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def emit_errors_for(runner)
|
60
|
+
runner.failed_results.each do |result|
|
61
|
+
stdout.puts
|
62
|
+
stdout.puts "**** #{result.command.join(" ")} failed with the following error(s):"
|
63
|
+
stdout.puts
|
64
|
+
stdout.puts result.stdout
|
65
|
+
stdout.puts result.stderr
|
66
|
+
stdout.puts
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/jive/cli.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "thor"
|
5
|
+
require "yaml"
|
6
|
+
|
7
|
+
require "jive"
|
8
|
+
|
9
|
+
module Jive
|
10
|
+
module Cli
|
11
|
+
class App < Thor
|
12
|
+
package_name "jive"
|
13
|
+
|
14
|
+
def self.exit_on_failure?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.handle_no_command_error(name)
|
19
|
+
::Jive::Cli::App.start(["exec", name])
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "docker SUBCOMMAND ...ARGS", "docker commands"
|
23
|
+
subcommand "docker", (Class.new(Thor) do
|
24
|
+
desc "build", "build the Dockerfile in the current directory"
|
25
|
+
def build
|
26
|
+
Docker.new.build(Pathname.pwd)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "launch", "launch a shell into a container"
|
30
|
+
def launch
|
31
|
+
Docker.new.launch(Pathname.pwd)
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "size", "print the size of each image"
|
35
|
+
def size
|
36
|
+
Docker.new.size(Pathname.pwd)
|
37
|
+
end
|
38
|
+
end)
|
39
|
+
|
40
|
+
desc "git SUBCOMMAND ...ARGS", "git commands"
|
41
|
+
subcommand "git", (Class.new(Thor) do
|
42
|
+
desc "semantic", "Print help for semantic commit messages"
|
43
|
+
def semantic
|
44
|
+
say <<~MESSAGE
|
45
|
+
Format: <type>(<scope>): <subject>
|
46
|
+
|
47
|
+
<scope> is optional
|
48
|
+
|
49
|
+
feat: add hat wobble
|
50
|
+
^--^ ^------------^
|
51
|
+
| |
|
52
|
+
| +-> Summary in present tense.
|
53
|
+
|
|
54
|
+
+-------> Type: chore, docs, feat, fix, refactor, style, or test.
|
55
|
+
|
56
|
+
chore: updating grunt tasks etc; no production code change
|
57
|
+
docs: changes to the documentation
|
58
|
+
feat: new feature for the user, not a new feature for build script
|
59
|
+
fix: bug fix for the user, not a fix to a build script
|
60
|
+
refactor: refactoring production code, eg. renaming a variable
|
61
|
+
style: formatting, missing semi colons, etc; no production code change
|
62
|
+
test: adding missing tests, refactoring tests; no production code change
|
63
|
+
MESSAGE
|
64
|
+
end
|
65
|
+
end)
|
66
|
+
|
67
|
+
desc "cd <org>/<project>", "cd to ~/src/github.com/<org>/<project>"
|
68
|
+
def cd(slug)
|
69
|
+
Jive.shell.run_safely { Git.new(Jive.shell).cd(slug) }
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "clone <org>/<project>", "git clone to ~/src/github.com/<org>/<project>"
|
73
|
+
def clone(slug)
|
74
|
+
Jive.shell.run_safely { Git.new(Jive.shell).clone(slug) }
|
75
|
+
end
|
76
|
+
|
77
|
+
desc "exec <command>", "run command from jive.yml"
|
78
|
+
def exec(command)
|
79
|
+
path = Pathname.pwd.join("jive.yml")
|
80
|
+
return shell.error("Error: jive.yml not found") unless path.exist?
|
81
|
+
|
82
|
+
Jive.shell.run_safely do
|
83
|
+
Jive.shell.execute(YAML.safe_load(path.read).dig("commands", command))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "bootstrap", "bootstrap the current project"
|
88
|
+
def bootstrap
|
89
|
+
Project
|
90
|
+
.new(Pathname.pwd)
|
91
|
+
.bootstrap(Jive.shell)
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "setup", "provide instructions to integrate into shell"
|
95
|
+
def setup
|
96
|
+
print "source #{::Jive.root.join("jive.sh")}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/jive/docker.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
class Docker
|
5
|
+
attr_reader :shell
|
6
|
+
|
7
|
+
def initialize(shell = ::Jive.shell)
|
8
|
+
@shell = shell
|
9
|
+
end
|
10
|
+
|
11
|
+
def build(path)
|
12
|
+
shell.execute([
|
13
|
+
"docker",
|
14
|
+
"build",
|
15
|
+
"--network=host",
|
16
|
+
"-t", image_tag_for(path),
|
17
|
+
"."
|
18
|
+
], env: { "DOCKER_BUILDKIT" => "1" })
|
19
|
+
end
|
20
|
+
|
21
|
+
def launch(path)
|
22
|
+
shell.execute([
|
23
|
+
"docker",
|
24
|
+
"run",
|
25
|
+
"--network=host",
|
26
|
+
'--entrypoint=""',
|
27
|
+
"-it", image_tag_for(path),
|
28
|
+
"/bin/bash -l"
|
29
|
+
])
|
30
|
+
end
|
31
|
+
|
32
|
+
def size(path)
|
33
|
+
shell.execute([
|
34
|
+
:docker, "image", "inspect", '--format="{{.Size}}"',
|
35
|
+
image_tag_for(path)
|
36
|
+
])
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def image_tag_for(path)
|
42
|
+
"#{path.basename.to_s.downcase}:latest"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/jive/git.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
class Git
|
5
|
+
attr_reader :shell
|
6
|
+
|
7
|
+
def initialize(shell)
|
8
|
+
@shell = shell
|
9
|
+
end
|
10
|
+
|
11
|
+
def clone(slug)
|
12
|
+
dir = target_dir_for(slug)
|
13
|
+
unless dir.exist?
|
14
|
+
shell.run_each([
|
15
|
+
[:mkdir, "-p", dir.parent.to_s],
|
16
|
+
[:git, "clone", "git@github.com:#{slug}.git", dir]
|
17
|
+
])
|
18
|
+
end
|
19
|
+
cd(slug)
|
20
|
+
end
|
21
|
+
|
22
|
+
def cd(slug)
|
23
|
+
dir = target_dir_for(slug)
|
24
|
+
if dir.exist?
|
25
|
+
shell.after_run([
|
26
|
+
["cd", dir],
|
27
|
+
["setenv", "JIVE_LAST_RUN=#{Time.now.to_i}"]
|
28
|
+
])
|
29
|
+
else
|
30
|
+
clone(slug)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def target_dir_for(slug)
|
37
|
+
Pathname.new(Dir.home).join("src/github.com/#{slug}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/jive/popen.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
module Popen
|
5
|
+
Result = Struct.new(:command, :stdout, :stderr, :status, :duration)
|
6
|
+
|
7
|
+
def self.popen(command, path = nil, env = {}, &block)
|
8
|
+
result = popen_with_detail(command, path, env, &block)
|
9
|
+
|
10
|
+
["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.popen_with_detail(command, path = Dir.pwd, env = {})
|
14
|
+
FileUtils.mkdir_p(path) unless File.directory?(path)
|
15
|
+
|
16
|
+
captured_stdout = ""
|
17
|
+
captured_stderr = ""
|
18
|
+
exit_status = nil
|
19
|
+
start = Time.now
|
20
|
+
|
21
|
+
Open3.popen3(env.merge("PWD" => path), *Array(command),
|
22
|
+
{ chdir: path }) do |stdin, stdout, stderr, wait_thr|
|
23
|
+
out_reader = Thread.new { stdout.read }
|
24
|
+
err_reader = Thread.new { stderr.read }
|
25
|
+
|
26
|
+
yield(stdin) if block_given?
|
27
|
+
|
28
|
+
stdin.close
|
29
|
+
captured_stdout = out_reader.value
|
30
|
+
captured_stderr = err_reader.value
|
31
|
+
exit_status = wait_thr.value
|
32
|
+
end
|
33
|
+
Result.new(command, captured_stdout, captured_stderr, exit_status,
|
34
|
+
Time.now - start)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/jive/project.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
class Project
|
5
|
+
attr_reader :path
|
6
|
+
|
7
|
+
def initialize(path)
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
def bootstrap(shell)
|
12
|
+
tasks = []
|
13
|
+
tasks << [:asdf, "install"]
|
14
|
+
tasks << [:bundle, "install"] if bundler?
|
15
|
+
tasks << [:yarn, "install"] if yarn?
|
16
|
+
|
17
|
+
shell.run_safely do
|
18
|
+
shell.run_each(tasks)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def bundler?
|
25
|
+
path.join("Gemfile").exist? ||
|
26
|
+
path.glob("*.gemspec").any?
|
27
|
+
end
|
28
|
+
|
29
|
+
def yarn?
|
30
|
+
path.join("yarn.lock").exist?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/jive/runner.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
class Runner
|
5
|
+
attr_reader :results
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@results = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(commands, &block)
|
12
|
+
commands.each do |command|
|
13
|
+
block.call(command) do
|
14
|
+
cmd_result = Popen.popen_with_detail(command)
|
15
|
+
results << cmd_result
|
16
|
+
cmd_result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def all_success_and_clean?
|
22
|
+
all_success? && all_stderr_empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def all_success?
|
26
|
+
results.all? { |result| result.status.success? }
|
27
|
+
end
|
28
|
+
|
29
|
+
def all_stderr_empty?
|
30
|
+
results.all? { |result| result.stderr.empty? }
|
31
|
+
end
|
32
|
+
|
33
|
+
def failed_results
|
34
|
+
results.reject { |result| result.status.success? }
|
35
|
+
end
|
36
|
+
|
37
|
+
def warned_results
|
38
|
+
results.select do |result|
|
39
|
+
result.status.success? && !result.stderr.empty?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/jive/shell.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jive
|
4
|
+
class Shell
|
5
|
+
COMMAND_MAP = {
|
6
|
+
cd: "/usr/bin/cd",
|
7
|
+
echo: "/usr/bin/echo",
|
8
|
+
git: "/usr/bin/git",
|
9
|
+
mkdir: "/usr/bin/mkdir"
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
def run_each(tasks)
|
13
|
+
tasks.each do |task|
|
14
|
+
break unless execute(task)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def execute(command, env: {})
|
19
|
+
system(env, expand(command))
|
20
|
+
end
|
21
|
+
|
22
|
+
def after_run(tasks)
|
23
|
+
finalizer_fd = 42
|
24
|
+
pipe = IO.new(finalizer_fd)
|
25
|
+
pipe.puts(tasks.map { |x| x.join(":") }.join("\n"))
|
26
|
+
rescue Errno::EBADF => e
|
27
|
+
puts e
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
def expand(command)
|
32
|
+
Array(command)
|
33
|
+
.flatten
|
34
|
+
.map { |x| COMMAND_MAP.fetch(x, x).to_s }
|
35
|
+
.join(" ")
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_safely
|
39
|
+
yield
|
40
|
+
rescue StandardError => e
|
41
|
+
puts e
|
42
|
+
after_run([%w[noop noop]])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/jive/version.rb
CHANGED
metadata
CHANGED
@@ -1,89 +1,131 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mo khan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: thor
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
40
|
+
version: '5.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '13.0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '13.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: rubocop
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
61
|
+
version: '1.7'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
68
|
+
version: '1.7'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop-minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.5'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.5'
|
55
97
|
description: The art just comes.
|
56
98
|
email:
|
57
|
-
- mo
|
99
|
+
- mo@mokhan.ca
|
58
100
|
executables:
|
59
101
|
- jive
|
60
102
|
extensions: []
|
61
103
|
extra_rdoc_files: []
|
62
104
|
files:
|
63
|
-
- ".github/workflows/test.yml"
|
64
|
-
- ".gitignore"
|
65
|
-
- ".rspec"
|
66
|
-
- ".travis.yml"
|
67
|
-
- Gemfile
|
68
|
-
- Gemfile.lock
|
69
105
|
- LICENSE.txt
|
70
106
|
- README.md
|
71
|
-
- Rakefile
|
72
|
-
- bin/console
|
73
|
-
- bin/setup
|
74
|
-
- bin/test
|
75
107
|
- exe/jive
|
76
108
|
- jive.gemspec
|
109
|
+
- jive.sh
|
77
110
|
- lib/jive.rb
|
111
|
+
- lib/jive/batch_runner.rb
|
112
|
+
- lib/jive/cli.rb
|
113
|
+
- lib/jive/docker.rb
|
114
|
+
- lib/jive/git.rb
|
115
|
+
- lib/jive/popen.rb
|
116
|
+
- lib/jive/project.rb
|
117
|
+
- lib/jive/runner.rb
|
118
|
+
- lib/jive/shell.rb
|
78
119
|
- lib/jive/version.rb
|
79
|
-
homepage: https://
|
120
|
+
homepage: https://rubygems.org/gems/jive
|
80
121
|
licenses:
|
81
122
|
- MIT
|
82
123
|
metadata:
|
83
|
-
homepage_uri: https://
|
84
|
-
|
85
|
-
|
86
|
-
|
124
|
+
homepage_uri: https://rubygems.org/gems/jive
|
125
|
+
post_install_message: |
|
126
|
+
Run the following command for setup instructions:
|
127
|
+
|
128
|
+
$ jive setup
|
87
129
|
rdoc_options: []
|
88
130
|
require_paths:
|
89
131
|
- lib
|
@@ -91,15 +133,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
133
|
requirements:
|
92
134
|
- - ">="
|
93
135
|
- !ruby/object:Gem::Version
|
94
|
-
version:
|
136
|
+
version: 2.5.0
|
95
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
138
|
requirements:
|
97
139
|
- - ">="
|
98
140
|
- !ruby/object:Gem::Version
|
99
141
|
version: '0'
|
100
142
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
102
|
-
signing_key:
|
143
|
+
rubygems_version: 3.2.3
|
144
|
+
signing_key:
|
103
145
|
specification_version: 4
|
104
146
|
summary: The art just comes.
|
105
147
|
test_files: []
|
data/.github/workflows/test.yml
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
name: Ruby
|
2
|
-
on: [push]
|
3
|
-
|
4
|
-
jobs:
|
5
|
-
build:
|
6
|
-
runs-on: ubuntu-latest
|
7
|
-
steps:
|
8
|
-
- uses: actions/checkout@v1
|
9
|
-
- name: Set up Ruby 2.6
|
10
|
-
uses: actions/setup-ruby@v1
|
11
|
-
with:
|
12
|
-
ruby-version: 2.6.x
|
13
|
-
- name: Build and test with Rake
|
14
|
-
run: |
|
15
|
-
gem install bundler
|
16
|
-
bundle install --jobs 4 --retry 3
|
17
|
-
./bin/test
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
jive (0.1.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: https://rubygems.org/
|
8
|
-
specs:
|
9
|
-
diff-lcs (1.3)
|
10
|
-
rake (10.5.0)
|
11
|
-
rspec (3.9.0)
|
12
|
-
rspec-core (~> 3.9.0)
|
13
|
-
rspec-expectations (~> 3.9.0)
|
14
|
-
rspec-mocks (~> 3.9.0)
|
15
|
-
rspec-core (3.9.0)
|
16
|
-
rspec-support (~> 3.9.0)
|
17
|
-
rspec-expectations (3.9.0)
|
18
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
19
|
-
rspec-support (~> 3.9.0)
|
20
|
-
rspec-mocks (3.9.0)
|
21
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
22
|
-
rspec-support (~> 3.9.0)
|
23
|
-
rspec-support (3.9.0)
|
24
|
-
|
25
|
-
PLATFORMS
|
26
|
-
ruby
|
27
|
-
|
28
|
-
DEPENDENCIES
|
29
|
-
bundler (~> 2.0)
|
30
|
-
jive!
|
31
|
-
rake (~> 10.0)
|
32
|
-
rspec (~> 3.0)
|
33
|
-
|
34
|
-
BUNDLED WITH
|
35
|
-
2.0.2
|
data/Rakefile
DELETED
data/bin/console
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "jive"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
data/bin/setup
DELETED