dapp 0.25.8 → 0.26.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fce0f6b6791bf4fba6bd882e3563b1b57272f452
4
- data.tar.gz: 344cfd21cf25a679ba1176b785ce2122d4673bcb
3
+ metadata.gz: f76da5bbcfb8d6dfe619a3070e565706c5fe3687
4
+ data.tar.gz: a3d24e6ac82d6112decf07c48e9fdf6aafcafab0
5
5
  SHA512:
6
- metadata.gz: fb9f90a3add54f6f4ec82490de02f9a47355af1ba91af60b50bc8b67fe9e394ae0a33e5a4e0c88ee08809d6fe56928f266756964097f6957ed964f5476f25ac8
7
- data.tar.gz: 2901374544207c428ce7dd926cc0760d195784a7a6338c0dbefe5833bd2b758ae1c4904d8c273ca8b14d227054310fdc899c3654a38c0b7f2dc6edf2db0f6874
6
+ metadata.gz: 361cf09b363732b5adde9a230e8f0ec895508067a34e6f41bb47a8daacacc35245b0328471230fd0c27767258dfa8d07f14f4b09ef03c1df506bac9b47481cdb
7
+ data.tar.gz: a25004f9b889e24acd5ce052c8565c1510f0eab6faaea03e36406077e763d3e8c676dfeae4002ea0fb396bf39ee11da8988652daeb4867bf581f4c1eb2faff8f
data/bin/dapp CHANGED
@@ -28,10 +28,6 @@ begin
28
28
  $stderr.puts "\033[1m\033[90mStacktrace dumped to #{filename}\033[0m"
29
29
  end
30
30
 
31
- if Dapp::CLI.dapp_object
32
- Dapp::CLI.dapp_object.sentry_exception(e)
33
- end
34
-
35
31
  raise
36
32
  end
37
33
  rescue Dapp::Error::Shellout => e
data/config/en/common.yml CHANGED
@@ -61,7 +61,6 @@ en:
61
61
  introspect_image_impossible: "WARNING: You can't introspect stage `%{name}`!"
62
62
  stage_dependencies_not_found: "WARNING: Stage dependencies `%{dependencies}` haven't been found in repo `%{repo}`!"
63
63
  unsupported_dapp_config_options: "WARNING: .dapp_config includes unsupported options [%{options}]: use only following options [%{supported_options}]"
64
- secret_key_dappfile_not_found: "WARNING: Project root directory can't be initialized: Dappfile not found!"
65
64
  group:
66
65
  install: 'Install group'
67
66
  setup: 'Setup group'
@@ -48,7 +48,7 @@ en:
48
48
  dapp:
49
49
  no_such_dimg: "No such dimg: `%{dimgs_patterns}`!"
50
50
  no_such_app: "No such app: `%{apps_patterns}`!"
51
- dappfile_not_found: "Dappfile not found!"
51
+ dappfile_not_found: "dappfile.yml, dappfile.yaml or Dappfile not found!"
52
52
  cannot_run_ssh_agent: "Can't run ssh-agent!"
53
53
  ssh_key_not_found: "Ssh key `%{path}` doesn't exist!"
54
54
  docker_not_found: "Docker not found!"
@@ -60,6 +60,7 @@ en:
60
60
  incorrect_dapp_config_option_color: ".dapp_config includes option `color` with incorrect value `%{value}`: expected one of the following values [%{expected}]"
61
61
  ci_environment_required: 'CI environment required (Travis or GitLab CI)!'
62
62
  git_branch_without_name: "Dimg has specific revision that isn't associated with a branch name!"
63
+ download_failed_bad_dappfile_yml_checksum: "Cannot download dappfile-yml binary dependency from %{url}: checksum validation failed"
63
64
  config:
64
65
  dimg_name_required: 'Dimg name required!'
65
66
  dimg_name_incorrect: "Dimg has incorrect name `%{value}`: doesn't match regex `%{pattern}`!"
data/lib/dapp.rb CHANGED
@@ -26,8 +26,8 @@ require 'zlib'
26
26
  require 'slugify'
27
27
  require 'base64'
28
28
  require 'io/console'
29
- require 'sentry-raven'
30
- require 'toml-rb'
29
+ require 'net/http'
30
+ require 'progressbar'
31
31
 
32
32
  require 'dapp/version'
33
33
  require 'dapp/core_ext/hash'
@@ -38,7 +38,6 @@ require 'dapp/helper/sha256'
38
38
  require 'dapp/helper/net_status'
39
39
  require 'dapp/helper/tar'
40
40
  require 'dapp/helper/yaml'
41
- require 'dapp/helper/url'
42
41
  require 'dapp/prctl'
43
42
  require 'dapp/error/mod/user'
44
43
  require 'dapp/error/base'
@@ -59,7 +58,6 @@ require 'dapp/config/directive/base'
59
58
  require 'dapp/config/config'
60
59
  require 'dapp/dapp/lock'
61
60
  require 'dapp/dapp/ssh_agent'
62
- require 'dapp/dapp/sentry'
63
61
  require 'dapp/dapp/git_artifact'
64
62
  require 'dapp/dapp/dappfile'
65
63
  require 'dapp/dapp/chef'
@@ -273,6 +271,7 @@ require 'dapp/dimg/dimg/path'
273
271
  require 'dapp/dimg/dimg/stages'
274
272
  require 'dapp/dimg/dimg'
275
273
  require 'dapp/dimg/artifact'
274
+ require 'dapp/downloader'
276
275
 
277
276
  module Dapp
278
277
  def self.root
data/lib/dapp/cli.rb CHANGED
@@ -38,10 +38,6 @@ BANNER
38
38
  show_options: true,
