capistrano-dockerbuild 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/capistrano-dockerbuild.gemspec +2 -2
- data/lib/capistrano/dockerbuild.rb +11 -0
- data/lib/capistrano/tasks/docker.rake +16 -21
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed984b515b7f0d43d3985d442dba5bf85c1539f3109d8360bf9864db5a549a2d
|
|
4
|
+
data.tar.gz: cbcea200c07484a17aec1edb9d6e5e99ec2548811e3bc3de34cec1f2deb993a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eb19d9ee91eb190e367a5dfe3fe75c9a695465afae9eff6d9a6f9d79c1548b4e6ede86a66f004bc4d9d23d5bbc56e70b719ca157903b59f8ca4251b4fc6342e7
|
|
7
|
+
data.tar.gz: 98752e45ab74d37285903f283efa3c8c2e167d51e8fd366c381099bc33b33b947c9a03ea018d93e90bfa91bcfbfd5a302288db93630a6700e671e7c9490f44e0
|
data/README.md
CHANGED
|
@@ -139,9 +139,11 @@ The temporary directory is removed automatically by `docker:clean` after `docker
|
|
|
139
139
|
|
|
140
140
|
#### docker:clone
|
|
141
141
|
- Clone repo to `#{docker_build_base_dir}` as mirror
|
|
142
|
+
- Serialized with `docker:update_mirror` via a `flock` keyed by `#{docker_build_base_dir}`'s basename, since both mutate the shared repo directory (a mirror by default, or a regular checkout under `:docker_build_no_worktree`) at `#{docker_build_base_dir}`. This matters when multiple deploys (e.g. CI jobs for different branches) target the same build host concurrently — without it, concurrent `git clone`/`git remote update` on the shared directory can corrupt its `.git/config` or fail with transport errors. Keying the lock by basename keeps unrelated consumers that share the same parent directory from serializing against each other.
|
|
142
143
|
|
|
143
144
|
#### docker:update_mirror
|
|
144
145
|
- git remote update `#{docker_build_base_dir}`
|
|
146
|
+
- Serialized with `docker:clone` via the same `flock` (see above)
|
|
145
147
|
|
|
146
148
|
#### docker:build
|
|
147
149
|
- Create `#{branch}` worktree to `#{docker_tag}-#{timestamp}`
|
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "capistrano-dockerbuild"
|
|
7
|
-
spec.version = "1.
|
|
7
|
+
spec.version = "1.2.0"
|
|
8
8
|
spec.authors = ["joker1007"]
|
|
9
9
|
spec.email = ["kakyoin.hierophant@gmail.com"]
|
|
10
10
|
|
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |spec|
|
|
|
22
22
|
|
|
23
23
|
spec.add_runtime_dependency "capistrano", ">= 3.2"
|
|
24
24
|
|
|
25
|
-
spec.add_development_dependency "bundler", "
|
|
25
|
+
spec.add_development_dependency "bundler", ">= 2.3"
|
|
26
26
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
27
27
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require "cgi"
|
|
2
2
|
require "uri"
|
|
3
3
|
require "securerandom"
|
|
4
|
+
require "shellwords"
|
|
4
5
|
|
|
5
6
|
class Capistrano::Dockerbuild < Capistrano::Plugin
|
|
6
7
|
def set_defaults
|
|
@@ -28,6 +29,16 @@ class Capistrano::Dockerbuild < Capistrano::Plugin
|
|
|
28
29
|
Pathname(fetch(:docker_build_base_dir))
|
|
29
30
|
end
|
|
30
31
|
|
|
32
|
+
# Lock serializing access to the shared repo dir at docker_build_base_path
|
|
33
|
+
# across concurrent deploys on the same build host (see README for the race).
|
|
34
|
+
#
|
|
35
|
+
# Keyed by basename, not a fixed name, so unrelated consumers sharing a parent
|
|
36
|
+
# directory don't serialize against each other.
|
|
37
|
+
def docker_build_lock_path
|
|
38
|
+
base = docker_build_base_path
|
|
39
|
+
base.dirname.join("capistrano_dockerbuild.#{base.basename}.lock").to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
31
42
|
def git_repo_url
|
|
32
43
|
if fetch(:git_http_username) && fetch(:git_http_password)
|
|
33
44
|
URI.parse(repo_url).tap do |repo_uri|
|
|
@@ -38,25 +38,20 @@ namespace :docker do
|
|
|
38
38
|
desc "Clone the repo to docker build base directory"
|
|
39
39
|
task :clone => [:'docker:check'] do
|
|
40
40
|
on roles(:docker_build) do |host|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
info t(:mirror_exists, at: dockerbuild_plugin.docker_build_base_path.to_s)
|
|
54
|
-
else
|
|
55
|
-
within dockerbuild_plugin.docker_build_base_path.dirname do
|
|
56
|
-
with dockerbuild_plugin.git_env(host) do
|
|
57
|
-
execute :git, :clone, "--mirror", dockerbuild_plugin.git_repo_url, dockerbuild_plugin.docker_build_base_path.to_s
|
|
41
|
+
within dockerbuild_plugin.docker_build_base_path.dirname do
|
|
42
|
+
with dockerbuild_plugin.git_env(host) do
|
|
43
|
+
path = dockerbuild_plugin.docker_build_base_path.to_s.shellescape
|
|
44
|
+
url = dockerbuild_plugin.git_repo_url.shellescape
|
|
45
|
+
# Existence check runs inside the same flock as the clone itself, not before
|
|
46
|
+
# acquiring it — otherwise two concurrent deploys can both observe the repo
|
|
47
|
+
# missing and the second `git clone` fails once the first has created it.
|
|
48
|
+
commands =
|
|
49
|
+
if fetch(:docker_build_no_worktree)
|
|
50
|
+
"[ -f #{path}/.git/HEAD ] || git clone #{url} #{path}"
|
|
51
|
+
else
|
|
52
|
+
"[ -f #{path}/HEAD ] || git clone --mirror #{url} #{path}"
|
|
58
53
|
end
|
|
59
|
-
|
|
54
|
+
execute :flock, dockerbuild_plugin.docker_build_lock_path.shellescape, "-c", commands.shellescape
|
|
60
55
|
end
|
|
61
56
|
end
|
|
62
57
|
end
|
|
@@ -67,8 +62,8 @@ namespace :docker do
|
|
|
67
62
|
on roles(:docker_build) do |host|
|
|
68
63
|
within dockerbuild_plugin.docker_build_base_path do
|
|
69
64
|
with dockerbuild_plugin.git_env(host) do
|
|
70
|
-
|
|
71
|
-
execute :
|
|
65
|
+
commands = "git remote set-url origin #{dockerbuild_plugin.git_repo_url.shellescape} && git remote update --prune"
|
|
66
|
+
execute :flock, dockerbuild_plugin.docker_build_lock_path.shellescape, "-c", commands.shellescape
|
|
72
67
|
end
|
|
73
68
|
end
|
|
74
69
|
end
|
|
@@ -90,7 +85,7 @@ namespace :docker do
|
|
|
90
85
|
submodule_cmd = fetch(:update_git_submodule) ? "; git submodule update --init --recursive" : ""
|
|
91
86
|
commands = "sha1=$(git rev-parse #{fetch(:branch)}); git reset --hard ${sha1}#{submodule_cmd}; #{build_cmd.map {|c| c.to_s.shellescape }.join(" ")}"
|
|
92
87
|
with dockerbuild_plugin.git_env(host) do
|
|
93
|
-
execute(:flock,
|
|
88
|
+
execute(:flock, dockerbuild_plugin.docker_build_lock_path.shellescape, "-c", "'#{commands}'")
|
|
94
89
|
end
|
|
95
90
|
else
|
|
96
91
|
timestamp = Time.now.to_i
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capistrano-dockerbuild
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- joker1007
|
|
@@ -27,14 +27,14 @@ dependencies:
|
|
|
27
27
|
name: bundler
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
|
-
- - "
|
|
30
|
+
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: '2.3'
|
|
33
33
|
type: :development
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
|
-
- - "
|
|
37
|
+
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '2.3'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
87
|
version: '0'
|
|
88
88
|
requirements: []
|
|
89
|
-
rubygems_version: 4.0.
|
|
89
|
+
rubygems_version: 4.0.16
|
|
90
90
|
specification_version: 4
|
|
91
91
|
summary: Capistrano task definition for `docker build`
|
|
92
92
|
test_files: []
|