dg 0.5 → 0.5.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 +4 -4
- data/bin/dg +3 -2
- data/dg.gemspec +2 -3
- data/lib/dg/docker.rb +208 -0
- data/lib/dg/version.rb +3 -0
- data/lib/dg.rb +2 -0
- metadata +5 -3
- data/lib/docker.rb +0 -205
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ea454cd0784d6c489275883291af104a9ea7b1f
|
4
|
+
data.tar.gz: 1ed46c4d42a64c437a8afbbadb68a961f6a9fc11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd252529938d78224bffeaa4e024610c3000d899839572e2bbdd7671f0ee86c46acbedb4e0017b812e29e88cb4365984588726371c5a0386c2638001579161f2
|
7
|
+
data.tar.gz: 20b50abd57ee7caccf42e2346734fdec9eaf8a4c3fb8b7fe81183095a1d485db2b14761c013c05c5ca8c982663aa8fa83e99185c6ef46d71a50128b8c3f7bb60
|
data/bin/dg
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
$:.push File.expand_path("../../lib", __FILE__)
|
4
|
+
require 'dg/docker'
|
4
5
|
|
5
6
|
COMMANDS = %w(
|
6
7
|
-h
|
@@ -18,7 +19,7 @@ COMMANDS = %w(
|
|
18
19
|
)
|
19
20
|
|
20
21
|
if COMMANDS.include?(ARGV.first)
|
21
|
-
Docker.send(ARGV.first.tr('-','').to_sym)
|
22
|
+
DG::Docker.send(ARGV.first.tr('-','').to_sym)
|
22
23
|
exit 0
|
23
24
|
else
|
24
25
|
STDERR.puts "You must supply a command (#{COMMANDS.join(', ')})"
|
data/dg.gemspec
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
$:.push File.expand_path("../lib", __FILE__)
|
2
|
-
|
3
|
-
VERSION = '0.5'
|
2
|
+
require 'dg/version'
|
4
3
|
|
5
4
|
# Describe your gem and declare its dependencies:
|
6
5
|
Gem::Specification.new do |s|
|
7
6
|
s.name = "dg"
|
8
|
-
s.version = VERSION
|
7
|
+
s.version = DG::VERSION
|
9
8
|
s.authors = ["Michael Malet"]
|
10
9
|
s.email = ["michael@nervd.com"]
|
11
10
|
s.homepage = "https://github.com/shinyscorpion/dg"
|
data/lib/dg/docker.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'pty'
|
2
|
+
require 'uri'
|
3
|
+
require 'net/http'
|
4
|
+
require 'dg/version'
|
5
|
+
|
6
|
+
module DG
|
7
|
+
class Docker
|
8
|
+
MATERIAL_NAME = ENV['MATERIAL_NAME'] || 'BITBUCKET'
|
9
|
+
SUDO = !!ENV["GO_REVISION_#{MATERIAL_NAME}"]
|
10
|
+
BASEPATH = Dir.pwd
|
11
|
+
|
12
|
+
FIG_YML_PATH = "#{BASEPATH}/fig.yml"
|
13
|
+
FIG_GEN_PATH = "#{BASEPATH}/fig_gen.yml"
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
def build
|
18
|
+
build_docker_image_with_tag
|
19
|
+
end
|
20
|
+
|
21
|
+
def debug
|
22
|
+
generate_fig_yaml
|
23
|
+
debug_app
|
24
|
+
end
|
25
|
+
|
26
|
+
def purge
|
27
|
+
run_with_output("docker rm $(docker ps -a -q) && docker rmi $(docker images -q)")
|
28
|
+
end
|
29
|
+
|
30
|
+
def push
|
31
|
+
run_with_output("docker push #{git_image_name.tr(':',' ')}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def deploy
|
35
|
+
required_envs = %w(GO_HOST GO_USER GO_PWD)
|
36
|
+
unless required_envs.reduce{ |acc, e| acc && ENV[e] }
|
37
|
+
error!(
|
38
|
+
RuntimeError.new("Environment variables {#{required_envs.join(', ')}} must be set"),
|
39
|
+
'triggering pipeline'
|
40
|
+
)
|
41
|
+
end
|
42
|
+
deploy_stages.each do |deploy_stage|
|
43
|
+
schedule_pipeline(project_name, deploy_stage, git_image_name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def deploy_stages
|
48
|
+
candidates = Dir['deploy-to*']
|
49
|
+
if candidates.size == 1
|
50
|
+
script = candidates.first
|
51
|
+
if File.executable?(script)
|
52
|
+
branch = ENV['GIT_BRANCH'] ||
|
53
|
+
`git symbolic-ref --short -q HEAD`.strip
|
54
|
+
return `./#{script} #{branch}`.strip.split(',')
|
55
|
+
else
|
56
|
+
error!(
|
57
|
+
RuntimeError.new(
|
58
|
+
%(Deploy-to script: "#{script}" must be executable! (e.g. chmod +x #{script}))
|
59
|
+
),
|
60
|
+
"determining stage to deploy to"
|
61
|
+
)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
error!(
|
65
|
+
RuntimeError.new(
|
66
|
+
"There must be a deploy-to* script " +
|
67
|
+
"(e.g. deploy-to.{rb|sh|js}): #{candidates.size} found"
|
68
|
+
),
|
69
|
+
"determining stage to deploy to"
|
70
|
+
)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def run
|
75
|
+
generate_fig_yaml
|
76
|
+
run_app
|
77
|
+
end
|
78
|
+
|
79
|
+
def test
|
80
|
+
generate_fig_yaml
|
81
|
+
run_tests
|
82
|
+
end
|
83
|
+
|
84
|
+
def version
|
85
|
+
puts "v#{DG::VERSION}"
|
86
|
+
end
|
87
|
+
alias_method :v, :version
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def error!(e, step = "executing")
|
92
|
+
STDERR.puts "An error occurred while #{step}: #{e.message}"
|
93
|
+
exit 1
|
94
|
+
end
|
95
|
+
|
96
|
+
def run_with_output(command)
|
97
|
+
sudo_command = SUDO ? "sudo -E bash -c '#{command}'" : command
|
98
|
+
puts "Running `#{sudo_command}` in #{Dir.pwd}"
|
99
|
+
PTY.spawn(sudo_command) do |stdin, stdout, pid|
|
100
|
+
stdin.each { |line| print line } rescue Errno::EIO
|
101
|
+
Process.wait(pid)
|
102
|
+
end
|
103
|
+
status_code = $?.exitstatus
|
104
|
+
|
105
|
+
error!(RuntimeError.new("exit code was #{status_code}"), "executing #{command}") if status_code != 0
|
106
|
+
rescue PTY::ChildExited
|
107
|
+
puts "The child process exited!"
|
108
|
+
end
|
109
|
+
|
110
|
+
def fig_yml
|
111
|
+
@@fig_yml ||= File.read(FIG_YML_PATH)
|
112
|
+
rescue => e
|
113
|
+
error!(e, "reading fig.yml from #{FIG_YML_PATH}")
|
114
|
+
end
|
115
|
+
|
116
|
+
def project_name
|
117
|
+
@@project_name ||= ENV['GO_PIPELINE_NAME'] || image_name.split('/').last
|
118
|
+
end
|
119
|
+
|
120
|
+
# Infer the project name from the image specified in the fig.yml
|
121
|
+
def image_name
|
122
|
+
@@image_name ||= fig_yml.match(/\s+image: (.*)/)[1]
|
123
|
+
end
|
124
|
+
|
125
|
+
# Add the git commit hash to the image name
|
126
|
+
def git_image_name
|
127
|
+
@@git_image_name ||=
|
128
|
+
"#{image_name}:#{ENV['GO_REVISION_BITBUCKET'] ||
|
129
|
+
`git rev-parse HEAD`.strip}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def generate_fig_yaml
|
133
|
+
File.write(
|
134
|
+
FIG_GEN_PATH,
|
135
|
+
fig_yml.sub(image_name, git_image_name)
|
136
|
+
)
|
137
|
+
rescue => e
|
138
|
+
error!(e, "generating new fig.yml")
|
139
|
+
end
|
140
|
+
|
141
|
+
def build_docker_image_with_tag
|
142
|
+
run_with_output("docker build -t #{git_image_name} #{BASEPATH}")
|
143
|
+
rescue => e
|
144
|
+
error!(e, "building docker image")
|
145
|
+
end
|
146
|
+
|
147
|
+
def run_tests
|
148
|
+
run_with_output("fig -f #{FIG_GEN_PATH} run test")
|
149
|
+
rescue => e
|
150
|
+
error!(e, "running tests")
|
151
|
+
end
|
152
|
+
|
153
|
+
def run_app
|
154
|
+
run_with_output("fig -f #{FIG_GEN_PATH} up -d web")
|
155
|
+
end
|
156
|
+
|
157
|
+
def debug_app
|
158
|
+
puts "docker run -it --entrypoint=/bin/bash #{git_image_name}"
|
159
|
+
end
|
160
|
+
|
161
|
+
def schedule_pipeline(project_name, deploy_stage, image_id)
|
162
|
+
pipeline_name = "docker-#{project_name}-#{deploy_stage}"
|
163
|
+
|
164
|
+
uri = URI("https://#{ENV['GO_HOST']}/go/api/pipelines/#{pipeline_name}/schedule")
|
165
|
+
request = Net::HTTP::Post.new(uri.path)
|
166
|
+
request.basic_auth ENV['GO_USER'], ENV['GO_PWD']
|
167
|
+
request.set_form_data({ 'variables[IMAGE_ID]' => git_image_name.gsub('/','\/') })
|
168
|
+
|
169
|
+
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
170
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
171
|
+
http.ssl_version = :SSLv3
|
172
|
+
http.request(request)
|
173
|
+
end
|
174
|
+
|
175
|
+
if response.code.to_i == 202
|
176
|
+
puts response.body.strip
|
177
|
+
else
|
178
|
+
error!(
|
179
|
+
RuntimeError.new(
|
180
|
+
"response code was #{response.code}: #{response.body.strip}"
|
181
|
+
),
|
182
|
+
"scheduling pipeline"
|
183
|
+
)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def help
|
188
|
+
puts "Usage: dg COMMAND
|
189
|
+
|
190
|
+
A helper for building, testing, and running docker images via docker & fig.
|
191
|
+
|
192
|
+
Commands:
|
193
|
+
build Build an image based on your fig.yml (tags with the project's Git commit hash)
|
194
|
+
debug Debug a previously built image (!) THIS MUST BE RUN IN A SUBSHELL: `$(dim debug)`
|
195
|
+
deploy Trigger the GoCD pipeline for this project
|
196
|
+
help Display this help text
|
197
|
+
purge Remove ALL docker containers and images (not just for this project!)
|
198
|
+
push Push the image to your docker registry
|
199
|
+
run Run the image using your fig.yml's `web` config
|
200
|
+
test Run the image using your fig.yml's `test` config
|
201
|
+
version Display the current dg version
|
202
|
+
".gsub(/^ {6}/,'')
|
203
|
+
end
|
204
|
+
alias_method :h, :help
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
end
|
data/lib/dg/version.rb
ADDED
data/lib/dg.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Malet
|
@@ -33,7 +33,9 @@ files:
|
|
33
33
|
- README.md
|
34
34
|
- bin/dg
|
35
35
|
- dg.gemspec
|
36
|
-
- lib/
|
36
|
+
- lib/dg.rb
|
37
|
+
- lib/dg/docker.rb
|
38
|
+
- lib/dg/version.rb
|
37
39
|
homepage: https://github.com/shinyscorpion/dg
|
38
40
|
licenses:
|
39
41
|
- MIT
|
@@ -54,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
56
|
version: '0'
|
55
57
|
requirements: []
|
56
58
|
rubyforge_project:
|
57
|
-
rubygems_version: 2.
|
59
|
+
rubygems_version: 2.2.2
|
58
60
|
signing_key:
|
59
61
|
specification_version: 4
|
60
62
|
summary: Provides integration between Docker and GoCD.
|
data/lib/docker.rb
DELETED
@@ -1,205 +0,0 @@
|
|
1
|
-
require 'pty'
|
2
|
-
require 'uri'
|
3
|
-
require 'net/http'
|
4
|
-
|
5
|
-
class Docker
|
6
|
-
MATERIAL_NAME = ENV['MATERIAL_NAME'] || 'BITBUCKET'
|
7
|
-
SUDO = !!ENV["GO_REVISION_#{MATERIAL_NAME}"]
|
8
|
-
BASEPATH = Dir.pwd
|
9
|
-
GIT_COMMIT = ENV['GO_REVISION_BITBUCKET'] || `git rev-parse HEAD`.strip
|
10
|
-
|
11
|
-
FIG_YML_PATH = "#{BASEPATH}/fig.yml"
|
12
|
-
FIG_GEN_PATH = "#{BASEPATH}/fig_gen.yml"
|
13
|
-
|
14
|
-
class << self
|
15
|
-
|
16
|
-
def build
|
17
|
-
build_docker_image_with_tag
|
18
|
-
end
|
19
|
-
|
20
|
-
def debug
|
21
|
-
generate_fig_yaml
|
22
|
-
debug_app
|
23
|
-
end
|
24
|
-
|
25
|
-
def purge
|
26
|
-
run_with_output("docker rm $(docker ps -a -q) && docker rmi $(docker images -q)")
|
27
|
-
end
|
28
|
-
|
29
|
-
def push
|
30
|
-
run_with_output("docker push #{git_image_name.tr(':',' ')}")
|
31
|
-
end
|
32
|
-
|
33
|
-
def deploy
|
34
|
-
required_envs = %w(GO_HOST GO_USER GO_PWD)
|
35
|
-
unless required_envs.reduce{ |acc, e| acc && ENV[e] }
|
36
|
-
error!(
|
37
|
-
RuntimeError.new("Environment variables {#{required_envs.join(', ')}} must be set"),
|
38
|
-
'triggering pipeline'
|
39
|
-
)
|
40
|
-
end
|
41
|
-
deploy_stages.each do |deploy_stage|
|
42
|
-
schedule_pipeline(project_name, deploy_stage, git_image_name)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def deploy_stages
|
47
|
-
candidates = Dir['deploy-to*']
|
48
|
-
if candidates.size == 1
|
49
|
-
script = candidates.first
|
50
|
-
if File.executable?(script)
|
51
|
-
branch = ENV['GIT_BRANCH'] ||
|
52
|
-
`git symbolic-ref --short -q HEAD`.strip
|
53
|
-
return `./#{script} #{branch}`.strip.split(',')
|
54
|
-
else
|
55
|
-
error!(
|
56
|
-
RuntimeError.new(
|
57
|
-
%(Deploy-to script: "#{script}" must be executable! (e.g. chmod +x #{script}))
|
58
|
-
),
|
59
|
-
"determining stage to deploy to"
|
60
|
-
)
|
61
|
-
end
|
62
|
-
else
|
63
|
-
error!(
|
64
|
-
RuntimeError.new(
|
65
|
-
"There must be a deploy-to* script " +
|
66
|
-
"(e.g. deploy-to.{rb|sh|js}): #{candidates.size} found"
|
67
|
-
),
|
68
|
-
"determining stage to deploy to"
|
69
|
-
)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def run
|
74
|
-
generate_fig_yaml
|
75
|
-
run_app
|
76
|
-
end
|
77
|
-
|
78
|
-
def test
|
79
|
-
generate_fig_yaml
|
80
|
-
run_tests
|
81
|
-
end
|
82
|
-
|
83
|
-
def version
|
84
|
-
puts "v#{VERSION}"
|
85
|
-
end
|
86
|
-
alias_method :v, :version
|
87
|
-
|
88
|
-
private
|
89
|
-
|
90
|
-
def error!(e, step = "executing")
|
91
|
-
STDERR.puts "An error occurred while #{step}: #{e.message}"
|
92
|
-
exit 1
|
93
|
-
end
|
94
|
-
|
95
|
-
def run_with_output(command)
|
96
|
-
sudo_command = SUDO ? "sudo -E bash -c '#{command}'" : command
|
97
|
-
puts "Running `#{sudo_command}` in #{Dir.pwd}"
|
98
|
-
PTY.spawn(sudo_command) do |stdin, stdout, pid|
|
99
|
-
stdin.each { |line| print line } rescue Errno::EIO
|
100
|
-
Process.wait(pid)
|
101
|
-
end
|
102
|
-
status_code = $?.exitstatus
|
103
|
-
|
104
|
-
error!(RuntimeError.new("exit code was #{status_code}"), "executing #{command}") if status_code != 0
|
105
|
-
rescue PTY::ChildExited
|
106
|
-
puts "The child process exited!"
|
107
|
-
end
|
108
|
-
|
109
|
-
def fig_yml
|
110
|
-
@@fig_yml ||= File.read(FIG_YML_PATH)
|
111
|
-
rescue => e
|
112
|
-
error!(e, "reading fig.yml from #{FIG_YML_PATH}")
|
113
|
-
end
|
114
|
-
|
115
|
-
def project_name
|
116
|
-
@@project_name ||= ENV['GO_PIPELINE_NAME'] || image_name.split('/').last
|
117
|
-
end
|
118
|
-
|
119
|
-
# Infer the project name from the image specified in the fig.yml
|
120
|
-
def image_name
|
121
|
-
@@image_name ||= fig_yml.match(/\s+image: (.*)/)[1]
|
122
|
-
end
|
123
|
-
|
124
|
-
# Add the git commit hash to the image name
|
125
|
-
def git_image_name
|
126
|
-
@@git_image_name ||= "#{image_name}:#{GIT_COMMIT}"
|
127
|
-
end
|
128
|
-
|
129
|
-
def generate_fig_yaml
|
130
|
-
File.write(
|
131
|
-
FIG_GEN_PATH,
|
132
|
-
fig_yml.sub(image_name, git_image_name)
|
133
|
-
)
|
134
|
-
rescue => e
|
135
|
-
error!(e, "generating new fig.yml")
|
136
|
-
end
|
137
|
-
|
138
|
-
def build_docker_image_with_tag
|
139
|
-
run_with_output("docker build -t #{git_image_name} #{BASEPATH}")
|
140
|
-
rescue => e
|
141
|
-
error!(e, "building docker image")
|
142
|
-
end
|
143
|
-
|
144
|
-
def run_tests
|
145
|
-
run_with_output("fig -f #{FIG_GEN_PATH} run test")
|
146
|
-
rescue => e
|
147
|
-
error!(e, "running tests")
|
148
|
-
end
|
149
|
-
|
150
|
-
def run_app
|
151
|
-
run_with_output("fig -f #{FIG_GEN_PATH} up -d web")
|
152
|
-
end
|
153
|
-
|
154
|
-
def debug_app
|
155
|
-
puts "docker run -it --entrypoint=/bin/bash #{git_image_name}"
|
156
|
-
end
|
157
|
-
|
158
|
-
def schedule_pipeline(project_name, deploy_stage, image_id)
|
159
|
-
pipeline_name = "docker-#{project_name}-#{deploy_stage}"
|
160
|
-
|
161
|
-
uri = URI("https://#{ENV['GO_HOST']}/go/api/pipelines/#{pipeline_name}/schedule")
|
162
|
-
request = Net::HTTP::Post.new(uri.path)
|
163
|
-
request.basic_auth ENV['GO_USER'], ENV['GO_PWD']
|
164
|
-
request.set_form_data({ 'variables[IMAGE_ID]' => git_image_name.gsub('/','\/') })
|
165
|
-
|
166
|
-
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
167
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
168
|
-
http.ssl_version = :SSLv3
|
169
|
-
http.request(request)
|
170
|
-
end
|
171
|
-
|
172
|
-
if response.code.to_i == 202
|
173
|
-
puts response.body.strip
|
174
|
-
else
|
175
|
-
error!(
|
176
|
-
RuntimeError.new(
|
177
|
-
"response code was #{response.code}: #{response.body.strip}"
|
178
|
-
),
|
179
|
-
"scheduling pipeline"
|
180
|
-
)
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def help
|
185
|
-
puts "Usage: dg COMMAND
|
186
|
-
|
187
|
-
A helper for building, testing, and running docker images via docker & fig.
|
188
|
-
|
189
|
-
Commands:
|
190
|
-
build Build an image based on your fig.yml (tags with the project's Git commit hash)
|
191
|
-
debug Debug a previously built image (!) THIS MUST BE RUN IN A SUBSHELL: `$(dim debug)`
|
192
|
-
deploy Trigger the GoCD pipeline for this project
|
193
|
-
help Display this help text
|
194
|
-
purge Remove ALL docker containers and images (not just for this project!)
|
195
|
-
push Push the image to your docker registry
|
196
|
-
run Run the image using your fig.yml's `web` config
|
197
|
-
test Run the image using your fig.yml's `test` config
|
198
|
-
version Display the current dg version
|
199
|
-
".gsub(/^ {6}/,'')
|
200
|
-
end
|
201
|
-
alias_method :h, :help
|
202
|
-
end
|
203
|
-
|
204
|
-
end
|
205
|
-
|