Skip to content

Commit 705925a

Browse files
authored
ci: Update Makefile to include operator-templating changes (#323)
1 parent cd8df40 commit 705925a

File tree

1 file changed

+119
-12
lines changed

1 file changed

+119
-12
lines changed

Makefile

Lines changed: 119 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@
1212
TAG := $(shell git rev-parse --short HEAD)
1313
OPERATOR_NAME := stackable-cockpit
1414
VERSION := $(shell cargo metadata --format-version 1 | jq -r '.packages[] | select(.name=="stackable-cockpitd") | .version')
15+
ARCH := $(shell uname -m | sed -e 's#x86_64#amd64#' | sed -e 's#aarch64#arm64#')
1516

1617
DOCKER_REPO := docker.stackable.tech
1718
ORGANIZATION := stackable
18-
# this will be overwritten by an environmental variable if called from the github action
19+
OCI_REGISTRY_HOSTNAME := oci.stackable.tech
20+
OCI_REGISTRY_PROJECT_IMAGES := sdp
21+
OCI_REGISTRY_PROJECT_CHARTS := sdp-charts
22+
# This will be overwritten by an environmental variable if called from the github action
1923
HELM_REPO := https://repo.stackable.tech/repository/helm-dev
24+
HELM_CHART_NAME := ${OPERATOR_NAME}
2025
HELM_CHART_ARTIFACT := target/helm/${OPERATOR_NAME}-${VERSION}.tgz
2126

2227
SHELL=/usr/bin/env bash -euo pipefail
@@ -27,11 +32,84 @@ SHELL=/usr/bin/env bash -euo pipefail
2732

2833
## Docker related targets
2934
docker-build:
30-
docker build --force-rm --build-arg VERSION=${VERSION} -t "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}" -f docker/Dockerfile .
35+
docker build --force-rm --build-arg VERSION=${VERSION} -t "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}" -f docker/Dockerfile .
36+
docker tag "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}" "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-${ARCH}"
3137

3238
docker-publish:
39+
# Push to Nexus
3340
echo "${NEXUS_PASSWORD}" | docker login --username github --password-stdin "${DOCKER_REPO}"
34-
docker push --all-tags "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}"
41+
DOCKER_OUTPUT=$$(docker push --all-tags "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}");\
42+
# Obtain the digest of the pushed image from the output of `docker push`, because signing by tag is deprecated and will be removed from cosign in the future\
43+
REPO_DIGEST_OF_IMAGE=$$(echo "$$DOCKER_OUTPUT" | awk '/^${VERSION}-${ARCH}: digest: sha256:[0-9a-f]{64} size: [0-9]+$$/ { print $$3 }');\
44+
if [ -z "$$REPO_DIGEST_OF_IMAGE" ]; then\
45+
echo 'Could not find repo digest for container image: ${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}';\
46+
exit 1;\
47+
fi;\
48+
# This generates a signature and publishes it to the registry, next to the image\
49+
# Uses the keyless signing flow with Github Actions as identity provider\
50+
cosign sign -y "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
51+
# Generate the SBOM for the operator image, this leverages the already generated SBOM for the operator binary by cargo-cyclonedx\
52+
syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${OPERATOR_NAME}" --source-version "${VERSION}" "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
53+
# Determine the PURL for the container image\
54+
PURL="pkg:docker/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE?repository_url=${DOCKER_REPO}";\
55+
# Get metadata from the image\
56+
IMAGE_DESCRIPTION=$$(docker inspect --format='{{.Config.Labels.description}}' "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
57+
IMAGE_NAME=$$(docker inspect --format='{{.Config.Labels.name}}' "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
58+
# Merge the SBOM with the metadata for the operator\
59+
jq -s '{"metadata":{"component":{"description":"'"$$IMAGE_NAME. $$IMAGE_DESCRIPTION"'","supplier":{"name":"Stackable GmbH","url":["https://stackable.tech/"]},"author":"Stackable GmbH","purl":"'"$$PURL"'","publisher":"Stackable GmbH"}}} * .[0]' sbom.json > sbom.merged.json;\
60+
# Attest the SBOM to the image\
61+
cosign attest -y --predicate sbom.merged.json --type cyclonedx "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE"
62+
63+
# Push to Harbor
64+
# We need to use "value" here to prevent the variable from being recursively expanded by make (username contains a dollar sign, since it's a Harbor bot)
65+
docker login --username '${value OCI_REGISTRY_SDP_USERNAME}' --password '${OCI_REGISTRY_SDP_PASSWORD}' '${OCI_REGISTRY_HOSTNAME}'
66+
DOCKER_OUTPUT=$$(docker push --all-tags '${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}');\
67+
# Obtain the digest of the pushed image from the output of `docker push`, because signing by tag is deprecated and will be removed from cosign in the future\
68+
REPO_DIGEST_OF_IMAGE=$$(echo "$$DOCKER_OUTPUT" | awk '/^${VERSION}-${ARCH}: digest: sha256:[0-9a-f]{64} size: [0-9]+$$/ { print $$3 }');\
69+
if [ -z "$$REPO_DIGEST_OF_IMAGE" ]; then\
70+
echo 'Could not find repo digest for container image: ${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-${ARCH}';\
71+
exit 1;\
72+
fi;\
73+
# This generates a signature and publishes it to the registry, next to the image\
74+
# Uses the keyless signing flow with Github Actions as identity provider\
75+
cosign sign -y "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
76+
# Generate the SBOM for the operator image, this leverages the already generated SBOM for the operator binary by cargo-cyclonedx\
77+
syft scan --output cyclonedx-json=sbom.json --select-catalogers "-cargo-auditable-binary-cataloger" --scope all-layers --source-name "${OPERATOR_NAME}" --source-version "${VERSION}" "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE";\
78+
# Determine the PURL for the container image\
79+
PURL="pkg:docker/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE?repository_url=${OCI_REGISTRY_HOSTNAME}";\
80+
# Get metadata from the image\
81+
IMAGE_DESCRIPTION=$$(docker inspect --format='{{.Config.Labels.description}}' "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
82+
IMAGE_NAME=$$(docker inspect --format='{{.Config.Labels.name}}' "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-${ARCH}");\
83+
# Merge the SBOM with the metadata for the operator\
84+
jq -s '{"metadata":{"component":{"description":"'"$$IMAGE_NAME. $$IMAGE_DESCRIPTION"'","supplier":{"name":"Stackable GmbH","url":["https://stackable.tech/"]},"author":"Stackable GmbH","purl":"'"$$PURL"'","publisher":"Stackable GmbH"}}} * .[0]' sbom.json > sbom.merged.json;\
85+
# Attest the SBOM to the image\
86+
cosign attest -y --predicate sbom.merged.json --type cyclonedx "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}@$$REPO_DIGEST_OF_IMAGE"
87+
88+
# This assumes "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-amd64 and "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-arm64 are build and pushed
89+
docker-manifest-list-build:
90+
docker manifest create "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}" --amend "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-amd64" --amend "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}-arm64"
91+
docker manifest create "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}" --amend "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-amd64" --amend "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}-arm64"
92+
93+
docker-manifest-list-publish:
94+
# Push to Nexus
95+
echo "${NEXUS_PASSWORD}" | docker login --username github --password-stdin "${DOCKER_REPO}"
96+
# `docker manifest push` directly returns the digest of the manifest list
97+
# As it is an experimental feature, this might change in the future
98+
# Further reading: https://docs.docker.com/reference/cli/docker/manifest/push/
99+
DIGEST_NEXUS=$$(docker manifest push "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}");\
100+
# Refer to image via its digest (oci.stackable.tech/sdp/airflow@sha256:0a1b2c...)\
101+
# This generates a signature and publishes it to the registry, next to the image\
102+
# Uses the keyless signing flow with Github Actions as identity provider\
103+
cosign sign -y "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}@$$DIGEST_NEXUS"
104+
105+
# Push to Harbor
106+
# We need to use "value" here to prevent the variable from being recursively expanded by make (username contains a dollar sign, since it's a Harbor bot)
107+
docker login --username '${value OCI_REGISTRY_SDP_USERNAME}' --password '${OCI_REGISTRY_SDP_PASSWORD}' '${OCI_REGISTRY_HOSTNAME}'
108+
DIGEST_HARBOR=$$(docker manifest push "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}");\
109+
# Refer to image via its digest (oci.stackable.tech/sdp/airflow@sha256:0a1b2c...);\
110+
# This generates a signature and publishes it to the registry, next to the image\
111+
# Uses the keyless signing flow with Github Actions as identity provider\
112+
cosign sign -y "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}@$$DIGEST_HARBOR"
35113

36114
# TODO remove if not used/needed
37115
docker: docker-build docker-publish
@@ -40,8 +118,25 @@ print-docker-tag:
40118
@echo "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}"
41119

42120
helm-publish:
121+
# Push to Nexus
43122
curl --fail -u "github:${NEXUS_PASSWORD}" --upload-file "${HELM_CHART_ARTIFACT}" "${HELM_REPO}/"
44123

124+
# Push to Harbor
125+
# We need to use "value" here to prevent the variable from being recursively expanded by make (username contains a dollar sign, since it's a Harbor bot)
126+
helm registry login --username '${value OCI_REGISTRY_SDP_CHARTS_USERNAME}' --password '${OCI_REGISTRY_SDP_CHARTS_PASSWORD}' '${OCI_REGISTRY_HOSTNAME}'
127+
# Obtain the digest of the pushed artifact from the output of `helm push`, because signing by tag is deprecated and will be removed from cosign in the future\
128+
HELM_OUTPUT=$$(helm push '${HELM_CHART_ARTIFACT}' 'oci://${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_CHARTS}' 2>&1);\
129+
REPO_DIGEST_OF_ARTIFACT=$$(echo "$$HELM_OUTPUT" | awk '/^Digest: sha256:[0-9a-f]{64}$$/ { print $$2 }');\
130+
if [ -z "$$REPO_DIGEST_OF_ARTIFACT" ]; then\
131+
echo 'Could not find repo digest for helm chart: ${HELM_CHART_NAME}';\
132+
exit 1;\
133+
fi;\
134+
# Login to Harbor, needed for cosign to be able to push the signature for the Helm chart\
135+
docker login --username '${value OCI_REGISTRY_SDP_CHARTS_USERNAME}' --password '${OCI_REGISTRY_SDP_CHARTS_PASSWORD}' '${OCI_REGISTRY_HOSTNAME}';\
136+
# This generates a signature and publishes it to the registry, next to the chart artifact\
137+
# Uses the keyless signing flow with Github Actions as identity provider\
138+
cosign sign -y "${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_CHARTS}/${HELM_CHART_NAME}@$$REPO_DIGEST_OF_ARTIFACT"
139+
45140
helm-package:
46141
mkdir -p target/helm && helm package --destination target/helm deploy/helm/${OPERATOR_NAME}
47142

@@ -62,29 +157,41 @@ config:
62157
cp -r deploy/config-spec/* "deploy/helm/${OPERATOR_NAME}/configs";\
63158
fi
64159

65-
# crds:
66-
# mkdir -p deploy/helm/"${OPERATOR_NAME}"/crds
67-
# cargo run --bin "${OPERATOR_NAME}" -- crd | yq eval '.metadata.annotations["helm.sh/resource-policy"]="keep"' - > "deploy/helm/${OPERATOR_NAME}/crds/crds.yaml"
160+
#crds:
161+
# mkdir -p deploy/helm/"${OPERATOR_NAME}"/crds
162+
# cargo run --bin stackable-"${OPERATOR_NAME}" -- crd | yq eval '.metadata.annotations["helm.sh/resource-policy"]="keep"' - > "deploy/helm/${OPERATOR_NAME}/crds/crds.yaml"
68163

69164
chart-lint: compile-chart
70165
docker run -it -v $(shell pwd):/build/helm-charts -w /build/helm-charts quay.io/helmpack/chart-testing:v3.5.0 ct lint --config deploy/helm/ct.yaml
71166

72167
clean: chart-clean
73168
cargo clean
74169
docker rmi --force "${DOCKER_REPO}/${ORGANIZATION}/${OPERATOR_NAME}:${VERSION}"
170+
docker rmi --force '${OCI_REGISTRY_HOSTNAME}/${OCI_REGISTRY_PROJECT_IMAGES}/${OPERATOR_NAME}:${VERSION}'
75171

76172
regenerate-charts: chart-clean compile-chart
77173

78-
# The explicit '--extra-experimental-features flakes' parameter was added,
79-
# because the command requires Flakes to be enabled, but most non-Nix users
80-
# don't enable them via the global nix rc file.
81174
regenerate-nix:
82-
nix run --extra-experimental-features flakes -f . regenerateNixLockfiles
175+
nix run --extra-experimental-features "nix-command flakes" -f . regenerateNixLockfiles
83176

84177
build: regenerate-charts regenerate-nix helm-package docker-build
85178

179+
# This target is used by the CI
180+
# It doesn't make use of any nix dependencies and thus aviods building the
181+
# operator unnecessarily often.
182+
build-ci: regenerate-charts helm-package docker-build
183+
86184
publish: docker-publish helm-publish
87185

88-
run-dev:
186+
check-nix:
187+
@which nix || (echo "Error: 'nix' is not installed. Please install it to proceed."; exit 1)
188+
189+
check-kubernetes:
190+
@kubectl cluster-info > /dev/null 2>&1 || (echo "Error: Kubernetes is not running or kubectl is not properly configured."; exit 1)
191+
192+
run-dev: check-nix check-kubernetes
89193
kubectl apply -f deploy/stackable-operators-ns.yaml
90-
nix run -f. tilt -- up --port 5480 --namespace stackable-operators
194+
nix run --extra-experimental-features "nix-command flakes" -f. tilt -- up --port 5480 --namespace stackable-operators
195+
196+
stop-dev: check-nix check-kubernetes
197+
nix run --extra-experimental-features "nix-command flakes" -f. tilt -- down

0 commit comments

Comments
 (0)