dapp 0.1.5 → 0.2.4

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTQ5NzZmNDM5NTE5OWU5ZDcyMmRkZWE4YzU1MDZhNDVkYzI0ZmFlNA==
4
+ NWVjYjY0MmM4ZDBlYzIyMDJmNWM0YjkxNDY0ZmUxN2VhZDZhNzZjMw==
5
5
  data.tar.gz: !binary |-
6
- ZjFlYjI4ZTNmZWY4ODU1ZTcxZTYxYWRlNDhjNTc5ZGQzMzk2NGE1Yw==
6
+ MjBiNDMyMmQ1NmY5MTQxMTU0YWQ3NWI5OWEyNjNlMDM2OTc4YzhlYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MDEzNmU1NDY0MmIyZGVkYzViNjg5ZGM0YzYyYTU0N2U3NGNiYjA1NmQyNzIy
10
- Zjg0NGQyN2Y3ODdlY2RjNTdmNDA4ODdiMDUzZmJkMzEyMTM0MjQ0ZDY4N2Q0
11
- MTZmOTkzMDQxMTA5OWQ1ZWNlOWFhY2Y1MjI1MWE5N2VlNDA5ZTI=
9
+ ZjE4Y2ZlNDI1ZjU3MzczMTQ0NzJlNjI1NWYzMGNlZjI1ZTMyYTBlNjk0NDAw
10
+ OWE5OTExYjIxODU3Y2Q3YzMzMjRmN2FlYzJmMTYwMzcyYzdlMDc1NWQzNDcx
11
+ YWZmN2E4MTgwZjIxOTllYTU1Nzk5MDk4OWRhZTY0M2Y4YzYxZTI=
12
12
  data.tar.gz: !binary |-
13
- Yjc0ZDI5NDhmNDRlMTU2ZjMwZmFiODYzZDk3NjBjYzRkYjMwNTQ0MGRiYTIx
14
- MDZlZTcwZDYxMDZmMGI0ZjEzMzQzZTNlM2IwOTFmNWIwNmEyOTE2MzI3YWQ3
15
- Y2VhMmI5NzdmN2JkZDA2MjczYjQ4NTJkY2JjNDE5NWRjZmZhNmI=
13
+ NzVmY2ZlNjdmMzVjZmI0Y2FhNzdhZTY2OGM5NDljOGQ1NDZlMmFiYzNiYzk5
14
+ NWIyMWI1MWU3MDllMjY2YjUyOTRlZjAyM2JhZmMxZWI1YmQ2NWY2NmU5MjNi
15
+ ZjI4ZTNkYjE1ZTdkNWMzMzU5ODA2MTE4YmE0MjhmZTgzYTJlYzg=
data/bin/dapp CHANGED
@@ -5,18 +5,13 @@
5
5
  require 'rubygems'
6
6
  require 'dapp'
7
7
 
8
- def net_status_message(exception)
9
- net_status = exception.net_status.net_status_normalize(context: exception.net_status.delete(:context))
10
- net_status[:message] || [net_status[:error], net_status[:code]].compact.join(': ')
11
- end
12
-
13
8
  begin
14
9
  Dapp::CLI.new.run
15
10
  rescue Dapp::Error::Shellout => e
16
- $stderr.puts(net_status_message(e))
11
+ $stderr.puts(Dapp::Helper::NetStatus.message(e))
17
12
  exit 1
18
13
  rescue Dapp::Error::Base => e
19
- $stderr.puts(Dapp::Helper::Paint.paint_string(net_status_message(e), :warning))
14
+ $stderr.puts(Dapp::Helper::Paint.paint_string(Dapp::Helper::NetStatus.message(e), :warning))
20
15
  exit 1
21
16
  rescue Interrupt => _e
22
17
  $stderr.puts(Dapp::Helper::Paint.paint_string('Interrupted', :warning))
@@ -21,3 +21,6 @@ en:
21
21
  state:
22
22
  using_cache: '[USING CACHE]'
23
23
  build: '[BUILD]'
24
+ push: '[PUSH]'
25
+ introspect:
26
+ stage: "Introspect stage '%{name}'"
@@ -11,7 +11,7 @@ en:
11
11
  from_image_required: 'Missing from_image!'
12
12
  image_already_untagged: "Image `%{name}` already untagged!"
13
13
  image_not_exist: "Image `%{name}` not exist!"
14
- image_already_tagged: 'Image with other id already tagged!'
14
+ another_image_already_tagged: 'Image with other id already tagged!'
15
15
  built_id_not_defined: '`from.built_id` not defined!'
16
16
  controller:
17
17
  push_command_unexpected_apps: "Push command can process only one application!"
@@ -24,6 +24,7 @@ require 'dapp/helper/log'
24
24
  require 'dapp/helper/paint'
25
25
  require 'dapp/helper/streaming'