39
39
  exit: 0
40
40
 
41
- class << self
42
- attr_accessor :dapp_object
43
- end
44
-
45
41
  def initialize(*args)
46
42
  super(*args)
47
43
 
@@ -58,8 +58,6 @@ module Dapp
58
58
 
59
59
  def run_dapp_command(run_method, options: {}, log_running_time: true, try_host_docker_login: false)
60
60
  dapp = ::Dapp::Dapp.new(options: options)
61
- ::Dapp::CLI.dapp_object = dapp
62
- dapp.sentry_message("Manual usage: `#{options[:dapp_command]}` command") unless ENV['CI']
63
61
 
64
62
  log_dapp_running_time(dapp, ignore: !log_running_time) do
65
63
  begin
@@ -76,10 +74,6 @@ module Dapp
76
74
  end
77
75
  end
78
76
 
79
- def run_method
80
- class_to_lowercase
81
- end
82
-
83
77
  def log_dapp_running_time(dapp, ignore: false)
84
78
  return yield if ignore
85
79
 
@@ -101,7 +95,7 @@ module Dapp
101
95
  self.class.print_error_with_help_and_die! self, "cannot use alias options --run-dir, --build-dir, --deploy-dir at the same time"
102
96
  end
103
97
 
104
- config.merge(build_dir: dirs.compact.first, dapp_command: run_method, **kwargs)
98
+ config.merge(build_dir: dirs.compact.first, **kwargs)
105
99
  end
106
100
  end
107
101
  end
@@ -12,6 +12,13 @@ module Dapp
12
12
  _clone
13
13
  end
14
14
 
15
+ def encode_with(coder)
16
+ (instance_variables - [:@dapp]).each do |var|
17
+ var = var.to_s
18
+ coder[var.gsub('@', '')] = instance_variable_get(var)
19
+ end
20
+ end
21
+
15
22
  protected
16
23
 
17
24
  attr_reader :dapp
data/lib/dapp/dapp.rb CHANGED
@@ -17,13 +17,10 @@ module Dapp
17
17
  include Logging::Paint
18
18
 
19
19
  include SshAgent
20
- include Sentry
21
-
22
20
  include Helper::Sha256
23
- extend Helper::Trivia
21
+ extend Helper::Trivia
24
22
  include Helper::Trivia
25
23
  include Helper::Tar
26
- include Helper::Url
27
24
 
28
25
  include Deps::Toolchain
29
26
  include Deps::Gitartifact
@@ -46,18 +43,6 @@ module Dapp
46
43
  self.class.options
47
44
  end
48
45
 
49
- def settings
50
- @settings ||= begin
51
- settings_path = File.join(self.class.home_dir, "settings.toml")
52
-
53
- if File.exists? settings_path
54
- TomlRB.load_file(settings_path)
55
- else
56
- {}
57
- end
58
- end
59
- end
60
-
61
46
  def name
62
47
  @name ||= begin
63
48
  n = begin
@@ -98,8 +83,12 @@ module Dapp
98
83
  nil
99
84
  end
100
85
 
86
+ def work_dir
87
+ File.expand_path(options[:dir] || Dir.pwd)
88
+ end
89
+
101
90
  def path(*path)
102
- @path ||= expand_path(dappfile_path)
91
+ @path ||= make_path(work_dir)
103
92
  make_path(@path, *path)
104
93
  end
105
94
 
@@ -107,8 +96,8 @@ module Dapp
107
96
  self.class.tmp_base_dir
108
97
  end
109
98
 
110
- def build_dir
111
- @build_dir ||= begin
99
+ def build_path(*path)
100
+ @build_path ||= begin
112
101
  if option_build_dir
113
102
  Pathname.new(option_build_dir)
114
103
  else
@@ -116,10 +105,7 @@ module Dapp
116
105
  Pathname.new(dir)
117
106
  end.expand_path.tap(&:mkpath)
118
107
  end
119
- end
120
-
121
- def build_path(*path)
122
- make_path(build_dir, *path)
108
+ make_path(@build_path, *path)
123
109
  end
124
110
 
125
111
  def local_git_artifact_exclude_paths(&blk)
@@ -1,58 +1,150 @@
1
1
  module Dapp
2
2
  class Dapp
3
3
  module Dappfile
4
+ module Error
5
+ class DappfileYmlErrorResponse < ::Dapp::Error::Default
6
+ def initialize(error_code, response)
7
+ net_status = {}
8
+ net_status[:code] = error_code
9
+ net_status[:message] = response["message"] if response["message"]
10
+ super(net_status)
11
+ end
12
+ end
13
+ end
14
+
4
15
  def local_git_artifact_exclude_paths(&blk)
5
16
  super do |exclude_paths|
6
17
  exclude_paths << 'Dappfile'
18
+ exclude_paths << "dappfile.yml"
19
+ exclude_paths << "dappfile.yaml"
7
20
 
8
21
  yield exclude_paths if block_given?
9
22
  end
10
23
  end
11
24
 
12
- def dappfile_exists?
13
- !!search_file_upward('Dappfile')
14
- end
15
-
16
- def dappfile_path
17
- raise Error::Dapp, code: :dappfile_not_found unless (dappfile_path = search_file_upward('Dappfile'))
18
- dappfile_path
19
- end
20
-
21
- def work_dir
22
- File.expand_path(options[:dir] || Dir.pwd)
23
- end
24
-
25
25
  def expand_path(path, number = 1)
26
26
  path = File.expand_path(path)
27
27
  number.times.each { path = File.dirname(path) }
28
28
  path
29
29
  end
30
30
 
