brocket 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/Gemfile +8 -0
- data/README.md +42 -8
- data/lib/brocket.rb +19 -0
- data/lib/brocket/base.rb +5 -11
- data/lib/brocket/cli.rb +1 -1
- data/lib/brocket/configurable.rb +55 -0
- data/lib/brocket/docker.rb +45 -33
- data/lib/brocket/git.rb +20 -12
- data/lib/brocket/version.rb +1 -1
- data/lib/brocket/version_file.rb +14 -6
- data/spec/brocket/Dockerfiles/Dockerfile-gcr +22 -0
- data/spec/brocket/Dockerfiles/Dockerfile-hook +3 -0
- data/spec/brocket/Dockerfiles/Dockerfile-invalid-version +19 -0
- data/spec/brocket/Dockerfiles/Dockerfile-working_dir +21 -0
- data/spec/brocket/Dockerfiles/VERSION +1 -0
- data/spec/brocket/base_spec.rb +39 -0
- data/spec/brocket/docker_spec.rb +99 -7
- data/spec/brocket/git_spec.rb +94 -2
- data/spec/brocket/multi_app_proj/README.md +13 -0
- data/spec/brocket/multi_app_proj/app1/docker/Dockerfile +22 -0
- data/spec/brocket/multi_app_proj/app1/docker/VERSION.txt +1 -0
- data/spec/brocket/multi_app_proj/app2/Dockerfile +23 -0
- data/spec/brocket/multi_app_proj/app2/VERSION +1 -0
- data/spec/brocket/multi_app_proj_spec.rb +148 -0
- data/spec/brocket/test_gem/Dockerfile +18 -0
- data/spec/brocket/test_gem/README.md +7 -0
- data/spec/brocket/test_gem/lib/test_gem/version.rb +3 -0
- data/spec/brocket/test_gem_spec.rb +23 -0
- data/spec/brocket/version_file_spec.rb +33 -4
- data/spec/spec_helper.rb +18 -0
- metadata +49 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54c63386ef0806f1a1e9ac34e9692c8529ad2cc0
|
4
|
+
data.tar.gz: 5965c22451aec6eb6e003df5bbba94219383d1b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e80157b476a1ff419dcf54501b44dbaabb419ea62ed3d7e4c842fba6f1a2b46f7d0f1d21072097f2e4597b2642b6e809b212d8334a4ab1bdacbf285adb2bd07
|
7
|
+
data.tar.gz: 1cfadc60e0bf8e3b6cd42536d31311e394663b619dd6f80b5afcd21481764c709c295aa01a54ab755bc895ddefbb60efeb9635f536168a183c10279878fc3bdb
|
data/.rspec
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--format
|
1
|
+
--format Fuubar
|
2
2
|
--color
|
data/Gemfile
CHANGED
@@ -2,3 +2,11 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in brocket.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem "fuubar"
|
8
|
+
gem "yard" , require: false
|
9
|
+
gem 'simplecov' , require: false
|
10
|
+
gem 'simplecov-rcov', require: false
|
11
|
+
gem "pry"
|
12
|
+
end
|
data/README.md
CHANGED
@@ -12,11 +12,12 @@ config IMAGE_NAME and hooks like BEFORE_BUILD and AFTER_BUILD.
|
|
12
12
|
3. push by git
|
13
13
|
4. push by docker
|
14
14
|
- `brocket docker build`
|
15
|
-
1.
|
16
|
-
2.
|
15
|
+
1. cd WORKING_DIR
|
16
|
+
2. call BEFORE_BUILD
|
17
|
+
3. `docker build` with arguments
|
17
18
|
- call ON_BUILD_COMPLETE on success
|
18
19
|
- call ON_BUILD_ERROR on failure
|
19
|
-
|
20
|
+
4. call AFTER_BUILD
|
20
21
|
|
21
22
|
## Installation
|
22
23
|
|
@@ -54,6 +55,7 @@ add following line to your Dockerfile.
|
|
54
55
|
|
55
56
|
example https://github.com/tengine/brocket/blob/master/spec/brocket/Dockerfiles/Dockerfile-basic#L2
|
56
57
|
|
58
|
+
|
57
59
|
### bump up VERSION
|
58
60
|
|
59
61
|
When you increment VERSION file, you can use theese commands.
|
@@ -71,13 +73,14 @@ You can define commands to execute around `docker build` like this:
|
|
71
73
|
```
|
72
74
|
# [config] IMAGE_NAME: "groovenauts/rails-example"
|
73
75
|
# [config]
|
76
|
+
# [config] WORKING_DIR: ".."
|
77
|
+
# [config]
|
74
78
|
# [config] BEFORE_BUILD:
|
75
|
-
# [config] -
|
76
|
-
# [config] -
|
79
|
+
# [config] - rm log/*.log
|
80
|
+
# [config] - cp some/files dest
|
77
81
|
# [config]
|
78
82
|
# [config] AFTER_BUILD:
|
79
|
-
# [config] -
|
80
|
-
# [config] - mno
|
83
|
+
# [config] - rm -rf tmp/build
|
81
84
|
# [config]
|
82
85
|
# [config] ON_BUILD_COMPLETE: foo bar
|
83
86
|
# [config]
|
@@ -85,9 +88,40 @@ You can define commands to execute around `docker build` like this:
|
|
85
88
|
# [config]
|
86
89
|
```
|
87
90
|
|
88
|
-
|
89
91
|
https://github.com/tengine/brocket/blob/master/spec/brocket/Dockerfiles/Dockerfile-hook
|
90
92
|
|
93
|
+
### Other configurations
|
94
|
+
|
95
|
+
#### WORKING_DIR
|
96
|
+
|
97
|
+
The directory which the build command and hooks are executed in.
|
98
|
+
|
99
|
+
#### VERSION_FILE
|
100
|
+
|
101
|
+
A text file to define the container version. It must be a relative path from Dockerfile.
|
102
|
+
|
103
|
+
#### VERSION_SCRIPT
|
104
|
+
|
105
|
+
A script to get the container version. It runs in the directory of Dockerfile.
|
106
|
+
|
107
|
+
`ruby -r ./lib/test_gem/version.rb -e 'puts TestGem::VERSION'`
|
108
|
+
|
109
|
+
#### GIT_TAG_PREFIX
|
110
|
+
|
111
|
+
The prefix for the version tags on git.
|
112
|
+
|
113
|
+
#### DOCKER_PUSH_COMMAND
|
114
|
+
|
115
|
+
Set `gcloud docker push` to push to [Google Cloud Registry](https://cloud.google.com/container-registry/docs/).
|
116
|
+
|
117
|
+
#### DOCKER_PUSH_REGISTRY
|
118
|
+
|
119
|
+
Set the registry host name to push not to hub.docker.com .
|
120
|
+
|
121
|
+
#### DOCKER_PUSH_USERNAME
|
122
|
+
|
123
|
+
Set the user name on the registry host to push.
|
124
|
+
|
91
125
|
|
92
126
|
### For more information
|
93
127
|
|
data/lib/brocket.rb
CHANGED
@@ -1,12 +1,31 @@
|
|
1
1
|
require "brocket/version"
|
2
2
|
|
3
|
+
require 'logger'
|
4
|
+
|
3
5
|
module BRocket
|
4
6
|
autoload :Cli , "brocket/cli"
|
5
7
|
autoload :Base , "brocket/base"
|
8
|
+
autoload :Configurable, "brocket/configurable"
|
6
9
|
autoload :VersionFile, "brocket/version_file"
|
7
10
|
autoload :Git , "brocket/git"
|
8
11
|
autoload :Docker , "brocket/docker"
|
9
12
|
|
10
13
|
class BuildError < StandardError
|
11
14
|
end
|
15
|
+
|
16
|
+
USER_PWD = Dir.pwd
|
17
|
+
|
18
|
+
class << self
|
19
|
+
attr_writer :logger
|
20
|
+
attr_writer :user_pwd
|
21
|
+
|
22
|
+
def logger
|
23
|
+
@logger ||= Logger.new($stderr)
|
24
|
+
end
|
25
|
+
|
26
|
+
def user_pwd
|
27
|
+
@user_pwd ||= USER_PWD
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
12
31
|
end
|
data/lib/brocket/base.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require "brocket"
|
2
2
|
|
3
|
-
require 'logger'
|
4
|
-
|
5
3
|
require 'thor'
|
6
4
|
require 'logger_pipe'
|
7
5
|
|
@@ -18,16 +16,12 @@ module BRocket
|
|
18
16
|
task
|
19
17
|
end
|
20
18
|
|
21
|
-
def opts
|
22
|
-
@opts ||= options || {}
|
23
|
-
end
|
24
|
-
|
25
19
|
def dryrun?
|
26
|
-
|
20
|
+
options[:dryrun]
|
27
21
|
end
|
28
22
|
|
29
23
|
def verbose?
|
30
|
-
|
24
|
+
options[:verbose]
|
31
25
|
end
|
32
26
|
|
33
27
|
def verbose(msg)
|
@@ -46,11 +40,11 @@ module BRocket
|
|
46
40
|
end
|
47
41
|
|
48
42
|
def logger
|
49
|
-
|
43
|
+
BRocket.logger
|
50
44
|
end
|
51
45
|
|
52
|
-
def sh(cmd
|
53
|
-
LoggerPipe.run(logger, cmd
|
46
|
+
def sh(cmd)
|
47
|
+
LoggerPipe.run(logger, cmd, dry_run: dryrun?)
|
54
48
|
end
|
55
49
|
|
56
50
|
end
|
data/lib/brocket/cli.rb
CHANGED
@@ -0,0 +1,55 @@
|
|
1
|
+
require "brocket"
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'thor'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
module BRocket
|
8
|
+
class Configurable < Base
|
9
|
+
CONFIG_LINE_SEP = "[config]".freeze
|
10
|
+
CONFIG_LINE_HEADER = /\A\#\s*#{Regexp.escape(CONFIG_LINE_SEP)}\s?/.freeze
|
11
|
+
|
12
|
+
class_option :dockerfile, aliases: '-f', type: :string, default: "Dockerfile", desc: "Dockerfile to build"
|
13
|
+
|
14
|
+
no_commands do
|
15
|
+
def config_image_name
|
16
|
+
img_name = (config_hash['IMAGE_NAME'] || '').strip
|
17
|
+
error "No IMAGE_NAME found in Dockerfile. Please add `# #{CONFIG_LINE_SEP} IMAGE_NAME: [IMAGE NAME on DockerHub]` in Dockerfile" if img_name.empty?
|
18
|
+
img_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def working_dir
|
22
|
+
dir = config_hash['WORKING_DIR'] || '.'
|
23
|
+
File.expand_path(dir, File.dirname(config_filepath))
|
24
|
+
end
|
25
|
+
|
26
|
+
def config_hash
|
27
|
+
@config_hash ||= load_config_hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_config_hash
|
31
|
+
content = read_config_file
|
32
|
+
lines = content.lines.select{|line| line =~ CONFIG_LINE_HEADER}.
|
33
|
+
map{|line| line.sub(CONFIG_LINE_HEADER, "")}
|
34
|
+
return (YAML.load(lines.join("\n")) || {})
|
35
|
+
end
|
36
|
+
|
37
|
+
def config_filepath
|
38
|
+
@config_filepath ||= File.expand_path(options[:dockerfile] || './Dockerfile', BRocket.user_pwd)
|
39
|
+
end
|
40
|
+
|
41
|
+
def config_relpath
|
42
|
+
config_p = Pathname.new(config_filepath)
|
43
|
+
base_p = Pathname.new(working_dir)
|
44
|
+
config_p.relative_path_from(base_p).to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
def read_config_file
|
48
|
+
unless File.readable?(config_filepath)
|
49
|
+
error "File not found: #{config_filepath}"
|
50
|
+
end
|
51
|
+
File.read(config_filepath)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/brocket/docker.rb
CHANGED
@@ -4,9 +4,7 @@ require 'yaml'
|
|
4
4
|
require 'thor'
|
5
5
|
|
6
6
|
module BRocket
|
7
|
-
class Docker <
|
8
|
-
CONFIG_LINE_SEP = "[config]".freeze
|
9
|
-
CONFIG_LINE_HEADER = /\A\#\s*#{Regexp.escape(CONFIG_LINE_SEP)}\s?/.freeze
|
7
|
+
class Docker < Configurable
|
10
8
|
|
11
9
|
desc "config", "show configurations in Dockerfile"
|
12
10
|
def config
|
@@ -17,17 +15,18 @@ module BRocket
|
|
17
15
|
def build
|
18
16
|
info("[docker build] starting")
|
19
17
|
c = config_hash
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
18
|
+
Dir.chdir(working_dir) do
|
19
|
+
begin
|
20
|
+
execute(c['BEFORE_BUILD'])
|
21
|
+
cmd = build_build_command
|
22
|
+
execute(cmd)
|
23
|
+
execute(c['ON_BUILD_COMPLETE'])
|
24
|
+
rescue
|
25
|
+
execute(c['ON_BUILD_ERROR'])
|
26
|
+
raise
|
27
|
+
ensure
|
28
|
+
execute(c['AFTER_BUILD'])
|
29
|
+
end
|
31
30
|
end
|
32
31
|
success("[docker build] OK")
|
33
32
|
end
|
@@ -35,40 +34,53 @@ module BRocket
|
|
35
34
|
desc "push", "push docker image to docker hub"
|
36
35
|
def push
|
37
36
|
info("[docker push] starting")
|
38
|
-
|
39
|
-
img_name = config_image_name(c)
|
40
|
-
version = sub(VersionFile).current
|
41
|
-
cmd = "docker push #{img_name}:#{version}"
|
37
|
+
cmd = build_push_command
|
42
38
|
sh(cmd)
|
43
39
|
success("[docker push] OK")
|
44
40
|
end
|
45
41
|
|
46
42
|
desc "call_before_build", "call BEFORE_BUILD callback manually"
|
47
43
|
def call_before_build
|
48
|
-
|
44
|
+
Dir.chdir(working_dir) do
|
45
|
+
execute(config_hash['BEFORE_BUILD'])
|
46
|
+
end
|
49
47
|
end
|
50
48
|
|
51
49
|
desc "call_after_build", "call AFTER_BUILD callback manually"
|
52
50
|
def call_after_build
|
53
|
-
|
51
|
+
Dir.chdir(working_dir) do
|
52
|
+
execute(config_hash['AFTER_BUILD'])
|
53
|
+
end
|
54
54
|
end
|
55
55
|
|
56
56
|
no_commands do
|
57
|
-
def
|
58
|
-
img_name =
|
59
|
-
|
60
|
-
img_name
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
57
|
+
def build_build_command
|
58
|
+
img_name = config_image_name
|
59
|
+
version = sub(VersionFile).current
|
60
|
+
cmd = "docker build -t #{img_name}:#{version}"
|
61
|
+
if options[:dockerfile]
|
62
|
+
fp = config_relpath
|
63
|
+
unless fp == "Dockerfile"
|
64
|
+
cmd << ' -f ' << config_relpath
|
65
|
+
end
|
66
|
+
end
|
67
|
+
cmd << ' .'
|
68
|
+
return cmd
|
68
69
|
end
|
69
70
|
|
70
|
-
def
|
71
|
-
|
71
|
+
def build_push_command
|
72
|
+
registry = config_hash['DOCKER_PUSH_REGISTRY']
|
73
|
+
username = config_hash['DOCKER_PUSH_USERNAME']
|
74
|
+
img_name = [registry, username, config_image_name].compact.join('/')
|
75
|
+
version = sub(VersionFile).current
|
76
|
+
build_cmd = config_hash['DOCKER_PUSH_COMMAND'] || 'docker push'
|
77
|
+
cmd = [
|
78
|
+
(registry || username) ?
|
79
|
+
"docker tag -f #{config_image_name}:#{version} #{img_name}:#{version}" :
|
80
|
+
nil,
|
81
|
+
"#{build_cmd} #{img_name}:#{version}",
|
82
|
+
].compact.join(' && ')
|
83
|
+
return cmd
|
72
84
|
end
|
73
85
|
|
74
86
|
def execute(commands)
|
data/lib/brocket/git.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
require "brocket"
|
2
2
|
|
3
|
+
require 'logger_pipe/runner'
|
4
|
+
|
3
5
|
module BRocket
|
4
|
-
class Git <
|
6
|
+
class Git < Configurable
|
5
7
|
|
6
8
|
desc "guard_clean", "Raise error if some difference exists."
|
7
9
|
def guard_clean
|
8
|
-
clean? && committed?
|
9
|
-
|
10
|
+
(clean? && committed?) ?
|
11
|
+
success("[git guard_clean] OK") :
|
12
|
+
error("There are files that need to be committed first. Run `git status`")
|
10
13
|
end
|
11
14
|
|
12
15
|
desc "push", "push commit and tag it"
|
@@ -18,16 +21,23 @@ module BRocket
|
|
18
21
|
|
19
22
|
no_commands do
|
20
23
|
|
21
|
-
|
24
|
+
# This method is called from BRocket::VersionFile#bump_on
|
25
|
+
def add_and_commit(filepath, msg)
|
22
26
|
sh("git add #{filepath} && git commit -m \"#{msg}\"")
|
23
27
|
end
|
24
28
|
|
25
29
|
def clean?
|
26
|
-
|
30
|
+
sh("git diff --exit-code")
|
31
|
+
return true
|
32
|
+
rescue LoggerPipe::Failure
|
33
|
+
return false
|
27
34
|
end
|
28
35
|
|
29
36
|
def committed?
|
30
|
-
|
37
|
+
sh("git diff-index --quiet --cached HEAD")
|
38
|
+
return true
|
39
|
+
rescue LoggerPipe::Failure
|
40
|
+
return false
|
31
41
|
end
|
32
42
|
|
33
43
|
def tag_version
|
@@ -36,20 +46,18 @@ module BRocket
|
|
36
46
|
yield if block_given?
|
37
47
|
rescue
|
38
48
|
$stderr.puts "Untagging #{version_tag} due to error."
|
39
|
-
|
49
|
+
sh "git tag -d #{version_tag}"
|
40
50
|
raise
|
41
51
|
end
|
42
52
|
|
43
53
|
def git_push
|
44
54
|
perform_git_push
|
45
|
-
perform_git_push '
|
55
|
+
perform_git_push '--tags'
|
46
56
|
$stdout.puts "Pushed git commits and tags."
|
47
57
|
end
|
48
58
|
|
49
|
-
def perform_git_push(options =
|
50
|
-
|
51
|
-
out, code = sh_with_code(cmd)
|
52
|
-
error "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0
|
59
|
+
def perform_git_push(options = nil)
|
60
|
+
sh(['git push', options].compact.join(' ' ))
|
53
61
|
end
|
54
62
|
|
55
63
|
def already_tagged?
|
data/lib/brocket/version.rb
CHANGED
data/lib/brocket/version_file.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require "brocket"
|
2
2
|
|
3
3
|
module BRocket
|
4
|
-
class VersionFile <
|
4
|
+
class VersionFile < Configurable
|
5
5
|
FILENAME = "VERSION".freeze
|
6
6
|
INITIAL_VERSION = "0.0.1".freeze
|
7
7
|
|
@@ -32,14 +32,22 @@ module BRocket
|
|
32
32
|
|
33
33
|
no_commands do
|
34
34
|
def filepath
|
35
|
-
|
35
|
+
File.expand_path(config_hash['VERSION_FILE'] || 'VERSION', File.dirname(config_filepath))
|
36
36
|
end
|
37
37
|
|
38
38
|
def read_file
|
39
|
-
|
40
|
-
|
39
|
+
vs = config_hash['VERSION_SCRIPT']
|
40
|
+
if vs
|
41
|
+
Dir.chdir(File.dirname(config_filepath)) do
|
42
|
+
res = `#{vs}`.strip
|
43
|
+
return $? == 0 ? res : error("Error on VERSION_SCRIPT: #{vs}")
|
44
|
+
end
|
41
45
|
else
|
42
|
-
|
46
|
+
if File.readable?(filepath)
|
47
|
+
File.read(filepath).strip
|
48
|
+
else
|
49
|
+
error "File not found #{filepath}. You can run `#{$0} init`"
|
50
|
+
end
|
43
51
|
end
|
44
52
|
end
|
45
53
|
alias_method :current, :read_file
|
@@ -62,7 +70,7 @@ module BRocket
|
|
62
70
|
ver = parts.join(".")
|
63
71
|
ver << "-" << suffix if suffix
|
64
72
|
write_file(ver)
|
65
|
-
sub(Git).
|
73
|
+
sub(Git).add_and_commit(filepath, "bump up #{pos.to_s} version: #{ver}")
|
66
74
|
success("[git #{pos.to_s}] #{ver}")
|
67
75
|
ver
|
68
76
|
end
|