26
26
  require 'dapp/helper/shellout'
27
+ require 'dapp/helper/net_status'
27
28
  require 'dapp/cli'
28
29
  require 'dapp/cli/base'
29
30
  require 'dapp/cli/build'
@@ -71,6 +72,8 @@ require 'dapp/git_repo/base'
71
72
  require 'dapp/git_repo/own'
72
73
  require 'dapp/git_repo/remote'
73
74
  require 'dapp/git_artifact'
75
+ require 'dapp/exception/base'
76
+ require 'dapp/exception/introspect_image'
74
77
  require 'dapp/error/base'
75
78
  require 'dapp/error/application'
76
79
  require 'dapp/error/build'
@@ -32,15 +32,15 @@ module Dapp
32
32
  end
33
33
 
34
34
  def export!(repo)
35
- fail Error::Application, code: :application_not_built unless last_stage.image.tagged? || dry_run?
35
+ raise Error::Application, code: :application_not_built unless last_stage.image.tagged? || dry_run?
36
36
 
37
37
  tags.each do |tag|
38
38
  image_name = [repo, tag].join(':')
39
39
  if dry_run?
40
- log_state(image_name, state: 'PUSH', styles: { status: :success })
40
+ log_state(image_name, state: t(code: 'state.push'), styles: { status: :success })
41
41
  else
42
42
  log_process(image_name, process: t(code: 'status.process.pushing')) do
43
- last_stage.image.export!(image_name, log_verbose: log_verbose?, log_time: log_time?)
43
+ last_stage.image.export!(image_name, log_verbose: log_verbose?, log_time: log_time?, force: cli_options[:force])
44
44
  end
45
45
  end
46
46
  end
@@ -66,7 +66,7 @@ module Dapp
66
66
  process = paint_string(rjust(process, message), style[:process])
67
67
  info = paint_string(message, style[:message]) + process
68
68
  success_message = paint_string(slice(message), style[:message]) +
69
- paint_string(rjust(t(code: 'status.success.default'), message), style[:success])
69
+ paint_string(rjust(t(code: 'status.success.default'), message), style[:success])
70
70
  failed_message = paint_string(slice(message) +
71
71
  rjust(t(code: 'status.failed.default'), message), style[:failed])
72
72
  log_process_default(info, success_message, failed_message, &blk)
@@ -84,7 +84,7 @@ module Dapp
84
84
  message = success_message
85
85
  start = Time.now
86
86
  yield
87
- rescue Error::Base, SignalException, StandardError => _e
87
+ rescue Exception::Base, Error::Base, SignalException, StandardError => _e
88
88
  message = failed_message
89
89
  raise
90
90
  ensure
@@ -3,12 +3,6 @@ module Dapp
3
3
  class Application
4
4
  # Path
5
5
  module Path
6
- def build_cache_path(*path)
7
- make_path(@build_cache_path, *path).expand_path.tap do |p|
8
- FileUtils.mkdir_p p.parent
9
- end
10
- end
11
-
12
6
  def home_path(*path)
13
7
  make_path(config._home_path, *path).expand_path
14
8
  end
@@ -17,6 +11,10 @@ module Dapp
17
11
  make_path(@build_path, *path).expand_path.tap { |p| FileUtils.mkdir_p p.parent }
18
12
  end
19
13
 
14
+ def build_cache_path(*path)
15
+ make_path(@build_cache_path, *path).expand_path.tap { |p| FileUtils.mkdir_p p.parent }
16
+ end
17
+
20
18
  def container_build_path(*path)
21
19
  make_path('/.build', *path)
22
20
  end
@@ -21,7 +21,7 @@ module Dapp
21
21
 
22
22
  def branch_tags
23
23
  return [] unless cli_options[:tag_branch]
24
- fail Error::Application, code: :git_branch_without_name if (branch = git_repo.branch) == 'HEAD'
24
+ raise Error::Application, code: :git_branch_without_name if (branch = git_repo.branch) == 'HEAD'
25
25
  [branch]
26
26
  end
27
27
 
@@ -39,7 +39,7 @@ module Dapp
39
39
  elsif ENV['TRAVIS']
40
40
  build_id = ENV['TRAVIS_BUILD_NUMBER']
41
41
  else
42
- fail Error::Application, code: :ci_environment_required
42
+ raise Error::Application, code: :ci_environment_required
43
43
  end
44
44
 
45
45
  [build_id]
@@ -55,7 +55,7 @@ module Dapp
55
55
  branch = ENV['TRAVIS_BRANCH']
56
56
  tag = ENV['TRAVIS_TAG']
57
57
  else
58
- fail Error::Application, code: :ci_environment_required
58
+ raise Error::Application, code: :ci_environment_required
59
59
  end
60
60
 
61
61
  [branch, tag].compact
@@ -16,9 +16,9 @@ module Dapp
16
16
  @next_stage.prev_stage = self
