avm-tools 0.45.0 → 0.50.0

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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/lib/avm/git/issue/complete.rb +1 -1
  3. data/lib/avm/git/issue/complete/_test.rb +16 -2
  4. data/lib/avm/git/issue/complete/_validations.rb +9 -14
  5. data/lib/avm/git/issue/complete/validation.rb +31 -0
  6. data/lib/avm/git/revision_test.rb +2 -2
  7. data/lib/avm/instances/configuration/_tests.rb +14 -0
  8. data/lib/avm/rails.rb +9 -0
  9. data/lib/avm/rails/runners.rb +11 -0
  10. data/lib/avm/rails/runners/bundle.rb +35 -0
  11. data/lib/avm/rails/runners/runner.rb +48 -0
  12. data/lib/avm/ruby.rb +0 -20
  13. data/lib/avm/stereotypes/eac_redmine_base0/deploy.rb +2 -2
  14. data/lib/avm/stereotypes/eac_webapp_base0/instance.rb +3 -3
  15. data/lib/avm/tools/runner/eac_rails_base0/bundle.rb +14 -0
  16. data/lib/avm/tools/runner/eac_rails_base0/runner.rb +14 -0
  17. data/lib/avm/tools/runner/eac_redmine_base0/bundle.rb +2 -24
  18. data/lib/avm/tools/runner/eac_redmine_base0/runner.rb +14 -0
  19. data/lib/avm/tools/runner/files/format.rb +1 -1
  20. data/lib/avm/tools/runner/git.rb +1 -1
  21. data/lib/avm/tools/runner/launcher.rb +12 -0
  22. data/lib/avm/tools/version.rb +1 -1
  23. data/lib/eac_launcher.rb +17 -0
  24. data/lib/eac_launcher/context.rb +81 -0
  25. data/lib/eac_launcher/context/instance_discovery.rb +54 -0
  26. data/lib/eac_launcher/context/instance_manager.rb +94 -0
  27. data/lib/eac_launcher/context/settings.rb +51 -0
  28. data/lib/eac_launcher/git.rb +7 -0
  29. data/lib/eac_launcher/git/base.rb +100 -0
  30. data/lib/eac_launcher/git/base/class_methods.rb +26 -0
  31. data/lib/eac_launcher/git/base/dirty_files.rb +30 -0
  32. data/lib/eac_launcher/git/base/remotes.rb +38 -0
  33. data/lib/eac_launcher/git/base/subrepo.rb +42 -0
  34. data/lib/eac_launcher/git/base/underlying.rb +59 -0
  35. data/lib/eac_launcher/git/error.rb +11 -0
  36. data/lib/eac_launcher/git/mirror_update.rb +36 -0
  37. data/lib/eac_launcher/git/publish_base.rb +118 -0
  38. data/lib/eac_launcher/git/remote.rb +53 -0
  39. data/lib/eac_launcher/git/sub_warp_base.rb +30 -0
  40. data/lib/eac_launcher/git/warp_base.rb +54 -0
  41. data/lib/eac_launcher/instances.rb +6 -0
  42. data/lib/eac_launcher/instances/base.rb +91 -0
  43. data/lib/eac_launcher/instances/base/cache.rb +41 -0
  44. data/lib/eac_launcher/instances/error.rb +8 -0
  45. data/lib/eac_launcher/instances/runner_helper.rb +42 -0
  46. data/lib/eac_launcher/instances/settings.rb +23 -0
  47. data/lib/eac_launcher/paths.rb +4 -0
  48. data/lib/eac_launcher/paths/logical.rb +80 -0
  49. data/lib/eac_launcher/paths/real.rb +42 -0
  50. data/lib/eac_launcher/project.rb +16 -0
  51. data/lib/eac_launcher/publish.rb +4 -0
  52. data/lib/eac_launcher/publish/base.rb +45 -0
  53. data/lib/eac_launcher/publish/check_result.rb +65 -0
  54. data/lib/eac_launcher/ruby.rb +3 -0
  55. data/lib/eac_launcher/ruby/gem.rb +4 -0
  56. data/lib/eac_launcher/ruby/gem/build.rb +123 -0
  57. data/lib/eac_launcher/ruby/gem/specification.rb +61 -0
  58. data/lib/eac_launcher/runner.rb +21 -0
  59. data/lib/eac_launcher/runner/instances.rb +41 -0
  60. data/lib/eac_launcher/runner/projects.rb +46 -0
  61. data/lib/eac_launcher/runner/publish.rb +59 -0
  62. data/lib/eac_launcher/stereotype.rb +52 -0
  63. data/lib/eac_launcher/stereotypes.rb +14 -0
  64. data/lib/eac_launcher/stereotypes/git.rb +21 -0
  65. data/lib/eac_launcher/stereotypes/git/publish.rb +13 -0
  66. data/lib/eac_launcher/stereotypes/git/warp.rb +25 -0
  67. data/lib/eac_launcher/stereotypes/git_subrepo.rb +30 -0
  68. data/lib/eac_launcher/stereotypes/git_subrepo/publish.rb +12 -0
  69. data/lib/eac_launcher/stereotypes/git_subrepo/warp.rb +85 -0
  70. data/lib/eac_launcher/stereotypes/git_subtree.rb +47 -0
  71. data/lib/eac_launcher/stereotypes/git_subtree/publish.rb +10 -0
  72. data/lib/eac_launcher/stereotypes/git_subtree/warp.rb +27 -0
  73. data/lib/eac_launcher/stereotypes/rails.rb +21 -0
  74. data/lib/eac_launcher/stereotypes/redmine_plugin.rb +21 -0
  75. data/lib/eac_launcher/stereotypes/ruby_gem.rb +27 -0
  76. data/lib/eac_launcher/stereotypes/ruby_gem/publish.rb +127 -0
  77. data/lib/eac_launcher/vendor.rb +3 -0
  78. data/lib/eac_launcher/vendor/github.rb +18 -0
  79. data/lib/eac_launcher/version.rb +5 -0
  80. metadata +122 -9
  81. data/lib/avm/patches/eac_launcher_git_base.rb +0 -77
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'eac_ruby_utils/console/docopt_runner'
4
4
  require 'eac_ruby_utils/require_sub'
