From 2233e9c052e4adb32f038568463e522f7676e904 Mon Sep 17 00:00:00 2001 From: Aaron Kuehler Date: Thu, 21 Dec 2023 15:02:57 -0500 Subject: [PATCH] Use docker bake to build development image (#31) Related to: #30 Using the image building infrastructure added in #30, this moves the build configuration of the development tooling image into docker bake. Additionally, this removes vestigial configuration and targets from the `Makefile`. This also normalizes the `Makefile` target names; for easier discover-ability of alike tasks. For example, all testing related targets now start with `test-`; `test-unit` for unit tests, `tests-helm` for chart tests, etc. The project's developer documentation is also updated to reflect these changes. --- .github/workflows/ci.yaml | 6 +- CHANGELOG.md | 20 +++- Makefile | 207 +++++++++++++++------------------- docker-bake.hcl | 13 ++- docker/development/Dockerfile | 15 ++- docs/development.md | 38 ++++--- 6 files changed, 155 insertions(+), 144 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 52a4e5406..1831f8e65 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -37,7 +37,7 @@ jobs: - uses: actions/setup-go@v4 with: go-version-file: go.mod - - run: make ci-unit-test + - run: make test-unit-ci integration-test: name: Integration test @@ -68,7 +68,7 @@ jobs: driver: none - name: Add redisfailover CRD run: kubectl create -f manifests/databases.spotahome.com_redisfailovers.yaml - - run: make ci-integration-test + - run: make test-integration-ci chart-test: name: Chart testing @@ -84,7 +84,7 @@ jobs: version: v3.7.2 - name: Helm test - run: make helm-test + run: make test-helm-ci dockerhub-image: needs: diff --git a/CHANGELOG.md b/CHANGELOG.md index b9a86e618..7c8bb33a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,16 +1,34 @@ # Changelog -Check [releases](https://github.com/powerhome/redis-operator/releases) section for Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +Also check this project's [releases](https://github.com/powerhome/redis-operator/releases) for official release notes. ## Unreleased +### Changed +- [Use the new docker bake tooling to build the developer tools image and remove vestigial development targets from the Makefile](https://github.com/powerhome/redis-operator/pull/31). + +## [v1.8.0-rc2] - 2023-12-20 + +### Changed +- [Automate image publishing to the public image repository](https://github.com/powerhome/redis-operator/pull/30) +- [Run CI on the master branch](https://github.com/powerhome/redis-operator/pull/29) + ## [v1.8.0-rc1] - 2023-12-15 +### Added - [Add public image repository](https://github.com/powerhome/redis-operator/pull/28) ## [v1.7.1] - 2023-12-14 +### Changed - [Use finer grained NetworkPolicies](https://github.com/powerhome/redis-operator/pull/25) + +### Fixed - [Fix PodDisruptionBudget deprecation warnings on kube 1.21+](https://github.com/powerhome/redis-operator/pull/19) ## [v1.1.0-rc.3] - 2022-01-19 diff --git a/Makefile b/Makefile index 387b8a8b6..4a9f2ef96 100644 --- a/Makefile +++ b/Makefile @@ -9,154 +9,108 @@ IMAGE_NAME := powerhome/$(SERVICE_NAME) # Repository url for this project REPOSITORY := $(IMAGE_NAME) -# Shell to use for running scripts -SHELL := $(shell which bash) - # Get docker path or an empty string DOCKER := $(shell command -v docker) -# Get the main unix group for the user running make (to be used by docker-compose later) -GID := $(shell id -g) - -# Get the unix user id for the user running make (to be used by docker-compose later) +# Get the unix user id for the user running make (to be used by docker bake) UID := $(shell id -u) -# Commit hash from git -COMMIT=$(shell git rev-parse HEAD) -GITTAG_COMMIT := $(shell git rev-list --tags --max-count=1) -GITTAG := $(shell git describe --abbrev=0 --tags ${GITTAG_COMMIT} 2>/dev/null || true) - -# Branch from git -BRANCH=$(shell git rev-parse --abbrev-ref HEAD) - -TAG := $(GITTAG) -ifneq ($(COMMIT), $(GITTAG_COMMIT)) - TAG := $(COMMIT) -endif - +GIT_COMMIT=$(shell git rev-parse HEAD) +IMAGE_TAG := $(GIT_COMMIT) ifneq ($(shell git status --porcelain),) - TAG := $(TAG)-dirty + IMAGE_TAG := $(IMAGE_TAG)-dirty endif - PROJECT_PACKAGE := github.com/spotahome/redis-operator CODEGEN_IMAGE := ghcr.io/slok/kube-code-generator:v1.27.0 PORT := 9710 +# workdir +WORKDIR := /go/src/github.com/spotahome/redis-operator + # CMDs UNIT_TEST_CMD := go test `go list ./... | grep -v /vendor/` -v +HELM_TEST_CMD := ./scripts/helm-tests.sh GO_GENERATE_CMD := go generate `go list ./... | grep -v /vendor/` GO_INTEGRATION_TEST_CMD := go test `go list ./... | grep test/integration` -v -tags='integration' -GET_DEPS_CMD := dep ensure -UPDATE_DEPS_CMD := dep ensure MOCKS_CMD := go generate ./mocks - -# environment dirs -DEV_DIR := docker/development -APP_DIR := docker/app - -# workdir -WORKDIR := /go/src/github.com/spotahome/redis-operator +DOCKER_RUN_CMD := $(DOCKER) run -ti --rm \ + -v $(PWD):$(WORKDIR) \ + -u $(UID):$(UID) \ + --name $(SERVICE_NAME) \ + -p $(PORT):$(PORT) \ + $(REPOSITORY)-dev # The default action of this Makefile is to build the development docker image .PHONY: default -default: build - -# Run the development environment in non-daemonized mode (foreground) -.PHONY: docker-build -docker-build: deps-development - docker build \ - --build-arg uid=$(UID) \ - -t $(REPOSITORY)-dev:latest \ - -t $(REPOSITORY)-dev:$(COMMIT) \ - -f $(DEV_DIR)/Dockerfile \ - . - -# Run a shell into the development docker image +default: test + +.PHONY: ensure-docker +# Test if the dependencies we need to run this Makefile are installed +ensure-docker: +ifndef DOCKER + @echo "Docker is not available. Please install docker" + @exit 1 +endif + +# Build the operator image for local, end-to-end testing purposes +.PHONY: image-local +image-local: ensure-docker + docker buildx bake \ + --set build-local.tags="$(IMAGE_NAME):latest" \ + --set build-local.tags="$(IMAGE_NAME):$(IMAGE_TAG)" \ + build-local + +# Build the development environment docker image +.PHONY: image-dev-tools +image-dev-tools: ensure-docker + docker buildx bake \ + --set dev.args.uid=$(UID) \ + --set dev.tags="$(IMAGE_NAME)-dev:latest" \ + dev + +# Connect to a BASH shell the development docker image .PHONY: shell -shell: docker-build - docker run -ti --rm -v ~/.kube:/.kube:ro -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) -p $(PORT):$(PORT) $(REPOSITORY)-dev /bin/bash - -# Build redis-failover executable file -.PHONY: build -build: docker-build - docker run -ti --rm -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) $(REPOSITORY)-dev ./scripts/build.sh - -# Run the development environment in the background -.PHONY: run -run: docker-build - docker run -ti --rm -v ~/.kube:/.kube:ro -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) -p $(PORT):$(PORT) $(REPOSITORY)-dev ./scripts/run.sh - -# Build the production image based on the public one -.PHONY: image -image: deps-development - docker build \ - -t $(SERVICE_NAME) \ - -t $(REPOSITORY):latest \ - -t $(REPOSITORY):$(COMMIT) \ - -t $(REPOSITORY):$(BRANCH) \ - -f $(APP_DIR)/Dockerfile \ - . +shell: image-dev-tools + $(DOCKER_RUN_CMD) /bin/bash +# Create a git tag using the VERSION .PHONY: tag tag: git tag $(VERSION) -# Test stuff in dev -.PHONY: unit-test -unit-test: docker-build - docker run -ti --rm -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) $(REPOSITORY)-dev /bin/sh -c '$(UNIT_TEST_CMD)' - -.PHONY: ci-unit-test -ci-unit-test: - $(UNIT_TEST_CMD) - -.PHONY: ci-integration-test -ci-integration-test: - $(GO_INTEGRATION_TEST_CMD) - -.PHONY: integration-test -integration-test: - ./scripts/integration-tests.sh +# Run unit tests in the development docker container (DEV) +.PHONY: test-unit +test-unit: image-dev-tools + $(DOCKER_RUN_CMD) /bin/sh -c '$(UNIT_TEST_CMD)' -.PHONY: helm-test -helm-test: - ./scripts/helm-tests.sh +# Run helm tests in the development docker container (DEV) +.PHONY: test-helm +test-helm: + $(DOCKER_RUN_CMD) $(HELM_TEST_CMD) -# Run all tests +# Run all (DEV) tests .PHONY: test -test: ci-unit-test ci-integration-test helm-test - -.PHONY: go-generate -go-generate: docker-build - docker run -ti --rm -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) $(REPOSITORY)-dev /bin/sh -c '$(GO_GENERATE_CMD)' - -.PHONY: generate -generate: go-generate - -.PHONY: get-deps -get-deps: docker-build - docker run -ti --rm -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) $(REPOSITORY)-dev /bin/sh -c '$(GET_DEPS_CMD)' +test: test-unit test-helm -.PHONY: update-deps -update-deps: docker-build - docker run -ti --rm -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) $(REPOSITORY)-dev /bin/sh -c '$(UPDATE_DEPS_CMD)' +# Run unit tests on the host (CI) +.PHONY: test-unit-ci +test-unit-ci: + $(UNIT_TEST_CMD) -.PHONY: mocks -mocks: docker-build - docker run -ti --rm -v $(PWD):$(WORKDIR) -u $(UID):$(UID) --name $(SERVICE_NAME) $(REPOSITORY)-dev /bin/sh -c '$(MOCKS_CMD)' +# Run integration tests on the host (CI) +.PHONY: test-integration-ci +test-integration-ci: + $(GO_INTEGRATION_TEST_CMD) -.PHONY: deps-development -# Test if the dependencies we need to run this Makefile are installed -deps-development: -ifndef DOCKER - @echo "Docker is not available. Please install docker" - @exit 1 -endif +# Run helm tests on the host (CI) +.PHONY: test-helm-ci +test-helm-ci: + $(HELM_TEST_CMD) -# Generate kubernetes code for types.. -.PHONY: update-codegen -update-codegen: +# Generate kubernetes client +.PHONY: generate-client +generate-client: @echo ">> Generating code for Kubernetes CRD types..." docker run --rm -it \ -v $(PWD):/go/src/$(PROJECT_PACKAGE) \ @@ -167,6 +121,8 @@ update-codegen: -e GENERATION_TARGETS="deepcopy,client" \ $(CODEGEN_IMAGE) +# Generate kubernetes Custom Resource Definitions +.PHONY: generate-crd generate-crd: docker run -it --rm \ -v $(PWD):/go/src/$(PROJECT_PACKAGE) \ @@ -175,3 +131,24 @@ generate-crd: -e CRD_OUT_PATH=/go/src/$(PROJECT_PACKAGE)/manifests \ $(CODEGEN_IMAGE) update-crd.sh cp -f manifests/databases.spotahome.com_redisfailovers.yaml manifests/kustomize/base + +.PHONY: generate-go +generate-go: image-dev-tools + docker run -ti --rm \ + -v $(PWD):$(WORKDIR) \ + -u $(UID):$(UID) \ + --name $(SERVICE_NAME) $(REPOSITORY)-dev \ + /bin/sh -c '$(GO_GENERATE_CMD)' + +# Generate testing mocks +.PHONY: generate-mocks +generate-mocks: image-dev-tools + docker run -ti --rm \ + -v $(PWD):$(WORKDIR) \ + -u $(UID):$(UID) \ + --name $(SERVICE_NAME) \ + $(REPOSITORY)-dev /bin/sh -c '$(MOCKS_CMD)' + +# Run all code generators +.PHONY: generate +generate: generate-go generate-mocks generate-client generate-crd diff --git a/docker-bake.hcl b/docker-bake.hcl index fe439e691..1b2f535b5 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -23,6 +23,17 @@ target "build" { "linux/arm/v6", "linux/arm/v7", "linux/arm64", - "linux/386" + "linux/386", ] } + +variable UID { default = 1000 } +variable GID { default = 1000 } +target "dev" { + dockerfile = "docker/development/Dockerfile" + output = ["type=docker"] + args = { + uid: "${UID}", + gid: "${GID}", + } +} diff --git a/docker/development/Dockerfile b/docker/development/Dockerfile index 03d71d908..c47ed048f 100644 --- a/docker/development/Dockerfile +++ b/docker/development/Dockerfile @@ -1,6 +1,7 @@ FROM golang:1.20-alpine -ENV CODEGEN_VERSION="1.11.9" +ARG TARGETOS +ARG TARGETARCH RUN apk --no-cache add \ bash \ @@ -8,8 +9,14 @@ RUN apk --no-cache add \ g++ \ openssl +# Helm for running helm template tests locally +ENV HELM_VERSION="v3.12.0" +RUN wget -c https://get.helm.sh/helm-${HELM_VERSION}-${TARGETOS}-${TARGETARCH}.tar.gz -O - | tar zxv -C /tmp && \ + mv /tmp/${TARGETOS}-${TARGETARCH}/helm /go/bin/helm + # Code generator stuff # Check: https://github.com/kubernetes/kubernetes/pull/57656 +ENV CODEGEN_VERSION="1.11.9" RUN wget http://github.com/kubernetes/code-generator/archive/kubernetes-${CODEGEN_VERSION}.tar.gz && \ mkdir -p /go/src/k8s.io/code-generator/ && \ tar zxvf kubernetes-${CODEGEN_VERSION}.tar.gz --strip 1 -C /go/src/k8s.io/code-generator/ && \ @@ -17,11 +24,8 @@ RUN wget http://github.com/kubernetes/code-generator/archive/kubernetes-${CODEGE touch /go/src/k8s.io/kubernetes/hack/boilerplate/boilerplate.go.txt # Mock creator -# Alpine labels ARM architectures differently than Mockery: https://wiki.alpinelinux.org/wiki/Architecture ARG MOCKERY_VERSION="2.32.0" -RUN export ARCH="$(uname -m)" \ - && if [[ "${ARCH}" == "aarch64" ]]; then export ARCH="arm64"; fi \ - && wget -c https://github.com/vektra/mockery/releases/download/v${MOCKERY_VERSION}/mockery_${MOCKERY_VERSION}_$(uname -o)_${ARCH}.tar.gz -O - | tar -xz -C /go/bin/ +RUN wget -c https://github.com/vektra/mockery/releases/download/v${MOCKERY_VERSION}/mockery_${MOCKERY_VERSION}_$(uname -o)_${TARGETARCH}.tar.gz -O - | tar -xz -C /go/bin/ # Create user ARG uid=1000 @@ -30,6 +34,5 @@ RUN addgroup -g $gid rf && \ adduser -D -u $uid -G rf rf && \ chown rf:rf -R /go - USER rf WORKDIR /go/src/github.com/spotahome/redis-operator diff --git a/docs/development.md b/docs/development.md index e174a943a..637932444 100644 --- a/docs/development.md +++ b/docs/development.md @@ -26,23 +26,25 @@ You can do the following commands with make: -- Build the development container. - `make docker-build` +- Generate kubernetes client + `make generate-client` +- Generate kubernetes Custom Resource Definitions + `make generate-crd` +- Generate go code. + `make generate-mocks` - Generate mocks. - `make go-generate` -- Generate client - `make update-codegen` -- Run tests. - `make test` -- Build the executable file. - `make build` -- Run the app. - `make run` -- Access the docker instance with a shell. + `make generate-mocks` +- Run all code generators + `make generate` +- Build the development environment docker image. + `make image-dev-tools` +- Build the operator image for local, end-to-end testing purposes + `make image-local` +- Connect to a BASH shell the development environment docker image `make shell` -- Install dependencies - `make get-deps` -- Update dependencies - `make update-deps` -- Build the app image. - `make image` +- Run unit tests in the development docker container + `make test-unit` +- Run helm tests in the development docker container + `make test-heml` +- Run all development tests + `make test`