dapp 0.13.3 → 0.13.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/bin/dapp +0 -13
  3. data/config/en/common.yml +4 -2
  4. data/config/en/net_status.yml +15 -3
  5. data/lib/dapp.rb +11 -6
  6. data/lib/dapp/cli.rb +1 -1
  7. data/lib/dapp/cli/command/base.rb +4 -4
  8. data/lib/dapp/config/directive/base.rb +4 -2
  9. data/lib/dapp/core_ext/hash.rb +14 -0
  10. data/lib/dapp/dapp.rb +32 -6
  11. data/lib/dapp/dapp/dapp_config.rb +85 -0
  12. data/lib/dapp/dapp/dappfile.rb +4 -0
  13. data/lib/dapp/dapp/deps/base.rb +2 -2
  14. data/lib/dapp/dapp/deps/gitartifact.rb +2 -2
  15. data/lib/dapp/dapp/logging/base.rb +5 -5
  16. data/lib/dapp/dapp/logging/process.rb +5 -7
  17. data/lib/dapp/dapp/shellout/base.rb +16 -17
  18. data/lib/dapp/deployment/cli/command/deployment.rb +2 -3
  19. data/lib/dapp/deployment/dapp/command/apply.rb +6 -6
  20. data/lib/dapp/deployment/dapp/dapp.rb +0 -1
  21. data/lib/dapp/deployment/kube_app.rb +1 -1
  22. data/lib/dapp/deployment/kube_base.rb +1 -1
  23. data/lib/dapp/dimg/build/stage/artifact_base.rb +3 -8
  24. data/lib/dapp/dimg/build/stage/base.rb +57 -38
  25. data/lib/dapp/dimg/build/stage/docker_instructions.rb +1 -1
  26. data/lib/dapp/dimg/build/stage/from.rb +6 -2
  27. data/lib/dapp/dimg/build/stage/ga_archive_dependencies.rb +2 -2
  28. data/lib/dapp/dimg/build/stage/ga_artifact_patch.rb +1 -5
  29. data/lib/dapp/dimg/build/stage/ga_base.rb +1 -14
  30. data/lib/dapp/dimg/build/stage/ga_latest_patch.rb +7 -31
  31. data/lib/dapp/dimg/build/stage/ga_related_dependencies_base.rb +21 -0
  32. data/lib/dapp/dimg/build/stage/import_artifact.rb +10 -3
  33. data/lib/dapp/dimg/build/stage/install/ga_post_install_patch_dependencies.rb +3 -3
  34. data/lib/dapp/dimg/build/stage/install/ga_pre_install_patch_dependencies.rb +3 -3
  35. data/lib/dapp/dimg/build/stage/mod/group.rb +19 -7
  36. data/lib/dapp/dimg/build/stage/mod/logging.rb +7 -20
  37. data/lib/dapp/dimg/build/stage/setup/ga_post_setup_patch_dependencies.rb +1 -1
  38. data/lib/dapp/dimg/build/stage/setup/ga_pre_setup_patch_dependencies.rb +3 -3
  39. data/lib/dapp/dimg/builder/chef.rb +2 -2
  40. data/lib/dapp/dimg/builder/chef/cookbook.rb +2 -2
  41. data/lib/dapp/dimg/cli/command/dimg.rb +1 -1
  42. data/lib/dapp/dimg/cli/command/dimg/build.rb +15 -8
  43. data/lib/dapp/dimg/config/directive/artifact_base.rb +13 -4
  44. data/lib/dapp/dimg/config/directive/dimg/instance_methods.rb +1 -1
  45. data/lib/dapp/dimg/config/directive/dimg/validation.rb +6 -1
  46. data/lib/dapp/dimg/config/directive/docker/base.rb +1 -2
  47. data/lib/dapp/dimg/config/directive/git_artifact_local.rb +3 -0
  48. data/lib/dapp/dimg/config/directive/git_artifact_remote.rb +1 -1
  49. data/lib/dapp/dimg/config/directive/mount.rb +9 -1
  50. data/lib/dapp/dimg/dapp/command/build_context/export.rb +13 -15
  51. data/lib/dapp/dimg/dapp/command/build_context/import.rb +3 -3
  52. data/lib/dapp/dimg/dapp/command/cleanup.rb +1 -1
  53. data/lib/dapp/dimg/dapp/command/common.rb +17 -6
  54. data/lib/dapp/dimg/dapp/command/mrproper.rb +9 -4
  55. data/lib/dapp/dimg/dapp/command/stages/cleanup_local.rb +19 -17
  56. data/lib/dapp/dimg/dapp/command/stages/cleanup_repo.rb +1 -1
  57. data/lib/dapp/dimg/dimg.rb +5 -5
  58. data/lib/dapp/dimg/dimg/git_artifact.rb +11 -6
  59. data/lib/dapp/dimg/dimg/path.rb +2 -6
  60. data/lib/dapp/dimg/git_artifact.rb +118 -66
  61. data/lib/dapp/dimg/git_repo/base.rb +1 -1
  62. data/lib/dapp/dimg/git_repo/own.rb +1 -1
  63. data/lib/dapp/dimg/git_repo/remote.rb +23 -14
  64. data/lib/dapp/dimg/image/docker.rb +11 -11
  65. data/lib/dapp/dimg/image/scratch.rb +33 -9
  66. data/lib/dapp/dimg/image/stage.rb +3 -3
  67. data/lib/dapp/helper/cli.rb +8 -0
  68. data/lib/dapp/helper/tar.rb +31 -0
  69. data/lib/dapp/kube/cli/command/kube.rb +5 -4
  70. data/lib/dapp/kube/cli/command/kube/deploy.rb +5 -0
  71. data/lib/dapp/kube/cli/command/kube/minikube_setup.rb +13 -0
  72. data/lib/dapp/kube/cli/command/kube/{secret_file_encrypt.rb → secret_extract.rb} +3 -3
  73. data/lib/dapp/kube/cli/command/kube/secret_generate.rb +11 -1
  74. data/lib/dapp/kube/client.rb +1 -1
  75. data/lib/dapp/kube/client/error.rb +1 -1
  76. data/lib/dapp/kube/dapp/command/common.rb +29 -4
  77. data/lib/dapp/kube/dapp/command/deploy.rb +43 -21
  78. data/lib/dapp/kube/dapp/command/dismiss.rb +1 -1
  79. data/lib/dapp/{deployment → kube}/dapp/command/minikube_setup.rb +12 -12
  80. data/lib/dapp/kube/dapp/command/secret_extract.rb +46 -0
  81. data/lib/dapp/kube/dapp/command/secret_generate.rb +33 -4
  82. data/lib/dapp/kube/dapp/dapp.rb +3 -2
  83. data/lib/dapp/kube/error/kubernetes.rb +7 -0
  84. data/lib/dapp/kube/secret.rb +1 -1
  85. data/lib/dapp/version.rb +2 -2
  86. metadata +11 -7
  87. data/lib/dapp/deployment/cli/command/deployment/minikube_setup.rb +0 -13
  88. data/lib/dapp/kube/dapp/command/secret_file_encrypt.rb +0 -22