31
+ def dappfile_exists?
32
+ File.exist?(path("dappfile.yml")) ||
33
+ File.exist?(path("dappfile.yaml")) ||
34
+ File.exist?(path("Dappfile")) ||
35
+ ENV["DAPP_LOAD_CONFIG_PATH"]
36
+ end
37
+
31
38
  def config
32
39
  @config ||= begin
33
- ::Dapp::Config::Config.new(dapp: self).tap do |config|
34
- begin
35
- config.instance_eval File.read(dappfile_path), dappfile_path
36
- config.after_parsing!
37
- config.validate!
38
- rescue SyntaxError, StandardError => e
39
- backtrace = e.backtrace.find { |line| line.start_with?(dappfile_path) }
40
- message = begin
41
- case e
42
- when NoMethodError
43
- e.message =~ /`.*'/
44
- "undefined method #{Regexp.last_match}"
45
- when NameError then e.message[/.*(?= for)/]
46
- else
47
- e.message
48
- end
40
+ config = nil
41
+
42
+ dappfile_yml = path("dappfile.yml").to_s
43
+ dappfile_yaml = path("dappfile.yaml").to_s
44
+ dappfile_ruby = path("Dappfile").to_s
45
+
46
+ if ENV["DAPP_LOAD_CONFIG_PATH"]
47
+ config = YAML.load_file ENV["DAPP_LOAD_CONFIG_PATH"]
48
+ elsif File.exist? dappfile_yml
49
+ config = load_dappfile_yml(dappfile_yml)
50
+ elsif File.exist? dappfile_yaml
51
+ config = load_dappfile_yml(dappfile_yaml)
52
+ elsif File.exist? dappfile_ruby
53
+ config = load_dappfile_ruby(dappfile_ruby)
54
+ else
55
+ raise ::Dapp::Error::Dapp, code: :dappfile_not_found
56
+ end
57
+
58
+ if ENV["DAPP_DUMP_CONFIG"]
59
+ puts "-- DAPP_DUMP_CONFIG BEGIN"
60
+ puts YAML.dump(config)
61
+ puts "-- DAPP_DUMP_CONFIG END"
62
+ end
63
+
64
+ config
65
+ end # begin
66
+ end
67
+
68
+ def load_dappfile_ruby(dappfile_path)
69
+ ::Dapp::Config::Config.new(dapp: self).tap do |config|
70
+ begin
71
+ config.instance_eval File.read(dappfile_path), dappfile_path
72
+ config.after_parsing!
73
+ config.validate!
74
+ rescue SyntaxError, StandardError => e
75
+ backtrace = e.backtrace.find { |line| line.start_with?(dappfile_path) }
76
+ message = begin
77
+ case e
78
+ when NoMethodError
79
+ e.message =~ /`.*'/
80
+ "undefined method #{Regexp.last_match}"
81
+ when NameError then e.message[/.*(?= for)/]
82
+ else
83
+ e.message
49
84
  end
50
- message = "#{backtrace[/.*(?=:in)/]}: #{message}" if backtrace
51
- raise Error::Dappfile, code: :incorrect, data: { error: e.class.name, message: message }
52
85
  end
86
+ message = "#{backtrace[/.*(?=:in)/]}: #{message}" if backtrace
87
+ raise ::Dapp::Error::Dappfile, code: :incorrect, data: { error: e.class.name, message: message }
88
+ end # begin-rescue
89
+ end
90
+ end
91
+
92
+ def load_dappfile_yml(dappfile_path)
93
+ if dappfile_yml_bin_path = ENV["DAPP_BIN_DAPPFILE_YML"]
94
+ unless File.exists? dappfile_yml_bin_path
95
+ raise ::Dapp::Error::Dapp, code: :dappfile_yml_bin_path_not_found, data: {path: dappfile_yml_bin_path}
96
+ end
97
+ else
98
+ dappfile_yml_bin_path = File.join(::Dapp::Dapp.home_dir, "bin", "dappfile-yml", ::Dapp::VERSION, "dappfile-yml")
99
+ unless File.exists? dappfile_yml_bin_path
100
+ download_dappfile_yml_bin(dappfile_yml_bin_path)
53
101
  end
54
102
  end
103
+
104
+ cmd_res = shellout "#{dappfile_yml_bin_path} -dappfile #{dappfile_path}"
105
+
106
+ raw_json_response = nil
107
+ if cmd_res.exitstatus == 0
108
+ raw_json_response = cmd_res.stdout
109
+ elsif cmd_res.exitstatus == 16
110
+ raw_json_response = cmd_res.stderr
111
+ else
112
+ shellout_cmd_should_succeed! cmd_res
113
+ end
114
+
115
+ response = JSON.parse(raw_json_response)
116
+
117
+ raise ::Dapp::Dapp::Error::DappfileYmlErrorResponse.new(response["error"], response) if response["error"]
118
+
119
+ YAML.load response["dappConfig"]
120
+ end
121
+
122
+ def download_dappfile_yml_bin(dappfile_yml_bin_path)
123
+ lock("downloader.bin.dappfile-yml", default_timeout: 1800) do
124
+ return if File.exists? dappfile_yml_bin_path
125
+
126
+ log_process("Downloading dappfile-yml dapp dependency") do
127
+ # FIXME use flant repo
128
+ location = URI("https://dl.bintray.com/diafour/dapp/#{::Dapp::VERSION}/dappfile-yml")
129
+
130
+ tmp_bin_path = File.join(self.class.tmp_base_dir, "dappfile-yml-#{SecureRandom.uuid}")
131
+ ::Dapp::Downloader.download(location, tmp_bin_path, show_progress: true, progress_titile: dappfile_yml_bin_path)
132
+
133
+ checksum_location = URI("https://dl.bintray.com/diafour/dapp/#{::Dapp::VERSION}/dappfile-yml.sha")
134
+ tmp_bin_checksum_path = tmp_bin_path + ".checksum"
135
+ ::Dapp::Downloader.download(checksum_location, tmp_bin_checksum_path)
136
+
137
+ if Digest::SHA256.hexdigest(File.read(tmp_bin_path)) != File.read(tmp_bin_checksum_path).strip
138
+ raise ::Dapp::Error::Dapp, code: :download_failed_bad_dappfile_yml_checksum, data: {url: location.to_s, checksum_url: checksum_location.to_s}
139
+ end
140
+
141
+ File.chmod(0755, tmp_bin_path)
142
+ FileUtils.mkdir_p File.dirname(dappfile_yml_bin_path)
143
+ FileUtils.mv tmp_bin_path, dappfile_yml_bin_path
144
+ end # log_process
145
+ end # lock
55
146
  end
