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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6281244f3600328a55a9a4e197933273d53201e499c012d0f920a93f7ee1e4e3
4
- data.tar.gz: 59651c78078fbb18dbcf078648fd0f661ce51386e64c93b885cd16d9d04a8bc6
3
+ metadata.gz: bb4eb9f7fb9d9ff62d257c2ed146acd462cb2c4db1b07a4a3cc0a43399ce1073
4
+ data.tar.gz: bb87b75d4635bc12169def9878ab89c7822df1497cd2a39a7aa209c8d8e01489
5
5
  SHA512:
6
- metadata.gz: e0b953652bf6867534fff58d96996d652b11087f8830660d3b0ba1466cf3f950076e95168237087173638f5bd701ea46be21b235f3cef14167b16c2226168f55
7
- data.tar.gz: 52446f569a68c88aa2a75685b32fe96d2532f3074a183ebc26ae2ceb0b7b17fec17da412f10208e938b743b4888a5d40f4f5c60dfd8c5c85207c8be4d6580cd8
6
+ metadata.gz: 7d72ccd8285b0726e1465f6caec69dfddec99b0a9b60594da5de94e4dc898356e009d4e924ec9ae863396e2f4fa2cefa2b912793ae69424c345443de16406ed2
7
+ data.tar.gz: 625c5dc105d2b53c9d9d7a6173761523439ea506dee48dc895252e4392b399a1c5b7d274a5f4bac1cffbdf72661f8c663f561c3ab4b5790f82d3c2b5df81b10c
data/README.md CHANGED
@@ -1,38 +1,34 @@
1
1
  # Jive
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/jive`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![Build Status](https://github.com/xlgmokha/jive/workflows/ci/badge.svg)](https://github.com/xlgmokha/jive/actions)
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
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
- TODO: Write usage instructions here
13
+ $ jive --help
14
+
26
15
 
27
16
  ## Development
28
17
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
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`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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/[USERNAME]/jive.
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
@@ -1,3 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "jive"
4
+ require "jive/cli"
5
+
6
+ ::Jive::Cli::App.start(ARGV)
data/jive.gemspec CHANGED
@@ -1,32 +1,39 @@
1
- lib = File.expand_path("lib", __dir__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "jive/version"
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.khan@gmail.com"]
9
+ spec.email = ["mo@mokhan.ca"]
10
10
 
11
- spec.summary = %q{The art just comes.}
12
- spec.description = %q{The art just comes.}
13
- spec.homepage = "https://github.com/mokhan/jive"
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.metadata["source_code_uri"] = "https://github.com/mokhan/jive"
18
- spec.metadata["changelog_uri"] = "https://github.com/mokhan/jive"
19
-
20
- # Specify which files should be added to the gem when it is released.
21
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
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{^exe/}) { |f| File.basename(f) }
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.add_development_dependency "bundler", "~> 2.0"
30
- spec.add_development_dependency "rake", "~> 10.0"
31
- spec.add_development_dependency "rspec", "~> 3.0"
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.run(tasks)
11
- Jive::BatchRunner.new.run(tasks)
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
- class BatchRunner
47
- attr_reader :runner, :stdout
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
- class Runner
106
- attr_reader :results
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
@@ -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
@@ -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
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Jive
2
- VERSION = "0.1.0"
4
+ VERSION = "0.3.0"
3
5
  end
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.1.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: 2019-10-19 00:00:00.000000000 Z
11
+ date: 2021-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: thor
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
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: '2.0'
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: '10.0'
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: '10.0'
54
+ version: '13.0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: rspec
56
+ name: rubocop
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '3.0'
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: '3.0'
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.khan@gmail.com
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://github.com/mokhan/jive
120
+ homepage: https://rubygems.org/gems/jive
80
121
  licenses:
81
122
  - MIT
82
123
  metadata:
83
- homepage_uri: https://github.com/mokhan/jive
84
- source_code_uri: https://github.com/mokhan/jive
85
- changelog_uri: https://github.com/mokhan/jive
86
- post_install_message:
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: '0'
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.0.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: []
@@ -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
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
-
10
- # rspec failure tracking
11
- .rspec_status
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.4
7
- before_install: gem install bundler -v 2.0.2
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in jive.gemspec
4
- gemspec
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
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
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
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/bin/test DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH.unshift(File.expand_path(File.join(__dir__, '../lib')))
4
-
5
- require 'jive'
6
-
7
- exit Jive.run([%w[bundle exec rspec]])