Skip to content

Commit aa072b2

Browse files
committed
feat: publish images on release
Signed-off-by: Adam Talbot <adamtalbot93@googlemail.com>
1 parent 5d744d2 commit aa072b2

File tree

9 files changed

+496
-0
lines changed

9 files changed

+496
-0
lines changed

.github/workflows/release.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ jobs:
2323
run: |
2424
make print-go-version >> "$GITHUB_OUTPUT"
2525
26+
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
27+
with:
28+
registry: quay.io
29+
username: ${{ secrets.QUAY_USERNAME }}
30+
password: ${{ secrets.QUAY_PASSWORD }}
31+
2632
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
2733
with:
2834
registry: ghcr.io

klone.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ targets:
4242
repo_ref: main
4343
repo_hash: c28bd0abb20c7b89754f4e5cc44420975c6ea5f1
4444
repo_path: modules/klone
45+
- folder_name: oci-build
46+
repo_url: https://github.com/cert-manager/makefile-modules.git
47+
repo_ref: main
48+
repo_hash: c28bd0abb20c7b89754f4e5cc44420975c6ea5f1
49+
repo_path: modules/oci-build
50+
- folder_name: oci-publish
51+
repo_url: https://github.com/cert-manager/makefile-modules.git
52+
repo_ref: main
53+
repo_hash: c28bd0abb20c7b89754f4e5cc44420975c6ea5f1
54+
repo_path: modules/oci-publish
4555
- folder_name: repository-base
4656
repo_url: https://github.com/cert-manager/makefile-modules.git
4757
repo_ref: main

make/00_mod.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
repo_name := github.com/cert-manager/cmctl
1616

17+
build_names := cmctl
1718
exe_build_names := cmctl
1819
gorelease_file := .goreleaser.yml
1920

@@ -24,3 +25,8 @@ go_cmctl_ldflags := \
2425
-X github.com/cert-manager/cert-manager/pkg/util.AppGitCommit=$(GITCOMMIT)
2526

2627
golangci_lint_config := .golangci.yaml
28+
29+
oci_cmctl_base_image_flavor := static
30+
oci_cmctl_image_name := quay.io/jetstack/cmctl
31+
oci_cmctl_image_tag := $(VERSION)
32+
oci_cmctl_image_name_development := cert-manager.local/cmctl

make/02_mod.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@ shared_generate_targets += generate-conversion
5252
## @category [shared] Release
5353
release: | $(NEEDS_CRANE) $(bin_dir)/scratch
5454
$(MAKE) exe-publish
55+
$(MAKE) oci-push-cmctl
5556

5657
@echo "Release complete!"