147
+
56
148
  end # Dappfile
57
149
  end # Dapp
58
150
  end # Dapp
@@ -7,12 +7,6 @@ module Dapp
7
7
 
8
8
  def tags_by_scheme
9
9
  @tags_by_scheme_name ||= begin
10
- if slug_tags[:custom].any?
11
- if settings.fetch("sentry", {}).fetch("detect-push-tag-usage", false)
12
- sentry_message("--tag or --tag-slug usage detected", extra: {"slug_tags" => slug_tags})
13
- end
14
- end
15
-
16
10
  {}.tap do |tags_by_scheme|
17
11
  [slug_tags, branch_tags, ci_tags].each do |_tags_by_scheme|
18
12
  _tags_by_scheme.each do |scheme, tags|
@@ -95,4 +89,4 @@ module Dapp
95
89
  end
96
90
  end # Tags
97
91
  end # Dapp
98
- end # Dapp
92
+ end # Dapp
@@ -189,10 +189,8 @@ module Dapp
189
189
  commits[git_artifact] ||= begin
190
190
  if image.built?
191
191
  image.labels[dimg.dapp.dimgstage_g_a_commit_label(git_artifact.paramshash)]
192
- elsif g_a_stage? && !empty?
192
+ else
193
193
  git_artifact.latest_commit
194
- elsif prev_stage
195
- prev_stage.layer_commit(git_artifact)
196
194
  end
197
195
  end
198
196
  end
@@ -10,7 +10,7 @@ module Dapp
10
10
  image.add_volume "#{dimg.tmp_path('patches')}:#{dimg.container_tmp_path('patches')}:ro"
11
11
 
12
12
  dimg.git_artifacts.each do |git_artifact|
13
- image.add_service_change_label(dimg.dapp.dimgstage_g_a_commit_label(git_artifact.paramshash).to_sym => layer_commit(git_artifact))
13
+ image.add_service_change_label(dimg.dapp.dimgstage_g_a_commit_label(git_artifact.paramshash).to_sym => git_artifact.latest_commit)
14
14
  image.add_command git_artifact.send(apply_command_method, self)
15
15
  end
16
16
  end
@@ -28,9 +28,7 @@ module Dapp
28
28
  private
29
29
 
30
30
  def commit_list
31
- dimg.git_artifacts
32
- .select { |ga| ga.repo.commit_exists?(prev_stage.layer_commit(ga)) && ga.patch_any_changes?(self) }
33
- .map(&method(:layer_commit))
31
+ dimg.git_artifacts.map { |git_artifact| layer_commit(git_artifact) }
34
32
  end
35
33
 
36
34
  def git_artifacts_dev_patch_hashes
@@ -9,6 +9,10 @@ module Dapp::Dimg::CLI
9
9
  self.class.parse_options(self, argv)
10
10
  run_dapp_command(run_method, options: cli_options(dimgs_patterns: cli_arguments))
11
11
  end
12
+
13
+ def run_method
14
+ class_to_lowercase
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -4,8 +4,6 @@ module Dapp
4
4
  module Directive
5
5
  class Dimg < Base
6
6
  module Validation
7
- include Helper::Trivia
8
-
9
7
  def validate!
10
8
  directives_validate!
11
9
  validate_scratch!
@@ -140,13 +138,29 @@ module Dapp
140
138
  end
141
139
 
142
140
  def validate_artifact!(verifiable_artifact, artifact)
143
- cases = []
144
- cases << verifiable_artifact[:include_paths].any? do |verifiable_path|
145
- !ignore_path?(verifiable_path, paths: artifact[:include_paths], exclude_paths: artifact[:exclude_paths])
141
+ verifiable_artifact[:include_paths].each do |verifiable_path|
142
+ potential_conflicts = artifact[:include_paths].select { |path| path.start_with?(verifiable_path) }
143
+ validate_artifact_path!(verifiable_artifact, potential_conflicts)
144
+ end
145
+
146
+ if verifiable_artifact[:include_paths].empty?
147
+ if artifact[:include_paths].empty? || verifiable_artifact[:exclude_paths].empty?
148
+ raise ::Dapp::Error::Config, code: :artifact_conflict
149
+ else
150
+ validate_artifact_path!(verifiable_artifact, artifact[:include_paths])
151
+ end
146
152
  end
147
- cases << (verifiable_artifact[:include_paths].empty? && artifact[:include_paths].empty?)
153
+ end
148
154
 
149
- raise ::Dapp::Error::Config, code: :artifact_conflict if cases.any?
155
+ def validate_artifact_path!(verifiable_artifact, potential_conflicts)
156
+ raise ::Dapp::Error::Config, code: :artifact_conflict unless begin
157
+ potential_conflicts.all? do |path|
158
+ loop do
159
+ break if verifiable_artifact[:exclude_paths].include?(path) || ((path = File.dirname(path)) == '.')
160
+ end
161
+ verifiable_artifact[:exclude_paths].include?(path)
162
+ end
163
+ end
150
164
  end
