From 1bf6eef1185f44e212662531b63254ccfc9ea8c6 Mon Sep 17 00:00:00 2001 From: dtfranz Date: Thu, 2 Mar 2023 09:56:07 -0800 Subject: [PATCH] Operator Controller Release Adds a release github action and implements goreleaser, borrowing heavily from rukpak but stripped down a bit. Signed-off-by: dtfranz --- .dockerignore | 4 --- .github/workflows/release.yaml | 63 ++++++++++++++++++++++++++++++++++ .gitignore | 10 +++++- .goreleaser.template.yml | 50 +++++++++++++++++++++++++++ Dockerfile | 36 +++++-------------- Makefile | 36 ++++++++++++++----- bin/.dockerignore | 8 +++++ 7 files changed, 166 insertions(+), 41 deletions(-) delete mode 100644 .dockerignore create mode 100644 .github/workflows/release.yaml create mode 100644 .goreleaser.template.yml create mode 100644 bin/.dockerignore diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 0f046820f..000000000 --- a/.dockerignore +++ /dev/null @@ -1,4 +0,0 @@ -# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file -# Ignore build and test binaries. -bin/ -testbin/ diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..28b318b96 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,63 @@ +name: release + +on: + workflow_dispatch: + push: + branches: + - 'main' + tags: + - 'v*' + pull_request: + branches: + - main + +jobs: + goreleaser: + name: goreleaser + runs-on: ubuntu-latest + steps: + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version-file: "go.mod" + + - name: Docker Login + if: ${{ github.event_name != 'pull_request' }} + uses: docker/login-action@v1 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} + + - name: Set the release related variables + run: | + if [[ $GITHUB_REF == refs/tags/* ]]; then + # Release tags. + echo IMAGE_TAG="${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV + echo GORELEASER_ARGS="--rm-dist" >> $GITHUB_ENV + echo DISABLE_RELEASE_PIPELINE=false >> $GITHUB_ENV + elif [[ $GITHUB_REF == refs/heads/* ]]; then + # Branch build. + echo IMAGE_TAG="$(echo "${GITHUB_REF#refs/heads/}" | sed -r 's|/+|-|g')" >> $GITHUB_ENV + echo GORELEASER_ARGS="--rm-dist --skip-validate" >> $GITHUB_ENV + elif [[ $GITHUB_REF == refs/pull/* ]]; then + # PR build. + echo IMAGE_TAG="pr-$(echo "${GITHUB_REF}" | sed -E 's|refs/pull/([^/]+)/?.*|\1|')" >> $GITHUB_ENV + else + echo IMAGE_TAG="$(git describe --tags --always)" >> $GITHUB_ENV + fi + + - name: Generate the operator-controller release manifests + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + run: | + make quickstart VERSION=${GITHUB_REF#refs/tags/} + + - name: Run goreleaser + run: make release + env: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.gitignore b/.gitignore index e917e5cef..81a264299 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ *.dll *.so *.dylib -bin +bin/* testbin/* Dockerfile.cross @@ -15,6 +15,11 @@ Dockerfile.cross # Output of the go coverage tool, specifically when used with LiteIDE *.out +# Release output +dist/** +.goreleaser.yml +operator-controller.yaml + # Kubernetes Generated files - skip generated files, except for vendored files !vendor/**/zz_generated.* @@ -24,3 +29,6 @@ Dockerfile.cross *.swp *.swo *~ + +# TODO dfranz remove this line and the bin folder when tools binaries are moved to their own folder +!bin/.dockerignore diff --git a/.goreleaser.template.yml b/.goreleaser.template.yml new file mode 100644 index 000000000..95924d5a5 --- /dev/null +++ b/.goreleaser.template.yml @@ -0,0 +1,50 @@ +env: +- GOPROXY=https://proxy.golang.org|direct +- GO111MODULE=on +- CGO_ENABLED=0 +before: + hooks: + - go mod tidy + - go mod download +builds: + - id: operator-controller + main: ./ + binary: bin/manager + tags: $GO_BUILD_TAGS + goos: + - linux + ldflags: + - -X main.Version={{ .Version }} +dockers: +- image_templates: + - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}" + dockerfile: Dockerfile + goos: linux +docker_manifests: +- name_template: "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}" + image_templates: + - "{{ .Env.IMAGE_REPO }}:{{ .Env.IMAGE_TAG }}" +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}-next" +changelog: + use: github-native + skip: $DISABLE_RELEASE_PIPELINE +release: + disable: $DISABLE_RELEASE_PIPELINE + extra_files: + - glob: 'operator-controller.yaml' + header: | + ## Installation + + ```bash + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/{{ .Env.CERT_MGR_VERSION }}/cert-manager.yaml + kubectl wait --for=condition=Available --namespace=cert-manager deployment/cert-manager-webhook --timeout=60s + kubectl apply -f https://github.com/operator-framework/rukpak/releases/latest/download/rukpak.yaml + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/core --timeout=60s + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/helm-provisioner --timeout=60s + kubectl wait --for=condition=Available --namespace=rukpak-system deployment/rukpak-webhooks --timeout=60s + kubectl apply -f https://github.com/operator-framework/operator-controller/releases/download/{{ .Tag }}/operator-controller.yaml + kubectl wait --for=condition=Available --namespace=operator-controller-system deployment/operator-controller --timeout=60s + ``` diff --git a/Dockerfile b/Dockerfile index 8f0d54e8f..1266e95ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,34 +1,14 @@ -# Build the manager binary -FROM golang:1.19 as builder -ARG TARGETOS -ARG TARGETARCH +# 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 /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 +WORKDIR / -# Copy the go source -COPY main.go main.go -COPY api/ api/ -COPY controllers/ controllers/ -COPY internal/ internal/ +COPY manager manager -# Build -# the GOARCH has not a default value to allow the binary 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 -a -o manager main.go +EXPOSE 8080 -# Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -FROM gcr.io/distroless/static:nonroot -WORKDIR / -COPY --from=builder /workspace/manager . USER 65532:65532 -ENTRYPOINT ["/manager"] +ENTRYPOINT ["/manager"] \ No newline at end of file diff --git a/Makefile b/Makefile index 69f3a22bf..d9d91c7fc 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,7 @@ export IMAGE_REPO ?= quay.io/operator-framework/operator-controller export IMAGE_TAG ?= devel export GO_BUILD_TAGS ?= upstream export CERT_MGR_VERSION ?= v1.9.0 +export GORELEASER_VERSION ?= v1.15.2 export WAIT_TIMEOUT ?= 60s IMG?=$(IMAGE_REPO):$(IMAGE_TAG) @@ -94,8 +95,8 @@ kind-cluster-cleanup: kind ## Delete the kind cluster ##@ Build .PHONY: build -build: manifests generate fmt vet ## Build manager binary. - go build -o bin/manager main.go +build: manifests generate fmt vet goreleaser ## Build manager binary using goreleaser for current GOOS and GOARCH. + CGO_ENABLED=0 ${GORELEASER} build ${GORELEASER_ARGS} --single-target -o bin/manager .PHONY: run run: docker-build kind-cluster kind-load cert-mgr rukpak install deploy wait ## Build the operator-controller then deploy it into a new kind cluster. @@ -108,12 +109,9 @@ wait: # (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: generate ## Build docker image with the operator-controller. - docker build -t ${IMG} . - -.PHONY: docker-push -docker-push: ## Push docker image with the manager. - docker push ${IMG} +docker-build: export GOOS=linux +docker-build: build ## Build docker image with the operator-controller. + docker build -t ${IMG} -f Dockerfile ./bin/ # PLATFORMS defines the target platforms for the manager image be build to provide support to multiple # architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: @@ -132,6 +130,22 @@ docker-buildx: test ## Build and push docker image for the manager for cross-pla - docker buildx rm project-v3-builder rm Dockerfile.cross +########### +# Release # +########### + +##@ Release: +export DISABLE_RELEASE_PIPELINE ?= true +export GORELEASER_ARGS ?= --snapshot --rm-dist +release: goreleaser ## Runs goreleaser for the operator-controller. 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. + envsubst < .goreleaser.template.yml > .goreleaser.yml + $(GORELEASER) $(GORELEASER_ARGS) + +quickstart: VERSION ?= $(shell git describe --abbrev=0 --tags) +quickstart: generate ## Generate the installation release manifests + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMAGE_REPO}:${VERSION} + kubectl kustomize config/default > operator-controller.yaml + ##@ Deployment ifndef ignore-not-found @@ -178,6 +192,7 @@ KUSTOMIZE ?= $(LOCALBIN)/kustomize CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen KIND ?= $(LOCALBIN)/kind GINKGO ?= $(LOCALBIN)/ginkgo +GORELEASER := $(LOCALBIN)/goreleaser ENVTEST ?= $(LOCALBIN)/setup-envtest ## Tool Versions @@ -194,6 +209,11 @@ ginkgo: $(GINKGO) ## Download ginkgo locally if necessary. $(GINKGO): $(LOCALBIN) test -s $(LOCALBIN)/ginkgo || GOBIN=$(LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo@v2.1.4 +.PHONY: goreleaser +goreleaser: $(GORELEASER) ## Builds a local copy of goreleaser +$(GORELEASER): $(LOCALBIN) + test -s $(LOCALBIN)/goreleaser || GOBIN=$(LOCALBIN) go install github.com/goreleaser/goreleaser@${GORELEASER_VERSION} + KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" .PHONY: kustomize kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading. diff --git a/bin/.dockerignore b/bin/.dockerignore new file mode 100644 index 000000000..97e40c0e3 --- /dev/null +++ b/bin/.dockerignore @@ -0,0 +1,8 @@ +# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file +# Ignore tools binaries +# TODO dfranz: We don't need this file anymore once we move the tool binaries out. +controller-gen +ginkgo +goreleaser +kind +kustomize