buildizer 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTgxMGMxNTEzOTg5MDhjMmExZGUwOWM3M2JjMmM0NjdhYjNkODBiOA==
4
+ NzJlYTY0NmI3OGFiMTRmOGEwMjg4ZmY2YjFkZmFkNTJlZjc5ZDQyZg==
5
5
  data.tar.gz: !binary |-
6
- MjRhZjU1NzlmOGM3ZjMyMzEzMDk5NDY5ZmQ0ZGJhZGY1ZGI5YjdhMQ==
6
+ OTdiYzQ0YWNjYjZmM2VlYmI3Mzk2ZjNlODNkZjFjYmVkOWZkZTY4ZA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- Nzk3ZjIyMzVlMmNhOTczMDk5YjQ3NjA3NTIzNjVhZGE4MTY4NjQzMWY4ZjQ5
10
- NDc2OWIxZmYyYTE3NzgxMTE4N2ZkYjNmZDQxNzVkMzFjNzc1MWNjMWNmODI0
11
- ZmI2MzZjYzhiYzY4MmFkMjExMTM3MDJkMDA3M2MzYTNmYmU3ZDk=
9
+ MGVlZmNiYzFkN2U3NDM5NWVmZDg0ZDNmNmU0ZjJiN2UxZmE3OTg0YWJlYWIx
10
+ NGQwYTg4NTA4MDkzYTdhZDFjYzI3MzJkNGI3MTVlZTNlNDlhZGJjNzhkOGRl
11
+ NTA5OGNlN2Y5Y2ZmNzMxOTQ1MDE1OTI1ZDNjZmM1ZTkxODRhNmE=
12
12
  data.tar.gz: !binary |-
13
- YTljMjYyZmJiZDdmY2E3MDRhNTVjNjY1ZTJmMWQ3NjUyYWU5YTAxNTU4OTE3
14
- YjRlOTJhOTA4YTc5NjExZjk0ZWQxOTE3ZmIzMThhYjU2YTc2YmQ4OGRkMmVm
15
- OTNlNWFmZDNmMDBmYWQ2OTE2YWE3ZWQwZGRjYzhjMDQyNjJkNDg=
13
+ ZTU5ZTRhYTgyOTJhMWQ4ZDY4ZjQ1YWFlZWU3ODk4MGMyOGMyMDgxYTBlZWNh
14
+ ZWVjYTE4NzUzMGYzOTIwMTIyMTQ1ZGE2MWI4NTUwYmIxY2JmM2VmZWI5MTM1
15
+ OGIxYzJhYzBiNzhhYjE5NjQ1OTZjZDdhZTcxNDEyMWViZWU0YWM=
data/Gemfile.lock CHANGED
@@ -1,6 +1,6 @@
1
1
  GIT
2
2
  remote: https://github.com/flant/shellfold.git
3
- revision: 7429a46664b45ab246ba7a88eac24f614d1945a7
3
+ revision: 4db6a6a953412f2973fb6a814a0517cd04b0658c
4
4
  specs:
5
5
  shellfold (0.0.3)
6
6
  mixlib-shellout (>= 2.2.6, < 3.0)
@@ -8,8 +8,9 @@ GIT
8
8
  PATH
9
9
  remote: .
10
10
  specs:
11
- buildizer (0.0.7)
11
+ buildizer (0.0.8)
12
12
  net_status (>= 0.0.1, < 1.0)
13
+ overcommit (>= 0.33.0, < 1.0)
13
14
  package_cloud (>= 0.2, < 1.0)
14
15
  shellfold (>= 0.0.1, < 1.0)
15
16
  thor (>= 0.19.1, < 1.0)
@@ -21,6 +22,8 @@ GEM
21
22
  backports (3.6.8)
22
23
  binding_of_caller (0.7.2)
23
24
  debug_inspector (>= 0.0.1)
25
+ childprocess (0.5.9)
26
+ ffi (~> 1.0, >= 1.0.11)
24
27
  coderay (1.1.1)
25
28
  colorize (0.6.0)
26
29
  debug_inspector (0.0.2)
@@ -40,6 +43,7 @@ GEM
40
43
  net-http-persistent (>= 2.7)
41
44
  net-http-pipeline
42
45
  highline (1.6.20)
46
+ iniparse (1.4.2)
43
47
  json (1.8.3)