@@ -63,7 +63,7 @@ module Dapp
63
63
  @_git_artifact ||= GitArtifact.new(dapp: dapp)
64
64
  end
65
65
 
66
- [:build_dir, :tmp_dir].each do |mount_type|
66
+ [:build_dir, :tmp_dir, :custom_dir].each do |mount_type|
67
67
  define_method "_#{mount_type}_mount" do
68
68
  _mount.select { |m| m._type == mount_type }
69
69
  end
@@ -29,11 +29,16 @@ module Dapp
29
29
  elm.validate! if elm.respond_to?(:validate!)
30
30
  end
31
31
  end
32
+ _mount.map(&:_to).tap do |mounts_points|
33
+ mounts_points.each do |path|
34
+ raise Error::Config, code: :mount_duplicate_to, data: { path: path } if mounts_points.count(path) > 1
35
+ end
36
+ end
32
37
  end
33
38
 
34
39
  def validate_scratch_directives!
35
40
  directives = [[:_shell, :shell], [:_chef, :chef], [:_git_artifact, :git],
36
- [:_tmp_dir_mount, :mount], [:_build_dir_mount, :mount]]
41
+ [:_tmp_dir_mount, :mount], [:_build_dir_mount, :mount], [:_custom_dir_mount, :mount]]
37
42
  directives.each do |name, user_name|
38
43
  raise Error::Config,
39
44
  code: :scratch_unsupported_directive,
@@ -10,8 +10,7 @@ module Dapp
10
10
  sub_directive_eval do
11
11
  image = image.to_s
12
12
  raise(Error::Config, code: :docker_from_incorrect, data: { name: image }) unless ::Dapp::Dimg::Image::Docker.image_name?(image)
13
- raise(Error::Config, code: :docker_from_without_tag, data: { name: image }) unless image.include?(':')
14
- @_from = image
13
+ @_from = image.include?(':') ? image : [image, 'latest'].join(':')
15
14
  @_from_cache_version = cache_version
16
15
  end
17
16
  end
@@ -3,6 +3,9 @@ module Dapp
3
3
  module Config
4
4
  module Directive
5
5
  class GitArtifactLocal < ArtifactBase
6
+ def export(absolute_dir_path = '/', &blk)
7
+ super
8
+ end
6
9
  alias add export
7
10
  undef_method :export
8
11
 
@@ -13,7 +13,7 @@ module Dapp
13
13
  end
14
14
 
15
15
  def branch(value)
16
- sub_directive_eval { @_branch = value }
16
+ sub_directive_eval { @_branch = value.to_s }
17
17
  end
18
18
 
19
19
  def commit(value)
@@ -4,6 +4,7 @@ module Dapp
4
4
  module Directive
5
5
  class Mount < Base
6
6
  attr_reader :_to
7
+ attr_reader :_from
7
8
  attr_reader :_type
8
9
 
9
10
  def initialize(to, **kwargs, &blk)
@@ -21,8 +22,15 @@ module Dapp
21
22
  end