151
165
 
152
166
  def _associated_artifacts
@@ -3,13 +3,14 @@ module Dapp
3
3
  module Config
4
4
  module Directive
5
5
  class GitArtifactRemote < GitArtifactLocal
6
- include ::Dapp::Helper::Url
7
-
8
6
  attr_reader :_url, :_name, :_branch, :_commit
9
7
 
10
8
  def initialize(url, **kwargs, &blk)
11
9
  @_url = url
12
- @_name = git_url_to_name(url)
10
+
11
+ url_without_scheme = url.split("://", 2).last
12
+ url_without_creds = url_without_scheme.split(":", 2).last
13
+ @_name = url_without_creds.gsub(%r{.*?([^\/ ]+\/[^\/ ]+)\.git}, '\\1')
13
14
 
14
15
  super(**kwargs, &blk)
15
16
  end
@@ -189,8 +189,6 @@ module Dapp
189
189
  end
190
190
 
191
191
  def cleanup_tmp
192
- return unless tmp_dir_exists?
193
-
194
192
  # В tmp-директории могли остаться файлы, владельцами которых мы не являемся.
195
193
  # Такие файлы могут попасть туда при экспорте файлов артефакта.
196
194
  # Чтобы от них избавиться — запускаем docker-контейнер под root-пользователем
@@ -6,10 +6,6 @@ module Dapp
6
6
  dapp.path(*path).expand_path
7
7
  end
8
8
 
9
- def tmp_dir_exists?
10
- @tmp_path != nil
11
- end
12
-
13
9
  def tmp_path(*path)
14
10
  @tmp_path ||= Dir.mktmpdir('dapp-', dapp.tmp_base_dir)
15
11
  make_path(@tmp_path, *path).expand_path.tap { |p| p.parent.mkpath }
@@ -35,6 +35,7 @@ module Dapp
35
35
  end
36
36
 
37
37
  def image_delete(tag)
38
+ image_blobs(tag).each { |hash| blob_delete(hash.values.first) }
38
39
  api_request(repo_suffix, "/manifests/#{image_digest(tag)}",
39
40
  method: :delete,
40
41
  expects: [202, 404],
@@ -53,6 +54,10 @@ module Dapp
53
54
  headers: { Accept: 'application/vnd.docker.distribution.manifest.v2+json' }).headers['Docker-Content-Digest']
54
55
  end
55
56
 
57
+ def image_blobs(tag)
58
+ manifest_v1(tag)['fsLayers']
59
+ end
60
+
56
61
  def manifest_v1(tag)
57
62
  api_request(repo_suffix, "/manifests/#{tag}")
58
63
  end
@@ -62,6 +67,11 @@ module Dapp
62
67
  headers: { Accept: 'application/vnd.docker.distribution.manifest.v2+json' })
63
68
  end
64
69
 
70
+ def blob_delete(id)
71
+ api_request(repo_suffix, "/blobs/#{id}",
72
+ method: :delete, expects: [202, 404])
73
+ end
74
+
65
75
  def api_request(*uri, **options)
66
76
  JSON.load(raw_api_request(*uri, **options).body)
67
77
  end
@@ -121,7 +121,7 @@ module Dapp
121
121
  last_part_path = path_parts.shift
122
122
  test_path = [test_path, last_part_path].compact.join('/')
123
123
 
124
- non_match = !File.fnmatch(test_path, embedded_rel_path, File::FNM_PATHNAME|File::FNM_DOTMATCH)
124
+ non_match = !File.fnmatch(test_path, embedded_rel_path, File::FNM_PATHNAME)
125
125
  part_for_all = (last_part_path == '**')
126
126
 
127
127
  if non_match || part_for_all
@@ -104,12 +104,12 @@ module Dapp
104
104
 
105
105
  def patches(from, to, paths: [], exclude_paths: [], **kwargs)
106
106
  diff(from, to, **kwargs).patches.select do |patch|
107
- !ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
107
+ ignore_patch?(patch, paths: paths, exclude_paths: exclude_paths)
108
108
  end
109
109
  end
110
110
 
111
111
  def ignore_patch?(patch, paths: [], exclude_paths: [])
112
- ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
112
+ !ignore_path?(patch.delta.new_file[:path], paths: paths, exclude_paths: exclude_paths)
113
113
  end
114
114
 
115
115
  def entries(commit, paths: [], exclude_paths: [])
@@ -227,6 +227,22 @@ module Dapp
227
227
  paths.empty? || paths.any? { |p| check_path?(path, p) || check_subpath?(path, p) }
228
228
  end
229
229
  end
230
+
231
+ def ignore_path?(path, paths: [], exclude_paths: [])
232
+ ignore_path_base(path, exclude_paths: exclude_paths) do
233
+ paths.empty? ||
234
+ paths.any? do |p|
235
+ File.fnmatch?(p, path, File::FNM_PATHNAME) ||
236
+ File.fnmatch?(File.join(p, '**', '*'), path, File::FNM_PATHNAME)
237
+ end
238
+ end
239
+ end
240
+
241
+ def ignore_path_base(path, exclude_paths: [])
242
+ is_exclude_path = exclude_paths.any? { |p| check_path?(path, p) }
243
+ is_include_path = yield
244
+ is_exclude_path || !is_include_path
245
+ end
230
246
  end
231
247
  end
232
248
  end
@@ -48,9 +48,9 @@ module Dapp
48
48
  delta_new_file = patch.delta.new_file
