jive 0.1.0 → 0.2.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/.github/workflows/ci.yml +28 -0
- data/.gitignore +0 -4
- data/.rubocop.yml +37 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +35 -20
- data/README.md +14 -18
- data/Rakefile +11 -3
- data/bin/console +1 -7
- data/bin/run +7 -0
- data/bin/setup +4 -6
- data/bin/shipit +7 -0
- data/bin/style +6 -0
- data/bin/test +9 -4
- data/exe/jive +4 -1
- data/jive.gemspec +24 -15
- data/jive.sh +87 -0
- data/lib/jive.rb +5 -132
- data/lib/jive/batch_runner.rb +70 -0
- data/lib/jive/cli.rb +60 -0
- data/lib/jive/popen.rb +37 -0
- data/lib/jive/runner.rb +43 -0
- data/lib/jive/version.rb +3 -1
- metadata +73 -23
- data/.github/workflows/test.yml +0 -17
- data/.rspec +0 -3
- data/.travis.yml +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1e99fd45b1d45c356ac45300a941833cf34dbcfc3995f935234c9c08f06dba74
|
|
4
|
+
data.tar.gz: a68176da0fe8547d201ddbc573fb6d49e0773ca983fa312e4b6dc313c9a4157b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c41233baa8f43d3a9277435661eb9ccb13e874d5a5ed338f4de60cd095942c6b8ad3f13f74be5a34819d5efea3b8fd090c68369a6f39bacb8f2f10edf313e1c6
|
|
7
|
+
data.tar.gz: cafe522151627f9e4649391e620cb4419970454a04cd62d2b31d329699c7d3cb0bb73dfb2b1faaa9b8ffbec43ee89750b06dc10b75723bf343609bbf1751a2be
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
branches: [main]
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
matrix:
|
|
12
|
+
ruby-version: ['2.5', '2.6', '2.7', '3.0']
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v2
|
|
15
|
+
- uses: ruby/setup-ruby@v1
|
|
16
|
+
with:
|
|
17
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
18
|
+
bundler-cache: true
|
|
19
|
+
- run: ./bin/test
|
|
20
|
+
style:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v2
|
|
24
|
+
- uses: ruby/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: '3'
|
|
27
|
+
bundler-cache: true
|
|
28
|
+
- run: ./bin/style
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require:
|
|
2
|
+
- rubocop-minitest
|
|
3
|
+
- rubocop-rake
|
|
4
|
+
|
|
5
|
+
AllCops:
|
|
6
|
+
NewCops: enable
|
|
7
|
+
TargetRubyVersion: 2.5
|
|
8
|
+
|
|
9
|
+
Layout/LineLength:
|
|
10
|
+
Max: 120
|
|
11
|
+
|
|
12
|
+
Layout/EndOfLine:
|
|
13
|
+
EnforcedStyle: lf
|
|
14
|
+
|
|
15
|
+
Layout/FirstArrayElementIndentation:
|
|
16
|
+
EnforcedStyle: consistent
|
|
17
|
+
|
|
18
|
+
Metrics/AbcSize:
|
|
19
|
+
Exclude:
|
|
20
|
+
- lib/jive/batch_runner.rb
|
|
21
|
+
- lib/jive/popen.rb
|
|
22
|
+
|
|
23
|
+
Metrics/MethodLength:
|
|
24
|
+
Exclude:
|
|
25
|
+
- lib/jive/batch_runner.rb
|
|
26
|
+
- lib/jive/popen.rb
|
|
27
|
+
|
|
28
|
+
Style/Documentation:
|
|
29
|
+
Enabled: false
|
|
30
|
+
|
|
31
|
+
Style/StringLiterals:
|
|
32
|
+
Enabled: true
|
|
33
|
+
EnforcedStyle: double_quotes
|
|
34
|
+
|
|
35
|
+
Style/StringLiteralsInInterpolation:
|
|
36
|
+
Enabled: true
|
|
37
|
+
EnforcedStyle: double_quotes
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
jive (0.
|
|
4
|
+
jive (0.2.0)
|
|
5
|
+
thor (~> 1.1)
|
|
5
6
|
|
|
6
7
|
GEM
|
|
7
8
|
remote: https://rubygems.org/
|
|
8
9
|
specs:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
ast (2.4.2)
|
|
11
|
+
minitest (5.14.3)
|
|
12
|
+
parallel (1.20.1)
|
|
13
|
+
parser (3.0.0.0)
|
|
14
|
+
ast (~> 2.4.1)
|
|
15
|
+
rainbow (3.0.0)
|
|
16
|
+
rake (13.0.3)
|
|
17
|
+
regexp_parser (2.0.3)
|
|
18
|
+
rexml (3.2.4)
|
|
19
|
+
rubocop (1.9.1)
|
|
20
|
+
parallel (~> 1.10)
|
|
21
|
+
parser (>= 3.0.0.0)
|
|
22
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
23
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
24
|
+
rexml
|
|
25
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
|
26
|
+
ruby-progressbar (~> 1.7)
|
|
27
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
28
|
+
rubocop-ast (1.4.1)
|
|
29
|
+
parser (>= 2.7.1.5)
|
|
30
|
+
rubocop-minitest (0.10.3)
|
|
31
|
+
rubocop (>= 0.87, < 2.0)
|
|
32
|
+
rubocop-rake (0.5.1)
|
|
33
|
+
rubocop
|
|
34
|
+
ruby-progressbar (1.11.0)
|
|
35
|
+
thor (1.1.0)
|
|
36
|
+
unicode-display_width (2.0.0)
|
|
24
37
|
|
|
25
38
|
PLATFORMS
|
|
26
39
|
ruby
|
|
27
40
|
|
|
28
41
|
DEPENDENCIES
|
|
29
|
-
bundler (~> 2.0)
|
|
30
42
|
jive!
|
|
31
|
-
|
|
32
|
-
|
|
43
|
+
minitest (~> 5.0)
|
|
44
|
+
rake (~> 13.0)
|
|
45
|
+
rubocop (~> 1.7)
|
|
46
|
+
rubocop-minitest (~> 0.1)
|
|
47
|
+
rubocop-rake (~> 0.5)
|
|
33
48
|
|
|
34
49
|
BUNDLED WITH
|
|
35
|
-
2.
|
|
50
|
+
2.2.8
|
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/Rakefile
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "bundler/gem_tasks"
|
|
2
|
-
require "
|
|
4
|
+
require "rake/testtask"
|
|
5
|
+
require "rubocop/rake_task"
|
|
3
6
|
|
|
4
|
-
|
|
7
|
+
Rake::TestTask.new(:test) do |task|
|
|
8
|
+
task.libs << "lib"
|
|
9
|
+
task.libs << "test"
|
|
10
|
+
task.test_files = FileList["test/**/*_test.rb"]
|
|
11
|
+
end
|
|
12
|
+
RuboCop::RakeTask.new
|
|
5
13
|
|
|
6
|
-
task :
|
|
14
|
+
task default: %i[test rubocop]
|
data/bin/console
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
require "bundler/setup"
|
|
4
5
|
require "jive"
|
|
5
6
|
|
|
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
7
|
require "irb"
|
|
14
8
|
IRB.start(__FILE__)
|
data/bin/run
ADDED
data/bin/setup
CHANGED
data/bin/shipit
ADDED
data/bin/style
ADDED
data/bin/test
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
#!/
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -e
|
|
2
3
|
|
|
3
|
-
$
|
|
4
|
+
cd "$(dirname "$0")/.."
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
export RUBYOPT="-Ilib:test"
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
if [ $# -gt 0 ]; then
|
|
9
|
+
bundle exec ruby "$@"
|
|
10
|
+
else
|
|
11
|
+
bundle exec ruby test/**/*_test.rb
|
|
12
|
+
fi
|
data/exe/jive
CHANGED
data/jive.gemspec
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
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.metadata["source_code_uri"] = "https://github.com/mokhan/jive"
|
|
18
|
-
spec.metadata["changelog_uri"] = "https://github.com/mokhan/jive"
|
|
19
18
|
|
|
20
19
|
# Specify which files should be added to the gem when it is released.
|
|
21
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
22
|
-
spec.files
|
|
23
|
-
`git ls-files -z`.split("\x0").reject
|
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
23
|
+
f.match(%r{^(test|spec|features)/})
|
|
24
|
+
end
|
|
24
25
|
end
|
|
25
26
|
spec.bindir = "exe"
|
|
26
|
-
spec.executables = spec.files.grep(%r{
|
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
27
28
|
spec.require_paths = ["lib"]
|
|
29
|
+
spec.post_install_message = <<~MESSAGE
|
|
30
|
+
Include the following in your ~/.bash_profile
|
|
31
|
+
|
|
32
|
+
source #{__dir__}/jive.sh
|
|
33
|
+
MESSAGE
|
|
28
34
|
|
|
29
|
-
spec.
|
|
30
|
-
spec.add_development_dependency "
|
|
31
|
-
spec.add_development_dependency "
|
|
35
|
+
spec.add_dependency "thor", "~> 1.1"
|
|
36
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
|
37
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
38
|
+
spec.add_development_dependency "rubocop", "~> 1.7"
|
|
39
|
+
spec.add_development_dependency "rubocop-minitest", "~> 0.1"
|
|
40
|
+
spec.add_development_dependency "rubocop-rake", "~> 0.5"
|
|
32
41
|
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 9>"${tmpfile}" # Open the tempfile for writing on FD 9.
|
|
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 9<&- # close FD 9.
|
|
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,17 @@
|
|
|
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/popen"
|
|
8
|
+
require "jive/runner"
|
|
9
|
+
require "jive/version"
|
|
10
|
+
|
|
7
11
|
module Jive
|
|
8
12
|
class Error < StandardError; end
|
|
9
13
|
|
|
10
14
|
def self.run(tasks)
|
|
11
15
|
Jive::BatchRunner.new.run(tasks)
|
|
12
16
|
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
|
|
44
|
-
end
|
|
45
|
-
|
|
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
|
|
103
|
-
end
|
|
104
|
-
|
|
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
|
|
143
|
-
end
|
|
144
17
|
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,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "thor"
|
|
4
|
+
require "jive"
|
|
5
|
+
require "pathname"
|
|
6
|
+
|
|
7
|
+
module Jive
|
|
8
|
+
module Cli
|
|
9
|
+
class App < Thor
|
|
10
|
+
def self.exit_on_failure?
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc "clone <org>/<project>", "git clone to ~/src/github.com/<org>/<project>"
|
|
15
|
+
def clone(slug)
|
|
16
|
+
target_dir = Pathname.new(Dir.home).join("src/github.com/#{slug}")
|
|
17
|
+
run_each([
|
|
18
|
+
[:mkdir, "-p", target_dir.parent.to_s],
|
|
19
|
+
[:git, "clone", "git@github.com:#{slug}.git", target_dir]
|
|
20
|
+
])
|
|
21
|
+
after_run([
|
|
22
|
+
["cd", target_dir],
|
|
23
|
+
["setenv", "JIVE_LAST_RUN=#{Time.now.to_i}"]
|
|
24
|
+
])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
COMMAND_MAP = {
|
|
30
|
+
cd: "/usr/bin/cd",
|
|
31
|
+
echo: "/usr/bin/echo",
|
|
32
|
+
git: "/usr/bin/git",
|
|
33
|
+
mkdir: "/usr/bin/mkdir"
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
def run_each(tasks)
|
|
37
|
+
tasks.each do |task|
|
|
38
|
+
break unless execute(task)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def execute(command, env: {})
|
|
43
|
+
system(env, expand(command))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def after_run(tasks)
|
|
47
|
+
finalizer_fd = 9
|
|
48
|
+
pipe = IO.new(finalizer_fd)
|
|
49
|
+
pipe.puts(tasks.map { |x| x.join(":") }.join("\n"))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def expand(command)
|
|
53
|
+
Array(command)
|
|
54
|
+
.flatten
|
|
55
|
+
.map { |x| COMMAND_MAP.fetch(x, x).to_s }
|
|
56
|
+
.join(" ")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
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/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/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,89 +1,139 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jive
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.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-06 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/
|
|
105
|
+
- ".github/workflows/ci.yml"
|
|
64
106
|
- ".gitignore"
|
|
65
|
-
- ".
|
|
66
|
-
- ".travis.yml"
|
|
107
|
+
- ".rubocop.yml"
|
|
67
108
|
- Gemfile
|
|
68
109
|
- Gemfile.lock
|
|
69
110
|
- LICENSE.txt
|
|
70
111
|
- README.md
|
|
71
112
|
- Rakefile
|
|
72
113
|
- bin/console
|
|
114
|
+
- bin/run
|
|
73
115
|
- bin/setup
|
|
116
|
+
- bin/shipit
|
|
117
|
+
- bin/style
|
|
74
118
|
- bin/test
|
|
75
119
|
- exe/jive
|
|
76
120
|
- jive.gemspec
|
|
121
|
+
- jive.sh
|
|
77
122
|
- lib/jive.rb
|
|
123
|
+
- lib/jive/batch_runner.rb
|
|
124
|
+
- lib/jive/cli.rb
|
|
125
|
+
- lib/jive/popen.rb
|
|
126
|
+
- lib/jive/runner.rb
|
|
78
127
|
- lib/jive/version.rb
|
|
79
|
-
homepage: https://
|
|
128
|
+
homepage: https://rubygems.org/gems/jive
|
|
80
129
|
licenses:
|
|
81
130
|
- MIT
|
|
82
131
|
metadata:
|
|
83
|
-
homepage_uri: https://
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
132
|
+
homepage_uri: https://rubygems.org/gems/jive
|
|
133
|
+
post_install_message: |
|
|
134
|
+
Include the following in your ~/.bash_profile
|
|
135
|
+
|
|
136
|
+
source /home/mokha/src/github.com/xlgmokha/jive/jive.sh
|
|
87
137
|
rdoc_options: []
|
|
88
138
|
require_paths:
|
|
89
139
|
- lib
|
|
@@ -91,15 +141,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
91
141
|
requirements:
|
|
92
142
|
- - ">="
|
|
93
143
|
- !ruby/object:Gem::Version
|
|
94
|
-
version:
|
|
144
|
+
version: 2.5.0
|
|
95
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
146
|
requirements:
|
|
97
147
|
- - ">="
|
|
98
148
|
- !ruby/object:Gem::Version
|
|
99
149
|
version: '0'
|
|
100
150
|
requirements: []
|
|
101
|
-
rubygems_version: 3.
|
|
102
|
-
signing_key:
|
|
151
|
+
rubygems_version: 3.2.3
|
|
152
|
+
signing_key:
|
|
103
153
|
specification_version: 4
|
|
104
154
|
summary: The art just comes.
|
|
105
155
|
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/.rspec
DELETED