44
48
  json_pure (1.8.1)
45
49
  launchy (2.4.3)
@@ -52,6 +56,9 @@ GEM
52
56
  net-http-persistent (2.9.4)
53
57
  net-http-pipeline (1.0.1)
54
58
  net_status (0.0.2)
59
+ overcommit (0.33.0)
60
+ childprocess (~> 0.5.8)
61
+ iniparse (~> 1.4)
55
62
  package_cloud (0.2.29)
56
63
  colorize (= 0.6.0)
57
64
  highline (= 1.6.20)
data/bin/buildizer CHANGED
@@ -5,7 +5,7 @@
5
5
  require 'buildizer'
6
6
 
7
7
  begin
8
- Buildizer::Cli.start
8
+ Buildizer::Cli::Main.start
9
9
  rescue Buildizer::Error => e
10
10
  $stderr.puts [e.net_status[:error], e.net_status[:message]].compact.join(': ')
11
11
  exit 1
data/buildizer.gemspec CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.add_dependency "net_status", ">= 0.0.1", "< 1.0"
21
21
  spec.add_dependency "shellfold", ">= 0.0.1", "< 1.0"
22
22
  spec.add_dependency "package_cloud", ">= 0.2", "< 1.0"
23
+ spec.add_dependency "overcommit", ">= 0.33.0", "< 1.0"
23
24
 
24
25
  spec.add_development_dependency "bundler", "~> 1.7"
25
26
  spec.add_development_dependency "rake", "~> 10.0"
@@ -95,7 +95,7 @@ module Buildizer
95
95
  def _required_params!(required_params, params)
96
96
  Array(required_params).each do |param|
97
97
  unless params[param] and not params[param].to_s.empty?
98
- raise Error, error: :input_error, message: "#{param} is not defined"
98
+ raise Error, error: :input_error, message: "Buildizer #{param} is not defined"
99
99
  end
100
100
  end
101
101
  end
@@ -107,7 +107,7 @@ module Buildizer
107
107
  def verify
108
108
  targets.tap do |res|
109
109
  unless res.any?
110
- raise Error, error: :input_error, message: "target is not defined"
110
+ raise Error, error: :input_error, message: "Buildizer target is not defined"
111
111
  end
112
112
  end
113
113
  end
@@ -170,7 +170,7 @@ module Buildizer
170
170
 
171
171
  packager.package_cloud_org.each do |org, token|
172
172
  unless token
173
- warn "No packagecloud token defined for org '#{org}' " +
173
+ warn "No package cloud token defined for org '#{org}' " +
174
174
  "(PACKAGECLOUD_TOKEN or PACKAGECLOUD_TOKEN_#{org.upcase}) [WARN]"
175
175
  end
176
176
  end
