-
Notifications
You must be signed in to change notification settings - Fork 25
/
Rakefile
180 lines (163 loc) · 5.71 KB
/
Rakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
require 'rubygems/package'
ALL_PLATFORMS = {
ubuntu: [ "14.04", "16.04", "18.04", "20.04", "22.04"]
}
TARGET_ARCHITECTURES = ['amd64', 'arm64']
def selected_platforms
platform = ENV.fetch('PLATFORM', 'ubuntu-22.04').strip
if platform == 'all'
ALL_PLATFORMS
else
os, version = platform.split('-')
{
os.to_sym => version.nil? ? ALL_PLATFORMS[os.to_sym] : [ version ]
}
end
end
desc "build the docker base images"
task "build:docker:base_images" do
selected_platforms.each_pair do |os, versions|
versions.each do |version|
build_docker_image(os, version)
end
end
end
desc "test the docker base images"
task "test:docker:base_images" do
selected_platforms.each_pair do |os, versions|
versions.each do |version|
TARGET_ARCHITECTURES.each do |arch|
import_multiarch_docker_image(os, version, arch)
run_rspec("baseimage_spec", os, version, arch)
end
end
end
end
desc "publish the docker base images"
task "publish:docker:base_images" do
selected_platforms.each_pair do |os, versions|
versions.each do |version|
publish_docker_image(os, version)
end
end
end
desc "build the vagrant baseboxes"
task "build:vagrant:baseboxes" do
selected_platforms.each_pair do |os, versions|
versions.each do |version|
build_vagrant_basebox(os, version)
end
end
end
desc "test the vagrant baseboxes"
task "test:vagrant:baseboxes" do
selected_platforms.each_pair do |os, versions|
versions.each do |version|
TARGET_ARCHITECTURES.each do |arch|
import_multiarch_docker_image(os, version, arch)
run_rspec("basebox_spec", os, version, arch)
end
end
end
end
desc "publish the vagrant baseboxes"
task "publish:vagrant:baseboxes" do
selected_platforms.each_pair do |os, versions|
versions.each do |version|
publish_vagrant_basebox(os, version)
end
end
end
desc "clean output directories and destroy builders"
task "build:cleanup" do
sh "git clean -ffdx"
destroy_multiarch_docker_builder()
end
def build_docker_image(os, version)
create_multiarch_docker_builder()
sh "docker buildx build --no-cache --platform=#{docker_platform(TARGET_ARCHITECTURES)} -t #{docker_image_name(os, version)} #{dir(os, version)}"
end
def create_multiarch_docker_builder()
sh "docker buildx rm --builder=baseimage-builder || true"
sh "docker buildx create --name=baseimage-builder --platform=#{docker_platform(TARGET_ARCHITECTURES)} --use"
sh "docker buildx inspect"
end
def use_multiarch_docker_builder()
sh "docker buildx use --builder=baseimage-builder"
sh "docker buildx inspect"
end
def destroy_multiarch_docker_builder()
sh "docker buildx rm --builder=baseimage-builder || true"
end
def import_multiarch_docker_image(os, version, arch)
use_multiarch_docker_builder()
sh "docker rmi #{docker_image_name(os, version)} -f"
sh "docker buildx build --load --platform=#{docker_platform([arch])} -t #{docker_image_name(os, version)} #{dir(os, version)}"
end
def publish_docker_image(os, version)
use_multiarch_docker_builder()
sh <<~SCRIPT
set -e
docker login
docker buildx build --push --platform=#{docker_platform(TARGET_ARCHITECTURES)} -t #{docker_image_name(os, version)} #{dir(os, version)}
docker logout
SCRIPT
end
def publish_vagrant_basebox(os, version)
desc = "A Vagrant-friendly docker baseimage for #{os.capitalize} #{version}. See https://github.com/tknerr/vagrant-docker-baseimages"
# NOTE: we use architecture 'unknown' here so the same architecture independent basebox will be used
sh "vagrant cloud publish --release --no-private --short-description='#{desc}' --version-description='#{desc}' --architecture='unknown' \
#{vagrant_box_name(os, version)} 1.0.0 docker #{vagrant_box_path(os, version)}"
end
def build_vagrant_basebox(os, version)
box = File.open("#{vagrant_box_path(os, version)}", 'wb')
Gem::Package::TarWriter.new(box) do |tar|
tar.add_file("metadata.json", 0644) do |f|
# NOTE: we don't add architecture info here, so that the box remains architecture independent
# see https://developer.hashicorp.com/vagrant/docs/boxes/format
f.write <<~METADATA
{
"provider": "docker"
}
METADATA
end
tar.add_file("Vagrantfile", 0644) do |f|
# NOTE: we don't add `create_args = '--platform=linux/amd64'` here, so that the Vagrantfile remains
# architecture independent. The vagrant docker provider will choose the correct arch / docker image
# to pull based on the host architecture (or can be overridden via DOCKER_DEFAULT_PLATFORM env var)
# see https://developer.hashicorp.com/vagrant/docs/providers/docker/configuration
f.write <<~VAGRANTFILE
Vagrant.configure(2) do |config|
config.vm.provider "docker" do |d|
d.image = "#{docker_image_name(os, version)}"
d.has_ssh = true
end
end
VAGRANTFILE
end
end
end
def run_rspec(spec_name, os, version, arch)
ENV['OS_UNDER_TEST'] = os.to_s
ENV['VERSION_UNDER_TEST'] = version.to_s
ENV['ARCH_UNDER_TEST'] = arch.to_s
sh "rspec --format doc --color --tty \
--format RspecJunitFormatter --out out/test-results/junit/#{spec_name}-#{os}-#{version}-#{arch}-junit-report.xml \
--format html --out out/test-results/#{spec_name}-#{os}-#{version}-#{arch}-test-report.html \
spec/#{spec_name}.rb"
end
def dir(os, version)
"#{os}-#{version.delete('.')}"
end
def docker_image_name(os, version)
"tknerr/baseimage-#{os}:#{version}"
end
def docker_platform(archs)
archs.map {|arch| "linux/#{arch}"}.join(',')
end
def vagrant_box_name(os, version)
"tknerr/baseimage-#{os}-#{version}"
end
def vagrant_box_path(os, version)
"#{dir(os, version)}/baseimage-#{os}-#{version}.box"
end