49
49
  args = [delta_new_file[:path], paths: paths, exclude_paths: exclude_paths]
50
50
  if nested_git_repository_mode?(delta_new_file[:mode])
51
- ignore_directory?(*args)
51
+ !ignore_directory?(*args)
52
52
  else
53
- ignore_path?(*args)
53
+ !ignore_path?(*args)
54
54
  end
55
55
  end
56
56
 
@@ -0,0 +1,117 @@
1
+ module Dapp
2
+ module Downloader
3
+ module Error
4
+ class DownloadFailed < ::Exception
5
+ end
6
+ end
7
+
8
+ class BytesCount
9
+ attr_reader :bytes, :total_bytes_count
10
+
11
+ def initialize(bytes, total_bytes_count: nil)
12
+ @bytes = bytes.to_f
13
+ @total_bytes_count = total_bytes_count
14
+ end
15
+
16
+ def to_s(*a)
17
+ max_bytes = @total_bytes_count || self
18
+ width = sprintf("%.2f", max_bytes.bytes/1024/1024).bytesize
19
+ sprintf("%#{width}.2f", @bytes/1024/1024)
20
+ end
21
+
22
+ [:+, :-, :*, :/].each do |method|
23
+ define_method(method) do |arg|
24
+ res = case arg
25
+ when BytesCount
26
+ @bytes.send(method, arg.bytes)
27
+ else
28
+ @bytes.send(method, arg)
29
+ end
30
+ self.class.new(res, total_bytes_count: total_bytes_count)
31
+ end
32
+ end
33
+
34
+ [:>, :<, :==].each do |method|
35
+ define_method(method) do |arg|
36
+ case arg
37
+ when BytesCount
38
+ @bytes.send(method, arg.bytes)
39
+ else
40
+ @bytes.send(method, arg)
41
+ end
42
+ end
43
+ end
44
+
45
+ def method_missing(method, *args, &blk)
46
+ case method
47
+ when :to_f, :to_i
48
+ @bytes.send(method, *args, &blk)
49
+ else
50
+ raise
51
+ end
52
+ end
53
+ end # BytesCount
54
+
55
+ class << self
56
+ def download(url, destination, show_progress: false, progress_titile: nil)
57
+ resp = nil
58
+ location = URI(url)
59
+ done = false
60
+ state = {}
61
+
62
+ loop do
63
+ Net::HTTP.start(location.host, location.port, use_ssl: true) do |http|
64
+ req = Net::HTTP::Get.new location
65
+ http.request req do |resp|
66
+ case resp
67
+ when Net::HTTPRedirection
68
+ location = URI(resp["location"])
69
+ next
70
+ when Net::HTTPSuccess
71
+ File.open(destination, "wb") do |file|
72
+ file_size_bytes = nil
73
+ file_size_bytes = BytesCount.new(resp.to_hash["content-length"].first.to_f) if show_progress
74
+
75
+ if show_progress
76
+ old_DEFAULT_BEGINNING_POSITION = ProgressBar::Progress.send(:remove_const, :DEFAULT_BEGINNING_POSITION)
77
+ ProgressBar::Progress.send(:const_set, :DEFAULT_BEGINNING_POSITION, BytesCount.new(0, total_bytes_count: file_size_bytes))
78
+ end
79
+
80
+ begin
81
+ progressbar = nil
82
+ progressbar = ProgressBar.create(
83
+ format: " %cMB / %CMB %B %t",
84
+ starting_at: BytesCount.new(0, total_bytes_count: file_size_bytes),
85
+ total: file_size_bytes,
86
+ progress_mark: "#",
87
+ remainder_mark: ".",
88
+ title: progress_titile,
89
+ length: 100,
90
+ autofinish: true
91
+ ) if show_progress
92
+
93
+ resp.read_body do |segment|
94
+ progressbar.progress = progressbar.progress + segment.bytesize if show_progress
95
+ file.write segment
96
+ end
97
+ ensure
98
+ if show_progress
99
+ ProgressBar::Progress.send(:remove_const, :DEFAULT_BEGINNING_POSITION)
100
+ ProgressBar::Progress.send(:const_set, :DEFAULT_BEGINNING_POSITION, old_DEFAULT_BEGINNING_POSITION)
101
+ end
102
+ end
103
+ end # File.open
104
+
105
+ done = true
106
+ else
107
+ raise Error::DownloadFailed, "Failed to download #{url}: #{resp.code} #{resp.message}"
108
+ end # when
109
+ end # http.request
110
+ end # Net::HTTP.start
111
+
112
+ break if done
113
+ end # loop
114
+ end
115
+ end
116
+ end # Downloader
117
+ end # Dapp
@@ -28,28 +28,12 @@ module Dapp
28
28
  Pathname.new(File.join(base.to_s, *path.compact.map(&:to_s)))
29
29
  end
30
30
 
31
- def ignore_path?(path, paths: [], exclude_paths: [])
32
- ignore_path_base(path, exclude_paths: exclude_paths) do
33
- paths.empty? ||
34
- paths.any? do |p|
35
- File.fnmatch?(p, path, File::FNM_PATHNAME|File::FNM_DOTMATCH) ||
36
- File.fnmatch?(File.join(p, '**', '*'), path, File::FNM_PATHNAME|File::FNM_DOTMATCH)
37
- end
38
- end
39
- end
40
-
41
- def ignore_path_base(path, exclude_paths: [])
42
- is_exclude_path = exclude_paths.any? { |p| check_path?(path, p) }
43
- is_include_path = yield
44
- is_exclude_path || !is_include_path
45
- end
46
-
47
31
  def check_path?(path, format)