make/_shared/oci-build/00_mod.mk

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Copyright 2023 The cert-manager Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Use distroless as minimal base image to package the manager binary
16+
# To get latest SHA run "crane digest quay.io/jetstack/base-static:latest"
17+
base_image_static := quay.io/jetstack/base-static@sha256:1da2e7de36c9d7a1931d765e8054a3c9fe7ed5126bacf728bb7429e923386146
18+
19+
# Use custom apko-built image as minimal base image to package the manager binary
20+
# To get latest SHA run "crane digest quay.io/jetstack/base-static-csi:latest"
21+
base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:05ec9b9d5798fdd80680a54eab9eb69134d3cdaae948935bb1af07dadeb6e9be
22+
23+
# Utility functions
24+
fatal_if_undefined = $(if $(findstring undefined,$(origin $1)),$(error $1 is not set))
25+
fatal_if_deprecated_defined = $(if $(findstring undefined,$(origin $1)),,$(error $1 is deprecated, use $2 instead))
26+
27+
# Validate globals that are required
28+
$(call fatal_if_undefined,build_names)
29+
30+
# Set default config values
31+
CGO_ENABLED ?= 0
32+
GOEXPERIMENT ?= # empty by default
33+
oci_platforms ?= linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le
34+
35+
# Default variables per build_names entry
36+
#
37+
# $1 - build_name
38+
define default_per_build_variables
39+
go_$1_cgo_enabled ?= $(CGO_ENABLED)
40+
go_$1_goexperiment ?= $(GOEXPERIMENT)
41+
go_$1_flags ?= -tags=
42+
oci_$1_platforms ?= $(oci_platforms)
43+
oci_$1_additional_layers ?=
44+
oci_$1_linux_capabilities ?=
45+
oci_$1_build_args ?=
46+
endef
47+
48+
$(foreach build_name,$(build_names),$(eval $(call default_per_build_variables,$(build_name))))
49+
50+
# Validate variables per build_names entry
51+
#
52+
# $1 - build_name
53+
define check_per_build_variables
54+
# Validate deprecated variables
55+
$(call fatal_if_deprecated_defined,cgo_enabled_$1,go_$1_cgo_enabled)
56+
$(call fatal_if_deprecated_defined,goexperiment_$1,go_$1_goexperiment)
57+
$(call fatal_if_deprecated_defined,oci_additional_layers_$1,oci_$1_additional_layers)
58+
59+
# Validate required config exists
60+
$(call fatal_if_undefined,go_$1_ldflags)
61+
$(call fatal_if_undefined,go_$1_main_dir)
62+
$(call fatal_if_undefined,go_$1_mod_dir)
63+
$(call fatal_if_undefined,oci_$1_base_image_flavor)
64+
$(call fatal_if_undefined,oci_$1_image_name_development)
65+
66+
# Validate we have valid base image config
67+
ifeq ($(oci_$1_base_image_flavor),static)
68+
oci_$1_base_image := $(base_image_static)
69+
else ifeq ($(oci_$1_base_image_flavor),csi-static)
70+
oci_$1_base_image := $(base_image_csi-static)
71+
else ifeq ($(oci_$1_base_image_flavor),custom)
72+
$$(call fatal_if_undefined,oci_$1_base_image)
73+
else
74+
$$(error oci_$1_base_image_flavor has unknown value "$(oci_$1_base_image_flavor)")
75+
endif
76+
77+
# Validate the config required to build the golang based images
78+
ifneq ($(go_$1_main_dir:.%=.),.)
79+
$$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES start with ".")
80+
endif
81+
ifeq ($(go_$1_main_dir:%/=/),/)
82+
$$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with "/")
83+
endif
84+
ifeq ($(go_$1_main_dir:%.go=.go),.go)
85+
$$(error go_$1_main_dir "$(go_$1_main_dir)" should be a directory path that DOES NOT end with ".go")
86+
endif
87+
ifneq ($(go_$1_mod_dir:.%=.),.)
88+
$$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES start with ".")
89+
endif
90+
ifeq ($(go_$1_mod_dir:%/=/),/)
91+
$$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with "/")
92+
endif
93+
ifeq ($(go_$1_mod_dir:%.go=.go),.go)
94+
$$(error go_$1_mod_dir "$(go_$1_mod_dir)" should be a directory path that DOES NOT end with ".go")
95+
endif
96+
ifeq ($(wildcard $(go_$1_mod_dir)/go.mod),)
97+
$$(error go_$1_mod_dir "$(go_$1_mod_dir)" does not contain a go.mod file)
98+
endif
99+
ifeq ($(wildcard $(go_$1_mod_dir)/$(go_$1_main_dir)/main.go),)
100+
$$(error go_$1_main_dir "$(go_$1_mod_dir)/$(go_$1_main_dir)" does not contain a main.go file)
101+
endif
102+
103+
# Validate the config required to build OCI images
104+
ifneq ($(words $(oci_$1_image_name_development)),1)
105+
$$(error oci_$1_image_name_development "$(oci_$1_image_name_development)" should be a single image name)
106+
endif
107+
108+
# Validate that the build name does not end in __local
109+
ifeq ($(1:%__local=__local),__local)
110+
$$(error build_name "$1" SHOULD NOT end in __local)
111+
endif
112+
endef
113+
114+
$(foreach build_name,$(build_names),$(eval $(call check_per_build_variables,$(build_name))))
115+
116+
# Create variables holding targets
117+
#
118+
# We create the following targets for each $(build_names)
119+
# - oci-build-$(build_name) = build the oci directory (multi-arch)
120+
# - oci-build-$(build_name)__local = build the oci directory (local arch: linux/$(HOST_ARCH))
121+
# - oci-load-$(build_name) = load the image into docker using the oci_$(build_name)_image_name_development variable
122+
# - docker-tarball-$(build_name) = build a "docker load" compatible tarball of the image
123+
oci_build_targets := $(build_names:%=oci-build-%)
124+
oci_build_targets += $(build_names:%=oci-build-%__local)
125+
oci_load_targets := $(build_names:%=oci-load-%)
126+
docker_tarball_targets := $(build_names:%=docker-tarball-%)
127+
128+
# Derive config based on user config
129+
#
130+
# - oci_layout_path_$(build_name) = path that the OCI image will be saved in OCI layout directory format
131+
# - oci_digest_path_$(build_name) = path to the file that will contain the digests
132+
# - docker_tarball_path_$(build_name) = path that the docker tarball that the docker-tarball-$(build_name) will produce
133+
$(foreach build_name,$(build_names),$(eval oci_layout_path_$(build_name) := $(bin_dir)/scratch/image/oci-layout-$(build_name)))
134+
$(foreach build_name,$(build_names),$(eval oci_digest_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).digests))
135+
$(foreach build_name,$(build_names),$(eval docker_tarball_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).docker.tar))