17
17
  end
18
18
 
19
- # rubocop:disable Metrics/AbcSize
19
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
20
20
  def build!
21
- return if image.tagged? && !application.log_verbose?
21
+ return if should_be_skipped?
22
22
  prev_stage.build! if prev_stage
23
23
  begin
24
24
  if image.tagged?
@@ -33,8 +33,11 @@ module Dapp
33
33
  ensure
34
34
  log_build
35
35
  end
36
+ raise Exception::IntrospectImage,
37
+ message: application.t(code: 'introspect.stage', data: { name: name }),
38
+ data: { built_id: image.built_id, options: image.send(:prepared_options) } if should_be_introspected?
36
39
  end
37
- # rubocop:enable Metrics/AbcSize
40
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
38
41
 
39
42
  def save_in_cache!
40
43
  return if image.tagged?
@@ -65,13 +68,24 @@ module Dapp
65
68
  image.send(:bash_commands).empty?
66
69
  end
67
70
 
71
+ def should_be_skipped?
72
+ image.tagged? && !application.log_verbose? && application.cli_options[:introspect_stage].nil?
73
+ end
74
+
75
+ def should_be_introspected?
76
+ application.cli_options[:introspect_stage] == name && !application.dry_run?
77
+ end
78
+
68
79
  def image_build!
69
- image.build!(log_verbose: application.log_verbose?, log_time: application.log_time?)
80
+ image.build!(log_verbose: application.log_verbose?,
81
+ log_time: application.log_time?,
82
+ introspect_error: application.cli_options[:introspect_error],
83
+ introspect_before_error: application.cli_options[:introspect_before_error])
70
84
  end
71
85
 
72
86
  def from_image
73
87
  prev_stage.image if prev_stage || begin
74
- fail Error::Build, code: :from_image_required
88
+ raise Error::Build, code: :from_image_required
75
89
  end
76
90
  end
77
91
 
@@ -87,12 +101,13 @@ module Dapp
87
101
 
88
102
  def format_image_info
89
103
  date, bytesize = image_info
90
- application.t(code: 'image.info', data: { date: Time.parse(date).localtime, size: to_mb(bytesize.to_i)})
104
+ application.t(code: 'image.info', data: { date: Time.parse(date).localtime, size: to_mb(bytesize.to_i) })
91
105
  end
92
106
 
107
+ # rubocop:disable Metrics/AbcSize
93
108
  def log_build
94
109
  application.with_log_indent do
95
- application.log_info application.t(code: 'image.signature', data: { signature: image_name})
110
+ application.log_info application.t(code: 'image.signature', data: { signature: image_name })
96
111
  application.log_info format_image_info if image.tagged?
97
112
  unless (bash_commands = image.send(:bash_commands)).empty?
98
113
  application.log_info application.t(code: 'image.commands')
@@ -17,7 +17,7 @@ module Dapp
17
17
  protected
18
18
 
19
19
  def image_build!
20
- from_image.pull!(log_verbose: application.log_verbose?, log_time: application.log_time?)
20
+ from_image.pull!(log_time: application.log_time?)
21
21
  super
22
22
  end
23
23
 
@@ -28,7 +28,7 @@ module Dapp
28
28
  end
29
29
 
30
30
  def from_image
31
- StageImage.new(name: from_image_name)
31
+ @from_image ||= StageImage.new(name: from_image_name)
32
32
  end
33
33
 
34
34
  def image_info
@@ -17,29 +17,22 @@ module Dapp
17
17
  end
18
18
 
19
19
  def signature
20
- hashsum [super, *exposes]
20
+ hashsum [super, change_options]
21
21
  end
22
22
 
23
23
  def image
24
24
  super do |image|
25
- image.add_expose(exposes) unless exposes.empty?
26
- image.add_env(envs) unless envs.empty?
27
- image.add_workdir(workdir) unless workdir.nil?
25
+ change_options.each do |k, v|
26
+ next if v.nil? || v.empty?
27
+ image.public_send("add_change_#{k}", v)
28
+ end
28
29
  end
29
30
  end
30
31
 
31
32
  protected
32
33
 
33
- def exposes
34
- application.config._docker._expose
35
- end
36
-
37
- def envs
38
- application.config._docker._env
39
- end
40
-
41
- def workdir
42
- application.config._docker._workdir
34
+ def change_options
35
+ application.config._docker._change_options
43
36
  end
44
37
 
45
38
  def layers_commits_write!
@@ -26,14 +26,17 @@ module Dapp
26
26
 
27
27
  def image
28
28
  super do |image|
