buildizer 0.0.7 → 0.0.8

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.
data/lib/buildizer/cli.rb CHANGED
@@ -1,64 +1,4 @@
1
1
  module Buildizer
2
- class Cli < ::Thor
3
- class << self
4
- def shared_options
5
- (@shared_options || {}).each do |name, options|
6
- method_option name, options
7
- end
8
- end
9
-
10
- def construct_packager(options)
11
- Packager.new(options: {'latest' => options['latest']}, debug: options['debug'])
12
- end
13
- end # << self
14
-
15
- @shared_options = {
16
- debug: {type: :boolean, default: false, desc: "turn on live logging for external commands"},
17
- }
18
-
19
- desc "init", "Initialize settings (.travis.yml, .buildizer.yml, git pre-commit hook)"
20
- shared_options
21
- method_option :latest,
22
- type: :boolean,
23
- desc: "use buildizer github master branch"
24
- def init
25
- self.class.construct_packager(options).init!
26
- end
27
-
28
- desc "update", "Regenerate .travis.yml"
29
- shared_options
30
- def update
31
- self.class.construct_packager(options).update!
32
- end
33
-
34
- desc "deinit", "Deinitialize settings (.buildizer.yml, git pre-commit hook)"
35
- shared_options
36
- def deinit
37
- self.class.construct_packager(options).deinit!
38
- end
39
-
40
- desc "prepare", "Prepare images for building packages"
41
- shared_options
42
- def prepare
43
- self.class.construct_packager(options).prepare!
44
- end
45
-
46
- desc "build", "Build packages"
47
- shared_options
48
- def build
49
- self.class.construct_packager(options).build!
50
- end
51
-
52
- desc "deploy", "Deploy packages"
53
- shared_options
54
- def deploy
55
- self.class.construct_packager(options).deploy!
56
- end
57
-
58
- desc "verify", "Verify targets params"
59
- shared_options
60
- def verify
61
- self.class.construct_packager(options).verify!
62
- end
2
+ module Cli
63
3
  end # Cli
64
4
  end # Buildizer
@@ -32,9 +32,9 @@ module Buildizer
32
32
 
33
33
  def with_cache(&blk)
34
34
  warn("No docker cache account settings " +
35
- "(BUILDIZER_DOCKER_CACHE, BUILDIZER_DOCKER_CACHE_USERNAME, " +
36
- "BUILDIZER_DOCKER_CACHE_PASSWORD, BUILDIZER_DOCKER_CACHE_EMAIL, " +
37
- "BUILDIZER_DOCKER_CACHE_SERVER) [WARN]") unless cache
35
+ "(BUILDIZER_DOCKER_CACHE, BUILDIZER_DOCKER_CACHE_USERNAME," +
36
+ " BUILDIZER_DOCKER_CACHE_PASSWORD, BUILDIZER_DOCKER_CACHE_EMAIL," +
37
+ " BUILDIZER_DOCKER_CACHE_SERVER) [WARN]") unless cache
38
38
 
39
39
  cache_login! if cache
40
40
  begin
@@ -49,7 +49,7 @@ module Buildizer
49
49
 
50
50
  cmd = ["docker login"]
51
51
  cmd << "--email=#{cache[:email]}" if cache[:email]
52
- cmd << "--username=#{cache[:username]}" if cache[:username]
52
+ cmd << "--username=#{cache[:user]}" if cache[:user]
53
53
  cmd << "--password=#{cache[:password]}" if cache[:password]
54
54
  cmd << "--server=#{cache[:server]}" if cache[:server]
55
55
  builder.packager.command! cmd.join(' '), desc: "Docker cache account login"
@@ -61,16 +61,30 @@ module Buildizer
61
61
  end
62
62
 
63
63
  def pull_image(image)