22
23
  end
23
24
 
25
+ def from_path(path)
26
+ sub_directive_eval do
27
+ @_from = path_format(path)
28
+ @_type = :custom_dir
29
+ end
30
+ end
31
+
24
32
  def validate!
25
- raise Error::Config, code: :mount_from_required if _type.nil?
33
+ raise Error::Config, code: :mount_from_or_from_path_required if _type.nil?
26
34
  end
27
35
  end
28
36
  end
@@ -20,27 +20,25 @@ module Dapp
20
20
  end.flatten
21
21
 
22
22
  log_secondary_process(:images, short: true) do
23
- Image::Docker.save!(context_images_names, build_context_images_tar)
23
+ Image::Docker.save!(context_images_names, build_context_images_tar, verbose: true, quiet: log_quiet?)
24
24
  end unless context_images_names.empty?
25
25
  end
26
26
  end
27
27
 
28
28
  def export_build_context_build_tar
29
29
  log_secondary_process(:build_dir, short: true) do
30
- File.open(build_context_build_tar, File::RDWR | File::CREAT) do |f|
31
- Gem::Package::TarWriter.new(f) do |tar|
32
- Dir.glob(File.join(build_path, '**/*'), File::FNM_DOTMATCH).each do |path|
33
- archive_file_path = path
34
- .reverse
35
- .chomp(build_path.to_s.reverse)
36
- .chomp('/')
37
- .reverse
38
- if File.directory?(path)
39
- tar.mkdir archive_file_path, File.stat(path).mode
40
- else
41
- tar.add_file archive_file_path, File.stat(path).mode do |tf|
42
- tf.write File.read(path)
43
- end
30
+ tar_write(build_context_build_tar) do |tar|
31
+ Dir.glob(File.join(build_path, '**/*'), File::FNM_DOTMATCH).each do |path|
32
+ archive_file_path = path
33
+ .reverse
34
+ .chomp(build_path.to_s.reverse)
35
+ .chomp('/')
36
+ .reverse
37
+ if File.directory?(path)
38
+ tar.mkdir archive_file_path, File.stat(path).mode
39
+ else
40
+ tar.add_file archive_file_path, File.stat(path).mode do |tf|
41
+ tf.write File.read(path)
44
42
  end
45
43
  end
46
44
  end
@@ -20,7 +20,7 @@ module Dapp
20
20
  if build_context_images_tar.exist?
21
21
  log_secondary_process(:images, short: true) do
22
22
  lock("#{name}.images") do
23
- Image::Docker.load!(build_context_images_tar)
23
+ Image::Docker.load!(build_context_images_tar, verbose: true, quiet: log_quiet?)
24
24
  end
25
25
  end
26
26
  else
@@ -33,8 +33,8 @@ module Dapp
33
33
  log_secondary_process(:build_dir, short: true) do
34
34
  store_current_build_dir
35
35
 
36
- File.open(build_context_build_tar, File::RDONLY) do |f|
37
- Gem::Package::TarReader.new(f).each_entry do |entry|
36
+ tar_read(build_context_build_tar) do |tar|
37
+ tar.each_entry do |entry|
38
38
  header = entry.header
39
39
  path = File.join(build_path, entry.full_name)
40
40
 
@@ -9,7 +9,7 @@ module Dapp
9
9
  dapp_containers_flush
10
10
  dapp_dangling_images_flush
11
11
  remove_images_by_query([
12
- 'docker images',
12
+ "#{host_docker_bin} images",
13
13
  %(--format '{{if ne "#{stage_cache}" .Repository }}{{.Repository}}:{{.Tag}}{{ end }}'),
14
14
  %(-f "label=dapp=#{stage_dapp_label}")
15
15
  ].join(' ')) # FIXME: negative filter is not currently supported by the Docker CLI
@@ -6,19 +6,19 @@ module Dapp
6
6
  protected
7
7
 
8
8
  def dapp_images_names