@@ -0,0 +1,76 @@
1
+ module Buildizer
2
+ module Ci
3
+ class Base
4
+ using Refine
5
+
6
+ attr_reader :packager
7
+
8
+ def initialize(packager)
9
+ super()
10
+
11
+ @packager = packager
12
+ end
13
+
14
+ def conf
15
+ @conf ||= conf_path.load_yaml
16
+ end
17
+
18
+ def conf_path
19
+ packager.package_path.join(conf_file_name)
20
+ end
21
+
22
+ def conf_file_name
23
+ ".#{ci_name}.yml"
24
+ end
25
+
26
+ def ci_name
27
+ self.class.ci_name
28
+ end
29
+
30
+ def setup!
31
+ raise
32
+ end
33
+
34
+ def configuration_actual?
35
+ raise
36
+ end
37
+
38
+ def git_tag
39
+ res = _git_tag.to_s
40
+ if res.empty? then nil else res end
41
+ end
42
+
43
+ def _git_tag
44
+ raise
45
+ end
46
+
47
+ def buildizer_install_instructions(master: nil)
48
+ if master
49
+ ['git clone https://github.com/flant/buildizer ~/buildizer',
50
+ 'echo "export BUNDLE_GEMFILE=~/buildizer/Gemfile" | tee -a ~/.bashrc',
51
+ 'export BUNDLE_GEMFILE=~/buildizer/Gemfile',
52
+ 'gem install bundler',
53
+ 'gem install overcommit',
54
+ 'bundle install',
55
+ ]
56
+ else
57
+ 'gem install buildizer'
58
+ end
59
+ end
60
+
61
+ def package_cloud_setup!
62
+ raise
63
+ end
64
+
65
+ def docker_cache_setup!
66
+ raise
67
+ end
68
+
69
+ class << self
70
+ def ci_name
71
+ raise
72
+ end
73
+ end # << self
74
+ end # Base
75
+ end # Ci
76
+ end # Buildizer
@@ -0,0 +1,15 @@
1
+ module Buildizer
2
+ module Ci
3
+ class GitlabCi < Base
4
+ def _git_tag
5
+ ENV['CI_BUILD_TAG']
6
+ end
7
+
8
+ class << self
9
+ def ci_name
10
+ 'gitlab-ci'
11
+ end
12
+ end # << self
13
+ end # GitlabCi
14
+ end # Ci
15
+ end # Buildizer
@@ -0,0 +1,47 @@
1
+ module Buildizer
2
+ module Ci
3
+ class Travis
4
+ module DockerCacheMod
5
+ class << self
6
+ def included(base)
7
+ base.class_eval do
8
+ env_vars prefix: :docker_cache, repo: 'BUILDIZER_DOCKER_CACHE',
9
+ user: 'BUILDIZER_DOCKER_CACHE_USERNAME',
10
+ password: 'BUILDIZER_DOCKER_CACHE_PASSWORD',
11
+ email: 'BUILDIZER_DOCKER_CACHE_EMAIL',
12
+ server: 'BUILDIZER_DOCKER_CACHE_SERVER'
13
+ end # class_eval
14
+ end
15
+ end # << self
16
+
17
+ def docker_cache_setup!
18
+ if packager.docker_cache_clear_settings?
19
+ with_travis do
20
+ packager.with_log(desc: "Travis docker cache settings") do |&fin|
21
+ docker_cache_repo_var_delete!
22
+ docker_cache_user_var_delete!
23
+ docker_cache_password_var_delete!
24
+ docker_cache_email_var_delete!
25
+ docker_cache_server_var_delete!
26
+
27
+ fin.call 'DELETED'
28
+ end # with_log
29
+ end # with_travis
30
+ elsif packager.docker_cache_update_settings?
31
+ with_travis do
32
+ packager.with_log(desc: "Travis docker cache settings") do |&fin|
33
+ docker_cache_repo_var_update! packager.setup_docker_cache_repo, public: true
34
+ docker_cache_user_var_update! packager.setup_docker_cache_user, public: false
35
+ docker_cache_password_var_update! packager.setup_docker_cache_password, public: false
36
+ docker_cache_email_var_update! packager.setup_docker_cache_email, public: false
37
+ docker_cache_server_var_update! packager.setup_docker_cache_server, public: true
38
+
39
+ fin.call 'UPDATED'
40
+ end # with_log
41
+ end # with_travis
42
+ end
43
+ end
44
+ end # DockerCacheMod
45
+ end # Travis
46
+ end # Ci
47
+ end # Buildizer
@@ -0,0 +1,76 @@
1
+ module Buildizer
2
+ module Ci
3
+ class Travis
4
+ module PackageCloudMod
5
+ class << self
6
+ def included(base)
7
+ base.class_eval do
8
+ env_vars prefix: :package_cloud, repo_list: 'PACKAGECLOUD'
9
+ end # class_eval
10
+ end
11
+ end # << self
12
+
13
+ def package_cloud_token_var_name(org: nil)
14
+ if org
15
+ "PACKAGECLOUD_TOKEN_#{org.upcase}"
16
+ else
17
+ 'PACKAGECLOUD_TOKEN'
18
+ end
19
+ end
20
+
21
+ def package_cloud_token_var(org: nil)
22
+ repo.env_vars[package_cloud_token_var_name(org: org)]
23
+ end
24
+
25
+ def package_cloud_token_var_delete!(**kwargs)
26
+ var = package_cloud_token_var(**kwargs)
27
+ var.delete if var
28
+ end
29
+
30
+ def package_cloud_token_var_update!(value, org: nil, **kwargs)
31
+ if value
32
+ repo.env_vars.upsert(package_cloud_token_var_name(org: org), value, **kwargs)
33
+ else
34
+ package_cloud_token_var_delete!(org: org)
35
+ end
36
+ end
37
+
38
+ def package_cloud_setup!
39
+ if packager.package_cloud_clear_settings?
40
+ with_travis do
41
+ repo_list = []
42
+ repo_list = package_cloud_repo_list_var.value.split(',') if package_cloud_repo_list_var
43
+ org_list = repo_list.map {|repo| repo.split('/').first}.uniq
44
+ org_list.each do |org|
45
+ packager.with_log(desc: "Travis package cloud token for '#{org}'") do |&fin|
46
+ package_cloud_token_var_delete! org: org
47
+ fin.call 'DELETED'
48
+ end
49
+ end
50
+
51
+ packager.with_log(desc: "Travis package cloud repo list") do |&fin|
52
+ package_cloud_repo_list_var_delete!
53
+ fin.call 'DELETED'
54
+ end
55
+ end # with_travis
56
+ elsif packager.package_cloud_update_settings?
57
+ with_travis do
58
+ packager.with_log(desc: "Travis package cloud repo list") do |&fin|
59
+ package_cloud_repo_list_var_update! packager.setup_package_cloud_repo_list.join(','), public: true
60
+ fin.call 'UPDATED'
61
+ end # with_log
62
+
63
+ packager.setup_package_cloud_org_desc_list.each do |desc|
64
+ next unless desc[:token]
65
+ packager.with_log(desc: "Travis package cloud token for '#{desc[:org]}'") do |&fin|
66
+ package_cloud_token_var_update! desc[:token], org: desc[:org], public: false
67
+ fin.call 'UPDATED'
68
+ end # with_log
69
+ end
70
+ end # with_travis
71
+ end
72
+ end
73
+ end # PackageCloudMod
74
+ end # Travis
75
+ end # Ci
76
+ end # Buildizer
@@ -0,0 +1,42 @@
1
+ module Buildizer
2
+ module Ci
3
+ class Travis
4
+ module PackageVersionTagMod
5
+ using Refine
6
+
7
+ def require_tag_var_name
8
+ 'BUILDIZER_REQUIRE_TAG'
9
+ end
10
+
11
+ def require_tag_var
12
+ repo.env_vars[require_tag_var_name]
13
+ end
14
+
15
+ def require_tag_var_upsert(**kwargs)
16
+ repo.env_vars.upsert(require_tag_var_name, kwargs.delete(:value), public: true, **kwargs)
17
+ end
18
+
19
+ def require_tag_setup!
20
+ with_travis do
21
+ packager.with_log(desc: "Travis require tag for deploy") do |&fin|
22
+ if packager.cli.options['require_tag'].nil?
23
+ unless require_tag_var
24
+ require_tag_var_upsert(value: true.to_env)
25
+ fin.call 'ENABLED'
26
+ else
27
+ fin.call
28
+ end
29
+ elsif packager.cli.options['require_tag']
30
+ require_tag_var_upsert(value: true.to_env)
31
+ fin.call 'ENABLED'
32
+ else
33
+ require_tag_var_upsert(value: false.to_env)
34
+ fin.call 'DISABLED'
35
+ end
36
+ end # with_log
37
+ end # with_travis
38
+ end
39
+ end # PackageVersionTagMod
40
+ end # Travis
41
+ end # Ci
42
+ end # Buildizer
@@ -0,0 +1,124 @@
1
+ module Buildizer
2
+ module Ci
3
+ class Travis < Base
4
+ class << self
5
+ def ci_name
6
+ 'travis'
7
+ end
8
+
9
+ def env_vars(prefix:, **kwargs)
10
+ kwargs.each do |name, var_name|
11
+ define_method("#{prefix}_#{name}_var") {repo.env_vars[var_name]}
12
+ define_method("#{prefix}_#{name}_var_name") {var_name}
13
+ define_method("#{prefix}_#{name}_var_delete!") do
14
+ var = send("#{prefix}_#{name}_var")
15
+ var.delete if var
16
+ end
17
+ define_method("#{prefix}_#{name}_var_update!") do |value, **kwargs|
18
+ if value
19
+ repo.env_vars.upsert(var_name, value, **kwargs)
20
+ else
21
+ send("#{prefix}_#{name}_var_delete!")
22
+ end
23
+ end
24
+ end # each
25
+ end
26
+ end # << self
27
+
28
+ autoload :PackageCloudMod, 'buildizer/ci/travis/package_cloud_mod'
29
+ autoload :DockerCacheMod, 'buildizer/ci/travis/docker_cache_mod'
30
+ autoload :PackageVersionTagMod, 'buildizer/ci/travis/package_version_tag_mod'
31
+
32
+ include PackageCloudMod
33
+ include DockerCacheMod
34
+ include PackageVersionTagMod
35
+
36
+ def setup!
37
+ packager.write_path(conf_path, YAML.dump(actual_conf))
38
+ require_tag_setup!
39
+ end
40
+
41
+ def configuration_actual?
42
+ conf == actual_conf
43
+ end
44
+
45
+ def actual_conf
46
+ install = [
47
+ 'sudo apt-get update',
48
+ 'sudo apt-get install -y apt-transport-https ca-certificates',
49
+ 'sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D',
50
+ 'echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" | sudo tee /etc/apt/sources.list.d/docker.list',
51
+ 'sudo apt-get update',
52
+
53
+ # FIXME [https://github.com/docker/docker/issues/20316]:
54
+ 'sudo apt-get -o dpkg::options::="--force-confnew" install -y docker-engine=1.9.1-0~trusty',
55
+
56
+ 'echo "docker-engine hold" | sudo dpkg --set-selections',
57
+ ]
58
+ install.push(*Array(buildizer_install_instructions(master: packager.project_settings['master'])))
59
+
60
+ env = packager.targets.map {|t| "BUILDIZER_TARGET=#{t}"}
61
+ conf.merge(
62
+ 'dist' => 'trusty',
63
+ 'sudo' => 'required',
64
+ 'cache' => 'apt',
65
+ 'language' => 'ruby',
66
+ 'rvm' => '2.2.1',
67
+ 'install' => install,
68
+ 'before_script' => 'buildizer prepare',
69
+ 'script' => 'buildizer build',
70
+ 'env' => env,
71
+ 'after_success' => 'buildizer deploy',
72
+ )
73
+ end
74
+
75
+ def _git_tag
76
+ ENV['TRAVIS_TAG']
77
+ end
78
+
79
+ def repo_name
80
+ packager.git_remote_url.split(':')[1].split('.')[0]
81
+ rescue
82
+ raise Error, error: :input_error,
83
+ message: "unable to determine travis repo name " +
84
+ "from git remote url #{packager.git_remote_url}"
85
+ end
86
+
87
+ def repo
88
+ ::Travis::Repository.find(repo_name)
89
+ end
90
+
91
+ def login
92
+ @logged_in ||= begin
93
+ packager.with_log(desc: "Login into travis") do |&fin|
94
+ packager.user_settings['travis'] ||= {}
95
+
96
+ if packager.cli.options['reset_github_token']
97
+ packager.user_settings['travis'].delete('github_token')
98
+ packager.user_settings_save!
99
+ end
100
+
101
+ packager.user_settings['travis']['github_token'] ||= begin
102
+ reset_github_token = true
103
+ packager.cli.ask("GitHub access token:", echo: false).tap{puts}
104
+ end
105
+
106
+ ::Travis.github_auth(packager.user_settings['travis']['github_token'])
107
+ packager.user_settings_save! if reset_github_token
108
+
109
+ fin.call "LOGGED IN: #{::Travis::User.current.name}"
110
+ end # with_log
111
+
112
+ true
113
+ end
114
+ end
115
+
116
+ def with_travis(&blk)
117
+ login
118
+ yield
119
+ rescue ::Travis::Client::Error => err
120
+ raise Error, message: "travis: #{err.message}"
121
+ end
122
+ end # Travis
123
+ end # Ci
124
+ end # Buildizer
@@ -0,0 +1,4 @@
1
+ module Buildizer
2
+ module Ci
3
+ end # Ci
4
+ end # Buildizer
@@ -0,0 +1,17 @@
1
+ module Buildizer
2
+ module Cli
3
+ class Base < ::Thor
4
+ include OptionMod
5
+
6
+ add_shared_options(
7
+ debug: {type: :boolean, default: false, desc: "turn on live logging for external commands"},
8
+ )
9
+
10
+ no_commands do
11
+ def packager
12
+ @packager ||= Buildizer::Packager.new(self)
13
+ end
14
+ end # no_commands
15
+ end # Base
16
+ end # Cli
17
+ end # Buildizer
@@ -0,0 +1,85 @@
1
+ module Buildizer
2
+ module Cli
3
+ class Main < Base
4
+ include OptionMod
5
+
6
+ desc "setup", "Setup buildizer"
7
+ shared_options
8
+ method_option :master, type: :boolean, default: nil,
9
+ desc: "use latest master branch of buildizer from github in ci"
10
+ method_option :verify_ci, type: :boolean, default: false,
11
+ desc: "only verify ci configuration is up to date"
12
+ method_option :reset_github_token, type: :boolean, default: false,
13
+ desc: "delete github token from user settings and enter new"
14
+ method_option :require_tag, type: :boolean, default: nil,
15
+ desc: "pass only git tagged commits for deploy stage"
16
+
17
+ method_option :package_cloud, type: :array, default: nil,
18
+ desc: "package cloud repo list"
19
+ method_option :reset_package_cloud_token, type: :boolean, default: false,
20
+ desc: "delete package cloud tokens " +
21
+ "from user settings for each specified repo " +
22
+ "and enter new"
23
+ method_option :clear_package_cloud, type: :boolean, default: false,
24
+ desc: "clear all package cloud settings"
25
+
26
+ method_option :docker_cache, type: :string, default: nil,
27
+ desc: "docker cache repo name in format '<org>/<name>'"
28
+ method_option :docker_cache_user, type: :string, default: nil,
29
+ desc: "docker cache login user name to access specified repo"
30
+ method_option :docker_cache_email, type: :string, default: nil,
31
+ desc: "docker cache login email to access specified repo"
32
+ method_option :docker_cache_server, type: :string, default: nil,
33
+ desc: "docker cache login server to access specified repo"
34
+ method_option :reset_docker_cache_password, type: :boolean, default: false,
35
+ desc: "delete docker cache user password " +
36
+ "from user settings and enter new"
37
+ method_option :clear_docker_cache, type: :boolean, default: false,
38
+ desc: "clear all docker cache settings"
39
+ def setup
40
+ if options['verify_ci']
41
+ raise(Error, message: "#{packager.ci.ci_name} confugration update needed") unless packager.ci.configuration_actual?
42
+ else
43
+ packager.project_settings_setup!
44
+ packager.user_settings_setup!
45
+ packager.ci.setup!
46
+ packager.package_cloud_setup!
47
+ packager.docker_cache_setup!
48
+ packager.overcommit_setup!
49
+ packager.overcommit_verify_setup!
50
+ packager.overcommit_ci_setup!
51
+ end
52
+ end
53
+
54
+ desc "deinit", "Deinitialize settings (.buildizer.yml, git pre-commit hook)"
55
+ shared_options
56
+ def deinit
57
+ packager.deinit!
58
+ end
59
+
60
+ desc "prepare", "Prepare images for building packages"
61
+ shared_options
62
+ def prepare
63
+ packager.prepare!
64
+ end
65
+
66
+ desc "build", "Build packages"
67
+ shared_options
68
+ def build
69
+ packager.build!
70
+ end
71
+
72
+ desc "deploy", "Deploy packages"
73
+ shared_options
74
+ def deploy
75
+ packager.deploy!
76
+ end
77
+
78
+ desc "verify", "Verify targets params"
79
+ shared_options
80
+ def verify
81
+ packager.verify!
82
+ end
83
+ end # Main
84
+ end # Cli
85
+ end # Buildizer
@@ -0,0 +1,35 @@
1
+ module Buildizer
2
+ module Cli
3
+ module OptionMod
4
+ class << self
5
+ def included(base)
6
+ base.send(:extend, ClassMethods)
7
+ end
8
+ end # << self
9
+
10
+ module ClassMethods
11
+ def _shared_options
12
+ @_shared_options ||= {}
13
+ end
14
+
15
+ def _all_shared_options
16
+ res = _shared_options
17
+ if klass = self.superclass and klass.respond_to?(:_all_shared_options)
18
+ res = res.merge(klass._all_shared_options)
19
+ end
20
+ res
21
+ end
22
+
23
+ def add_shared_options(options)
24
+ _shared_options.merge! options
25
+ end
26
+
27
+ def shared_options
28
+ _all_shared_options.each do |name, options|
29
+ method_option name, options
30
+ end
31
+ end
32
+ end # ClassMethods
33
+ end # OptionMod
34
+ end # Cli
35
+ end # Buildizer