capistrano-dockerbuild 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1478c1f08638b7fbd90429775a474e501920403a455dc222b43bb7c031d2c873
4
- data.tar.gz: 6d77122f43ed9fe79f9c672f4b2d209056c44396a4767efa24f0bd7886a94b45
3
+ metadata.gz: 411b02ef1e66127fab930b7476e2f4e618276c0f0e60ac8327543e6f0051bd35
4
+ data.tar.gz: ffed26862d2999bf476f464da9e2a11aa4844088a7cb34a01d01a401331524c5
5
5
  SHA512:
6
- metadata.gz: db2802cde724287f42aadc207c9f195d6a14b9475196c49d3f8a476a6ef61babdf23b3013a1a5d18dfee0c3703beb7b8ace4d989c1af8bf977f4f178b4ed0fe4
7
- data.tar.gz: 759048b911f58047325cd50aae2f84937cee18834b78cb8596a4e185d88e0e8a241eb3c82019cec2e18b64bbc6942d179564bd8514af987bf59d5e7425476560
6
+ metadata.gz: 636f6d7114ee9ed6a1e156d0bd7c41d46ab91e52e747afa1142599b2e12c90ae5a3b8cf126fd4152b6729eab2e0a6b3ceefea181601b3f980762867173c34315
7
+ data.tar.gz: 9f585640710fb132e198ddb94493d5a1fc600cee7e542e41cd97667ede164f508fe5393c922a22dbb97c3d307dbd34aa2ce889f6701839cbca0853a11413ba62
data/README.md CHANGED
@@ -30,6 +30,48 @@ require 'capistrano/dockerbuild'
30
30
  install_plugin Capistrano::Dockerbuild