5
- require 'avm/patches/eac_launcher_git_base'
5
+ require 'eac_launcher/git/base'
6
6
  ::EacRubyUtils.require_sub(__FILE__)
7
7
 
8
8
  module Avm
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_launcher/runner'
4
+
5
+ module Avm
6
+ module Tools
7
+ class Runner < ::EacRubyUtils::Console::DocoptRunner
8
+ class Launcher < ::EacLauncher::Runner
9
+ end
10
+ end
11
+ end
12
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Avm
4
4
  module Tools
5
- VERSION = '0.45.0'
5
+ VERSION = '0.50.0'
6
6
  end
7
7
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ GIT_SUBREPO_LIB = ::File.join(::File.dirname(__dir__), 'vendor', 'git-subrepo', 'lib')
4
+ ENV['PATH'] = "#{GIT_SUBREPO_LIB}#{::File::PATH_SEPARATOR}#{ENV['PATH']}"
5
+
6
+ module EacLauncher
7
+ require 'eac_launcher/context'
8
+ require 'eac_launcher/paths'
9
+ require 'eac_launcher/project'
10
+ require 'eac_launcher/stereotype'
11
+ require 'eac_launcher/git'
12
+ require 'eac_launcher/instances'
13
+ require 'eac_launcher/publish'
14
+ require 'eac_launcher/ruby'
15
+ require 'eac_launcher/stereotypes'
16
+ require 'eac_launcher/vendor'
17
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/hash/indifferent_access'
4
+ require 'eac_ruby_utils/simple_cache'
5
+ require 'eac_ruby_utils/console/speaker'
6
+ require 'eac_launcher/context/instance_discovery'
7
+ require 'eac_launcher/context/instance_manager'
8
+ require 'eac_launcher/context/settings'
9
+ require 'eac_launcher/paths/logical'
10
+ require 'eac_launcher/project'
11
+
12
+ module EacLauncher
13
+ class Context
14
+ include ::EacRubyUtils::SimpleCache
15
+ include ::EacRubyUtils::Console::Speaker
16
+
17
+ DEFAULT_PROJECTS_ROOT = '.'
18
+ DEFAULT_SETTINGS_FILE = ::File.join(ENV['HOME'], '.config', 'eac_launcher', 'settings.yml')
19
+ DEFAULT_CACHE_ROOT = ::File.join(ENV['HOME'], '.cache', 'eac_launcher')
20
+
21
+ class << self
22
+ attr_writer :current
23
+
24
+ def current
25
+ @current ||= default
26
+ end
27
+
28
+ def default
29
+ @default ||= Context.new
30
+ end
31
+ end
32
+
33
+ attr_reader :root, :settings, :cache_root
34
+ attr_accessor :publish_options, :recache, :instance_manager
35
+
36
+ def initialize(options = {})
37
+ @options = options.with_indifferent_access
38
+ @root = ::EacLauncher::Paths::Logical.new(self, nil, build_option(:projects_root), '/')
39
+ @settings = ::EacLauncher::Context::Settings.new(build_option(:settings_file))
40
+ @cache_root = build_option(:cache_root)
41
+ @publish_options = { new: false, confirm: false, stereotype: nil }
42
+ @instance_manager = ::EacLauncher::Context::InstanceManager.new(self)
43
+ @recache = false
44
+ end
45
+
46
+ def instance(name)
47
+ instances.find { |i| i.name == name }
48
+ end
49
+
50
+ def instances
51
+ @instance_manager.instances
52
+ end
53
+
54
+ def pending_instances
55
+ @instance_manager.pending_instances
56
+ end
57
+
58
+ private
59
+
60
+ def build_option(key)
61
+ @options[key] || env_option(key) || default_option(key)
62
+ end
63
+
64
+ def env_option(key)
65
+ ENV["EAC_LAUNCHER_#{key}".underscore.upcase]
66
+ end
67
+
68
+ def default_option(key)
69
+ self.class.const_get("DEFAULT_#{key}".underscore.upcase)
70
+ end
71
+
72
+ def projects_uncached
73
+ r = {}
74
+ instances.each do |i|
75
+ r[i.project_name] ||= []
76
+ r[i.project_name] << i
77
+ end
78
+ r.map { |name, instances| ::EacLauncher::Project.new(name, instances) }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ruby-progressbar'
4
+ require 'eac_launcher/instances/base'
5
+
6
+ module EacLauncher
7
+ class Context
8
+ class InstanceDiscovery
9
+ attr_reader :instances
10
+
11
+ def initialize(context)
12
+ @context = context
13
+ @progress = ::ProgressBar.create(title: 'Instance discovery', total: 1)
14
+ @instances = path_instances(@context.root, nil)
15
+ ensure
16
+ @progress&.finish
17
+ end
18
+
19
+ private
20
+
21
+ def path_instances(path, parent_instance)
22
+ update_progress_format(path)
23
+ on_rescued_path_instances(path) do |r|
24
+ if path.project?
25
+ parent_instance = ::EacLauncher::Instances::Base.instanciate(path, parent_instance)
26
+ r << path
27
+ end
28
+ children = path.children
29
+ update_progress_count(children)
30
+ r.concat(children.flat_map { |c| path_instances(c, parent_instance) })
31
+ end
32
+ end
33
+
34
+ def on_rescued_path_instances(path)
35
+ r = []
36
+ begin
37
+ yield(r) if path.included?
38
+ rescue StandardError => e
39
+ warn("#{path}: #{e}")
40
+ end
41
+ r
42
+ end
43
+
44
+ def update_progress_format(path)
45
+ @progress.format = "%t (Paths: %c/%C, Current: #{path.logical}) |%B| %a"
46
+ end
47
+
48
+ def update_progress_count(children)
49
+ @progress.total += children.count
50
+ @progress.increment
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('yaml')
4
+
5
+ module EacLauncher
6
+ class Context
7
+ class InstanceManager
8
+ include ::EacRubyUtils::SimpleCache
9
+
10
+ def initialize(context)
11
+ @context = context
12
+ end
13
+
14
+ def publish_state_set(instance, stereotype_name, check_status)
15
+ data = cached_instances_file_content_uncached
16
+ data[instance.logical] ||= {}
17
+ data[instance.logical][:publish_state] ||= {}
18
+ data[instance.logical][:publish_state][stereotype_name] = check_status
19
+ write_cache_file(data)
20
+ end
21
+
22
+ def pending_instances
23
+ instances.select { |instance| pending_instance?(instance) }
24
+ end
25
+
26
+ private
27
+
28
+ def instances_uncached
29
+ (cached_instances || search_instances).select(&:included?)
30
+ end
31
+
32
+ def search_instances
33
+ cache_instances(::EacLauncher::Context::InstanceDiscovery.new(@context).instances)
34
+ end
35
+
36
+ def cached_instances
37
+ return nil if @context.recache
38
+ return nil unless cached_instances_file_content
39
+
40
+ CachedInstances.new(cached_instances_file_content).instances
41
+ end
42
+
43
+ def cached_instances_file_content_uncached
44
+ r = YAML.load_file(cache_file_path)
45
+ r.is_a?(::Hash) ? r : nil
46
+ rescue Errno::ENOENT
47
+ nil
48
+ end
49
+
50
+ def cache_instances(instances)
51
+ write_cache_file(Hash[instances.map { |i| [i.logical, i.to_h] }])
52
+ instances
53
+ end
54
+
55
+ def write_cache_file(data)
56
+ ::File.write(cache_file_path, data.to_yaml)
57
+ end
58
+
59
+ def cache_file_path
60
+ ::File.join(@context.cache_root, 'instances.yml')
61
+ end
62
+
63
+ def pending_instance?(instance)
64
+ data = cached_instances_file_content
65
+ return false unless data[instance.logical]
66
+ return false unless data[instance.logical][:publish_state].is_a?(Hash)
67
+
68
+ data[instance.logical][:publish_state].any? do |_k, v|
69
+ ::EacLauncher::Publish::CheckResult.pending_status?(v)
70
+ end
71
+ end
72
+
73
+ class CachedInstances
74
+ def initialize(content)
75
+ @content = content
76
+ @instances = {}
77
+ end
78
+
79
+ def instances
80
+ @content.keys.map { |k| by_logical_path(k) }
81
+ end
82
+
83
+ def by_logical_path(key)
84
+ return @instances[key] if @instances.key?(key)
85
+
86
+ h = @content[key]
87
+ parent_instance = h[:parent] ? by_logical_path(h[:parent]) : nil
88
+ path = ::EacLauncher::Paths::Logical.from_h(@context, h)
89
+ @instances[key] = ::EacLauncher::Instances::Base.instanciate(path, parent_instance)
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/simple_cache'
4
+ require 'yaml'
5
+ require 'eac_launcher/instances/settings'
6
+
7
+ module EacLauncher
8
+ class Context
9
+ class Settings
10
+ include ::EacRubyUtils::SimpleCache
11
+
12
+ def initialize(file)
13
+ unless ::File.exist?(file)
14
+ ::FileUtils.mkdir_p(::File.dirname(file))
15
+ ::File.write(file, {}.to_yaml)
16
+ end
17
+ @data = YAML.load_file(file)
18
+ end
19
+
20
+ def instance_settings(instance)
21
+ ::EacLauncher::Instances::Settings.new(value(['Instances', instance.name]))
22
+ end
23
+
24
+ private
25
+
26
+ def excluded_projects_uncached
27
+ enum_value(%w[Projects Exclude])
28
+ end
29
+
30
+ def excluded_paths_uncached
31
+ enum_value(%w[Paths Exclude])
32
+ end
33
+
34
+ def enum_value(path)
35
+ r = value(path)
36
+ r.is_a?(Enumerable) ? r : []
37
+ end
38
+
39
+ def value(path)
40
+ node_value(@data, path)
41
+ end
42
+
43
+ def node_value(data, path)
44
+ return data if path.empty?
45
+ return nil unless data.is_a?(Hash)
46
+
47
+ node_value(data[path.first], path.drop(1))
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_launcher/git/base'
4
+ require 'eac_launcher/git/error'
5
+ require 'eac_launcher/git/mirror_update'
6
+ require 'eac_launcher/git/publish_base'
7
+ require 'eac_launcher/git/warp_base'
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+ require 'eac_ruby_utils/envs'
5
+ require 'eac_launcher/paths/real'
6
+ require 'eac_launcher/git/error'
7
+
8
+ module EacLauncher
9
+ module Git
10
+ class Base < ::EacLauncher::Paths::Real
11
+ require_sub __FILE__
12
+ enable_simple_cache
13
+ extend ::EacLauncher::Git::Base::ClassMethods
14
+ include ::EacLauncher::Git::Base::DirtyFiles
15
+ include ::EacLauncher::Git::Base::Remotes
16
+ include ::EacLauncher::Git::Base::Subrepo
17
+ include ::EacLauncher::Git::Base::Underlying
18
+
19
+ def init_bare
20
+ FileUtils.mkdir_p(self)
21
+ ::EacRubyUtils::Envs.local.command('git', 'init', '--bare', self).execute! unless
22
+ File.exist?(subpath('.git'))
23
+ end
24
+
25
+ def rev_parse(ref, required = false)
26
+ r = execute!('rev-parse', ref, exit_outputs: { 128 => nil, 32_768 => nil })
27
+ r.strip! if r.is_a?(String)
28
+ return r if r.present?
29
+ return nil unless required
30
+
31
+ raise "Reference \"#{ref}\" not found"
32
+ end
33
+
34
+ # @return [Pathname]
35
+ def root_path
36
+ @root_path ||= self.class.find_root(to_s)
37
+ end
38
+
39
+ def descendant?(descendant, ancestor)
40
+ base = merge_base(descendant, ancestor)
41
+ return false if base.blank?
42
+
43
+ revparse = execute!('rev-parse', '--verify', ancestor).strip
44
+ base == revparse
45
+ end
46
+
47
+ def merge_base(*commits)
48
+ refs = commits.dup
49
+ while refs.count > 1
50
+ refs[1] = merge_base_pair(refs[0], refs[1])
51
+ return nil if refs[1].blank?
52
+
53
+ refs.shift
54
+ end
55
+ refs.first
56
+ end
57
+
58
+ def subtree_split(prefix)
59
+ execute!('subtree', '-q', 'split', '-P', prefix).strip
60
+ end
61
+
62
+ def push(remote_name, refspecs, options = {})
63
+ refspecs = [refspecs] unless refspecs.is_a?(Array)
64
+ args = ['push']
65
+ args << '--dry-run' if options[:dryrun]
66
+ args << '--force' if options[:force]
67
+ system!(args + [remote_name] + refspecs)
68
+ end
69
+
70
+ def push_all(remote_name)
71
+ system!('push', '--all', remote_name)
72
+ system!('push', '--tags', remote_name)
73
+ end
74
+
75
+ def fetch(remote_name, options = {})
76
+ args = ['fetch', '-p', remote_name]
77
+ args += %w[--tags --prune-tags --force] if options[:tags]
78
+ execute!(*args)
79
+ end
80
+
81
+ def current_branch
82
+ execute!(%w[symbolic-ref -q HEAD]).gsub(%r{\Arefs/heads/}, '').strip
83
+ end
84
+
85
+ def reset_hard(ref)
86
+ execute!('reset', '--hard', ref)
87
+ end
88
+
89
+ def raise(message)
90
+ ::Kernel.raise EacLauncher::Git::Error.new(self, message)
91
+ end
92
+
93
+ private
94
+
95
+ def merge_base_pair(commit1, commit2)
96
+ execute!('merge-base', commit1, commit2, exit_outputs: { 256 => '' }).strip
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EacLauncher
4
+ module Git
5
+ class Base < ::EacLauncher::Paths::Real
6
+ module ClassMethods
7
+ # @return [EacLauncher::Git::Base]
8
+ def by_root(search_base_path)
9
+ new(find_root(search_base_path).to_path)
10
+ end
11
+
12
+ # Searches the root path for the Git repository which includes +search_base_path+.
13
+ # @return [Pathname]
14
+ def find_root(search_base_path)
15
+ path = search_base_path.to_pathname.expand_path
16
+ loop do
17
+ return path if path.join('.git').exist?
18
+ raise "\".git\" not found for \"#{search_base_path}\"" if path.parent.root?
19
+
20
+ path = path.parent
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end