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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 395a6c76f1aac739197b1721dfedca93dfffcfcf456d3fc748fa16f024fb5a94
4
- data.tar.gz: c2915512107075ee0fb3bafbfe50033925410241fef29dd54db747a2d0686328
3
+ metadata.gz: a40e01844f1a9b034d592696cf6af915622c834a9e231f0c56209c03d11660ad
4
+ data.tar.gz: facbe98a7362ec81b5f819af27a554807790a1445c7cc47161a85d5f0d5b7276
5
5
  SHA512:
6
- metadata.gz: 802cfbb81399c9ec9494b98036c7bd5932e735eb028b44ff84abc1ff0f2ff7930fe4d5a2d9b2bdae2b493684289e0e1d8631e570c942c71351321faa641bac85
7
- data.tar.gz: 3b895f090fb9c73aac047c234a13191702393cf7fdff8c6b9eb0437daed931e7ae71ba0d6c8113d45b84d6424897309c66f310bfd470f58c955c1b508aa771d9
6
+ metadata.gz: 72f5ea393c498311acf74a482b02670d94f11704a75032e31e914e68b947de694bec077ba03e22b75fd73c9307f9f98242ea35009f5341c2ab9b3d1af0314901
7
+ data.tar.gz: 4bf6650c80d7defc1dd3b2850c21b74c54ecdb7f4dd374c0a98dd3bfe2610c7175f7102a71de53d6367a4dfd1fcdae47437a2db24bee83bc1c195a4c0fea9da7
@@ -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
+
@@ -0,0 +1,8 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ Style/Documentation:
4
+ Enabled: false
5
+
6
+ Metrics/BlockLength:
7
+ Exclude:
8
+ - spec/**/*
@@ -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
@@ -1,3 +1,7 @@
1
+ ## 0.5.0 - 13/07/2020
2
+ * [FEATURE] Adds local command task
3
+ * [FEATURE] Template Args for entire djin.yml
4
+
1
5
  ## 0.4.0 - 25/06/2020
2
6
  * [FEATURE] Adds Custom Args and Environment support in djin.yml
3
7
 
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in djin.gemspec
4
6
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- djin (0.4.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.1)
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.4.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.4.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.4.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.4.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
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
- require_relative "lib/djin"
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 :default => :spec
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
- git!('add lib/djin/version.rb')
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
- git!('add README.md')
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')
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "djin"
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 "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
@@ -1,38 +1,40 @@
1
- lib = File.expand_path("lib", __dir__)
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 "djin/version"
5
+ require 'djin/version'
4
6
 
5
7
  Gem::Specification.new do |spec|
6
- spec.name = "djin"
8
+ spec.name = 'djin'
7
9
  spec.version = Djin::VERSION
8
- spec.authors = ["Carlos Atkinson"]
9
- spec.email = ["carlos.atks@gmail.com"]
10
+ spec.authors = ['Carlos Atkinson']
11
+ spec.email = ['carlos.atks@gmail.com']
10
12
 
11
- spec.summary = %q{djin is a make-like utility for docker containers}
12
- spec.homepage = "https://github.com/catks/djin"
13
- spec.license = "MIT"
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('..', __FILE__)) do
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 = "exe"
26
+ spec.bindir = 'exe'
25
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
- spec.require_paths = ["lib"]
28
+ spec.require_paths = ['lib']
27
29
 
28
- spec.add_dependency "dry-struct", "~> 1.3.0"
29
- spec.add_dependency "dry-cli", "~> 0.6.0"
30
- spec.add_dependency "dry-validation", "~> 1.5.1"
31
- spec.add_dependency "vseries", "~> 0.1.0"
32
- spec.add_dependency "mustache", "~> 1.1.1"
33
- spec.add_development_dependency "bundler", "~> 2.0"
34
- spec.add_development_dependency "rake", "~> 13.0"
35
- spec.add_development_dependency "rspec", "~> 3.0"
36
- spec.add_development_dependency "rubocop"
37
- spec.add_development_dependency "byebug"
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.2.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
 
@@ -1,4 +1,6 @@
1
1
  ---
2
+ djin_version: '0.5.0'
3
+
2
4
  default:
3
5
  docker:
4
6
  image: "ruby:2.5"
