jive 0.1.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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]])