31
31
  ```
32
32
 
33
+ ```ruby
34
+ # deploy.rb
35
+
36
+ set :application, :sample_project
37
+
38
+ set :repo_url, 'git@github.com:example/example.git'
39
+
40
+ set :git_sha1, `git rev-parse HEAD`.chomp
41
+
42
+ set :branch, fetch(:git_sha1)
43
+
44
+ set :ssh_user, ENV["SSH_USER"] || ENV["USER"] || Etc.getlogin
45
+
46
+ set :ssh_options, {
47
+ user: fetch(:ssh_user),
48
+ port: 22,
49
+ use_agent: true,
50
+ }
51
+
52
+ # add :docker_build role to server definition
53
+ # add :arch property to server definition
54
+ server "docker-build-amd64.example.com", roles: [:docker_build], ssh_options: fetch(:ssh_options), arch: "amd64"
55
+ server "docker-build-arm64.example.com", roles: [:docker_build], ssh_options: fetch(:ssh_options), arch: "arm64"
56
+
57
+ set :docker_registry, "ghcr.io"
58
+ set :docker_build_base_dir, "/home/#{fetch(:ssh_user)}/#{fetch(:application)}"
59
+
60
+ # if docker_build_cmd is proc and has more than 1 arity, pass host object.
61
+ set :docker_build_cmd, ->(host) {
62
+ [:docker, "build", "-f", "Dockerfile", "-t", fetch(:docker_tag_with_arch).call(host), "--build-arg", "host=#{host}", "."]
63
+ }
64
+ set :docker_tag, "ghcr.io/NAMESPACE/IMAGE_NAME:#{fetch(:git_sha1)}"
65
+ ```
66
+
67
+ If any servers have `arch` property, this plugin enables multi architecture mode.
68
+
69
+ The behavior of multi architecture mode is following.
70
+
71
+ 1. build image with a arch suffix like `-amd64`
72
+ 1. push the image
73
+ 1. create a manifest list of pushed images and push it on first server
74
+
33
75
  ## Variables
34
76
 
35
77
  #### Common Variables
@@ -39,16 +81,10 @@ Use common variables
39
81
 
40
82
  | name | required | default | desc |
41
83
  | ---- | ---- | ---- | ---- |
42
- | docker_build_server_host | yes | nil | Build server hostname or SSH::Host object |
43
84
  | docker_build_base_dir | yes | nil | Repository clone to here, and execute build command here |
44
- | docker_registry | no | nil | Docker registry hostname. if use DockerHub, keep nil |
45
- | docker_build_cmd | no | `-> { [:docker, "build", "-t", fetch(:docker_tag_full), "."] }` | Execute command for image building |
46
- | docker_repository_name | no | `-> { fetch(:application) }` | Use by `docker tag {{docker_repository_name}}:tag` |
47
- | docker_tag | no | `-> { fetch(:branch) }` | Use by `docker tag repository:{{docker_tag}}` |
48
- | docker_tag_full | no | `-> { #{fetch(:docker_repository_name)}:#{fetch(:docker_tag)}" }` | Use by `docker tag {{docker_tag_full}}` |
49
- | docker_remote_repository_name | no | `-> { fetch(:docker_repository_name) }` | Use by `docker push docker_registry/{{docker_remote_repository_name}}:docker_remote_tag` |
50
- | docker_remote_tag | no | `-> { fetch(:docker_tag) }` | Use by `docker push docker_registry/docker_remote_repository_name:{{docker_remote_tag}}` |
51
- | docker_remote_tag_full | no | `-> { "#{fetch(:docker_registry) &.+ "/"}#{fetch(:docker_remote_repository_name)}:#{fetch(:docker_remote_tag)}" }` | Use by `docker push {{docker_remote_tag_full}}` |
85
+ | docker_build_cmd | no | `->(host) { [:docker, :build, "-t", fetch(:docker_tag_with_arch).call(host), "."] }` | Execute command for image building |
86
+ | docker_tag | no | `-> { fetch(:application) + ":" + fetch(:branch) }` | Use by `docker tag repository:{{docker_tag}}` |
87
+ | docker_latest_tag | no | false | Add latest tag to building image |
52
88
  | keep_docker_image_count | no | 10 | |
53
89
  | git_http_username | no | nil | See below |
54
90
  | git_http_password | no | nil | See below |
@@ -87,8 +123,7 @@ Update remote URL always if you set proper value to all of `repo_url`, `git_http
87
123
  - Clear worktree
88
124
 
89
125
  #### docker:push
90
- - docker tag `#{docker_tag_full}` `#{docker_remote_tag_full}`
91
- - docker push `#{docker_remote_tag_full}`
126
+ - docker push `#{docker_tag}`
92
127
 
93
128
  #### docker:cleanup_local_images
94
129
  - Remove docker images
@@ -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 = "0.2.2"
7
+ spec.version = "1.0.0"
8
8
  spec.authors = ["joker1007"]
9
9
  spec.email = ["kakyoin.hierophant@gmail.com"]
10
10
 
@@ -3,13 +3,14 @@ require "uri"
3
3
 
4
4
  class Capistrano::Dockerbuild < Capistrano::Plugin
5
5
  def set_defaults
6
- set_if_empty :docker_build_cmd, -> { [:docker, "build", "-t", fetch(:docker_tag_full), "."] }
7
- set_if_empty :docker_repository_name, -> { fetch(:application) }
8
- set_if_empty :docker_tag, -> { fetch(:branch) }
9
- set_if_empty :docker_tag_full, -> { "#{fetch(:docker_repository_name)}:#{fetch(:docker_tag)}" }
10
- set_if_empty :docker_remote_repository_name, -> { fetch(:docker_repository_name) }
11
- set_if_empty :docker_remote_tag, -> { fetch(:docker_tag) }
12
- set_if_empty :docker_remote_tag_full, -> { "#{fetch(:docker_registry) &.+ "/"}#{fetch(:docker_remote_repository_name)}:#{fetch(:docker_remote_tag)}" }
6
+ set_if_empty :docker_tag, -> { fetch(:application) + ":" + fetch(:branch) }
7
+ set :docker_tag_with_arch, ->(host) do
8
+ arch_suffix = host.properties.arch ? "-#{host.properties.arch}" : ""
9
+ fetch(:docker_tag) + arch_suffix
10
+ end
11
+ set_if_empty :docker_build_cmd, ->(host) do
12
+ [:docker, :build, "-t", fetch(:docker_tag_with_arch).call(host), "."]
13
+ end
13
14
  set_if_empty :docker_latest_tag, false
14
15
  set_if_empty :keep_docker_image_count, 10
15
16
  set_if_empty :git_gc_prune_date, "3.days.ago"
@@ -3,7 +3,7 @@ dockerbuild_plugin = self
3
3
  namespace :docker do
4
4
  desc "check directory exist"
5
5
  task :check do
6
- on fetch(:docker_build_server_host) do
6
+ on roles(:docker_build) do |host|
7
7
  execute :mkdir, "-p", dockerbuild_plugin.docker_build_base_path.dirname.to_s
8
8
  execute :git, :'ls-remote', dockerbuild_plugin.git_repo_url, "HEAD"
9
9
  end
@@ -11,7 +11,7 @@ namespace :docker do
11
11
 
12
12
  desc "Clone the repo to docker build base directory"
13
13
  task :clone => [:'docker:check'] do
14
- on fetch(:docker_build_server_host) do
14
+ on roles(:docker_build) do |host|
15
15
  if fetch(:docker_build_no_worktree)
16
16
  if test " [ -f #{dockerbuild_plugin.docker_build_base_path}/.git/HEAD ] "
17
17
  info "The repository is at #{dockerbuild_plugin.docker_build_base_path}"
@@ -34,7 +34,7 @@ namespace :docker do
34
34
 
35
35
  desc "Update the repo mirror to reflect the origin state"
36
36
  task update_mirror: :'docker:clone' do
37
- on fetch(:docker_build_server_host) do
37
+ on roles(:docker_build) do |host|
38
38
  within dockerbuild_plugin.docker_build_base_path do
39
39
  execute :git, :remote, "set-url", :origin, dockerbuild_plugin.git_repo_url
40
40
  execute :git, :remote, :update, "--prune"
@@ -42,12 +42,20 @@ namespace :docker do
42
42
  end
43
43
  end
44
44
 
45
- desc "build and push docker image on remote host"
45
+ desc "build docker image on remote host"
46
46
  task :build => [:'docker:update_mirror'] do
47
- on fetch(:docker_build_server_host) do
47
+ on roles(:docker_build) do |host|
48
+ build_cmd = fetch(:docker_build_cmd)
49
+ if build_cmd.is_a?(Proc)
50
+ if build_cmd.arity != 0
51
+ build_cmd = build_cmd.call(host)
52
+ else
53
+ build_cmd = build_cmd.call
54
+ end
55
+ end
48
56
  within dockerbuild_plugin.docker_build_base_path do
49
57
  if fetch(:docker_build_no_worktree)
50
- commands = "sha1=$(git rev-parse #{fetch(:branch)}); git reset --hard ${sha1}; #{fetch(:docker_build_cmd).map {|c| c.to_s.shellescape }.join(" ")}"
58
+ commands = "sha1=$(git rev-parse #{fetch(:branch)}); git reset --hard ${sha1}; #{build_cmd.map {|c| c.to_s.shellescape }.join(" ")}"
51
59
  execute(:flock, "capistrano_dockerbuild.lock", "-c", "'#{commands}'")
52
60
  else
53
61
  timestamp = Time.now.to_i
@@ -58,7 +66,7 @@ namespace :docker do
58
66
 
59
67
  begin
60
68
  within worktree_dir_name do
61
- execute(*fetch(:docker_build_cmd))
69
+ execute(*build_cmd)
62
70
  end
63
71
  ensure
64
72
  execute(:rm, "-rf", worktree_dir_name)
@@ -71,32 +79,52 @@ namespace :docker do
71
79
  end
72
80
  end
73
81
 
82
+ desc "push docker image on remote host"
74
83
  task :push => [:'docker:build'] do
75
- on fetch(:docker_build_server_host) do
76
- execute(:docker, :tag, fetch(:docker_tag_full), fetch(:docker_remote_tag_full))
77
- execute(:docker, :push, fetch(:docker_remote_tag_full))
84
+ on roles(:docker_build) do |host|
85
+ docker_tag_with_arch = fetch(:docker_tag_with_arch).call(host)
86
+ execute(:docker, :push, docker_tag_with_arch)
78
87
  if fetch(:docker_latest_tag)
79
- latest_tag = "#{fetch(:docker_registry) &.+ "/"}#{fetch(:docker_remote_repository_name)}:latest"
80
- execute(:docker, :tag, fetch(:docker_tag_full), latest_tag)
88
+ arch_suffix = host.properties.arch ? "-#{host.properties.arch}" : ""
89
+ latest_tag = docker_tag_with_arch.split(":").first + ":latest" + arch_suffix
90
+ execute(:docker, :tag, docker_tag_with_arch, latest_tag)
81
91
  execute(:docker, :push, latest_tag)
82
92
  end
83
93
  end
94
+
95
+ archs = roles(:docker_build).map { |host| host.properties.arch }.compact.uniq
96
+ unless archs.empty?
97
+ on roles(:docker_build).take(1) do |host|
98
+ manifest_tags = archs.map do |arch|
99
+ arch_suffix = "-#{arch}"
100
+ fetch(:docker_tag) + arch_suffix
101
+ end
102
+ execute(:docker, :manifest, :create, "--amend", fetch(:docker_tag), *manifest_tags)
103
+ execute(:docker, :manifest, :push, "--purge", fetch(:docker_tag))
104
+
105
+ if fetch(:docker_latest_tag)
106
+ latest_tag = fetch(:docker_tag).split(":").first + ":latest"
107
+ execute(:docker, :manifest, :create, "--amend", latest_tag, *manifest_tags)
108
+ execute(:docker, :manifest, :push, "--purge", latest_tag)
109
+ end
110
+ end
111
+ end
84
112
  end
85
113
 
86
114
  task :push_unless_exists => [:'docker:build'] do
87
- on fetch(:docker_build_server_host) do
88
- unless test "docker manifest inspect #{fetch(:docker_remote_tag_full)}"
115
+ on roles(:docker_build).take(1) do
116
+ unless test "docker manifest inspect #{fetch(:docker_tag)}"
89
117
  invoke "docker:push"
90
118
  end
91
119
  end
92
120
  end
93
121
 
94
122
  task :cleanup_local_images do
95
- on fetch(:docker_build_server_host) do
123
+ on roles(:docker_build) do |host|
96
124
  local_images = []
97
125
  capture(:docker, "images --format='{{.ID}}\t{{.Repository}}\t{{.CreatedAt}}'").split("\n").map do |line|
98
126
  id, repository, created_at = line.split("\t")
99
- if repository == fetch(:docker_repository_name)
127
+ if repository == fetch(:docker_tag).split(":").first
100
128
  local_images << { id: id, created_at: created_at }
101
129
  end
102
130
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-dockerbuild
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-09-13 00:00:00.000000000 Z
10
+ date: 2025-02-10 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: capistrano
@@ -73,7 +72,6 @@ homepage: https://github.com/reproio/capistrano-dockerbuild
73
72
  licenses:
74
73
  - MIT
75
74
  metadata: {}
76
- post_install_message:
77
75
  rdoc_options: []
78
76
  require_paths:
79
77
  - lib
@@ -88,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
86
  - !ruby/object:Gem::Version
89
87
  version: '0'
90
88
  requirements: []
91
- rubygems_version: 3.5.11
92
- signing_key:
89
+ rubygems_version: 3.6.2
93
90
  specification_version: 4
94
91
  summary: Capistrano task definition for `docker build`
95
92
  test_files: []