make/_shared/oci-build/01_mod.mk

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright 2023 The cert-manager Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
$(bin_dir)/scratch/image:
16+
@mkdir -p $@
17+
18+
.PHONY: $(oci_build_targets)
19+
## Build the OCI image.
20+
## - oci-build-$(build_name) = build the oci directory (multi-arch)
21+
## - oci-build-$(build_name)__local = build the oci directory (local arch: linux/$(HOST_ARCH))
22+
## @category [shared] Build
23+
$(oci_build_targets): oci-build-%: | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(NEEDS_IMAGE-TOOL) $(bin_dir)/scratch/image
24+
$(eval a := $(patsubst %__local,%,$*))
25+
$(eval is_local := $(if $(findstring $a__local,$*),true))
26+
$(eval layout_path := $(if $(is_local),$(oci_layout_path_$a).local,$(oci_layout_path_$a)))
27+
$(eval digest_path := $(if $(is_local),$(oci_digest_path_$a).local,$(oci_digest_path_$a)))
28+
29+
rm -rf $(CURDIR)/$(layout_path)
30+
31+
echo '{}' | \
32+
$(YQ) '.defaultBaseImage = "$(oci_$a_base_image)"' | \
33+
$(YQ) '.builds[0].id = "$a"' | \
34+
$(YQ) '.builds[0].dir = "$(go_$a_mod_dir)"' | \
35+
$(YQ) '.builds[0].main = "$(go_$a_main_dir)"' | \
36+
$(YQ) '.builds[0].env[0] = "CGO_ENABLED=$(go_$a_cgo_enabled)"' | \
37+
$(YQ) '.builds[0].env[1] = "GOEXPERIMENT=$(go_$a_goexperiment)"' | \
38+
$(YQ) '.builds[0].ldflags[0] = "-s"' | \
39+
$(YQ) '.builds[0].ldflags[1] = "-w"' | \
40+
$(YQ) '.builds[0].ldflags[2] = "{{.Env.LDFLAGS}}"' | \
41+
$(YQ) '.builds[0].flags[0] = "$(go_$a_flags)"' | \
42+
$(YQ) '.builds[0].linux_capabilities = "$(oci_$a_linux_capabilities)"' \
43+
> $(CURDIR)/$(layout_path).ko_config.yaml
44+
45+
GOWORK=off \
46+
KO_DOCKER_REPO=$(oci_$a_image_name_development) \
47+
KOCACHE=$(CURDIR)/$(bin_dir)/scratch/image/ko_cache \
48+
KO_CONFIG_PATH=$(CURDIR)/$(layout_path).ko_config.yaml \
49+
SOURCE_DATE_EPOCH=$(GITEPOCH) \
50+
KO_GO_PATH=$(GO) \
51+
LDFLAGS="$(go_$a_ldflags)" \
52+
$(KO) build $(go_$a_mod_dir)/$(go_$a_main_dir) \
53+
--platform=$(if $(is_local),linux/$(HOST_ARCH),$(oci_$a_platforms)) \
54+
$(oci_$a_build_args) \
55+
--oci-layout-path=$(layout_path) \
56+
--sbom-dir=$(CURDIR)/$(layout_path).sbom \
57+
--sbom=spdx \
58+
--push=false \
59+
--bare
60+
61+
$(IMAGE-TOOL) append-layers \
62+
$(CURDIR)/$(layout_path) \
63+
$(oci_$a_additional_layers)
64+
65+
$(IMAGE-TOOL) list-digests \
66+
$(CURDIR)/$(layout_path) \
67+
> $(digest_path)
68+
69+
# Only include the oci-load target if kind is provided by the kind makefile-module
70+
ifdef kind_cluster_name
71+
.PHONY: $(oci_load_targets)
72+
## Build OCI image for the local architecture and load
73+
## it into the $(kind_cluster_name) kind cluster.
74+
## @category [shared] Build
75+
$(oci_load_targets): oci-load-%: docker-tarball-% | kind-cluster $(NEEDS_KIND)
76+
$(KIND) load image-archive --name $(kind_cluster_name) $(docker_tarball_path_$*)
77+
endif
78+
79+
## Build Docker tarball image for the local architecture
80+
## @category [shared] Build
81+
.PHONY: $(docker_tarball_targets)
82+
$(docker_tarball_targets): docker-tarball-%: oci-build-%__local | $(NEEDS_GO) $(NEEDS_IMAGE-TOOL)
83+
$(IMAGE-TOOL) convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*).local $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag)