48
- path_checker(path) { |checking_path| File.fnmatch(format, checking_path, File::FNM_PATHNAME|File::FNM_DOTMATCH) }
32
+ path_checker(path) { |checking_path| File.fnmatch(format, checking_path, File::FNM_PATHNAME) }
49
33
  end
50
34
 
51
35
  def check_subpath?(path, format)
52
- path_checker(format) { |checking_path| File.fnmatch(checking_path, path, File::FNM_PATHNAME|File::FNM_DOTMATCH) }
36
+ path_checker(format) { |checking_path| File.fnmatch(checking_path, path, File::FNM_PATHNAME) }
53
37
  end
54
38
 
55
39
  def path_checker(path)
@@ -321,15 +321,11 @@ image: {{ tuple $name $context | include "_dimg2" }}
321
321
  unless (secret_key = ENV['DAPP_SECRET_KEY'])
322
322
  secret_key_not_found_in << '`DAPP_SECRET_KEY`'
323
323
 
324
- if dappfile_exists?
325
- file_path = path('.dapp_secret_key')
326
- if file_path.file?
327
- secret_key = path('.dapp_secret_key').read.chomp
328
- else
329
- secret_key_not_found_in << "`#{file_path}`"
330
- end
324
+ file_path = path('.dapp_secret_key')
325
+ if file_path.file?
326
+ secret_key = path('.dapp_secret_key').read.chomp
331
327
  else
332
- log_warning(desc: { code: :secret_key_dappfile_not_found })
328
+ secret_key_not_found_in << "`#{file_path}`"
333
329
  end
334
330
  end
335
331
 
@@ -162,7 +162,6 @@ module Dapp
162
162
  # Поэтому перехватываем и просто отображаем произошедшую
163
163
  # ошибку для информации пользователю без завершения работы dapp.
164
164
  $stderr.puts(::Dapp::Dapp.paint_string(::Dapp::Helper::NetStatus.message(e), :warning))
165
- sentry_exception(e, extra: {"job-spec" => job.spec})
166
165
  end
167
166
 
168
167
  end # Thread
@@ -13,8 +13,8 @@ module Dapp
13
13
  template_relative_path_pattern = Pathname(File.expand_path(template_path_pattern)).subpath_of(path('.helm'))
14
14
  template_relative_path_pattern ||= template_path_pattern
15
15
 
16
- File.fnmatch?(template_relative_path_pattern, template_path_without_chart_name, File::FNM_PATHNAME|File::FNM_DOTMATCH) ||
17
- File.fnmatch?(template_relative_path_pattern, template_path, File::FNM_PATHNAME|File::FNM_DOTMATCH)
16
+ File.fnmatch?(template_relative_path_pattern, template_path_without_chart_name, File::FNM_PATHNAME) ||
17
+ File.fnmatch?(template_relative_path_pattern, template_path, File::FNM_PATHNAME)
18
18
  end
19
19
  end
20
20
  else
data/lib/dapp/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Dapp
2
- VERSION = "0.25.8"
3
- BUILD_CACHE_VERSION = 26.2
2
+ VERSION = "0.26.1"
3
+ BUILD_CACHE_VERSION = 26
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.25.8
4
+ version: 0.26.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Stolyarov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-16 00:00:00.000000000 Z
11
+ date: 2018-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-shellout
@@ -187,33 +187,19 @@ dependencies:
187
187
  - !ruby/object:Gem::Version
188
188
  version: 1.0.6
189
189
  - !ruby/object:Gem::Dependency
190
- name: sentry-raven
190
+ name: progressbar
191
191
  requirement: !ruby/object:Gem::Requirement
192
192
  requirements:
193
193
  - - "~>"
194
194
  - !ruby/object:Gem::Version
195
- version: 2.7.2
195
+ version: 1.9.0
196
196
  type: :runtime
197
197
  prerelease: false
198
198
  version_requirements: !ruby/object:Gem::Requirement
199
199
  requirements:
200
200
  - - "~>"
201
201
  - !ruby/object:Gem::Version
202
- version: 2.7.2
203
- - !ruby/object:Gem::Dependency
204
- name: toml-rb
205
- requirement: !ruby/object:Gem::Requirement
206
- requirements:
207
- - - "~>"
208
- - !ruby/object:Gem::Version
209
- version: 1.1.1
210
- type: :runtime
211
- prerelease: false
212
- version_requirements: !ruby/object:Gem::Requirement
213
- requirements:
214
- - - "~>"
215
- - !ruby/object:Gem::Version
216
- version: 1.1.1
202
+ version: 1.9.0
217
203
  - !ruby/object:Gem::Dependency
218
204
  name: bundler
219
205
  requirement: !ruby/object:Gem::Requirement
@@ -476,7 +462,6 @@ files:
476
462
  - lib/dapp/dapp/logging/paint.rb
477
463
  - lib/dapp/dapp/logging/process.rb
478
464
  - lib/dapp/dapp/option_tags.rb
479
- - lib/dapp/dapp/sentry.rb
480
465
  - lib/dapp/dapp/shellout/base.rb
481
466
  - lib/dapp/dapp/shellout/streaming.rb
482
467
  - lib/dapp/dapp/slug.rb
@@ -664,6 +649,7 @@ files:
664
649
  - lib/dapp/dimg/image/stage.rb
665
650
  - lib/dapp/dimg/lock/base.rb
666
651
  - lib/dapp/dimg/lock/file.rb
652
+ - lib/dapp/downloader.rb
667
653
  - lib/dapp/error/base.rb
668
654
  - lib/dapp/error/command.rb
669
655
  - lib/dapp/error/config.rb
@@ -678,7 +664,6 @@ files:
678
664
  - lib/dapp/helper/sha256.rb
679
665
  - lib/dapp/helper/tar.rb
