capistrano-dockerbuild 0.2.2 → 1.0.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 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: []