djin 0.8.0 → 0.11.2
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 +27 -11
- data/.gitignore +1 -0
- data/.irbrc +4 -0
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +17 -0
- data/Dockerfile +10 -3
- data/Gemfile +4 -0
- data/Gemfile.lock +41 -18
- data/README.md +138 -11
- data/Vertofile +12 -19
- data/djin.gemspec +3 -1
- data/djin.yml +13 -2
- data/docker-compose.yml +16 -2
- data/docker-entrypoint.sh +7 -0
- data/examples/djin.yml +13 -7
- data/examples/djin_lib/test.yml +12 -0
- data/examples/local_tasks/.djin/server_tasks.yml +17 -0
- data/examples/local_tasks/djin.yml +22 -0
- data/examples/remote_tasks/djin.yml +9 -0
- data/lib/djin.rb +67 -17
- data/lib/djin/cli.rb +36 -0
- data/lib/djin/config_loader.rb +124 -30
- data/lib/djin/entities/include_config.rb +47 -0
- data/lib/djin/entities/include_config/base.rb +16 -0
- data/lib/djin/entities/include_config/local.rb +16 -0
- data/lib/djin/entities/{file_config.rb → main_config.rb} +16 -1
- data/lib/djin/extensions/hash_extensions.rb +14 -0
- data/lib/djin/extensions/object_extensions.rb +24 -0
- data/lib/djin/include_resolver.rb +50 -0
- data/lib/djin/interpreter.rb +11 -4
- data/lib/djin/interpreter/base_command_builder.rb +1 -0
- data/lib/djin/memory_cache.rb +17 -0
- data/lib/djin/repositories/remote_config_repository.rb +86 -0
- data/lib/djin/root_cli_parser.rb +46 -0
- data/lib/djin/version.rb +1 -1
- metadata +45 -3
data/Vertofile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
verto_version '0.
|
1
|
+
verto_version '0.10.0'
|
2
2
|
|
3
3
|
config {
|
4
4
|
version.prefix = 'v' # Adds a version_prefix
|
@@ -12,28 +12,21 @@ context(branch('master')) {
|
|
12
12
|
}
|
13
13
|
|
14
14
|
before_tag_creation {
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
puts "---------------------------"
|
20
|
-
version_changes = "## #{new_version} - #{Time.now.strftime('%d/%m/%Y')}\n#{version_changes}\n"
|
21
|
-
exit unless confirm("Create new Realease?\n" \
|
22
|
-
"---------------------------\n" \
|
23
|
-
"#{version_changes}" \
|
24
|
-
"---------------------------\n"
|
25
|
-
)
|
26
|
-
|
27
|
-
# CHANGELOG
|
28
|
-
file('CHANGELOG.md').prepend(version_changes)
|
15
|
+
update_changelog(with: :merged_pull_requests_with_bracketed_labels,
|
16
|
+
confirmation: true,
|
17
|
+
filename: 'CHANGELOG.md')
|
18
|
+
|
29
19
|
git!('add CHANGELOG.md')
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
|
21
|
+
files_to_change_version_once = %w[lib/djin/version.rb djin.yml] + Dir['examples/**/*.yml'] + Dir['spec/support/fixtures/**/*.yml']
|
22
|
+
|
23
|
+
files_to_change_version_once.each do |filename|
|
24
|
+
file(filename).replace(latest_version.to_s, new_version.to_s)
|
25
|
+
end
|
26
|
+
|
34
27
|
file('README.md').replace_all(latest_version.to_s, new_version.to_s)
|
35
28
|
|
36
|
-
git!(
|
29
|
+
git!("add #{files_to_change_version_once.join(' ')} README.md")
|
37
30
|
|
38
31
|
sh!('bundle install')
|
39
32
|
sh!('rake install')
|
data/djin.gemspec
CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
|
|
21
21
|
# Specify which files should be added to the gem when it is released.
|
22
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
23
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
-
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|docker)/}) }
|
25
25
|
end
|
26
26
|
spec.bindir = 'exe'
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency 'dry-equalizer', '~> 0.3.0'
|
32
32
|
spec.add_dependency 'dry-struct', '~> 1.3.0'
|
33
33
|
spec.add_dependency 'dry-validation', '~> 1.5.1'
|
34
|
+
spec.add_dependency 'git', '~> 1.8.1'
|
34
35
|
spec.add_dependency 'mustache', '~> 1.1.1'
|
35
36
|
spec.add_dependency 'vseries', '~> 0.1.0'
|
36
37
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
@@ -38,4 +39,5 @@ Gem::Specification.new do |spec|
|
|
38
39
|
spec.add_development_dependency 'rake', '~> 13.0'
|
39
40
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
41
|
spec.add_development_dependency 'rubocop'
|
42
|
+
spec.add_development_dependency 'simplecov', '~> 0.17.0'
|
41
43
|
end
|
data/djin.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
djin_version: '0.
|
1
|
+
djin_version: '0.11.2'
|
2
2
|
|
3
3
|
_default_run_options: &default_run_options
|
4
4
|
options: "--rm --entrypoint=''"
|
@@ -9,11 +9,21 @@ tasks:
|
|
9
9
|
docker-compose:
|
10
10
|
service: app
|
11
11
|
run:
|
12
|
-
commands: "
|
12
|
+
commands: "rspec {{args}}"
|
13
13
|
<<: *default_run_options
|
14
14
|
aliases:
|
15
15
|
- rspec
|
16
16
|
|
17
|
+
lint:
|
18
|
+
description: Lint
|
19
|
+
docker-compose:
|
20
|
+
service: app
|
21
|
+
run:
|
22
|
+
commands: "rubocop {{args}}"
|
23
|
+
<<: *default_run_options
|
24
|
+
aliases:
|
25
|
+
- rubocop
|
26
|
+
|
17
27
|
sh:
|
18
28
|
description: Enter app service shell
|
19
29
|
docker-compose:
|
@@ -31,5 +41,6 @@ tasks:
|
|
31
41
|
release:
|
32
42
|
local:
|
33
43
|
run:
|
44
|
+
- (source ~/.zshrc || true)
|
34
45
|
- verto tag up {{args}}
|
35
46
|
- bundle exec rake release
|
data/docker-compose.yml
CHANGED
@@ -1,6 +1,20 @@
|
|
1
|
-
version:
|
1
|
+
version: "3.9"
|
2
|
+
|
2
3
|
services:
|
3
4
|
app:
|
4
|
-
build:
|
5
|
+
build:
|
6
|
+
context: .
|
7
|
+
target: dev
|
8
|
+
entrypoint: 'sh docker-entrypoint.sh'
|
9
|
+
command: 'djin'
|
10
|
+
tty: true
|
11
|
+
stdin_open: true
|
5
12
|
volumes:
|
6
13
|
- .:/usr/src/djin
|
14
|
+
depends_on:
|
15
|
+
- gitserver
|
16
|
+
|
17
|
+
gitserver:
|
18
|
+
image: catks/gitserver-http:0.1.0
|
19
|
+
volumes:
|
20
|
+
- ./docker/git_server/repos/:/var/lib/initial/
|
data/examples/djin.yml
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
---
|
2
|
-
djin_version: '0.
|
2
|
+
djin_version: '0.11.2'
|
3
|
+
|
4
|
+
include:
|
5
|
+
- file: 'djin_lib/test.yml'
|
6
|
+
context:
|
7
|
+
variables:
|
8
|
+
namespace: 'test:'
|
9
|
+
|
10
|
+
- file: 'djin_lib/test.yml'
|
11
|
+
context:
|
12
|
+
variables:
|
13
|
+
namespace: 'test2:'
|
14
|
+
|
3
15
|
|
4
16
|
tasks:
|
5
17
|
default:
|
@@ -7,12 +19,6 @@ tasks:
|
|
7
19
|
image: "ruby:2.5"
|
8
20
|
run:
|
9
21
|
- "ruby -e 'puts \\\" Hello\\\"'"
|
10
|
-
test:
|
11
|
-
docker-compose:
|
12
|
-
service: app
|
13
|
-
run:
|
14
|
-
commands: rspec
|
15
|
-
options: "--rm"
|
16
22
|
|
17
23
|
script:
|
18
24
|
docker:
|
@@ -0,0 +1,17 @@
|
|
1
|
+
djin_version: '0.8.0'
|
2
|
+
|
3
|
+
tasks:
|
4
|
+
"{{namespace}}:ssh":
|
5
|
+
local:
|
6
|
+
run:
|
7
|
+
- ssh {{ssh_user}}@{{host}}
|
8
|
+
|
9
|
+
"{{namespace}}:restart":
|
10
|
+
local:
|
11
|
+
run:
|
12
|
+
- ssh -t {{ssh_user}}@{{host}} restart
|
13
|
+
|
14
|
+
"{{namespace}}:logs":
|
15
|
+
local:
|
16
|
+
run:
|
17
|
+
- ssh -t {{ssh_user}}@{{host}} tail -f /var/log/my_log
|
@@ -0,0 +1,22 @@
|
|
1
|
+
djin_version: '0.11.2'
|
2
|
+
|
3
|
+
include:
|
4
|
+
- file: '.djin/server_tasks.yml'
|
5
|
+
context:
|
6
|
+
variables:
|
7
|
+
namespace: host1
|
8
|
+
host: host1.com
|
9
|
+
ssh_user: my_user
|
10
|
+
|
11
|
+
- file: '.djin/server_tasks.yml'
|
12
|
+
context:
|
13
|
+
variables:
|
14
|
+
namespace: host2
|
15
|
+
host: host2.com
|
16
|
+
ssh_user: my_user
|
17
|
+
|
18
|
+
tasks:
|
19
|
+
hello_command:
|
20
|
+
local:
|
21
|
+
run:
|
22
|
+
- echo 'Hello Djin'
|
data/lib/djin.rb
CHANGED
@@ -8,44 +8,94 @@ require 'dry-validation'
|
|
8
8
|
require 'vseries'
|
9
9
|
require 'dry/cli'
|
10
10
|
require 'mustache'
|
11
|
+
require 'optparse'
|
12
|
+
require 'git'
|
11
13
|
require 'djin/extensions/hash_extensions'
|
14
|
+
require 'djin/extensions/object_extensions'
|
12
15
|
require 'djin/entities/types'
|
13
16
|
require 'djin/entities/task'
|
14
|
-
require 'djin/entities/
|
17
|
+
require 'djin/entities/include_config.rb'
|
18
|
+
require 'djin/entities/main_config'
|
15
19
|
require 'djin/interpreter/base_command_builder'
|
16
20
|
require 'djin/interpreter/docker_command_builder'
|
17
21
|
require 'djin/interpreter/docker_compose_command_builder'
|
18
22
|
require 'djin/interpreter/local_command_builder'
|
19
23
|
require 'djin/interpreter'
|
24
|
+
require 'djin/include_resolver'
|
20
25
|
require 'djin/config_loader'
|
21
26
|
require 'djin/executor'
|
27
|
+
require 'djin/root_cli_parser'
|
22
28
|
require 'djin/cli'
|
23
29
|
require 'djin/task_contract'
|
24
30
|
require 'djin/repositories/task_repository'
|
31
|
+
require 'djin/repositories/remote_config_repository'
|
32
|
+
require 'djin/memory_cache'
|
25
33
|
|
26
34
|
module Djin
|
27
35
|
class Error < StandardError; end
|
28
36
|
|
29
|
-
|
30
|
-
abort 'Error: djin.yml not found' unless path.exist?
|
37
|
+
using Djin::ObjectExtensions
|
31
38
|
|
32
|
-
|
39
|
+
class << self
|
40
|
+
def load_tasks!(*file_paths)
|
41
|
+
files = file_paths.presence || RootCliParser.parse![:files] || ['djin.yml']
|
33
42
|
|
34
|
-
|
35
|
-
tasks = Interpreter.load!(file_config)
|
43
|
+
file_config = ConfigLoader.load_files!(*files)
|
36
44
|
|
37
|
-
|
38
|
-
|
39
|
-
rescue Djin::Interpreter::InvalidConfigurationError => e
|
40
|
-
error_name = e.class.name.split('::').last
|
41
|
-
abort("[#{error_name}] #{e.message}")
|
42
|
-
end
|
45
|
+
# TODO: Make all tasks be under 'tasks' key, passing only the tasks here
|
46
|
+
tasks = Interpreter.load!(file_config)
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
48
|
+
@task_repository = TaskRepository.new(tasks)
|
49
|
+
|
50
|
+
remote_configs = file_config.include_configs.select { |f| f.type == :remote }
|
51
|
+
@remote_config_repository = RemoteConfigRepository.new(remote_configs)
|
52
|
+
|
53
|
+
CLI.load_tasks!(tasks)
|
54
|
+
rescue Djin::Interpreter::InvalidConfigurationError => e
|
55
|
+
error_name = e.class.name.split('::').last
|
56
|
+
abort("[#{error_name}] #{e.message}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def tasks
|
60
|
+
task_repository.all
|
61
|
+
end
|
62
|
+
|
63
|
+
def task_repository
|
64
|
+
@task_repository ||= TaskRepository.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def remote_config_repository
|
68
|
+
@remote_config_repository ||= RemoteConfigRepository.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def cache
|
72
|
+
@cache ||= MemoryCache.new
|
73
|
+
end
|
74
|
+
|
75
|
+
def root_path
|
76
|
+
Pathname.new File.expand_path(__dir__ + '/..')
|
77
|
+
end
|
78
|
+
|
79
|
+
def warn(message, type: 'WARNING')
|
80
|
+
stderr.puts "[#{type}] #{message}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def warn_once(message, type: 'WARNING')
|
84
|
+
return if warnings.include?(message)
|
85
|
+
|
86
|
+
warn(message, type: type)
|
87
|
+
|
88
|
+
warnings << message
|
89
|
+
end
|
90
|
+
|
91
|
+
def stderr
|
92
|
+
$stderr
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
47
96
|
|
48
|
-
|
49
|
-
|
97
|
+
def warnings
|
98
|
+
@warnings ||= []
|
99
|
+
end
|
50
100
|
end
|
51
101
|
end
|
data/lib/djin/cli.rb
CHANGED
@@ -28,6 +28,42 @@ module Djin
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
class File < Dry::CLI::Command
|
32
|
+
desc 'Specify a djin file to load (default: djin.yml)'
|
33
|
+
argument :filepath, required: true, desc: 'The file path to load'
|
34
|
+
|
35
|
+
def call(filename:, **)
|
36
|
+
# The actual behaviour is on RootCliParser
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module RemoteConfig
|
41
|
+
class Fetch < Dry::CLI::Command
|
42
|
+
desc 'Fetchs missing remote configs'
|
43
|
+
|
44
|
+
def call(*)
|
45
|
+
Djin.remote_config_repository.fetch_all
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Clear < Dry::CLI::Command
|
50
|
+
desc 'clear downloaded remote configs'
|
51
|
+
option :all,
|
52
|
+
type: :boolean,
|
53
|
+
default: false,
|
54
|
+
desc: 'Remove all remote configs, not only the ones referenced in the current djin file'
|
55
|
+
|
56
|
+
def call(all:)
|
57
|
+
return Djin.remote_config_repository.clear_all if all
|
58
|
+
|
59
|
+
Djin.remote_config_repository.clear
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
register '-f', File, aliases: ['--file']
|
31
65
|
register '--version', Version, aliases: ['-v']
|
66
|
+
register 'remote-config fetch', RemoteConfig::Fetch
|
67
|
+
register 'remote-config clear', RemoteConfig::Clear
|
32
68
|
end
|
33
69
|
end
|
data/lib/djin/config_loader.rb
CHANGED
@@ -4,20 +4,38 @@ module Djin
|
|
4
4
|
# TODO: Refactor this class to be the Interpreter
|
5
5
|
# class and use the current interpreter as
|
6
6
|
# a TaskLoader
|
7
|
+
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
7
9
|
class ConfigLoader
|
8
10
|
using Djin::HashExtensions
|
9
|
-
RESERVED_WORDS = %w[djin_version variables tasks].freeze
|
11
|
+
RESERVED_WORDS = %w[djin_version variables tasks include].freeze
|
12
|
+
|
13
|
+
# Change Base Error
|
14
|
+
FileNotFoundError = Class.new(Interpreter::InvalidConfigurationError)
|
15
|
+
|
16
|
+
def self.load_files!(*files, runtime_config: {}, base_directory: '.')
|
17
|
+
files.map do |file_path|
|
18
|
+
ConfigLoader.load!(file_path, runtime_config: runtime_config, base_directory: base_directory)
|
19
|
+
end&.reduce(:deep_merge)
|
20
|
+
end
|
10
21
|
|
11
|
-
def self.load!(
|
12
|
-
new(
|
22
|
+
def self.load!(template_file_path, runtime_config: {}, base_directory: '.')
|
23
|
+
new(template_file_path, runtime_config: runtime_config, base_directory: base_directory).load!
|
13
24
|
end
|
14
25
|
|
15
|
-
def initialize(
|
16
|
-
@
|
26
|
+
def initialize(template_file_path, runtime_config: {}, base_directory: '.')
|
27
|
+
@base_directory = Pathname.new(base_directory)
|
28
|
+
@template_file = @base_directory.join(template_file_path)
|
29
|
+
|
30
|
+
file_not_found!(@template_file) unless @template_file.exist?
|
31
|
+
|
32
|
+
@template_file_content = Djin.cache.fetch(@template_file.realpath.to_s) { @template_file.read }
|
33
|
+
@runtime_config = runtime_config
|
17
34
|
end
|
18
35
|
|
19
36
|
def load!
|
20
37
|
validate_version!
|
38
|
+
validate_missing_config!
|
21
39
|
|
22
40
|
file_config
|
23
41
|
end
|
@@ -25,52 +43,38 @@ module Djin
|
|
25
43
|
private
|
26
44
|
|
27
45
|
def file_config
|
28
|
-
|
46
|
+
MainConfig.new(
|
29
47
|
djin_version: version,
|
30
48
|
variables: variables,
|
31
49
|
tasks: tasks,
|
32
|
-
raw_tasks: raw_tasks
|
50
|
+
raw_tasks: raw_tasks,
|
51
|
+
include_configs: @include_configs || []
|
33
52
|
)
|
34
53
|
end
|
35
54
|
|
36
|
-
def raw_djin_config
|
37
|
-
@raw_djin_config ||= yaml_load(@template_file)
|
38
|
-
rescue Psych::SyntaxError => e
|
39
|
-
raise Interpreter::InvalidConfigFileError, e.message
|
40
|
-
end
|
41
|
-
|
42
|
-
def rendered_djin_config
|
43
|
-
@rendered_djin_config ||= begin
|
44
|
-
locals = env.merge(variables)
|
45
|
-
|
46
|
-
rendered_yaml = Mustache.render(@template_file,
|
47
|
-
args: args.join(' '),
|
48
|
-
args?: args.any?,
|
49
|
-
**locals)
|
50
|
-
yaml_load(rendered_yaml)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
55
|
def version
|
55
56
|
# TODO: Deprecates djin_version and use version instead
|
56
57
|
@version || raw_djin_config['djin_version']
|
57
58
|
end
|
58
59
|
|
59
60
|
def variables
|
60
|
-
@variables ||= raw_djin_config['variables']&.symbolize_keys || {}
|
61
|
+
@variables ||= included_variables.merge(raw_djin_config['variables']&.symbolize_keys || {})
|
61
62
|
end
|
62
63
|
|
63
64
|
def tasks
|
64
|
-
rendered_djin_config['tasks'] || legacy_tasks
|
65
|
+
included_tasks.merge(rendered_djin_config['tasks'] || legacy_tasks)
|
65
66
|
end
|
66
67
|
|
67
68
|
def raw_tasks
|
68
|
-
raw_djin_config['tasks'] || legacy_raw_tasks
|
69
|
+
included_raw_tasks.merge(raw_djin_config['tasks'] || legacy_raw_tasks)
|
69
70
|
end
|
70
71
|
|
71
72
|
def legacy_tasks
|
72
|
-
|
73
|
-
|
73
|
+
Djin.warn_once(
|
74
|
+
'Root tasks are deprecated and will be removed in Djin 1.0.0,' \
|
75
|
+
' put the tasks under \'tasks\' keyword',
|
76
|
+
type: 'DEPRECATED'
|
77
|
+
)
|
74
78
|
|
75
79
|
rendered_djin_config.except(*RESERVED_WORDS).reject { |task| task.start_with?('_') }
|
76
80
|
end
|
@@ -79,6 +83,57 @@ module Djin
|
|
79
83
|
raw_djin_config.except(*RESERVED_WORDS).reject { |task| task.start_with?('_') }
|
80
84
|
end
|
81
85
|
|
86
|
+
def included_variables
|
87
|
+
return {} unless included_config
|
88
|
+
|
89
|
+
included_config.variables
|
90
|
+
end
|
91
|
+
|
92
|
+
def included_tasks
|
93
|
+
return {} unless included_config
|
94
|
+
|
95
|
+
included_config.tasks
|
96
|
+
end
|
97
|
+
|
98
|
+
def included_raw_tasks
|
99
|
+
return {} unless included_config
|
100
|
+
|
101
|
+
included_config.raw_tasks
|
102
|
+
end
|
103
|
+
|
104
|
+
# TODO: Rename method
|
105
|
+
def included_config
|
106
|
+
@included_config ||= begin
|
107
|
+
present_include_configs&.map do |present_include|
|
108
|
+
ConfigLoader.load!(present_include.file, base_directory: @template_file.dirname,
|
109
|
+
# TODO: Rename to context_config
|
110
|
+
runtime_config: present_include.context)
|
111
|
+
end&.reduce(:deep_merge)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def present_include_configs
|
116
|
+
include_configs&.select(&:present?)
|
117
|
+
end
|
118
|
+
|
119
|
+
def missing_include_configs
|
120
|
+
include_configs&.select(&:missing?)
|
121
|
+
end
|
122
|
+
|
123
|
+
# TODO: Refactor to move include methods to a specific IncludeConfigLoader, maybe rename IncludeResolver
|
124
|
+
def include_configs
|
125
|
+
@include_configs ||= begin
|
126
|
+
# TODO: Rename the resolved variables
|
127
|
+
resolver = IncludeResolver.new(base_directory: @template_file.dirname)
|
128
|
+
|
129
|
+
include_djin_config = raw_djin_config['include'] || []
|
130
|
+
|
131
|
+
include_djin_config.map do |include_config|
|
132
|
+
resolver.call(include_config)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
82
137
|
def args
|
83
138
|
index = ARGV.index('--')
|
84
139
|
|
@@ -91,6 +146,24 @@ module Djin
|
|
91
146
|
@env ||= ENV.to_h.symbolize_keys
|
92
147
|
end
|
93
148
|
|
149
|
+
def raw_djin_config
|
150
|
+
@raw_djin_config ||= yaml_load(@template_file_content).deep_merge(@runtime_config)
|
151
|
+
rescue Psych::SyntaxError => e
|
152
|
+
raise Interpreter::InvalidConfigFileError, "File: #{@template_file.realpath}\n #{e.message}"
|
153
|
+
end
|
154
|
+
|
155
|
+
def rendered_djin_config
|
156
|
+
@rendered_djin_config ||= begin
|
157
|
+
locals = env.merge(variables)
|
158
|
+
|
159
|
+
rendered_yaml = Mustache.render(@template_file_content,
|
160
|
+
args: args.join(' '),
|
161
|
+
args?: args.any?,
|
162
|
+
**locals)
|
163
|
+
yaml_load(rendered_yaml).merge(@runtime_config)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
94
167
|
def yaml_load(text)
|
95
168
|
YAML.safe_load(text, [], [], true)
|
96
169
|
end
|
@@ -102,5 +175,26 @@ module Djin
|
|
102
175
|
|
103
176
|
raise Interpreter::VersionNotSupportedError, "Version #{version} is not supported, use #{Djin::VERSION} or higher"
|
104
177
|
end
|
178
|
+
|
179
|
+
def validate_missing_config!
|
180
|
+
missing_include_configs.each do |ic|
|
181
|
+
file_not_found!(ic.full_path) if ic.type == :local
|
182
|
+
|
183
|
+
missing_file_remote_error = "#{ic.git} exists but is missing %s," \
|
184
|
+
'if the file exists in upstream run djin remote-config fetch to fix'
|
185
|
+
|
186
|
+
file_not_found!(ic.full_path, missing_file_remote_error) if ic.type == :remote && ic.repository_fetched?
|
187
|
+
|
188
|
+
if ic.type == :remote
|
189
|
+
Djin.warn_once "Missing #{ic.git} with version '#{ic.version}', " \
|
190
|
+
'run `djin remote-config fetch` to fetch the config'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def file_not_found!(filename, message = "File '%s' not found")
|
196
|
+
raise FileNotFoundError, message % filename
|
197
|
+
end
|
105
198
|
end
|
199
|
+
# rubocop:enable Metrics/ClassLength
|
106
200
|
end
|