diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ba59934..099a34e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,24 +40,14 @@ jobs: if [[ $GITHUB_REF == refs/tags/* ]]; then # Release tags. echo VERSION="$(echo "${GITHUB_REF#refs/tags/}" | sed 's/^v//')" >> $GITHUB_ENV - echo RELEASE=true >> $GITHUB_ENV + echo ENABLE_RELEASE_PIPELINE=true >> $GITHUB_ENV elif [[ $GITHUB_REF == refs/heads/main ]]; then # 'main' branch build. echo TAG=snapshot >> $GITHUB_ENV - echo RELEASE=true >> $GITHUB_ENV + echo ENABLE_RELEASE_PIPELINE=true >> $GITHUB_ENV fi - name: Release run: make release - - - name: Create Release - id: create_release - uses: actions/create-release@v1 - if: startsWith(github.ref, 'refs/tags/') env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: Release ${{ github.ref }} - draft: false - prerelease: false + GITHUB_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore index 62df8bc..584b341 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ catalog/catalog.json *.so *.dylib bin/* +dist/* Dockerfile.cross # Test binary, built with `go test -c` diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..8faa251 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,178 @@ +before: + hooks: + - go mod tidy + - go mod download +builds: + - id: controller-binary + main: ./cmd + binary: manager + asmflags: "{{ .Env.GO_BUILD_ASMFLAGS }}" + gcflags: "{{ .Env.GO_BUILD_GCFLAGS }}" + ldflags: "{{ .Env.GO_BUILD_LDFLAGS }}" + tags: + - "{{ .Env.GO_BUILD_TAGS }}" + mod_timestamp: "{{ .CommitTimestamp }}" + goos: + - linux + goarch: + - amd64 + - arm64 + - ppc64le + - s390x +dockers: + # controller images + - image_templates: + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-amd64" + dockerfile: Dockerfile + goos: linux + goarch: amd64 + use: buildx + build_flag_templates: + - "--platform=linux/amd64" + - image_templates: + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-arm64" + dockerfile: Dockerfile + goos: linux + goarch: arm64 + use: buildx + build_flag_templates: + - "--platform=linux/arm64" + - image_templates: + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-ppc64le" + dockerfile: Dockerfile + goos: linux + goarch: ppc64le + use: buildx + build_flag_templates: + - "--platform=linux/ppc64le" + - image_templates: + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-s390x" + dockerfile: Dockerfile + goos: linux + goarch: s390x + use: buildx + build_flag_templates: + - "--platform=linux/s390x" + # bundle images + - image_templates: + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-amd64" + dockerfile: bundle.Dockerfile + goos: linux + goarch: amd64 + use: buildx + extra_files: + - bundle + build_flag_templates: + - "--platform=linux/amd64" + - image_templates: + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-arm64" + dockerfile: bundle.Dockerfile + goos: linux + goarch: arm64 + use: buildx + extra_files: + - bundle + build_flag_templates: + - "--platform=linux/arm64" + - image_templates: + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-ppc64le" + dockerfile: bundle.Dockerfile + goos: linux + goarch: ppc64le + use: buildx + extra_files: + - bundle + build_flag_templates: + - "--platform=linux/ppc64le" + - image_templates: + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-s390x" + dockerfile: bundle.Dockerfile + goos: linux + goarch: s390x + use: buildx + extra_files: + - bundle + build_flag_templates: + - "--platform=linux/s390x" + # catalog images + - image_templates: + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-amd64" + dockerfile: catalog.Dockerfile + goos: linux + goarch: amd64 + use: buildx + extra_files: + - catalog + build_flag_templates: + - "--platform=linux/amd64" + - image_templates: + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-arm64" + dockerfile: catalog.Dockerfile + goos: linux + goarch: arm64 + use: buildx + extra_files: + - catalog + build_flag_templates: + - "--platform=linux/arm64" + - image_templates: + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-ppc64le" + dockerfile: catalog.Dockerfile + goos: linux + goarch: ppc64le + use: buildx + extra_files: + - catalog + build_flag_templates: + - "--platform=linux/ppc64le" + - image_templates: + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-s390x" + dockerfile: catalog.Dockerfile + goos: linux + goarch: s390x + use: buildx + extra_files: + - catalog + build_flag_templates: + - "--platform=linux/s390x" +docker_manifests: + - name_template: "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}" + image_templates: + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-amd64" + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-arm64" + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-ppc64le" + - "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}-s390x" + - name_template: "{{ .Env.CONTROLLER_IMAGE }}:{{ .Env.TAG }}" + image_templates: + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-amd64" + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-arm64" + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-ppc64le" + - "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}-s390x" + - name_template: "{{ .Env.BUNDLE_IMAGE }}:{{ .Env.TAG }}" + image_templates: + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-amd64" + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-arm64" + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-ppc64le" + - "{{ .Env.CATALOG_IMAGE }}:{{ .Env.TAG }}-s390x" +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}-next" +changelog: + use: github-native + disable: '{{ ne .Env.ENABLE_RELEASE_PIPELINE "true" }}' +release: + disable: '{{ ne .Env.ENABLE_RELEASE_PIPELINE "true" }}' + mode: replace +# extra_files: +# - glob: '{{ .Env.STANDARD_RELEASE_MANIFEST }}' +# - glob: '{{ .Env.STANDARD_RELEASE_INSTALL }}' +# - glob: '{{ .Env.EXPERIMENTAL_RELEASE_MANIFEST }}' +# - glob: '{{ .Env.EXPERIMENTAL_RELEASE_INSTALL }}' +# - glob: '{{ .Env.RELEASE_CATALOGS }}' +# header: | +# ## Installation +# +# ```bash +# curl -L -s https://github.com/operator-framework/operator-controller/releases/download/{{ .Tag }}/install.sh | bash -s +# ``` diff --git a/Dockerfile b/Dockerfile index 7547f37..5336de9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,33 +1,10 @@ -# Build the manager binary -FROM golang:1.24 AS builder -ARG TARGETOS -ARG TARGETARCH - -WORKDIR /workspace -# Copy the Go Modules manifests -COPY go.mod go.mod -COPY go.sum go.sum -# cache deps before building and copying source so that we don't need to re-download as much -# and so that source changes don't invalidate our downloaded layer -RUN go mod download - -# Copy the go source -COPY cmd/main.go cmd/main.go -COPY api/ api/ -COPY internal/ internal/ - -# Build -# the GOARCH has no default value to allow the binary to be built according to the host where the command -# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO -# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, -# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. -RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -tags 'containers_image_openpgp' -o manager cmd/main.go - -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details +# Note: This dockerfile does not build the binaries +# required and is intended to be built only with the +# 'make build' or 'make release' targets. FROM gcr.io/distroless/static:nonroot WORKDIR / -COPY --from=builder /workspace/manager . +COPY manager manager +EXPOSE 8080 USER 65532:65532 ENTRYPOINT ["/manager"] diff --git a/Makefile b/Makefile index 0bcaf0c..c5799eb 100644 --- a/Makefile +++ b/Makefile @@ -24,11 +24,6 @@ BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) endif BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) -RELEASE ?= false -ifeq ($(RELEASE), true) - DOCKER_BUILDX_FLAGS += --push -endif - # IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. # This variable is used to construct full image tags for bundle and catalog images. # @@ -40,10 +35,10 @@ TAG ?= v$(VERSION) # BUNDLE_IMG defines the image:tag used for the bundle. # You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) -BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:$(TAG) +BUNDLE_IMG_BASE ?= $(IMAGE_TAG_BASE)-bundle # The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). -CATALOG_IMG ?= $(IMAGE_TAG_BASE)-index:$(TAG) +CATALOG_IMG_BASE ?= $(IMAGE_TAG_BASE)-index # BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) @@ -58,6 +53,8 @@ endif # Image URL to use all building/pushing image targets IMG ?= quay.io/olmtest/webhook-operator:$(TAG) +BUNDLE_IMAGE = $(BUNDLE_IMG_BASE):$(TAG) +CATALOG_IMAGE = $(CATALOG_IMG_BASE):$(TAG) # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -176,7 +173,10 @@ lint-config: $(GOLANGCI_LINT) ## Verify golangci-lint linter configuration $(GOLANGCI_LINT) config verify ##@ Build - +ifeq ($(origin CGO_ENABLED), undefined) +CGO_ENABLED := 0 +endif +export CGO_ENABLED export GIT_REPO := $(shell go list -m) export VERSION_PATH := ${GIT_REPO}/internal/shared/version @@ -190,7 +190,14 @@ export GO_BUILD_LDFLAGS := -s -w \ .PHONY: build build: manifests generate fmt vet ## Build manager binary. - go build $(GO_BUILD_FLAGS) $(GO_BUILD_EXTRA_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o bin/manager cmd/main.go + go build $(GO_BUILD_FLAGS) $(GO_BUILD_EXTRA_FLAGS) -tags '$(GO_BUILD_TAGS)' -ldflags '$(GO_BUILD_LDFLAGS)' -gcflags '$(GO_BUILD_GCFLAGS)' -asmflags '$(GO_BUILD_ASMFLAGS)' -o $(BUILDBIN)/manager cmd/main.go + +.PHONY: build-linux go-build-linux +build-linux: go-build-linux #EXHELP Build manager binary for GOOS=linux and local GOARCH. +go-build-linux: BUILDBIN := bin/linux +go-build-linux: export GOOS=linux +go-build-linux: export GOARCH=amd64 +go-build-linux: build .PHONY: run run: manifests generate fmt vet ## Run a controller from your host. @@ -200,30 +207,13 @@ run: manifests generate fmt vet ## Run a controller from your host. # (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it. # More info: https://docs.docker.com/develop/develop-images/build_enhancements/ .PHONY: docker-build -docker-build: ## Build docker image with the manager. - $(CONTAINER_TOOL) build -t ${IMG} . +docker-build: build-linux ## Build docker image with the manager. + $(CONTAINER_TOOL) build -t ${IMG} -f Dockerfile bin/linux .PHONY: docker-push docker-push: ## Push docker image with the manager. $(CONTAINER_TOOL) push ${IMG} -# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple -# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: -# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/ -# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/ -# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=> then the export will fail) -# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option. -PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le -.PHONY: docker-buildx -docker-buildx: ## Build and push docker image for the manager for cross-platform support - # copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile - sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross - - $(CONTAINER_TOOL) buildx create --name webhook-operator-builder - $(CONTAINER_TOOL) buildx use webhook-operator-builder - - $(CONTAINER_TOOL) buildx build $(DOCKER_BUILDX_FLAGS) --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross . - - $(CONTAINER_TOOL) buildx rm webhook-operator-builder - rm Dockerfile.cross - .PHONY: build-installer build-installer: manifests generate $(KUSTOMIZE) ## Generate a consolidated YAML with CRDs and deployment. mkdir -p dist @@ -291,26 +281,24 @@ bundle-build: ## Build the bundle image. bundle-push: ## Push the bundle image. $(MAKE) docker-push IMG=$(BUNDLE_IMG) -.PHONY: bundle-docker-buildx -bundle-docker-buildx: bundle ## Build and push bundle image with cross-platform support - - $(CONTAINER_TOOL) buildx create --name webhook-operator-bundle-builder - $(CONTAINER_TOOL) buildx use webhook-operator-bundle-builder - - $(CONTAINER_TOOL) buildx build $(DOCKER_BUILDX_FLAGS) --platform=$(PLATFORMS) --tag ${BUNDLE_IMG} -f bundle.Dockerfile . - - $(CONTAINER_TOOL) buildx rm webhook-operator-bundle-builder - -.PHONY: build-catalog -build-catalog: $(OPM) +.PHONY: catalog +catalog: $(OPM) @# Create base catalog from template sed "s/{{ VERSION }}/$(VERSION)/g" catalog/catalog.tpl > catalog/catalog.json @# Add bundle FBC $(OPM) render ./bundle >> catalog/catalog.json -.PHONY: catalog-docker-buildx -catalog-docker-buildx: bundle build-catalog ## Build and push docker image for the manager for cross-platform support - - $(CONTAINER_TOOL) buildx create --name webhook-operator-index-builder - $(CONTAINER_TOOL) buildx use webhook-operator-index-builder - - $(CONTAINER_TOOL) buildx build $(DOCKER_BUILDX_FLAGS) --platform=$(PLATFORMS) --tag ${CATALOG_IMG} -f catalog.Dockerfile . - - $(CONTAINER_TOOL) buildx rm webhook-operator-index-builder + +ifeq ($(origin ENABLE_RELEASE_PIPELINE), undefined) +ENABLE_RELEASE_PIPELINE := false +endif +ifeq ($(origin GORELEASER_ARGS), undefined) +GORELEASER_ARGS := --snapshot --clean +endif + +export ENABLE_RELEASE_PIPELINE +export GORELEASER_ARGS .PHONY: release -release: docker-buildx bundle-docker-buildx catalog-docker-buildx +release: $(GORELEASER) bundle catalog #EXHELP Runs goreleaser. By default, this will run only as a snapshot and will not publish any artifacts unless it is run with different arguments. To override the arguments, run with "GORELEASER_ARGS=...". When run as a github action from a tag, this target will publish a full release. + CONTROLLER_IMAGE=$(IMAGE_TAG_BASE) BUNDLE_IMAGE=$(BUNDLE_IMG_BASE) CATALOG_IMAGE=$(CATALOG_IMG_BASE) TAG=$(TAG) $(GORELEASER) $(GORELEASER_ARGS) diff --git a/catalog.Dockerfile b/catalog.Dockerfile index e932935..fcc3e90 100644 --- a/catalog.Dockerfile +++ b/catalog.Dockerfile @@ -1,13 +1,13 @@ # The builder image is expected to contain # /bin/opm (with serve subcommand) -FROM quay.io/operator-framework/opm:latest AS builder +FROM --platform=$BUILDPLATFORM quay.io/operator-framework/opm:latest AS builder # Copy FBC root into image at /configs and pre-populate serve cache ADD catalog/.indexignore /configs/.indexignore ADD catalog/catalog.json /configs/catalog.json RUN ["/bin/opm", "serve", "/configs", "--cache-dir=/tmp/cache", "--cache-only"] -FROM quay.io/operator-framework/opm:latest +FROM --platform=$BUILDPLATFORM quay.io/operator-framework/opm:latest # The base image is expected to contain # /bin/opm (with serve subcommand) and /bin/grpc_health_probe