64
- builder.packager.command!("docker pull #{image.base_image}",
65
- desc: "Docker pull #{image.base_image}")
66
-
67
- builder.packager.command("docker pull #{image.name}",
68
- desc: "Docker pull #{image.name}") if cache
64
+ builder.packager.command! "docker pull #{image.base_image}", desc: "Pull docker base image #{image.base_image}"
65
+ if cache
66
+ pull_cache_res = builder.packager.command(
67
+ "docker pull #{image.cache_name}",
68
+ desc: "Try to pull docker cache image #{image.cache_name}"
69
+ )
70
+ if pull_cache_res.status.success?
71
+ builder.packager.command! "docker tag -f #{image.cache_name} #{image.name}",
72
+ desc: "Tag cache image #{image.cache_name}" +
73
+ " as prepared build image #{image.name}"
74
+ builder.packager.command! "docker rmi #{image.cache_name}",
75
+ desc: "Remove cache image #{image.cache_name}"
76
+ end
77
+ end
69
78
  end
70
79
 
71
80
  def push_image(image)
72
- builder.packager.command("docker push #{image.name}",
73
- desc: "Docker push #{image.name}") if cache
81
+ if cache
82
+ builder.packager.command! "docker tag -f #{image.name} #{image.cache_name}",
83
+ desc: "Tag prepared build image #{image.name}" +
84
+ " as cache image #{image.cache_name}"
85
+ builder.packager.command! "docker push #{image.cache_name}",
86
+ desc: "Push cache image #{image.cache_name}"
87
+ end
74
88
  end
75
89
 
76
90
  def build_image!(target)
@@ -78,7 +92,7 @@ module Buildizer
78
92
 
79
93
  target.image_work_path.join('Dockerfile').write [*target.image.instructions, nil].join("\n")
80
94
  builder.packager.command! "docker build -t #{target.image.name} #{target.image_work_path}",
81
- desc: "Docker build image #{target.image.name}"
95
+ desc: "Build docker image #{target.image.name}"
82
96
 
83
97
  push_image target.image
84
98
  end
@@ -48,6 +48,10 @@ module Buildizer
48
48
  target.docker_image
49
49
  end
50
50
 
51
+ def cache_name
52
+ target.docker_cache_image
53
+ end
54
+
51
55
  def instruction(instruction, cmd)
52
56
  instructions << [instruction.to_s.upcase, cmd].join(' ')
53
57
  end