make/_shared/oci-publish/00_mod.mk

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2023 The cert-manager Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Push names is equivalent to build_names, additional names can be added for
16+
# pushing images that are not build with the oci-build module
17+
push_names ?=
18+
push_names += $(build_names)
19+
20+
# Sometimes we need to push to one registry, but pull from another. This allows
21+
# that.
22+
#
23+
# The lines should be in the format a=b
24+
#
25+
# The value on the left is the domain you include in your oci_<name>_image_name
26+
# variable, the one on the right is the domain that is actually pushed to.
27+
#
28+
# For example, if we set up a vanity domain for the current quay:
29+
#
30+
# oci_controller_image_name = registry.cert-manager.io/cert-manager-controller`
31+
# image_registry_rewrite += registry.cert-manager.io=quay.io/jetstack
32+
#
33+
# This would push to quay.io/jetstack/cert-manager-controller.
34+
#
35+
# The general idea is oci_<name>_image_name contains the final image name, after replication, after vanity domains etc.
36+
37+
image_registry_rewrite ?=
38+
39+
# Utilities for extracting the key and value from a foo=bar style line
40+
kv_key = $(word 1,$(subst =, ,$1))
41+
kv_value = $(word 2,$(subst =, ,$1))
42+
43+
# Apply the image_registry_rewrite rules, if no rules match an image then the
44+
# image name is not changed. Any rules that match will be applied.
45+
#
46+
# For example, if there was a rule vanity-domain.com=real-registry.com/foo
47+
# then any references to vanity-domain.com/image would be rewritten to
48+
# real-registry.com/foo/image
49+
image_registry_rewrite_rules_for_image = $(strip $(sort $(foreach rule,$(image_registry_rewrite),$(if $(findstring $(call kv_key,$(rule)),$1),$(rule)))))
50+
apply_image_registry_rewrite_rules_to_image = $(if $(call image_registry_rewrite_rules_for_image,$1),\
51+
$(foreach rule,$(call image_registry_rewrite_rules_for_image,$1),$(subst $(call kv_key,$(rule)),$(call kv_value,$(rule)),$1)),\
52+
$1)
53+
apply_image_registry_rewrite_rules = $(foreach image_name,$1,$(call apply_image_registry_rewrite_rules_to_image,$(image_name)))
54+
55+
# This is a helper function to return the image names for a given build_name.
56+
# It will apply all rewrite rules to the image names
57+
oci_image_names_for = $(call apply_image_registry_rewrite_rules,$(oci_$1_image_name))
58+
oci_image_tag_for = $(oci_$1_image_tag)

0 commit comments

Comments
 (0)