29
- if application.git_artifacts.any?
30
- image.add_volumes_from(gitartifact_container)
31
- image.add_commands 'export PATH=/.dapp/deps/gitartifact/bin:$PATH'
29
+ bash_commands = []
30
+ volumes = []
31
+ application.git_artifacts.each do |git_artifact|
32
+ volumes << "#{git_artifact.repo.dir_path}:#{git_artifact.repo.container_build_dir_path}"
33
+ bash_commands.concat(git_artifact.send(apply_command_method, self))
32
34
  end
33
35
 
34
- application.git_artifacts.each do |git_artifact|
35
- image.add_volume "#{git_artifact.repo.dir_path}:#{git_artifact.repo.container_build_dir_path}"
36
- image.add_commands git_artifact.send(apply_command_method, self)
36
+ unless bash_commands.empty?
37
+ image.add_volumes_from(gitartifact_container)
38
+ image.add_volume(volumes)
39
+ image.add_commands 'export PATH=/.dapp/deps/gitartifact/bin:$PATH', *bash_commands
37
40
  end
38
41
  yield image if block_given?
39
42
  end
@@ -61,7 +64,7 @@ module Dapp
61
64
 
62
65
  def gitartifact_container
63
66
  @gitartifact_container ||= begin
64
- if application.shellout("docker inspect #{gitartifact_container_name}").exitstatus != 0
67
+ if application.shellout("docker inspect #{gitartifact_container_name}").exitstatus.nonzero?
65
68
  application.log_secondary_process(application.t(code: 'process.git_artifact_loading'), short: true) do
