djin 0.4.0 → 0.5.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: 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
-