djin 0.4.0 → 0.5.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/ruby.yml +14 -0
- data/.rubocop.yml +8 -0
- data/.rubocop_todo.yml +17 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +2 -2
- data/README.md +40 -5
- data/Rakefile +6 -4
- data/Vertofile +4 -3
- data/bin/console +4 -3
- data/djin.gemspec +25 -23
- data/djin.yml +9 -2
- data/examples/djin.yml +2 -0
- data/exe/djin +2 -1
- data/lib/djin.rb +28 -23
- data/lib/djin/cli.rb +5 -3
- data/lib/djin/entities/task.rb +2 -0
- data/lib/djin/entities/types.rb +2 -0
- data/lib/djin/executor.rb +4 -11
- data/lib/djin/extensions/hash_extensions.rb +3 -1
- data/lib/djin/interpreter.rb +10 -51
- data/lib/djin/interpreter/base_command_builder.rb +26 -0
- data/lib/djin/interpreter/docker_command_builder.rb +29 -0
- data/lib/djin/interpreter/docker_compose_command_builder.rb +17 -0
- data/lib/djin/interpreter/local_command_builder.rb +11 -0
- data/lib/djin/repositories/task_repository.rb +2 -0
- data/lib/djin/task_contract.rb +37 -7
- data/lib/djin/template_renderer.rb +34 -0
- data/lib/djin/version.rb +3 -1
- metadata +35 -29
- data/lib/djin/extensions/custom_predicates.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a40e01844f1a9b034d592696cf6af915622c834a9e231f0c56209c03d11660ad
|
4
|
+
data.tar.gz: facbe98a7362ec81b5f819af27a554807790a1445c7cc47161a85d5f0d5b7276
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72f5ea393c498311acf74a482b02670d94f11704a75032e31e914e68b947de694bec077ba03e22b75fd73c9307f9f98242ea35009f5341c2ab9b3d1af0314901
|
7
|
+
data.tar.gz: 4bf6650c80d7defc1dd3b2850c21b74c54ecdb7f4dd374c0a98dd3bfe2610c7175f7102a71de53d6367a4dfd1fcdae47437a2db24bee83bc1c195a4c0fea9da7
|
data/.github/workflows/ruby.yml
CHANGED
@@ -18,3 +18,17 @@ jobs:
|
|
18
18
|
gem install bundler
|
19
19
|
bundle install --jobs 4 --retry 3
|
20
20
|
bundle exec rake
|
21
|
+
|
22
|
+
lint:
|
23
|
+
runs-on: ubuntu-16.04
|
24
|
+
name: Lint
|
25
|
+
steps:
|
26
|
+
- uses: actions/checkout@v2
|
27
|
+
- uses: actions/setup-ruby@v1
|
28
|
+
with:
|
29
|
+
ruby-version: '2.6'
|
30
|
+
- run: |
|
31
|
+
gem install bundler
|
32
|
+
bundle install --jobs 4 --retry 3
|
33
|
+
bundle exec rubocop
|
34
|
+
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2020-07-14 01:12:35 UTC using RuboCop version 0.86.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 2
|
10
|
+
# Configuration parameters: IgnoredMethods.
|
11
|
+
Metrics/AbcSize:
|
12
|
+
Max: 21
|
13
|
+
|
14
|
+
# Offense count: 2
|
15
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
16
|
+
Metrics/MethodLength:
|
17
|
+
Max: 19
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
djin (0.
|
4
|
+
djin (0.5.0)
|
5
5
|
dry-cli (~> 0.6.0)
|
6
6
|
dry-struct (~> 1.3.0)
|
7
7
|
dry-validation (~> 1.5.1)
|
@@ -33,7 +33,7 @@ GEM
|
|
33
33
|
concurrent-ruby (~> 1.0)
|
34
34
|
dry-core (~> 0.2)
|
35
35
|
dry-equalizer (~> 0.2)
|
36
|
-
dry-schema (1.5.
|
36
|
+
dry-schema (1.5.2)
|
37
37
|
concurrent-ruby (~> 1.0)
|
38
38
|
dry-configurable (~> 0.8, >= 0.8.3)
|
39
39
|
dry-core (~> 0.4)
|
data/README.md
CHANGED
@@ -25,7 +25,7 @@ If you use Rbenv you can install djin only once and create a alias in your .basr
|
|
25
25
|
To use djin first you need to create a djin.yml file:
|
26
26
|
|
27
27
|
```yaml
|
28
|
-
djin_version: '0.
|
28
|
+
djin_version: '0.5.0'
|
29
29
|
|
30
30
|
# With a docker image
|
31
31
|
script:
|
@@ -50,7 +50,7 @@ You can also set task dependencies with depends_on option:
|
|
50
50
|
|
51
51
|
|
52
52
|
```yaml
|
53
|
-
djin_version: '0.
|
53
|
+
djin_version: '0.5.0'
|
54
54
|
|
55
55
|
_default_run_options: &default_run_options
|
56
56
|
options: "--rm"
|
@@ -76,14 +76,49 @@ _default_run_options: &default_run_options
|
|
76
76
|
|
77
77
|
```
|
78
78
|
|
79
|
+
Or mix local commands and docker/docker-compose commands:
|
80
|
+
|
81
|
+
```yaml
|
82
|
+
djin_version: '0.5.0'
|
83
|
+
|
84
|
+
_default_run_options: &default_run_options
|
85
|
+
options: "--rm"
|
86
|
+
|
87
|
+
"db:create":
|
88
|
+
docker-compose:
|
89
|
+
service: app
|
90
|
+
run:
|
91
|
+
commands: rake db:create
|
92
|
+
<<: *default_run_options
|
93
|
+
|
94
|
+
"db:migrate":
|
95
|
+
docker-compose:
|
96
|
+
service: app
|
97
|
+
run:
|
98
|
+
commands: rake db:migrate
|
99
|
+
<<: *default_run_options
|
100
|
+
|
101
|
+
"setup:copy_samples":
|
102
|
+
local:
|
103
|
+
run:
|
104
|
+
- cp config/database.yml.sample config/database.yml
|
105
|
+
|
106
|
+
"setup":
|
107
|
+
depends_on:
|
108
|
+
- "setup:copy_samples"
|
109
|
+
- "db:create"
|
110
|
+
- "db:migrate"
|
111
|
+
|
112
|
+
```
|
113
|
+
|
79
114
|
After that you can run `djin {{task_name}}`, like `djin script` or `djin test`
|
80
115
|
|
81
116
|
## Using Environment variables and custom args in djin.yml run tasks
|
82
117
|
|
83
|
-
You can use environment variables using the '{{YOUR_ENV_HERE}}' syntax, like so:
|
118
|
+
You can also use environment variables using the '{{YOUR_ENV_HERE}}' syntax, like so:
|
84
119
|
|
85
120
|
```yaml
|
86
|
-
djin_version: '0.
|
121
|
+
djin_version: '0.5.0'
|
87
122
|
|
88
123
|
_default_run_options: &default_run_options
|
89
124
|
options: "--rm"
|
@@ -100,7 +135,7 @@ _default_run_options: &default_run_options
|
|
100
135
|
It's also possible to pass custom arguments to the command, wich means is possible to make a djin task act like the command itself:
|
101
136
|
|
102
137
|
```yaml
|
103
|
-
djin_version: '0.
|
138
|
+
djin_version: '0.5.0'
|
104
139
|
|
105
140
|
_default_run_options: &default_run_options
|
106
141
|
options: "--rm"
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require_relative 'lib/djin'
|
4
6
|
|
5
7
|
RSpec::Core::RakeTask.new(:spec)
|
6
8
|
|
7
|
-
task :
|
9
|
+
task default: :spec
|
8
10
|
|
9
11
|
desc 'Djin REPL'
|
10
12
|
task :console do
|
data/Vertofile
CHANGED
@@ -29,10 +29,11 @@ context(branch('master')) {
|
|
29
29
|
git!('add CHANGELOG.md')
|
30
30
|
|
31
31
|
file('lib/djin/version.rb').replace(latest_version.to_s, new_version.to_s)
|
32
|
-
|
33
|
-
|
32
|
+
file('djin.yml').replace(latest_version.to_s, new_version.to_s)
|
33
|
+
file('examples/djin.yml').replace(latest_version.to_s, new_version.to_s)
|
34
34
|
file('README.md').replace_all(latest_version.to_s, new_version.to_s)
|
35
|
-
|
35
|
+
|
36
|
+
git!('add lib/djin/version.rb djin.yml examples/djin.yml README.md')
|
36
37
|
|
37
38
|
sh!('bundle install')
|
38
39
|
sh!('rake install')
|
data/bin/console
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require
|
4
|
-
require
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'djin'
|
5
6
|
|
6
7
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
8
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +11,5 @@ require "djin"
|
|
10
11
|
# require "pry"
|
11
12
|
# Pry.start
|
12
13
|
|
13
|
-
require
|
14
|
+
require 'irb'
|
14
15
|
IRB.start(__FILE__)
|
data/djin.gemspec
CHANGED
@@ -1,38 +1,40 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
5
|
+
require 'djin/version'
|
4
6
|
|
5
7
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
8
|
+
spec.name = 'djin'
|
7
9
|
spec.version = Djin::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
10
|
+
spec.authors = ['Carlos Atkinson']
|
11
|
+
spec.email = ['carlos.atks@gmail.com']
|
10
12
|
|
11
|
-
spec.summary =
|
12
|
-
spec.homepage =
|
13
|
-
spec.license =
|
13
|
+
spec.summary = 'djin is a make-like utility for docker containers'
|
14
|
+
spec.homepage = 'https://github.com/catks/djin'
|
15
|
+
spec.license = 'MIT'
|
14
16
|
|
15
17
|
# spec.metadata["homepage_uri"] = spec.homepage
|
16
|
-
#spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
17
|
-
#spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
18
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
19
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
18
20
|
|
19
21
|
# Specify which files should be added to the gem when it is released.
|
20
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
-
spec.files = Dir.chdir(File.expand_path(
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
24
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
25
|
end
|
24
|
-
spec.bindir =
|
26
|
+
spec.bindir = 'exe'
|
25
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
-
spec.require_paths = [
|
28
|
+
spec.require_paths = ['lib']
|
27
29
|
|
28
|
-
spec.add_dependency
|
29
|
-
spec.add_dependency
|
30
|
-
spec.add_dependency
|
31
|
-
spec.add_dependency
|
32
|
-
spec.add_dependency
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency
|
36
|
-
spec.add_development_dependency
|
37
|
-
spec.add_development_dependency
|
30
|
+
spec.add_dependency 'dry-cli', '~> 0.6.0'
|
31
|
+
spec.add_dependency 'dry-struct', '~> 1.3.0'
|
32
|
+
spec.add_dependency 'dry-validation', '~> 1.5.1'
|
33
|
+
spec.add_dependency 'mustache', '~> 1.1.1'
|
34
|
+
spec.add_dependency 'vseries', '~> 0.1.0'
|
35
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
36
|
+
spec.add_development_dependency 'byebug'
|
37
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
38
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
39
|
+
spec.add_development_dependency 'rubocop'
|
38
40
|
end
|
data/djin.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
djin_version: '0.
|
1
|
+
djin_version: '0.5.0'
|
2
2
|
|
3
3
|
_default_run_options: &default_run_options
|
4
4
|
options: "--rm --entrypoint=''"
|
@@ -7,7 +7,7 @@ test:
|
|
7
7
|
docker-compose:
|
8
8
|
service: app
|
9
9
|
run:
|
10
|
-
commands: "cd /usr/src/djin && rspec"
|
10
|
+
commands: "cd /usr/src/djin && rspec {{args}}"
|
11
11
|
<<: *default_run_options
|
12
12
|
|
13
13
|
sh:
|
@@ -23,4 +23,11 @@ run:
|
|
23
23
|
commands: "sh -c '{{args}}'"
|
24
24
|
<<: *default_run_options
|
25
25
|
|
26
|
+
release:
|
27
|
+
local:
|
28
|
+
run:
|
29
|
+
- verto tag up {{args}}
|
30
|
+
- rake release
|
31
|
+
|
32
|
+
|
26
33
|
|
data/examples/djin.yml
CHANGED
data/exe/djin
CHANGED
data/lib/djin.rb
CHANGED
@@ -1,20 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'djin/version'
|
4
|
+
require 'pathname'
|
5
|
+
require 'yaml'
|
6
|
+
require 'dry-struct'
|
7
|
+
require 'dry-validation'
|
8
|
+
require 'vseries'
|
9
|
+
require 'dry/cli'
|
10
|
+
require 'mustache'
|
11
|
+
require 'djin/extensions/hash_extensions'
|
12
|
+
require 'djin/entities/types'
|
13
|
+
require 'djin/entities/task'
|
14
|
+
require 'djin/interpreter/base_command_builder'
|
15
|
+
require 'djin/interpreter/docker_command_builder'
|
16
|
+
require 'djin/interpreter/docker_compose_command_builder'
|
17
|
+
require 'djin/interpreter/local_command_builder'
|
18
|
+
require 'djin/interpreter'
|
19
|
+
require 'djin/template_renderer'
|
20
|
+
require 'djin/executor'
|
21
|
+
require 'djin/cli'
|
22
|
+
require 'djin/task_contract'
|
23
|
+
require 'djin/repositories/task_repository'
|
18
24
|
|
19
25
|
module Djin
|
20
26
|
class Error < StandardError; end
|
@@ -22,15 +28,15 @@ module Djin
|
|
22
28
|
def self.load_tasks!(path = Pathname.getwd.join('djin.yml'))
|
23
29
|
abort 'Error: djin.yml not found' unless path.exist?
|
24
30
|
|
25
|
-
|
31
|
+
rendered_djin_file = TemplateRenderer.render(path.read)
|
32
|
+
djin_config = YAML.safe_load(rendered_djin_file, [], [], true)
|
26
33
|
|
27
|
-
tasks =
|
34
|
+
tasks = Interpreter.load!(djin_config)
|
28
35
|
|
29
36
|
@task_repository = TaskRepository.new(tasks)
|
30
37
|
CLI.load_tasks!(tasks)
|
31
|
-
|
32
|
-
|
33
|
-
abort(ex.message)
|
38
|
+
rescue Djin::Interpreter::InvalidConfigurationError => e
|
39
|
+
abort(e.message)
|
34
40
|
end
|
35
41
|
|
36
42
|
def self.tasks
|
@@ -41,4 +47,3 @@ module Djin
|
|
41
47
|
@task_repository ||= TaskRepository.new
|
42
48
|
end
|
43
49
|
end
|
44
|
-
|
data/lib/djin/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Djin
|
2
4
|
class CLI
|
3
5
|
extend Dry::CLI::Registry
|
@@ -9,8 +11,8 @@ module Djin
|
|
9
11
|
|
10
12
|
define_method(:task) { task }
|
11
13
|
|
12
|
-
def call(
|
13
|
-
Executor.new
|
14
|
+
def call(**)
|
15
|
+
Executor.new.call(task)
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -19,7 +21,7 @@ module Djin
|
|
19
21
|
end
|
20
22
|
|
21
23
|
class Version < Dry::CLI::Command
|
22
|
-
desc
|
24
|
+
desc 'Prints Djin Version'
|
23
25
|
|
24
26
|
def call(*)
|
25
27
|
puts Djin::VERSION
|
data/lib/djin/entities/task.rb
CHANGED
data/lib/djin/entities/types.rb
CHANGED
data/lib/djin/executor.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Djin
|
2
4
|
class Executor
|
3
|
-
def initialize(task_repository: Djin.task_repository
|
5
|
+
def initialize(task_repository: Djin.task_repository)
|
4
6
|
@task_repository = task_repository
|
5
|
-
@args = args
|
6
7
|
end
|
7
8
|
|
8
9
|
def call(*tasks)
|
@@ -23,15 +24,7 @@ module Djin
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def run(command)
|
26
|
-
|
27
|
-
args: @args.join(' '),
|
28
|
-
args?: @args.any?,
|
29
|
-
**env)
|
30
|
-
system command_with_args
|
31
|
-
end
|
32
|
-
|
33
|
-
def env
|
34
|
-
@env = ENV.to_h.map {|k,v| [k.to_sym, v]}.to_h
|
27
|
+
system command
|
35
28
|
end
|
36
29
|
end
|
37
30
|
end
|
data/lib/djin/interpreter.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Djin
|
2
4
|
class Interpreter
|
3
5
|
using Djin::HashExtensions
|
@@ -13,7 +15,9 @@ module Djin
|
|
13
15
|
def load!(params)
|
14
16
|
version = params['djin_version']
|
15
17
|
raise MissingVersionError, 'Missing djin_version' unless version
|
16
|
-
|
18
|
+
unless version_supported?(version)
|
19
|
+
raise VersionNotSupportedError, "Version #{version} is not supported, use #{Djin::VERSION} or higher"
|
20
|
+
end
|
17
21
|
|
18
22
|
tasks_params = params.except(*RESERVED_WORDS).reject { |task| task.start_with?('_') }
|
19
23
|
contract = TaskContract.new
|
@@ -42,58 +46,13 @@ module Djin
|
|
42
46
|
# Validate that only one ot the two is passed
|
43
47
|
docker_params = params['docker']
|
44
48
|
docker_compose_params = params['docker-compose']
|
49
|
+
local_params = params['local']
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
def build_docker_commands(params, task_name:)
|
51
|
-
current_folder_name = Pathname.getwd.basename.to_s
|
52
|
-
image = params['image'] || "djin_#{current_folder_name}_#{task_name}"
|
53
|
-
|
54
|
-
build_params = params['build']
|
55
|
-
|
56
|
-
if build_params.is_a?(Hash)
|
57
|
-
build_context = build_params['context']
|
58
|
-
build_options = build_params['options']
|
59
|
-
end
|
60
|
-
|
61
|
-
build_context ||= build_params
|
62
|
-
|
63
|
-
run_command, run_options = build_run_params(params['run'])
|
64
|
-
|
65
|
-
command = %Q{docker run #{run_options} #{image} sh -c "#{run_command}"}.squeeze(' ')
|
66
|
-
|
67
|
-
build_command = "docker build #{build_context} #{build_options} -t #{image}".squeeze(' ') if build_context
|
68
|
-
|
69
|
-
[command, build_command]
|
70
|
-
end
|
71
|
-
|
72
|
-
def build_docker_compose_commands(params)
|
73
|
-
service = params['service']
|
74
|
-
|
75
|
-
compose_options = params['options']
|
76
|
-
|
77
|
-
run_command, run_options = build_run_params(params['run'])
|
78
|
-
|
79
|
-
[%Q{docker-compose #{compose_options} run #{run_options} #{service} sh -c "#{run_command}"}.squeeze(' '), nil]
|
80
|
-
end
|
81
|
-
|
82
|
-
def build_run_params(run_params)
|
83
|
-
run_command = run_params
|
84
|
-
|
85
|
-
if run_params.is_a?(Hash)
|
86
|
-
run_command = run_params['commands']
|
87
|
-
run_options = run_params['options']
|
88
|
-
end
|
89
|
-
|
90
|
-
run_command = run_command.join(' && ') if run_command.is_a?(Array)
|
91
|
-
|
92
|
-
[run_command, run_options]
|
93
|
-
end
|
94
|
-
|
95
|
-
def validate_version!(version)
|
51
|
+
# TODO: Refactor to use chain of responsability
|
52
|
+
return DockerCommandBuilder.call(docker_params, task_name: task_name) if docker_params
|
53
|
+
return DockerComposeCommandBuilder.call(docker_compose_params) if docker_compose_params
|
96
54
|
|
55
|
+
LocalCommandBuilder.call(local_params) if local_params
|
97
56
|
end
|
98
57
|
|
99
58
|
def version_supported?(version)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Djin
|
4
|
+
class Interpreter
|
5
|
+
class BaseCommandBuilder
|
6
|
+
def self.call(*options)
|
7
|
+
new.call(*options)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def build_run_params(run_params)
|
13
|
+
run_command = run_params
|
14
|
+
|
15
|
+
if run_params.is_a?(Hash)
|
16
|
+
run_command = run_params['commands']
|
17
|
+
run_options = run_params['options']
|
18
|
+
end
|
19
|
+
|
20
|
+
run_command = run_command.join(' && ') if run_command.is_a?(Array)
|
21
|
+
|
22
|
+
[run_command, run_options]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Djin
|
4
|
+
class Interpreter
|
5
|
+
class DockerCommandBuilder < BaseCommandBuilder
|
6
|
+
def call(params, task_name:)
|
7
|
+
current_folder_name = Pathname.getwd.basename.to_s
|
8
|
+
image = params['image'] || "djin_#{current_folder_name}_#{task_name}"
|
9
|
+
|
10
|
+
build_params = params['build']
|
11
|
+
|
12
|
+
if build_params.is_a?(Hash)
|
13
|
+
build_context = build_params['context']
|
14
|
+
build_options = build_params['options']
|
15
|
+
end
|
16
|
+
|
17
|
+
build_context ||= build_params
|
18
|
+
|
19
|
+
run_command, run_options = build_run_params(params['run'])
|
20
|
+
|
21
|
+
command = %(docker run #{run_options} #{image} sh -c "#{run_command}").squeeze(' ')
|
22
|
+
|
23
|
+
build_command = "docker build #{build_context} #{build_options} -t #{image}".squeeze(' ') if build_context
|
24
|
+
|
25
|
+
[command, build_command]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Djin
|
4
|
+
class Interpreter
|
5
|
+
class DockerComposeCommandBuilder < BaseCommandBuilder
|
6
|
+
def call(params, **_)
|
7
|
+
service = params['service']
|
8
|
+
|
9
|
+
compose_options = params['options']
|
10
|
+
|
11
|
+
run_command, run_options = build_run_params(params['run'])
|
12
|
+
|
13
|
+
[%(docker-compose #{compose_options} run #{run_options} #{service} sh -c "#{run_command}").squeeze(' '), nil]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/djin/task_contract.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Djin
|
2
4
|
class TaskContract < Dry::Validation::Contract
|
3
|
-
NOT_EMPTY = ->
|
4
|
-
OK = ->
|
5
|
+
NOT_EMPTY = ->(value) { !value.empty? }
|
6
|
+
OK = ->(_) { true }
|
7
|
+
NOT_OK = ->(_) { false }
|
5
8
|
|
6
9
|
BuildSchema = Dry::Schema.Params do
|
7
10
|
required(:context).filled(:string)
|
@@ -13,6 +16,10 @@ module Djin
|
|
13
16
|
required(:options).filled(:string)
|
14
17
|
end
|
15
18
|
|
19
|
+
RunLocalSchema = Dry::Schema.Params do
|
20
|
+
required(:commands).filled
|
21
|
+
end
|
22
|
+
|
16
23
|
DockerSchema = Dry::Schema.Params do
|
17
24
|
optional(:image).maybe(:string)
|
18
25
|
optional(:build)
|
@@ -25,32 +32,49 @@ module Djin
|
|
25
32
|
required(:run).filled
|
26
33
|
end
|
27
34
|
|
35
|
+
LocalSchema = Dry::Schema.Params do
|
36
|
+
required(:run).filled
|
37
|
+
end
|
38
|
+
|
28
39
|
params do
|
29
40
|
optional(:docker).filled do
|
30
41
|
hash(DockerSchema)
|
31
42
|
end
|
43
|
+
|
32
44
|
optional(:"docker-compose").filled do
|
33
45
|
hash(DockerComposeSchema)
|
34
46
|
end
|
35
47
|
|
48
|
+
optional(:local).filled do
|
49
|
+
hash(LocalSchema)
|
50
|
+
end
|
51
|
+
|
36
52
|
optional(:depends_on).each(:str?)
|
37
53
|
end
|
38
54
|
|
39
|
-
rule(:docker, :"docker-compose", :depends_on) do
|
40
|
-
|
55
|
+
rule(:docker, :"docker-compose", :local, :depends_on) do
|
56
|
+
unless values[:docker] || values[:"docker-compose"] || values[:depends_on] || values[:local]
|
57
|
+
key.failure('docker, docker-compose, local or depends_on key is required')
|
58
|
+
end
|
41
59
|
end
|
42
60
|
|
43
|
-
rule(:depends_on, :'docker-compose',docker: [
|
44
|
-
key.failure('image or build param is required for docker tasks') unless values.dig(:docker, :image) ||
|
61
|
+
rule(:depends_on, :'docker-compose', :local, docker: %i[image build]) do
|
62
|
+
key.failure('image or build param is required for docker tasks') unless values.dig(:docker, :image) ||
|
63
|
+
values.dig(:docker, :build) ||
|
64
|
+
values[:'docker-compose'] ||
|
65
|
+
values[:depends_on] ||
|
66
|
+
values.dig(:local, :run)
|
45
67
|
end
|
46
68
|
|
69
|
+
# TODO: Extract validations to command builders
|
70
|
+
|
47
71
|
rule(docker: :build) do
|
48
72
|
result, errors = validate_for(value, Hash => BuildSchema, String => NOT_EMPTY, NilClass => OK)
|
49
73
|
|
50
74
|
key.failure(errors) unless result
|
51
75
|
end
|
52
76
|
|
53
|
-
rule(
|
77
|
+
rule('docker-compose': :run) do
|
54
78
|
result, errors = validate_for(value, Hash => RunSchema, Array => NOT_EMPTY, NilClass => OK)
|
55
79
|
|
56
80
|
key.failure(errors) unless result
|
@@ -62,6 +86,12 @@ module Djin
|
|
62
86
|
key.failure(errors) unless result
|
63
87
|
end
|
64
88
|
|
89
|
+
rule(local: :run) do
|
90
|
+
result, errors = validate_for(value, Hash => RunLocalSchema, Array => NOT_EMPTY, NilClass => OK)
|
91
|
+
|
92
|
+
key.failure(errors) unless result
|
93
|
+
end
|
94
|
+
|
65
95
|
private
|
66
96
|
|
67
97
|
def validate_for(value, validations)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Djin
|
4
|
+
class TemplateRenderer
|
5
|
+
def self.render(template_file)
|
6
|
+
new(template_file).render
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(template_file)
|
10
|
+
@template_file = template_file
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
Mustache.render(@template_file,
|
15
|
+
args: args.join(' '),
|
16
|
+
args?: args.any?,
|
17
|
+
**env)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def args
|
23
|
+
index = ARGV.index('--')
|
24
|
+
|
25
|
+
return [] unless index
|
26
|
+
|
27
|
+
ARGV.slice((index + 1)..ARGV.size)
|
28
|
+
end
|
29
|
+
|
30
|
+
def env
|
31
|
+
@env ||= ENV.to_h.map { |k, v| [k.to_sym, v] }.to_h
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/djin/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: djin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Atkinson
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: dry-
|
14
|
+
name: dry-cli
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.6.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.6.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: dry-
|
28
|
+
name: dry-struct
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.3.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.3.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: dry-validation
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,33 +53,33 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 1.5.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: mustache
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.1.1
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 1.1.1
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: vseries
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.1.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.1.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: bundler
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,49 +95,49 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '2.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: byebug
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '13.0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '13.0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: rspec
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- - "
|
129
|
+
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0'
|
131
|
+
version: '3.0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- - "
|
136
|
+
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0'
|
138
|
+
version: '3.0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: rubocop
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - ">="
|
@@ -161,6 +161,8 @@ files:
|
|
161
161
|
- ".github/workflows/ruby.yml"
|
162
162
|
- ".gitignore"
|
163
163
|
- ".rspec"
|
164
|
+
- ".rubocop.yml"
|
165
|
+
- ".rubocop_todo.yml"
|
164
166
|
- ".travis.yml"
|
165
167
|
- CHANGELOG.md
|
166
168
|
- Dockerfile
|
@@ -182,11 +184,15 @@ files:
|
|
182
184
|
- lib/djin/entities/task.rb
|
183
185
|
- lib/djin/entities/types.rb
|
184
186
|
- lib/djin/executor.rb
|
185
|
-
- lib/djin/extensions/custom_predicates.rb
|
186
187
|
- lib/djin/extensions/hash_extensions.rb
|
187
188
|
- lib/djin/interpreter.rb
|
189
|
+
- lib/djin/interpreter/base_command_builder.rb
|
190
|
+
- lib/djin/interpreter/docker_command_builder.rb
|
191
|
+
- lib/djin/interpreter/docker_compose_command_builder.rb
|
192
|
+
- lib/djin/interpreter/local_command_builder.rb
|
188
193
|
- lib/djin/repositories/task_repository.rb
|
189
194
|
- lib/djin/task_contract.rb
|
195
|
+
- lib/djin/template_renderer.rb
|
190
196
|
- lib/djin/version.rb
|
191
197
|
homepage: https://github.com/catks/djin
|
192
198
|
licenses:
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Djin
|
2
|
-
module CustomPredicates
|
3
|
-
refine Dry::Logic::Predicates::Methods do
|
4
|
-
def is_one_of?(value, *options)
|
5
|
-
options.map do |option|
|
6
|
-
return option.call(value) if respond_to?(:call)
|
7
|
-
|
8
|
-
value.is_a?(option)
|
9
|
-
end.any?
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
refine Dry::Logic::Predicates do
|
14
|
-
extend Dry::Logic::Predicates::Methods
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|