9
- shellout!(%(docker images --format="{{.Repository}}:{{.Tag}}" #{stage_cache})).stdout.lines.map(&:strip)
9
+ shellout!(%(#{host_docker_bin} images --format="{{.Repository}}:{{.Tag}}" #{stage_cache})).stdout.lines.map(&:strip)
10
10
  end
11
11
 
12
12
  def dapp_images_ids
13
- shellout!(%(docker images #{stage_cache} -q --no-trunc)).stdout.lines.map(&:strip)
13
+ shellout!(%(#{host_docker_bin} images #{stage_cache} -q --no-trunc)).stdout.lines.map(&:strip)
14
14
  end
15
15
 
16
16
  def dapp_containers_flush
17
- remove_containers_by_query(%(docker ps -a -f "label=dapp" -f "name=#{container_name_prefix}" -q), force: true)
17
+ remove_containers_by_query(%(#{host_docker_bin} ps -a -f "label=dapp" -f "name=#{container_name_prefix}" -q), force: true)
18
18
  end
19
19
 
20
20
  def dapp_dangling_images_flush
21
- remove_images_by_query(%(docker images -f "dangling=true" -f "label=dapp=#{stage_dapp_label}" -q), force: true)
21
+ remove_images_by_query(%(#{host_docker_bin} images -f "dangling=true" -f "label=dapp=#{stage_dapp_label}" -q), force: true)
22
22
  end
23
23
 
24
24
  def remove_images_by_query(images_query, force: false)
@@ -26,7 +26,18 @@ module Dapp
26
26
  end
27
27
 
28
28
  def remove_images(ids, force: false)
29
- remove_base('docker rmi%{force_option} %{ids}', ids.uniq, force: force)
29
+ ids.uniq!
30
+ check_user_containers!(ids) unless force
31
+ remove_base("#{host_docker_bin} rmi%{force_option} %{ids}", ids, force: force)
32
+ end
33
+
34
+ def check_user_containers!(images_ids)
35
+ return if images_ids.empty?
36
+ log_step_with_indent(:'check user containers') do
37
+ run_command(%(#{host_docker_bin} ps -a -q #{images_ids.uniq.map { |image_id| "--filter=ancestor=#{image_id}" }.join(' ')})).tap do |res|
38
+ raise Error::Command, code: :user_containers_detected, data: { ids: res.stdout.strip } if !res.stdout.strip.empty? && !dry_run?
39
+ end
40
+ end
30
41
  end
31
42
 
32
43
  def remove_containers_by_query(containers_query, force: false)
@@ -34,7 +45,7 @@ module Dapp
34
45
  end
35
46
 
36
47
  def remove_containers(ids, force: false)
37
- remove_base('docker rm%{force_option} %{ids}', ids.uniq, force: force)
48
+ remove_base("#{host_docker_bin} rm%{force_option} %{ids}", ids.uniq, force: force)
38
49
  end
39
50
 
40
51
  def remove_base(query_format, ids, force: false)
@@ -12,6 +12,7 @@ module Dapp
12
12
 
13
13
  if proper_all?
14
14
  flush_by_label('dapp')
15
+ remove_build_dir
15
16
  elsif proper_dev_mode_cache?
16
17
  flush_by_label('dapp-dev-mode')
17
18
  elsif proper_cache_version?
@@ -31,6 +32,10 @@ module Dapp
31
32
  log_step_with_indent(:images) { dapp_images_flush_by_label(label) }
32
33
  end
33
34
 
35
+ def remove_build_dir
36
+ log_step_with_indent(:build_dir) { FileUtils.rm_rf(build_path) }
37
+ end
38
+
34
39
  def proper_all?
35
40
  !!options[:proper_all]
36
41
  end
@@ -40,11 +45,11 @@ module Dapp
40
45
  end
41
46
 
42
47
  def dapp_containers_flush_by_label(label)
43
- remove_containers_by_query(%(docker ps -a -f "label=#{label}" -q), force: true)
48
+ remove_containers_by_query(%(#{host_docker_bin} ps -a -f "label=#{label}" -q), force: true)
44
49
  end
45
50
 
46
51
  def dapp_dangling_images_flush_by_label(label)
47
- remove_images_by_query(%(docker images -f "dangling=true" -f "label=#{label}" -q), force: true)
52
+ remove_images_by_query(%(#{host_docker_bin} images -f "dangling=true" -f "label=#{label}" -q), force: true)
48
53
  end
49
54
 
50
55
  def dapp_images_flush_by_label(label)
@@ -54,7 +59,7 @@ module Dapp
54
59
 
55
60
  def dapp_images_by_label(label)
56
61
  @dapp_images ||= begin
57
- shellout!(%(docker images -f "dangling=false" --format="{{.Repository}}:{{.Tag}}" -f "label=#{label}"))
62
+ shellout!(%(#{host_docker_bin} images -f "dangling=false" --format="{{.Repository}}:{{.Tag}}" -f "label=#{label}"))
58
63
  .stdout
59
64
  .lines
60
65
  .map(&:strip)
@@ -63,7 +68,7 @@ module Dapp
63
68
 
64
69
  def proper_cache_all_images
65
70
  shellout!([
66
- 'docker images',
71
+ "#{host_docker_bin} images",
67
72
  '--format="{{.Repository}}:{{.Tag}}"',
68
73
  %(-f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}" -f "dangling=false")
69
74
  ].join(' ')).stdout.lines.map(&:strip)
@@ -4,15 +4,15 @@ module Dapp
4
4
  module Command
5
5
  module Stages
6
6
  module CleanupLocal
7
- def stages_cleanup_local(repo)
8
- lock_repo(repo, readonly: true) do
7
+ def stages_cleanup_local
8
+ lock_repo(option_repo, readonly: true) do
9
9
  raise Error::Command, code: :stages_cleanup_required_option unless stages_cleanup_option?
10
10
 
11
11
  dapp_containers_flush
12
12
 
13
- proper_cache if proper_cache_version?
14
- stages_cleanup_by_repo(repo) if proper_repo_cache?
15
- proper_git_commit if proper_git_commit?
13
+ proper_cache if proper_cache_version?
14
+ stages_cleanup_by_repo if proper_repo_cache?
15
+ proper_git_commit if proper_git_commit?
16
16
  end
17
17
  end
18
18
 
@@ -28,8 +28,8 @@ module Dapp
28
28
  end
29
29
  end
30
30
 
31
- def stages_cleanup_by_repo(repo)
32
- registry = registry(repo)
31
+ def stages_cleanup_by_repo
32
+ registry = registry(option_repo)
33
33
  repo_dimgs = repo_dimgs_images(registry)
34
34
 
35
35
  lock("#{name}.images") do
@@ -49,16 +49,18 @@ module Dapp
49
49
  end
50
50
 
51
51
  def actual_cache_images
52
- shellout!([
53
- 'docker images',
54
- '--format="{{.Repository}}:{{.Tag}}"',
55
- %(-f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}"),
56
- stage_cache
57
- ].join(' ')).stdout.lines.map(&:strip)
52
+ @actual_cache_images ||= begin
53
+ shellout!([
54
+ "#{host_docker_bin} images",
55
+ '--format="{{.Repository}}:{{.Tag}}"',
56
+ %(-f "label=dapp-cache-version=#{::Dapp::BUILD_CACHE_VERSION}"),
57
+ stage_cache
58
+ ].join(' ')).stdout.lines.map(&:strip)
59
+ end
58
60
  end
59
61
 
60
62
  def dapp_images_hash
61
- shellout!(%(docker images --format "{{.Repository}}:{{.Tag}};{{.ID}}" --no-trunc #{stage_cache})).stdout.lines.map do |line|
63
+ shellout!(%(#{host_docker_bin} images --format "{{.Repository}}:{{.Tag}};{{.ID}}" --no-trunc #{stage_cache})).stdout.lines.map do |line|
62
64
  line.strip.split(';')
63
65
  end.to_h
64
66
  end
@@ -77,7 +79,7 @@ module Dapp
77
79
  end
78
80
 
79
81
  def image_exist?(image_id)
80
- shellout!(%(docker inspect #{image_id}))
82
+ shellout!(%(#{host_docker_bin} inspect #{image_id}))
81
83
  true
82
84
  rescue ::Dapp::Error::Shellout
83
85
  false
@@ -88,7 +90,7 @@ module Dapp
88
90
  end
89
91
 
90
92
  def image_parent(image_id)
91
- shellout!(%(docker inspect -f {{.Parent}} #{image_id})).stdout.strip
93
+ shellout!(%(#{host_docker_bin} inspect -f {{.Parent}} #{image_id})).stdout.strip
92
94
  end
93
95
 
94
96
  def proper_git_commit
@@ -107,7 +109,7 @@ module Dapp
107
109
  def dapp_images_detailed
108
110
  @dapp_images_detailed ||= {}.tap do |images|
109
111
  dapp_images_names.each do |image_name|
110
- shellout!(%(docker inspect --format='{{json .}}' #{image_name})).stdout.strip.tap do |output|
112
+ shellout!(%(#{host_docker_bin} inspect --format='{{json .}}' #{image_name})).stdout.strip.tap do |output|
111
113
  images[image_name] = output == 'null' ? {} : JSON.parse(output)
112
114
  end
113
115
  end
@@ -112,7 +112,7 @@ module Dapp
112
112
 
113
113
  def remove_repo_images(registry, tags)
114
114
  tags.each do |tag|
115
- log(tag) if dry_run? || log_verbose?
115
+ log(tag) if log_verbose? || dry_run?
116
116
  registry.image_delete(tag) unless dry_run?
117
117
  end
118
118
  end
@@ -122,7 +122,7 @@ module Dapp
122
122
  end
123
123
 
124
124
  def run(docker_options, command)
125
- cmd = "docker run #{[docker_options, last_stage.image.built_id, command].flatten.compact.join(' ')}"
125
+ cmd = "#{dapp.host_docker_bin} run #{[docker_options, last_stage.image.built_id, command].flatten.compact.join(' ')}"
126
126
  if dapp.dry_run?
127
127
  dapp.log(cmd)
128
128
  else
@@ -159,7 +159,7 @@ module Dapp
159
159
  end
160
160
 
161
161
  def introspect_image!(image:, options:)
162
- cmd = "docker run -ti --rm --entrypoint #{dapp.bash_bin} #{options} #{image}"
162
+ cmd = "#{dapp.host_docker_bin} run -ti --rm --entrypoint #{dapp.bash_bin} #{options} #{image}"
163
163
  system(cmd)
164
164
  end
165
165
 
@@ -169,9 +169,9 @@ module Dapp
169
169
  # Чтобы от них избавиться — запускаем docker-контейнер под root-пользователем
170
170
  # и удаляем примонтированную tmp-директорию.
171
171
  cmd = "".tap do |cmd|
172
- cmd << "docker run --rm"
173
- cmd << " --volume #{tmp_base_dir}:#{tmp_base_dir}"
174
- cmd << " ubuntu:16.04"
172
+ cmd << "#{dapp.host_docker_bin} run --rm"
173
+ cmd << " --volume #{dapp.tmp_base_dir}:#{dapp.tmp_base_dir}"
174
+ cmd << " alpine:3.6"
175
175
  cmd << " rm -rf #{tmp_path}"
176
176
  end
177
177
  dapp.shellout! cmd
@@ -7,17 +7,22 @@ module Dapp
7
7
  end
8
8
 
9
9
  def local_git_artifacts
10
- @local_git_artifact_list ||= Array(config._git_artifact._local).map do |ga_config|
10
+ @local_git_artifact_list ||= begin
11
11
  repo = GitRepo::Own.new(self)
12
- ::Dapp::Dimg::GitArtifact.new(repo, **ga_config._artifact_options)
12
+ Array(config._git_artifact._local).map do |ga_config|
13
+ ::Dapp::Dimg::GitArtifact.new(repo, **ga_config._artifact_options)
14
+ end
13
15
  end
14
16
  end
15
17
 
16
18
  def remote_git_artifacts
17
- @remote_git_artifact_list ||= Array(config._git_artifact._remote).map do |ga_config|
18
- repo = GitRepo::Remote.new(self, ga_config._name, url: ga_config._url)
19
- repo.fetch!(ga_config._branch)
20
- ::Dapp::Dimg::GitArtifact.new(repo, **ga_config._artifact_options)
19
+ @remote_git_artifact_list ||= begin
20
+ repos = {}
21
+ Array(config._git_artifact._remote).map do |ga_config|
22
+ repo_key = [ga_config._url, ga_config._branch]
23
+ repos[repo_key] ||= GitRepo::Remote.new(self, ga_config._name, url: ga_config._url).tap { |repo| repo.fetch!(ga_config._branch) }
24
+ ::Dapp::Dimg::GitArtifact.new(repos[repo_key], **ga_config._artifact_options)
25
+ end
21
26
  end
22
27
  end
23
28
  end # GitArtifact
@@ -6,17 +6,13 @@ module Dapp
6
6
  dapp.path(*path).expand_path
7
7
  end
8
8
 
9
- def tmp_base_dir
10
- File.expand_path(dapp.options[:tmp_dir_prefix] || '/tmp')
11
- end
12
-
13
9
  def tmp_path(*path)
14
- @tmp_path ||= Dir.mktmpdir('dapp-', tmp_base_dir)
10
+ @tmp_path ||= Dir.mktmpdir('dapp-', dapp.tmp_base_dir)
15
11
  make_path(@tmp_path, *path).expand_path.tap { |p| p.parent.mkpath }
16
12
  end
17
13
 
18
14
  def build_path(*path)
19
- make_path(dapp.build_path, *path).expand_path.tap { |p| p.parent.mkpath }
15
+ dapp.build_path(*path).expand_path.tap { |p| p.parent.mkpath }
20
16
  end
21
17
 
22
18
  def container_dapp_path(*path)
@@ -2,6 +2,8 @@ module Dapp
2
2
  module Dimg
3
3
  # Git repo artifact
4
4
  class GitArtifact
5
+ include Helper::Tar
6
+
5
7
  attr_reader :repo
6
8
  attr_reader :name
7
9
 
@@ -31,45 +33,61 @@ module Dapp
31
33
 
32
34
  [].tap do |commands|
33
35
  commands << "#{repo.dimg.dapp.install_bin} #{credentials.join(' ')} -d #{to}"
34
- if any_changes?(nil, stage.layer_commit(self))
35
- commands << "#{sudo}#{repo.dimg.dapp.tar_bin} -xf #{archive_file(stage.layer_commit(self))} -C #{to}"
36
+ if archive_any_changes?(stage)
37
+ commands << "#{sudo}#{repo.dimg.dapp.tar_bin} -xf #{archive_file(*archive_stage_commits(stage))} -C #{to}"
36
38
  end
37
39
  end
38
40
  end
39
41
 
40
42
  def apply_patch_command(stage)
41
- patch_command(stage.prev_g_a_stage.layer_commit(self), stage.layer_commit(self))
42
- end
43
-
44
- def apply_dev_patch_command(stage)
45
- patch_command(stage.prev_g_a_stage.layer_commit(self), nil)
43
+ [].tap do |commands|
44
+ if dev_mode?
45
+ if any_changes?(*dev_patch_stage_commits(stage))
46
+ changed_files = diff_patches(*dev_patch_stage_commits(stage)).map {|p| File.join(to, cwd, p.delta.new_file[:path])}
47
+ commands << "#{sudo}#{repo.dimg.dapp.rm_bin} -rf #{changed_files.join(' ')}"
48
+ commands << "#{sudo}#{repo.dimg.dapp.tar_bin} -xf #{archive_file(*dev_patch_stage_commits(stage))} -C #{to}"
49
+ end
50
+ else
51
+ if patch_any_changes?(stage)
52
+ commands << "#{sudo}#{repo.dimg.dapp.git_bin} apply --whitespace=nowarn --directory=#{to} --unsafe-paths #{patch_file(*patch_stage_commits(stage))}"
53
+ end
54
+ end
55
+ end
46
56
  end
47
57
 
48
58
  def stage_dependencies_checksum(stage)
49
59
  return [] if (stage_dependencies = stages_dependencies[stage.name]).empty?
50
60
 
51
61
  paths = (include_paths(true) + base_paths(stage_dependencies, true)).uniq
62
+ to_commit = dev_mode? ? nil : latest_commit
52
63
 
53
- to_commit = if repo.is_a? GitRepo::Own and repo.dimg.dev_mode?
54
- nil
55
- else
56
- latest_commit
57
- end
64
+ stage_dependencies_key = [stage.name, to_commit]
65
+ @stage_dependencies_checksums ||= {}
66
+ @stage_dependencies_checksums[stage_dependencies_key] = begin
67
+ if @stage_dependencies_checksums.key?(stage_dependencies_key)
68
+ @stage_dependencies_checksums[stage_dependencies_key]
69
+ else
70
+ if (patches = diff_patches(nil, to_commit, paths: paths)).empty?
71
+ repo.dimg.dapp.log_warning(desc: { code: :stage_dependencies_not_found,
72
+ data: { repo: repo.respond_to?(:url) ? repo.url : 'local',
73
+ dependencies: stage_dependencies.join(', ') } })
74
+ end
58
75
 
59
- diff_patches(nil, to_commit, paths: paths)
60
- .sort_by {|patch| patch.delta.new_file[:path]}
61
- .reduce(nil) {|prev_hash, patch|
62
- Digest::SHA256.hexdigest [
63
- prev_hash,
64
- patch.delta.new_file[:path],
65
- patch.delta.new_file[:mode].to_s,
66
- patch.to_s
67
- ].compact.join(':::')
68
- }
76
+ patches.sort_by {|patch| patch.delta.new_file[:path]}
77
+ .reduce(nil) {|prev_hash, patch|
78
+ Digest::SHA256.hexdigest [
79
+ prev_hash,
80
+ patch.delta.new_file[:path],
81
+ patch.delta.new_file[:mode].to_s,
82
+ patch.to_s
83
+ ].compact.join(':::')
84
+ }
85
+ end
86
+ end
69
87
  end
70
88
 
71
- def patch_size(from, to)
72
- diff_patches(from, to).reduce(0) do |bytes, patch|
89
+ def patch_size(from_commit, to_commit)
90
+ diff_patches(from_commit, to_commit).reduce(0) do |bytes, patch|
73
91
  patch.hunks.each do |hunk|
74
92
  hunk.lines.each do |l|
75
93
  bytes +=
@@ -85,8 +103,13 @@ module Dapp
85
103
  end
86
104
  end
87
105
 
88
- def dev_patch_hash(stage)
89
- Digest::SHA256.hexdigest diff_patches(stage.prev_g_a_stage.layer_commit(self), nil).map(&:to_s).join(':::')
106
+ def dev_patch_hash
107
+ return unless dev_mode?
108
+
109
+ Digest::SHA256.hexdigest(diff_patches(latest_commit, nil).map do |patch|
110
+ next unless (path = repo.path.dirname.join(patch.delta.new_file[:path])).file?
111
+ File.read(path)
112
+ end.join(':::'))
90
113
  end
91
114
 
92
115
  def latest_commit
@@ -101,8 +124,12 @@ module Dapp
101
124
  "#{repo.name}#{name ? "_#{name}" : nil}"
102
125
  end
103
126
 
104
- def any_changes?(from, to = latest_commit)
105
- diff_patches(from, to).any?
127
+ def archive_any_changes?(stage)
128
+ any_changes?(*archive_stage_commits(stage))
129
+ end
130
+
131
+ def patch_any_changes?(stage)
132
+ any_changes?(*patch_stage_commits(stage))
106
133
  end
107
134
 
108
135
  protected
@@ -115,35 +142,34 @@ module Dapp
115
142
  attr_reader :group
116
143
  attr_reader :stages_dependencies
117
144
 
118
- def patch_command(prev_commit, current_commit)
119
- [].tap do |commands|
120
- if any_changes?(prev_commit, current_commit)
121
- commands << "#{sudo}#{repo.dimg.dapp.git_bin} apply --whitespace=nowarn --directory=#{to} --unsafe-paths " \
122
- "#{patch_file(prev_commit, current_commit)}"
123
- end
124
- end
125
- end
126
-
127
145
  def sudo
128
146
  repo.dimg.dapp.sudo_command(owner: owner, group: group)
129
147
  end
130
148
 
131
- def archive_file(to_commit)
132
- create_file(repo.dimg.tmp_path('archives', archive_file_name(to_commit))) do |f|
133
- Gem::Package::TarWriter.new(f) do |tar|
134
- diff_patches(nil, to_commit).each do |patch|
135
- entry = patch.delta.new_file
136
- if entry[:mode] == 40960 # symlink
137
- tar.add_symlink slice_cwd(entry[:path]), repo.lookup_object(entry[:oid]).content, entry[:mode]
149
+ def archive_file(from_commit, to_commit)
150
+ tar_write(repo.dimg.tmp_path('archives', archive_file_name(from_commit, to_commit))) do |tar|
151
+ diff_patches(from_commit, to_commit).each do |patch|
152
+ entry = patch.delta.new_file
153
+
154
+ content = begin
155
+ if to_commit == nil
156
+ next unless (path = repo.path.dirname.join(entry[:path])).file?
157
+ File.read(path)
138
158
  else
139
- tar.add_file slice_cwd(entry[:path]), entry[:mode] do |tf|
140
- tf.write repo.lookup_object(entry[:oid]).content
141
- end
159
+ repo.lookup_object(entry[:oid]).content
160
+ end
161
+ end
162
+
163
+ if entry[:mode] == 40960 # symlink
164
+ tar.add_symlink slice_cwd(entry[:path]), content, entry[:mode]
165
+ else
166
+ tar.add_file slice_cwd(entry[:path]), entry[:mode] do |tf|
167
+ tf.write content
142
168
  end
143
169
  end
144
170
  end
145
171
  end
146
- repo.dimg.container_tmp_path('archives', archive_file_name(to_commit))
172
+ repo.dimg.container_tmp_path('archives', archive_file_name(from_commit, to_commit))
147
173
  rescue Gem::Package::TooLongFileName => e
148
174
  raise Error::TarWriter, message: e.message
149
175
  end
@@ -156,15 +182,15 @@ module Dapp
156
182
  .reverse
157
183
  end
158
184
 
159
- def archive_file_name(commit)
160
- file_name(commit, 'tar')
185
+ def archive_file_name(from_commit, to_commit)
186
+ file_name(from_commit, to_commit, 'tar')
161
187
  end
162
188
 
163
- def patch_file(from, to)
164
- create_file(repo.dimg.tmp_path('patches', patch_file_name(from, to))) do |f|
165
- diff_patches(from, to).each { |patch| f.write change_patch_new_file_path(patch) }
189
+ def patch_file(from_commit, to_commit)
190
+ File.open(repo.dimg.tmp_path('patches', patch_file_name(from_commit, to_commit)), File::RDWR | File::CREAT) do |f|
191
+ diff_patches(from_commit, to_commit).each { |patch| f.write change_patch_new_file_path(patch) }
166
192
  end
167
- repo.dimg.container_tmp_path('patches', patch_file_name(from, to))
193
+ repo.dimg.container_tmp_path('patches', patch_file_name(from_commit, to_commit))
168
194
  end
169
195
 
170
196
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
@@ -209,23 +235,25 @@ module Dapp
209
235
  patch.delta.old_file[:mode] != patch.delta.new_file[:mode]
210
236
  end
211
237
 
212
- def patch_file_name(from, to)
213
- file_name(from, to, 'patch')
238
+ def patch_file_name(from_commit, to_commit)
239
+ file_name(from_commit, to_commit, 'patch')
214
240
  end
215
241
 
216
242
  def file_name(*args, ext)
217
- "#{[full_name, args].flatten.join('_')}.#{ext}"
243
+ "#{[paramshash, args].flatten.compact.join('_')}.#{ext}"
218
244
  end
219
245
 
220
- def create_file(file_path, &blk)
221
- File.open(file_path, File::RDWR | File::CREAT, &blk)
222
- end
223
-
224
- def diff_patches(from, to, paths: include_paths_or_cwd)
225
- (@diff_patches ||= {})[[from, to, paths]] ||= repo.patches(from, to,
226
- paths: paths,
227
- exclude_paths: exclude_paths(true),
228
- force_text: true)
246
+ def diff_patches(from_commit, to_commit, paths: include_paths_or_cwd)
247
+ (@diff_patches ||= {})[[from_commit, to_commit, paths]] ||= begin
248
+ options = {}.tap do |opts|
249
+ opts[:force_text] = true
250
+ if dev_mode?
251
+ opts[:include_untracked] = true
252
+ opts[:recurse_untracked_dirs] = true
253
+ end
254
+ end
255
+ repo.patches(from_commit, to_commit, paths: paths, exclude_paths: exclude_paths(true), **options)
256
+ end
229
257
  end
230
258
 
231
259
  def include_paths_or_cwd
@@ -257,6 +285,30 @@ module Dapp
257
285
  .reverse
258
286
  end
259
287
  end
288
+
289
+ def archive_stage_commits(stage)
290
+ [nil, stage.layer_commit(self)]
291
+ end
292
+
293
+ def patch_stage_commits(stage)
294
+ [stage.prev_g_a_stage.layer_commit(self), stage.layer_commit(self)]
295
+ end
296
+
297
+ def dev_patch_stage_commits(stage)
298
+ [stage.prev_g_a_stage.layer_commit(self), nil]
299
+ end
300
+
301
+ def any_changes?(from_commit, to_commit)
302
+ diff_patches(from_commit, to_commit).any?
303
+ end
304
+
305
+ def dev_mode?
306
+ local? && repo.dimg.dev_mode?
307
+ end
308
+
309
+ def local?
310
+ repo.is_a? GitRepo::Own
311
+ end
260
312
  end
261
313
  end
262
314
  end