66
69
  application.shellout ['docker run',
67
70
  '--restart=no',
@@ -9,35 +9,35 @@ module Dapp
9
9
  end
10
10
 
11
11
  def infra_install(_image)
12
- fail
12
+ raise
13
13
  end
14
14
 
15
15
  def infra_install_checksum
16
- fail
16
+ raise
17
17
  end
18
18
 
19
19
  def infra_setup(_image)
20
- fail
20
+ raise
21
21
  end
22
22
 
23
23
  def infra_setup_checksum
24
- fail
24
+ raise
25
25
  end
26
26
 
27
27
  def app_install(_image)
28
- fail
28
+ raise
29
29
  end
30
30
 
31
31
  def app_install_checksum
32
- fail
32
+ raise
33
33
  end
34
34
 
35
35
  def app_setup(_image)
36
- fail
36
+ raise
37
37
  end
38
38
 
39
39
  def app_setup_checksum
40
- fail
40
+ raise
41
41
  end
42
42
  end # Base
43
43
  end # Builder
@@ -4,6 +4,8 @@ module Dapp
4
4
  class CLI
5
5
  # CLI build subcommand
6
6
  class Build < Base
7
+ include Dapp::Helper::Shellout
8
+
7
9
  banner <<BANNER.freeze
8
10
  Version: #{Dapp::VERSION}
9
11
 
@@ -26,6 +28,31 @@ BANNER
26
28
  option :git_artifact_branch,
27
29
  long: '--git-artifact-branch BRANCH',
28
30
  description: 'Default branch to archive artifacts from'
31
+
32
+ option :introspect_error,
33
+ long: '--introspect-error',
34
+ boolean: true,
35
+ default: false
36
+
37
+ option :introspect_before_error,
38
+ long: '--introspect-before-error',
39
+ boolean: true,
40
+ default: false
41
+
42
+ option :introspect_stage,
43
+ long: '--introspect-stage STAGE',
44
+ proc: proc { |v| v.to_sym },
45
+ in: [nil, :from, :infra_install, :source_1_archive, :source_1, :app_install,
46
+ :source_2, :infra_setup, :source_3, :app_setup, :source_4, :source_5]
47
+
48
+ def run(*args)
49
+ super
50
+ rescue Exception::IntrospectImage => e
51
+ $stderr.puts(e.net_status[:message])
52
+ data = e.net_status[:data]
53
+ system("docker run -ti --rm #{data[:options]} #{data[:built_id]} bash")
54
+ shellout("docker rmi #{data[:built_id]}") if data[:rmi]
55
+ end
29
56
  end
30
57
  end
31
58
  end
@@ -49,6 +49,12 @@ BANNER
49
49
  description: 'Tag by git commit',
50
50
  boolean: true
51
51
 
52
+ option :force,
53
+ long: '--force',
54
+ description: 'Override existing image',
55
+ default: false,
56
+ boolean: true
57
+
52
58
  def run(argv = ARGV)
53
59
  self.class.parse_options(self, argv)
54
60
  repo = self.class.required_argument(self)
@@ -33,12 +33,12 @@ module Dapp
33
33
  end
34
34
 
35
35
  def chef
36
- fail Error::Config, code: :builder_type_conflict unless _builder == :chef
36
+ raise Error::Config, code: :builder_type_conflict unless _builder == :chef
37
37
  @_chef ||= Chef.new
38
38
  end
39
39
 
40
40
  def shell
41
- fail Error::Config, code: :builder_type_conflict unless _builder == :shell
41
+ raise Error::Config, code: :builder_type_conflict unless _builder == :shell
42
42
  @_shell ||= Shell.new
43
43
  end
44
44
 
@@ -51,7 +51,7 @@ module Dapp
51
51
  end
52
52
 
53
53
  def builder(type)
54
- fail Error::Config, code: :builder_type_unsupported, data: { type: type } unless [:chef, :shell].include?((type = type.to_sym))
54
+ raise Error::Config, code: :builder_type_unsupported, data: { type: type } unless [:chef, :shell].include?((type = type.to_sym))
55
55
  another_builder = [:chef, :shell].find { |t| t != type }
56
56
  instance_variable_set(:"@_#{another_builder}", Config.const_get(another_builder.capitalize).new)
57
57
  @_builder = type
@@ -2,12 +2,16 @@ module Dapp
2
2
  module Config
3
3
  # Docker
4
4
  class Docker
5
- attr_reader :_expose, :_workdir, :_env
5
+ attr_reader :_volume, :_expose, :_env, :_label, :_cmd, :_onbuild, :_workdir, :_user, :_entrypoint
6
6
  attr_reader :_from_cache_version
7
7
 
8
8
  def initialize
9
+ @_volume = []
9
10
  @_expose = []
10
11
  @_env = []
12
+ @_label = []
13
+ @_cmd = []
14
+ @_onbuild = []
11
15
  end
12
16
 
13
17
  def from(image_name, cache_version: nil)
@@ -15,20 +19,58 @@ module Dapp
15
19
  @_from_cache_version = cache_version
16
20
  end
17
21
 
18
- def expose(*args)
19
- @_expose.concat(args)
22
+ def volume(*args)
23
+ @_volume.concat(args)
20
24
  end
21
25
 
22
- def workdir(path)
23
- @_workdir = path
26
+ def expose(*args)
27
+ @_expose.concat(args)
24
28
  end
25
29
 
26
30
  def env(*args)
27
31
  @_env.concat(args)
28
32
  end
29
33
 
34
+ def label(*args)
35
+ @_label.concat(args)
36
+ end
37
+
38
+ def cmd(*args)
39
+ @_cmd.concat(args)
40
+ end
41
+
42
+ def onbuild(*args)
43
+ @_onbuild.concat(args)
44
+ end
45
+
46
+ def workdir(val)
47
+ @_workdir = val
48
+ end
49
+
50
+ def user(val)
51
+ @_user = val
52
+ end
53
+
54
+ def entrypoint(*cmd_with_args)
55
+ @_entrypoint = cmd_with_args.flatten
56
+ end
57
+
30
58
  def _from
31
- @_from || fail(Error::Config, code: :docker_from_not_defined)
59
+ @_from || raise(Error::Config, code: :docker_from_not_defined)
60
+ end
61
+
62
+ def _change_options
63
+ {
64
+ volume: _volume,
65
+ expose: _expose,
66
+ env: _env,
67
+ label: _label,
68
+ cmd: _cmd,
69
+ onbuild: _onbuild,
70
+ workdir: _workdir,
71
+ user: _user,
72
+ entrypoint: _entrypoint
73
+ }
32
74
  end
33
75
 
34
76
  def clone
@@ -31,8 +31,8 @@ module Dapp
31
31
  @_where_to_add = where_to_add
32
32
 
33
33
  options.each do |k, v|
34
- respond_to?("_#{k}=") ? send(:"_#{k}=", v) : fail(Error::Config, code: :git_artifact_unexpected_attribute,
35
- data: { type: object_name, attr: k })
34
+ respond_to?("_#{k}=") ? send(:"_#{k}=", v) : raise(Error::Config, code: :git_artifact_unexpected_attribute,
35
+ data: { type: object_name, attr: k })
36
36
  end
37
37
  end
38
38
 
@@ -6,7 +6,7 @@ module Dapp
6
6
 
7
7
  attr_reader :cli_options, :patterns
8
8
 
9
- def initialize(cli_options:, patterns: nil)
9
+ def initialize(cli_options: {}, patterns: nil)
10
10
  @cli_options = cli_options
11
11
  @cli_options[:log_indent] = 0
12
12
 
@@ -19,25 +19,25 @@ module Dapp
19
19
  end
20
20
 
21
21
  def build
22
- @build_confs.each do |build_conf|
22
+ build_confs.each do |build_conf|
23
23
  log_step(build_conf._name)
24
24
  with_log_indent { Application.new(config: build_conf, cli_options: cli_options).build! }
25
25
  end
26
26
  end
27
27
 
28
28
  def list
29
- @build_confs.each do |build_conf|
29
+ build_confs.each do |build_conf|
30
30
  log(build_conf._name)
31
31
  end
32
32
  end
33
33
 
34
34
  def push(repo)
35
- fail Error::Controller, code: :push_command_unexpected_apps unless @build_confs.one?
35
+ raise Error::Controller, code: :push_command_unexpected_apps unless @build_confs.one?
36
36
  Application.new(config: @build_confs.first, cli_options: cli_options, ignore_git_fetch: true).export!(repo)
37
37
  end
38
38
 
39
39
  def smartpush(repo_prefix)
40
- @build_confs.each do |build_conf|
40
+ build_confs.each do |build_conf|
41
41
  log_step(build_conf._name)
42
42
  repo = File.join(repo_prefix, build_conf._name)
43
43
  with_log_indent { Application.new(config: build_conf, cli_options: cli_options, ignore_git_fetch: true).export!(repo) }
@@ -45,7 +45,7 @@ module Dapp
45
45
  end
46
46
 
47
47
  def flush_build_cache
48
- @build_confs.each do |build_conf|
48
+ build_confs.each do |build_conf|
49
49
  log(build_conf._name)
50
50
  app = Application.new(config: build_conf, cli_options: cli_options, ignore_git_fetch: true)
51
51
  FileUtils.rm_rf app.build_cache_path
@@ -61,17 +61,13 @@ module Dapp
61
61
 
62
62
  def build_confs
63
63
  @build_confs ||= begin
64
- dappfiles = []
65
64
  if File.exist? dappfile_path
66
- dappfiles << dappfile_path
67
- elsif File.exist? dapps_path
68
- dappfiles += Dir.glob(File.join([dapps_path, '*', 'Dappfile'].compact))
69
- else
70
- fail Error::Controller, code: :dappfile_not_found
65
+ dappfiles = dappfile_path
66
+ elsif (dappfiles = dapps_dappfiles_pathes).empty? && (dappfiles = search_dappfile_up).nil?
67
+ raise Error::Controller, code: :dappfile_not_found
71
68
  end
72
- dappfiles.flatten.uniq!
73
- dappfiles.map { |dappfile| apps(dappfile, app_filters: patterns) }.flatten.tap do |apps|
74
- fail Error::Controller, code: :no_such_app, data: { path: dappfile_path, patterns: patterns.join(', ') } if apps.empty?
69
+ Array(dappfiles).map { |dappfile| apps(dappfile, app_filters: patterns) }.flatten.tap do |apps|
70
+ raise Error::Controller, code: :no_such_app, data: { path: dappfile_path, patterns: patterns.join(', ') } if apps.empty?
75
71
  end
76
72
  end
77
73
  end
@@ -84,11 +80,19 @@ module Dapp
84
80
  end
85
81
 
86
82
  def dappfile_path
87
- @dappfile_path ||= File.join [cli_options[:dir], 'Dappfile'].compact
83
+ File.join [cli_options[:dir], 'Dappfile'].compact
88
84
  end
89
85
 
90
- def dapps_path
91
- @dapps_path ||= File.join [cli_options[:dir], '.dapps'].compact
86
+ def dapps_dappfiles_pathes
87
+ Dir.glob(File.join([cli_options[:dir], '.dapps', '*', 'Dappfile'].compact))
88
+ end
89
+
90
+ def search_dappfile_up
91
+ cdir = Pathname(File.expand_path(cli_options[:dir] || Dir.pwd))
92
+ until (cdir = cdir.parent).root?
93
+ next unless (path = cdir.join('Dappfile')).exist?
94
+ return path.to_s
95
+ end
92
96
  end
93
97
 
94
98
  def paint_initialize
@@ -96,7 +100,7 @@ module Dapp
96
100
  when 'auto' then STDOUT.tty? ? 8 : 0
97
101
  when 'on' then 8
98
102
  when 'off' then 0
99
- else fail
103
+ else raise
100
104
  end
101
105
  end
102
106
  end # Controller
@@ -20,12 +20,12 @@ module Dapp
20
20
  end
21
21
 
22
22
  def untag!
23
- fail Error::Build, code: :image_already_untagged, data: { name: name } unless tagged?
23
+ raise Error::Build, code: :image_already_untagged, data: { name: name } unless tagged?
24
24
  shellout!("docker rmi #{name}")
25
25
  end
26
26
 
27
27
  def push!(log_verbose: false, log_time: false)
28
- fail Error::Build, code: :image_not_exist, data: { name: name } unless tagged?
28
+ raise Error::Build, code: :image_not_exist, data: { name: name } unless tagged?
29
29
  shellout!("docker push #{name}", log_verbose: log_verbose, log_time: log_time)
30
30
  end
31
31
 
@@ -44,7 +44,7 @@ module Dapp
44
44
  end
45
45
 
46
46
  def info
47
- fail Error::Build, code: :image_not_exist, data: { name: name } unless tagged?
47
+ raise Error::Build, code: :image_not_exist, data: { name: name } unless tagged?
48
48
  shellout!("docker inspect --format='{{.Created}} {{.Size}}' #{name}").stdout.strip.split
49
49
  end
50
50
  end # DockerImage
@@ -0,0 +1,10 @@
1
+ module Dapp
2
+ module Exception
3
+ # Base
4
+ class Base < NetStatus::Exception
5
+ def initialize(net_status = {})
6
+ super(net_status.merge(context: self.class.to_s.split('::').last.downcase))
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module Dapp
2
+ module Exception
3
+ # IntrospectImage
4
+ class IntrospectImage < Base; end
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ module Dapp
2
+ module Helper
3
+ # NetStatus
4
+ module NetStatus
5
+ def self.message(exception)
6
+ net_status = exception.net_status.net_status_normalize(context: exception.net_status.delete(:context))
7
+ net_status[:message] || [net_status[:error], net_status[:code]].compact.join(': ')
8
+ end
9
+ end
10
+ end # Helper
11
+ end # Dapp
@@ -13,7 +13,7 @@ module Dapp
13
13
 
14
14
  def paint_style(name)
15
15
  FORMAT[name].tap do |format|
16
- fail if format.nil?
16
+ raise if format.nil?
17
17
  end
18
18
  end
19
19
 
@@ -4,56 +4,87 @@ module Dapp
4
4
  def initialize(name:, built_id: nil, from: nil)
5
5
  @bash_commands = []
6
6
  @options = {}
7
+ @change_options = {}
7
8
  @container_name = SecureRandom.hex
8
9
  @built_id = built_id
9
10
  super(name: name, from: from)
10
11
  end
11
12
 
12
- def add_expose(value)
13
- add_option(:expose, value)
13
+ def add_change_volume(value)
14
+ add_change_option(:volume, value)
14
15
  end
15
16
 
16
- def add_volume(value)
17
- add_option(:volume, value)
17
+ def add_change_expose(value)
18
+ add_change_option(:expose, value)
18
19
  end
19
20
 
20
- def add_volumes_from(value)
21
- add_option(:'volumes-from', value)
21
+ def add_change_env(value)
22
+ add_change_option(:env, value)
23
+ end
24
+
25
+ def add_change_label(value)
26
+ add_change_option(:label, value)
27
+ end
28
+
29
+ def add_change_cmd(value)
30
+ add_change_option(:cmd, value)
31
+ end
32
+
33
+ def add_change_onbuild(value)
34
+ add_change_option(:onbuild, value)
35
+ end
36
+
37
+ def add_change_workdir(value)
38
+ add_change_option(:workdir, value)
39
+ end
40
+
41
+ def add_change_entrypoint(value)
42
+ add_change_option(:entrypoint, value)
43
+ end
44
+
45
+ def add_change_user(value)
46
+ add_change_option(:user, value)
22
47
  end
23
48
 
24
- def add_env(value)
25
- add_option(:env, value)
49
+ def add_volume(value)
50
+ add_option(:volume, value)
26
51
  end
27
52
 
28
- def add_workdir(value)
29
- add_option(:workdir, value)
53
+ def add_volumes_from(value)
54
+ add_option(:'volumes-from', value)
30
55
  end
31
56
 
32
57
  def add_commands(*commands)
33
- @bash_commands += commands.flatten
58
+ @bash_commands.concat(commands.flatten)
34
59
  end
35
60
 
36
61
  def built_id
37
62
  @built_id ||= id
38
63
  end
39
64
 
40
- def build!(log_verbose: false, log_time: false)
41
- run!(log_verbose: log_verbose, log_time: log_time)
42
- @built_id = commit!
43
- ensure
44
- shellout("docker rm #{container_name}")
65
+ def build!(**kvargs)
66
+ @built_id = if should_be_built?
67
+ begin
68
+ run!(**kvargs)
69
+ commit!
70
+ ensure
71
+ shellout("docker rm #{container_name}")
72
+ end
73
+ else
74
+ from.built_id
75
+ end
45
76
  end
46
77
 
47
- def export!(name, log_verbose: false, log_time: false)
78
+ def export!(name, log_verbose: false, log_time: false, force: false)
48
79
  image = self.class.new(built_id: built_id, name: name)
49
- image.tag!(log_verbose: log_verbose, log_time: log_time)
80
+ image.tag!(log_verbose: log_verbose, log_time: log_time, force: force)
50
81
  image.push!(log_verbose: log_verbose, log_time: log_time)
51
82
  image.untag!
52
83
  end
53
84
 
54
- def tag!(log_verbose: false, log_time: false)
55
- unless (existed_id = id).nil?
56
- fail Error::Build, code: :image_already_tagged if built_id != existed_id
85
+ def tag!(log_verbose: false, log_time: false, force: false)
86
+ if !(existed_id = id).nil? && !force
87
+ raise Error::Build, code: :another_image_already_tagged if built_id != existed_id
57
88
  return
58
89
  end
59
90
  shellout!("docker tag #{built_id} #{name}", log_verbose: log_verbose, log_time: log_time)
@@ -63,34 +94,61 @@ module Dapp
63
94
 
64
95
  attr_reader :container_name
65
96
  attr_reader :bash_commands
66
- attr_reader :options
97
+ attr_reader :options, :change_options
67
98
 
68
99
  def add_option(key, value)
69
- options[key] = (options[key].nil? ? value : (Array(options[key]) << value).flatten)
100
+ add_option_default(options, key, value)
101
+ end
102
+
103
+ def add_change_option(key, value)
104
+ add_option_default(change_options, key, value)
105
+ end
106
+
107
+ def add_option_default(hash, key, value)
108
+ hash[key] = (hash[key].nil? ? value : (Array(hash[key]) << value).flatten)
70
109
  end
71
110
 
72
- def run!(log_verbose: false, log_time: false)
73
- fail Error::Build, code: :built_id_not_defined if from.built_id.nil?
111
+ def run!(log_verbose: false, log_time: false, introspect_error: false, introspect_before_error: false)
112
+ raise Error::Build, code: :built_id_not_defined if from.built_id.nil?
74
113
  shellout!("docker run #{prepared_options} --name=#{container_name} #{from.built_id} #{prepared_bash_command}",
75
114
  log_verbose: log_verbose, log_time: log_time)
115
+ rescue Error::Shellout => e
116
+ raise unless introspect_error || introspect_before_error
117
+ built_id = introspect_error ? commit! : from.built_id
118
+ raise Exception::IntrospectImage, message: Dapp::Helper::NetStatus.message(e),
119
+ data: { built_id: built_id, options: prepared_options, rmi: introspect_error }
76
120
  end
77
121
 
78
122
  def commit!
79
- shellout!("docker commit #{container_name}").stdout.strip
123
+ shellout!("docker commit #{prepared_change} #{container_name}").stdout.strip
124
+ end
125
+
126
+ def should_be_built?
127
+ !(bash_commands.empty? && change_options.empty?)
80
128
  end
81
129
 
82
130
  def prepared_options
83
- options.map { |k, vals| Array(vals).map { |v| "--#{k}=#{v}" }.join(' ') }.join(' ')
131
+ prepared_options_default(options) { |k, vals| Array(vals).map { |v| "--#{k}=#{v}" }.join(' ') }
84
132
  end
85
133
 
86
- def prepared_bash_command
87
- if bash_commands.empty?
88
- 'true'
89
- else
90
- "bash -ec 'eval $(echo #{Base64.strict_encode64(prepared_commands.join(' && '))} | base64 --decode)'"
134
+ def prepared_change
135
+ prepared_options_default(change_options) do |k, vals|
136
+ if [:cmd, :entrypoint].include? k
137
+ %(-c '#{k.to_s.upcase} #{Array(vals)}')
138
+ else
139
+ Array(vals).map { |v| %(-c "#{k.to_s.upcase} #{v}") }.join(' ')
140
+ end
91
141
  end
92
142
  end
93
143
 
144
+ def prepared_options_default(hash)
145
+ hash.map { |k, vals| yield(k, vals) }.join(' ')
146
+ end
147
+
148
+ def prepared_bash_command
149
+ "bash -ec 'eval $(echo #{Base64.strict_encode64(prepared_commands.join(' && '))} | base64 --decode)'"
150
+ end
151
+
94
152
  def prepared_commands
95
153
  bash_commands.map { |command| command.gsub(/^[\ |;]*|[\ |;]*$/, '') } # strip [' ', ';']
96
154
  end
@@ -1,5 +1,5 @@
1
1
  # Version
2
2
  module Dapp
3
- VERSION = '0.1.5'.freeze
3
+ VERSION = '0.2.4'.freeze
4
4
  BUILD_CACHE_VERSION = 1
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Stolyarov
@@ -373,6 +373,8 @@ files:
373
373
  - lib/dapp/error/config.rb
374
374
  - lib/dapp/error/controller.rb
375
375
  - lib/dapp/error/shellout.rb
376
+ - lib/dapp/exception/base.rb
377
+ - lib/dapp/exception/introspect_image.rb
376
378
  - lib/dapp/filelock.rb
377
379
  - lib/dapp/git_artifact.rb
378
380
  - lib/dapp/git_repo/base.rb
@@ -381,6 +383,7 @@ files:
381
383
  - lib/dapp/helper/cli.rb
382
384
  - lib/dapp/helper/i18n.rb
383
385
  - lib/dapp/helper/log.rb
386
+ - lib/dapp/helper/net_status.rb
384
387
  - lib/dapp/helper/paint.rb
385
388
  - lib/dapp/helper/sha256.rb
386
389
  - lib/dapp/helper/shellout.rb