@@ -0,0 +1,63 @@
1
+ module Buildizer
2
+ class Packager
3
+ module BuildizerConfMod
4
+ using Refine
5
+
6
+ def buildizer_conf_path
7
+ package_path.join('Buildizer')
8
+ end
9
+
10
+ def buildizer_conf
11
+ @buildizer_conf ||= buildizer_conf_path.load_yaml
12
+ end
13
+
14
+ def buildizer_conf_update(conf)
15
+ buildizer_conf.update conf
16
+ end
17
+
18
+ def buildizer_conf_setup!
19
+ write_path(buildizer_conf_path, YAML.dump(buildizer_conf))
20
+ end
21
+
22
+ def package_name
23
+ buildizer_conf['package_name']
24
+ end
25
+
26
+ def package_version
27
+ buildizer_conf['package_version']
28
+ end
29
+
30
+ def before_prepare
31
+ Array(buildizer_conf['before_prepare'])
32
+ end
33
+
34
+ def after_prepare
35
+ Array(buildizer_conf['after_prepare'])
36
+ end
37
+
38
+ def targets
39
+ targets = Array(buildizer_conf['target'])
40
+ restrict_targets = ENV['BUILDIZER_TARGET']
41
+ restrict_targets = restrict_targets.split(',').map(&:strip) if restrict_targets
42
+ targets = targets & restrict_targets if restrict_targets
43
+ targets
44
+ end
45
+
46
+ def prepare
47
+ Array(buildizer_conf['prepare'])
48
+ end
49
+
50
+ def build_dep
51
+ Array(buildizer_conf['build_dep']).to_set
52
+ end
53
+
54
+ def before_build
55
+ Array(buildizer_conf['before_build'])
56
+ end
57
+
58
+ def maintainer
59
+ buildizer_conf['maintainer']
60
+ end
61
+ end # BuildizerConfMod
62
+ end # Packager
63
+ end # Buildizer
@@ -0,0 +1,27 @@
1
+ module Buildizer
2
+ class Packager
3
+ module CiMod
4
+ def ci_name
5
+ @ci_name ||= begin
6
+ case git_remote_url.to_s
7
+ when /github/
8
+ 'travis'
9
+ when /gitlab/
10
+ 'gitlab-ci'
11
+ else
12
+ raise Error, error: :input_error, message: "unable to determine ci to use"
13
+ end
14
+ end
15
+ end
16
+
17
+ def ci
18
+ @ci ||= begin
19
+ klass = {'travis' => Ci::Travis,
20
+ 'gitlab-ci' => Ci::GitlabCi}[ci_name.to_s.downcase]
21
+ raise Error, message: "unknown ci '#{ci_name}'" unless klass
22
+ klass.new(self)
23
+ end
24
+ end
25
+ end # CiMod
26
+ end # Packager
27
+ end # Buildizer
@@ -0,0 +1,103 @@
1
+ module Buildizer
2
+ class Packager
3
+ module DockerCacheMod
4
+ def docker_cache
5
+ return unless repo = ENV['BUILDIZER_DOCKER_CACHE']
6
+ {user: ENV['BUILDIZER_DOCKER_CACHE_USERNAME'],
7
+ password: ENV['BUILDIZER_DOCKER_CACHE_PASSWORD'],
8
+ email: ENV['BUILDIZER_DOCKER_CACHE_EMAIL'],
9
+ server: ENV['BUILDIZER_DOCKER_CACHE_SERVER'],
10
+ repo: repo}
11
+ end
12
+
13
+ def setup_docker_cache_repo
14
+ cli.options['docker_cache']
15
+ end
16
+
17
+ def setup_docker_cache_org
18
+ setup_docker_cache_repo.split('/').first
19
+ end
20
+
21
+ def setup_docker_cache_user
22
+ cli.options['docker_cache_user'] || user_settings_docker_cache_user_list(setup_docker_cache_org).first
23
+ end
24
+
25
+ def setup_docker_cache_password
26
+ @setup_docker_cache_password ||= begin
27
+ settings_password = user_settings_docker_cache_user(setup_docker_cache_user)['password']
28
+ if cli.options['reset_docker_cache_password'] or settings_password.nil?
29
+ cli.ask("Docker cache user '#{setup_docker_cache_user}' password:", echo: false).tap{puts}
30
+ else
31
+ settings_password
32
+ end
33
+ end
34
+ end
35
+
36
+ def setup_docker_cache_email
37
+ cli.options['docker_cache_email'] || user_settings_docker_cache_user(setup_docker_cache_user)['email']
38
+ end
39
+
40
+ def setup_docker_cache_server
41
+ cli.options['docker_cache_server'] || user_settings_docker_cache_user(setup_docker_cache_user)['server']
42
+ end
43
+
44
+ def user_settings_docker_cache
45
+ user_settings['docker_cache'] ||= {}
46
+ end
47
+
48
+ def user_settings_docker_cache_org(org)
49
+ user_settings_docker_cache['org'] ||= {}
50
+ user_settings_docker_cache['org'][org] ||= {}
51
+ end
52
+
53
+ def user_settings_docker_cache_user(user)
54
+ user_settings_docker_cache['user'] ||= {}
55
+ user_settings_docker_cache['user'][user] ||= {}
56
+ end
57
+
58
+ def user_settings_docker_cache_user_list(org)
59
+ user_settings_docker_cache_org(org)['user'] ||= []
60
+ end
61
+
62
+ def user_settings_docker_cache_repo_list(org)
63
+ user_settings_docker_cache_org(org)['repo'] ||= []
64
+ end
65
+
66
+ def docker_cache_update_settings?
67
+ not setup_docker_cache_repo.nil?
68
+ end
69
+
70
+ def docker_cache_clear_settings?
71
+ cli.options['clear_docker_cache']
72
+ end
73
+
74
+ def docker_cache_setup!
75
+ if docker_cache_update_settings?
76
+ raise Error, error: :input_error,
77
+ message: "docker cache user required" unless setup_docker_cache_user
78
+ raise Error, error: :input_error,
79
+ message: "bad docker cache user" if setup_docker_cache_user.empty?
80
+
81
+ user_list = user_settings_docker_cache_user_list(setup_docker_cache_org)
82
+ user_list.push(setup_docker_cache_user) unless user_list.include? setup_docker_cache_user
83
+
84
+ raise Error, error: :input_error,
85
+ message: 'docker cache email required' unless setup_docker_cache_email
86
+ raise Error, error: :input_error,
87
+ message: "bad docker cache email" unless setup_docker_cache_email =~ /.+@.+/
88
+
89
+ user_settings_docker_cache_user(setup_docker_cache_user)['email'] = setup_docker_cache_email
90
+ user_settings_docker_cache_user(setup_docker_cache_user)['server'] = setup_docker_cache_server
91
+ user_settings_docker_cache_user(setup_docker_cache_user)['password'] = setup_docker_cache_password
92
+
93
+ repo_list = user_settings_docker_cache_repo_list(setup_docker_cache_org)
94
+ repo_list.push(setup_docker_cache_repo) unless repo_list.include? setup_docker_cache_repo
95
+
96
+ user_settings_save!
97
+ end
98
+
99
+ ci.docker_cache_setup!
100
+ end
101
+ end # DockerCacheMod
102
+ end # Packager
103
+ end # Buildizer
@@ -0,0 +1,16 @@
1
+ module Buildizer
2
+ class Packager
3
+ module GitMod
4
+ def git_available?
5
+ res = raw_command 'git status'
6
+ res.status.success?
7
+ end
8
+
9
+ def git_remote_url
10
+ return unless git_available?
11
+ res = raw_command 'git config --get remote.origin.url'
12
+ res.stdout.strip
13
+ end
14
+ end # GitMod
15
+ end # Packager
16
+ end # Buildizer
@@ -0,0 +1,61 @@
1
+ module Buildizer
2
+ class Packager
3
+ module MiscMod
4
+ def command(*args, do_raise: false, log_failure: nil, **kwargs)
5
+ if debug
6
+ Shellfold.run(*args, log_failure: log_failure, **kwargs).tap do |cmd|
7
+ if not cmd.status.success? and do_raise
8
+ raise Error.new(error: :error, message: "external command error")
9
+ end
10
+ end
11
+ else
12
+ raw_command(*args, do_raise: do_raise, **kwargs)
13
+ end
14
+ end
15
+
16
+ def command!(*args, **kwargs)
17
+ command(*args, do_raise: true, log_failure: true, **kwargs)
18
+ end
19
+
20
+ def raw_command(*args, do_raise: false, **kwargs)
21
+ Mixlib::ShellOut.new(*args, **kwargs).tap do |cmd|
22
+ cmd.run_command
23
+ if not cmd.status.success? and do_raise
24
+ raise Error.new(error: :error,
25
+ message: "external command error: " +
26
+ [args.join(' '),
27
+ cmd.stdout + cmd.stderr].reject(&:empty?).join(' => '))
28
+ end
29
+ end
30
+ end
31
+
32
+ def raw_command!(*args, **kwargs)
33
+ raw_command(*args, do_raise: true, **kwargs)
34
+ end
35
+
36
+ def write_path(path, value)
37
+ with_log(desc: "Write path #{path}") do |&fin|
38
+ recreate = path.exist?
39
+ if path.exist?
40
+ if path.read == value
41
+ fin.call 'OK'
42
+ else
43
+ path.write value
44
+ fin.call 'UPDATED'
45
+ end
46
+ else
47
+ path.write value
48
+ fin.call 'CREATED'
49
+ end
50
+ end
51
+ end
52
+
53
+ def with_log(desc: nil, &blk)
54
+ puts(" #{desc}") if debug and desc
55
+ blk.call do |status|
56
+ puts("=> #{desc} [#{status || 'OK'}]") if debug and desc
57
+ end
58
+ end
59
+ end # MiscMod
60
+ end # Packager
61
+ end # Buildizer
@@ -0,0 +1,85 @@
1
+ module Buildizer
2
+ class Packager
3
+ module OvercommitMod
4
+ using Refine
5
+
6
+ def overcommit_conf_path
7
+ package_path.join('.overcommit.yml')
8
+ end
9
+
10
+ def overcommit_hooks_path
11
+ package_path.join('.git-hooks')
12
+ end
13
+
14
+ def overcommit_hooks_pre_commit_path
15
+ overcommit_hooks_path.join('pre_commit')
16
+ end
17
+
18
+ def overcommit_conf
19
+ @overcommit_conf ||= overcommit_conf_path.load_yaml
20
+ end
21
+
22
+ def overcommit_conf_raw
23
+ YAML.dump(overcommit_conf)
24
+ end
25
+
26
+ def overcommit_conf_dump!
27
+ write_path overcommit_conf_path, overcommit_conf_raw
28
+ command! 'overcommit --sign'
29
+ end
30
+
31
+ def overcommit_setup!
32
+ overcommit_hooks_path.mkpath
33
+ overcommit_conf_dump!
34
+ command! 'overcommit --install'
35
+ end
36
+
37
+ def overcommit_verify_setup!
38
+ hookcode = <<-HOOKCODE
39
+ module Overcommit::Hook::PreCommit
40
+ class BuildizerVerify < Base
41
+ def run
42
+ return :fail unless system("buildizer verify")
43
+ :pass
44
+ end
45
+ end
46
+ end
47
+ HOOKCODE
48
+
49
+ _overcommit_add_precommit!(:buildizer_verify, hookcode, desc: "Verify Buildizer conf file")
50
+ end
51
+
52
+ def overcommit_ci_setup!
53
+ hookcode = <<-HOOKCODE
54
+ module Overcommit::Hook::PreCommit
55
+ class BuildizerCiVerify < Base
56
+ def run
57
+ return :fail unless system("buildizer setup --verify-ci")
58
+ :pass
59
+ end
60
+ end
61
+ end
62
+ HOOKCODE
63
+
64
+ _overcommit_add_precommit!(:buildizer_ci_verify, hookcode,
65
+ desc: "Verify #{ci.ci_name} configuration is up to date")
66
+ end
67
+
68
+ def _overcommit_add_precommit!(name, hookcode, desc: nil, required: true)
69
+ hook_name = name.to_s.split('_').map(&:capitalize).join
70
+ overcommit_conf['PreCommit'] ||= {}
71
+ overcommit_conf['PreCommit'][hook_name] = {}.tap do |hook|
72
+ hook['enabled'] = true
73
+ hook['required'] = required
74
+ hook['desc'] = desc if desc
75
+ end
76
+ overcommit_conf_dump!
77
+
78
+ overcommit_hooks_pre_commit_path.mkpath
79
+ path = overcommit_hooks_pre_commit_path.join("#{name}.rb")
80
+ write_path path, hookcode
81
+ command! 'overcommit --sign pre-commit'
82
+ end
83
+ end # OvercommitMod
84
+ end # Packager
85
+ end # Buildizer
@@ -0,0 +1,81 @@
1
+ module Buildizer
2
+ class Packager
3
+ module PackageCloudMod
4
+ def package_cloud_repo
5
+ ENV['PACKAGECLOUD'].to_s.split(',')
6
+ end
7
+
8
+ def package_cloud_org
9
+ default_token = ENV['PACKAGECLOUD_TOKEN']
10
+ package_cloud_repo.map {|repo| repo.split('/').first}.uniq.map do |org|
11
+ [org, ENV["PACKAGECLOUD_TOKEN_#{org.upcase}"] || default_token]
12
+ end.to_h
13
+ end
14
+
15
+ def package_cloud
16
+ tokens = package_cloud_org
17
+ package_cloud_repo.map do |repo|
18
+ org = repo.split('/').first
19
+ token = tokens[org]
20
+ {org: org, repo: repo, token: token}
21
+ end
22
+ end
23
+
24
+ def user_settings_package_cloud
25
+ user_settings['package_cloud'] ||= {}
26
+ end
27
+
28
+ def user_settings_package_cloud_token
29
+ user_settings_package_cloud['token'] ||= {}
30
+ end
31
+
32
+ def setup_package_cloud_repo_list
33
+ Array(cli.options['package_cloud']).uniq
34
+ end
35
+
36
+ def setup_package_cloud_repo_desc_list
37
+ setup_package_cloud_repo_list.map do |repo|
38
+ org, name = repo.split('/')
39
+ {repo: repo, org: org, name: name, token: user_settings_package_cloud_token[org]}
40
+ end
41
+ end
42
+
43
+ def setup_package_cloud_org_desc_list
44
+ setup_package_cloud_repo_desc_list.map {|desc| {org: desc[:org], token: desc[:token]}}.uniq
45
+ end
46
+
47
+ def setup_package_cloud_org_list
48
+ setup_package_cloud_repo_desc_list.map {|desc| desc[:org]}.uniq
49
+ end
50
+
51
+ def package_cloud_update_settings?
52
+ cli.options['package_cloud']
53
+ end
54
+
55
+ def package_cloud_clear_settings?
56
+ cli.options['clear_package_cloud']
57
+ end
58
+
59
+ def package_cloud_setup!
60
+ if package_cloud_update_settings?
61
+ update_user_settings = false
62
+ setup_package_cloud_org_list.each do |org|
63
+ if user_settings_package_cloud_token[org].nil? or
64
+ cli.options['reset_package_cloud_token']
65
+ token = cli.ask("Enter token for package_cloud org '#{org}':",
66
+ echo: false, default: 'none').tap{puts}
67
+ token = (token == 'none' ? nil : token)
68
+ if user_settings_package_cloud_token[org] != token
69
+ user_settings_package_cloud_token[org] = token
70
+ update_user_settings = true
71
+ end
72
+ end
73
+ end
74
+ user_settings_save! if update_user_settings
75
+ end
76
+
77
+ ci.package_cloud_setup!
78
+ end
79
+ end # PackageCloudMod
80
+ end # Packager
81
+ end # Buildizer
@@ -0,0 +1,15 @@
1
+ module Buildizer
2
+ class Packager
3
+ module PackageVersionTagMod
4
+ using Refine
5
+
6
+ def package_version_tag_required_for_deploy?
7
+ ENV['BUILDIZER_REQUIRE_TAG'].to_s.on?
8
+ end
9
+
10
+ def package_version_tag
11
+ ci.git_tag
12
+ end
13
+ end # PackageVersionTagMod
14
+ end # Packager
15
+ end # Buildizer
@@ -0,0 +1,27 @@
1
+ module Buildizer
2
+ class Packager
3
+ module ProjectSettingsMod
4
+ using Refine
5
+
6
+ def project_settings_path
7
+ package_path.join('.buildizer.yml')
8
+ end
9
+
10
+ def project_settings
11
+ @project_settings ||= begin
12
+ (project_settings_path.load_yaml || {}).tap do |settings|
13
+ settings['master'] = cli.options['master'] if cli.options.key? 'master'
14
+ end
15
+ end
16
+ end
17
+
18
+ def project_settings_save!
19
+ write_path(project_settings_path, YAML.dump(project_settings))
20
+ end
21
+
22
+ def project_settings_setup!
23
+ project_settings_save!
24
+ end
25
+ end # ProjectSettingsMod
26
+ end # Packager
27
+ end # Buildizer
@@ -0,0 +1,24 @@
1
+ module Buildizer
2
+ class Packager
3
+ module UserSettingsMod
4
+ using Refine
5
+
6
+ def user_settings_path
7
+ work_path.join('settings.yml')
8
+ end
9
+
10
+ def user_settings
11
+ @user_settings ||= (user_settings_path.load_yaml || {})
12
+ end
13
+
14
+ def user_settings_save!
15
+ write_path(user_settings_path, YAML.dump(user_settings))
16
+ user_settings_path.chmod(0600)
17
+ end
18
+
19
+ def user_settings_setup!
20
+ user_settings_save!
21
+ end
22
+ end # UserSettingsMod
23
+ end # Packager
24
+ end # Buildizer