680
666
  - lib/dapp/helper/trivia.rb
681
- - lib/dapp/helper/url.rb
682
667
  - lib/dapp/helper/yaml.rb
683
668
  - lib/dapp/kube.rb
684
669
  - lib/dapp/kube/cli/cli.rb
@@ -1,112 +0,0 @@
1
- module Dapp
2
- class Dapp
3
- module Sentry
4
- def sentry_message(msg, **kwargs)
5
- return if not ensure_sentry_configured
6
- kwargs[:level] ||= "info"
7
- Raven.capture_message(msg, _make_sentry_params(**kwargs))
8
- end
9
-
10
- def sentry_exception(exception, **kwargs)
11
- return if not ensure_sentry_configured
12
- (kwargs[:tags] ||= {})['error-code'] = begin
13
- net_status = exception.net_status
14
- [net_status[:context], net_status[:code]].compact.join('_')
15
- end
16
- Raven.capture_exception(exception, _make_sentry_params(**kwargs))
17
- end
18
-
19
- def ensure_sentry_configured
20
- return false unless sentry_settings = settings["sentry"]
21
-
22
- unless @sentry_settings_configured
23
- Raven.configure do |config|
24
- logger = ::Logger.new(STDOUT)
25
- logger.level = ::Logger::WARN
26
-
27
- config.logger = logger
28
- config.dsn = sentry_settings["dsn"]
29
- end
30
-
31
- @sentry_settings_configured = true
32
- end
33
-
34
- return true
35
- end
36
-
37
- def _make_sentry_params(level: nil, tags: {}, extra: {}, user: {})
38
- {
39
- level: level,
40
- tags: _sentry_tags_context.merge(tags),
41
- extra: _sentry_extra_context.merge(extra),
42
- user: _sentry_user_context.merge(user),
43
- }
44
- end
45
-
46
- def _sentry_extra_context
47
- @_sentry_extra_context ||= {
48
- "pwd" => Dir.pwd,
49
- "dapp-dir" => self.work_dir,
50
- "options" => self.options,
51
- "env-options" => {
52
- "DAPP_FORCE_SAVE_CACHE" => ENV["DAPP_FORCE_SAVE_CACHE"],
53
- "DAPP_BIN_DAPPFILE_YML" => ENV["DAPP_BIN_DAPPFILE_YML"],
54
- "ANSIBLE_ARGS" => ENV["ANSIBLE_ARGS"],
55
- "DAPP_CHEF_DEBUG" => ENV["DAPP_CHEF_DEBUG"],
56
- },
57
- }.tap {|extra|
58
- extra["ci-env"] = {"CI" => ENV["CI"]}
59
- ENV.select {|k, v| k.start_with?("CI_")}.each do |k, v|
60
- extra["ci-env"][k] = v
61
- end
62
- }
63
- end
64
-
65
- def _sentry_tags_context
66
- name = options[:name] ||
67
- @_sentry_tags_context ||= {
68
- "dapp-short-version" => ::Dapp::VERSION.split(".")[0..1].join("."),
69
- "dapp-version" => ::Dapp::VERSION,
70
- "dapp-build-cache-version" => ::Dapp::BUILD_CACHE_VERSION,
71
- "dapp-command" => self.options[:dapp_command],
72
- }.tap {|tags|
73
- git_config_path = File.join(Dir.pwd, ".git/config")
74
-
75
- tags["dapp-name"] = options[:name]
76
-
77
- if File.exists? git_config_path
78
- cfg = IniFile.load(File.join(Dir.pwd, ".git/config"))
79
- remote_origin_cfg = cfg['remote "origin"']
80
- remote_origin_url = remote_origin_cfg["url"]
81
- if remote_origin_url
82
- tags["dapp-name"] ||= begin
83
- repo_name = remote_origin_url.split('/').last
84
- repo_name = repo_name[/.*(?=\.git)/] if repo_name.end_with? '.git'
85
- repo_name
86
- end
87
-
88
- tags["git-host"] = self.get_host_from_git_url(remote_origin_url)
89
-
90
- git_name = self.git_url_to_name(remote_origin_url)
91
-
92
- tags["git-group"] = git_name.partition("/")[0]
93
- tags["git-name"] = git_name
94
- end
95
- end
96
-
97
- tags["dapp-name"] ||= File.basename(Dir.pwd)
98
-
99
- begin
100
- ver = self.class.host_docker_minor_version
101
- tags["docker-minor-version"] = ver.to_s
102
- rescue ::Exception
103
- end
104
- }
105
- end
106
-
107
- def _sentry_user_context
108
- @_sentry_user_context ||= {}
109
- end
110
- end # Sentry
111
- end # Dapp
112
- end # Dapp
@@ -1,23 +0,0 @@
1
- module Dapp
2
- module Helper
3
- module Url
4
- def git_url_to_name(url)
5
- url_without_scheme = url.split("://", 2).last
6
- # This may be broken, because "@" should delimit creds, not a ":"
7
- url_without_creds = url_without_scheme.split(":", 2).last
8
- url_without_creds.gsub(%r{.*?([^\/ ]+\/[^\/ ]+)\.git}, '\\1')
9
- end
10
-
11
- def get_host_from_git_url(url)
12
- url_without_scheme = url.split("://", 2).last
13
- url_without_creds = url_without_scheme.split("@", 2).last
14
-
15
- # Split out part after ":" in this kind of url: github.com:flant/dapp.git
16
- url_part = url_without_creds.split(":", 2).first
17
-
18
- # Split out part after first "/": github.com/flant/dapp.git
19
- url_part.split("/", 2).first
20
- end
21
- end # Url
22
- end # Helper
23
- end # Dapp