data/exe/djin CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- Signal.trap("INT") { exit 2 }
4
+ Signal.trap('INT') { exit 2 }
4
5
 
5
6
  require_relative '../lib/djin'
6
7
 
@@ -1,20 +1,26 @@
1
- require "djin/version"
2
- require "pathname"
3
- require "yaml"
4
- require "dry-struct"
5
- require "dry-validation"
6
- require "vseries"
7
- require "dry/cli"
8
- require "mustache"
9
- require "djin/extensions/hash_extensions"
10
- require "djin/extensions/custom_predicates"
11
- require "djin/entities/types"
12
- require "djin/entities/task"
13
- require "djin/interpreter"
14
- require "djin/executor"
15
- require "djin/cli"
16
- require "djin/task_contract"
17
- require "djin/repositories/task_repository"
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
- djin_file = YAML.safe_load(path.read, [], [], true)
31
+ rendered_djin_file = TemplateRenderer.render(path.read)
32
+ djin_config = YAML.safe_load(rendered_djin_file, [], [], true)
26
33
 
27
- tasks = Djin::Interpreter.load!(djin_file)
34
+ tasks = Interpreter.load!(djin_config)
28
35
 
29
36
  @task_repository = TaskRepository.new(tasks)
30
37
  CLI.load_tasks!(tasks)
31
-
32
- rescue Djin::Interpreter::InvalidConfigurationError => ex
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
-
@@ -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(args: [], **)
13
- Executor.new(args: args).call(task)
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 "Prints Djin Version"
24
+ desc 'Prints Djin Version'
23
25
 
24
26
  def call(*)
25
27
  puts Djin::VERSION
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Djin
2
4
  class Task < Dry::Struct
3
5
  attribute :name, Types::String
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Djin
2
4
  module Types
3
5
  include Dry.Types()
@@ -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, args: [])
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
- command_with_args = Mustache.render(command,
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
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Djin
2
4
  module HashExtensions
3
5
  refine Hash do
4
6
  def except(*keys)
5
- reject { |key,_| keys.include?(key) }
7
+ reject { |key, _| keys.include?(key) }
6
8
  end
7
9
  end
8
10
  end
@@ -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
- raise VersionNotSupportedError, "Version #{version} is not supported, use #{Djin::VERSION} or higher" unless version_supported?(version)
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
- return build_docker_commands(docker_params, task_name: task_name) if docker_params
47
- build_docker_compose_commands(docker_compose_params) if docker_compose_params
48
- end
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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Djin
4
+ class Interpreter
5
+ class LocalCommandBuilder < BaseCommandBuilder
6
+ def call(params, **_)
7
+ build_run_params(params['run'])
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class TaskRepository
2
4
  def initialize(tasks = [])
3
5
  @tasks = tasks
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Djin
2
4
  class TaskContract < Dry::Validation::Contract
3
- NOT_EMPTY = -> (value) { ! value.empty? }
4
- OK = -> (_) { true }
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
- key.failure('docker, docker-compose or depends_on key is required') unless values[:docker] || values[:"docker-compose"] || values[:depends_on]
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: [:image, :build]) do
44
- key.failure('image or build param is required for docker tasks') unless values.dig(:docker, :image) || values.dig(:docker, :build) || values[:'docker-compose'] || values[:depends_on]
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(:'docker-compose' => :run) do
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Djin
2
- VERSION = "0.4.0"
4
+ VERSION = '0.5.0'
3
5
  end
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.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-06-25 00:00:00.000000000 Z
11
+ date: 2020-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: dry-struct
14
+ name: dry-cli
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3.0
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: 1.3.0
26
+ version: 0.6.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: dry-cli
28
+ name: dry-struct
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.6.0
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: 0.6.0
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: vseries
56
+ name: mustache
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.1.0
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: 0.1.0
68
+ version: 1.1.1
69
69
  - !ruby/object:Gem::Dependency
70
- name: mustache
70
+ name: vseries
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 1.1.1
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: 1.1.1
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: rake
98
+ name: byebug
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '13.0'
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: '13.0'
110
+ version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec
112
+ name: rake
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
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: '3.0'
124
+ version: '13.0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: rubocop
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: byebug
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
-