diff --git a/.github/workflows/build-images-base.yaml b/.github/workflows/build-images-base.yaml index 6b25787..4967a61 100644 --- a/.github/workflows/build-images-base.yaml +++ b/.github/workflows/build-images-base.yaml @@ -69,7 +69,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: Read release string version + id: release + run: | + version=`make read-release-version` + echo version=$version >> $GITHUB_OUTPUT - name: Install qemu dependency run: | sudo apt-get update @@ -91,6 +96,7 @@ jobs: build-args: | GIT_SHA=${{ github.sha }} DIRTY=false + VERSION=${{ steps.release.outputs.version }} QUAY_IMAGE_EXPIRY=${{ inputs.quayImageExpiry }} - name: Push Image if: ${{ !env.ACT }} diff --git a/.github/workflows/build-images-for-tag-release.yaml b/.github/workflows/build-images-for-tag-release.yaml new file mode 100644 index 0000000..e230ec9 --- /dev/null +++ b/.github/workflows/build-images-for-tag-release.yaml @@ -0,0 +1,197 @@ +name: Build and Publish Images For Tag Release + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" +env: + IMG_REGISTRY_HOST: quay.io + IMG_REGISTRY_ORG: kuadrant + IMG_REGISTRY_REPO: limitador-operator + OPERATOR_NAME: limitador-operator + +jobs: + build: + name: Build and Push image + runs-on: ubuntu-latest + outputs: + build-tags: ${{ steps.build-image.outputs.tags }} + image: ${{ steps.push-to-quay.outputs.registry-path }} + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Read release string version + id: release + run: | + version=`make read-release-version` + echo version=$version >> $GITHUB_OUTPUT + + - name: Print tags + run: echo "Git reference name = ${{ github.ref_name }}, release version = ${{ steps.release.outputs.version }}" + - name: Verify git reference name matches the release version + if: ${{ github.ref_name != steps.release.outputs.version }} + run: exit 1 + + - name: Install qemu dependency + run: | + sudo apt-get update + sudo apt-get install -y qemu-user-static + + - name: Build Image + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + image: ${{ env.OPERATOR_NAME }} + tags: ${{ github.ref_name }} + platforms: linux/amd64,linux/arm64 + build-args: | + GIT_SHA=${{ github.sha }} + DIRTY=false + VERSION=${{ github.ref_name }} + + dockerfiles: | + ./Dockerfile + + - name: Print Build Info + run: echo "Image = ${{ steps.build-image.outputs.image }}, Tags = ${{ steps.build-image.outputs.tags }}" + + - name: Push Image + if: github.repository_owner == 'kuadrant' + id: push-to-quay + uses: redhat-actions/push-to-registry@v2 + with: + image: ${{ steps.build-image.outputs.image }} + tags: ${{ steps.build-image.outputs.tags }} + registry: ${{ env.IMG_REGISTRY_HOST }}/${{ env.IMG_REGISTRY_ORG }} + username: ${{ secrets.IMG_REGISTRY_USERNAME }} + password: ${{ secrets.IMG_REGISTRY_TOKEN }} + + - name: Print Image URL + run: echo "Image pushed to ${{ steps.push-to-quay.outputs.registry-paths }}" + + build-bundle: + name: Build and Push bundle image + needs: [build] + runs-on: ubuntu-latest + outputs: + build-tags: ${{ steps.build-image.outputs.tags }} + image: ${{ steps.push-to-quay.outputs.registry-path }} + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Install yq tool + run: | + # following sub-shells running make target should have yq already installed + make yq + - name: Read operator image reference URL from the manifest bundle + id: parsed-operator-image + run: | + url=`make bundle-operator-image-url` + echo url=$url >> $GITHUB_OUTPUT + - name: Print tags and references + run: echo "Operator image tag = ${{ needs.build.outputs.image }}, Reference in bundle = ${{ steps.parsed-operator-image.outputs.url }}" + - name: Verify referenced operator image tag matches the tag currently being built + if: ${{ needs.build.outputs.image != steps.parsed-operator-image.outputs.url }} + run: exit 1 + + - name: Install qemu dependency + run: | + sudo apt-get update + sudo apt-get install -y qemu-user-static + + - name: Build Image + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + image: ${{ env.OPERATOR_NAME }}-bundle + tags: ${{ needs.build.outputs.build-tags }} + platforms: linux/amd64,linux/arm64 + dockerfiles: | + ./bundle.Dockerfile + + - name: Print Build Info + run: echo "Image = ${{ steps.build-image.outputs.image }}, Tags = ${{ steps.build-image.outputs.tags }}, Operator IMG = ${{ steps.parsed-operator-image.outputs.url }}" + + - name: Push Image + if: github.repository_owner == 'kuadrant' + id: push-to-quay + uses: redhat-actions/push-to-registry@v2 + with: + image: ${{ steps.build-image.outputs.image }} + tags: ${{ steps.build-image.outputs.tags }} + registry: ${{ env.IMG_REGISTRY_HOST }}/${{ env.IMG_REGISTRY_ORG }} + username: ${{ secrets.IMG_REGISTRY_USERNAME }} + password: ${{ secrets.IMG_REGISTRY_TOKEN }} + + - name: Print Image URL + run: echo "Image pushed to ${{ steps.push-to-quay.outputs.registry-paths }}" + + build-catalog: + name: Build and Push catalog image + needs: [build, build-bundle] + runs-on: ubuntu-latest + outputs: + build-tags: ${{ steps.build-image.outputs.tags }} + image: ${{ steps.push-to-quay.outputs.registry-path }} + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Install yq tool + run: | + # following sub-shells running make target should have yq already installed + make yq + - name: Read operator bundle image reference + id: parsed-operator-bundle + run: | + image=`make print-bundle-image` + echo image=$image >> $GITHUB_OUTPUT + - name: Print tags and references + run: echo "Operator bundle image tag = ${{ needs.build-bundle.outputs.image }}, Reference in catalog = ${{ steps.parsed-operator-bundle.outputs.image }}" + - name: Verify referenced bundle tag matches the bundle tag currently being built + if: ${{ needs.build-bundle.outputs.image != steps.parsed-operator-bundle.outputs.image }} + run: exit 1 + - name: Generate Catalog Content + run: make catalog + - name: Install qemu dependency + run: | + sudo apt-get update + sudo apt-get install -y qemu-user-static + - name: Build Image + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + image: ${{ env.OPERATOR_NAME }}-catalog + tags: ${{ needs.build.outputs.build-tags }} + platforms: linux/amd64,linux/arm64 + context: ./catalog + dockerfiles: ./catalog/${{ env.OPERATOR_NAME }}-catalog.Dockerfile + + - name: Print Build Info + run: echo "Image = ${{ steps.build-image.outputs.image }}, Tags = ${{ steps.build-image.outputs.tags }}, Bundle IMG = ${{ steps.parsed-operator-bundle.outputs.image }}" + + - name: Push Image + if: github.repository_owner == 'kuadrant' + id: push-to-quay + uses: redhat-actions/push-to-registry@v2 + with: + image: ${{ steps.build-image.outputs.image }} + tags: ${{ steps.build-image.outputs.tags }} + registry: ${{ env.IMG_REGISTRY_HOST }}/${{ env.IMG_REGISTRY_ORG }} + username: ${{ secrets.IMG_REGISTRY_USERNAME }} + password: ${{ secrets.IMG_REGISTRY_TOKEN }} + + - name: Print Image URL + run: echo "Image pushed to ${{ steps.push-to-quay.outputs.registry-paths }}" + + verify-builds: + name: Ensure all image references are equal (operator, bundle, catalog) + needs: [build, build-bundle, build-catalog] + runs-on: ubuntu-latest + steps: + - name: Verify bundle and operator image tags match + if: ${{ needs.build.outputs.build-tags != needs.build-bundle.outputs.build-tags }} + run: exit 1 + - name: Verify catalog and bundle tags match + if: ${{ needs.build-bundle.outputs.build-tags != needs.build-catalog.outputs.build-tags }} + run: exit 1 diff --git a/Dockerfile b/Dockerfile index 2ac6bc4..35dc391 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,15 +14,17 @@ COPY main.go main.go COPY api/ api/ COPY controllers/ controllers/ COPY pkg/ pkg/ -COPY version/ version/ # Build ARG GIT_SHA ARG DIRTY +ARG VERSION ENV GIT_SHA=${GIT_SHA:-unknown} ENV DIRTY=${DIRTY:-unknown} -RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags "-X main.gitSHA=${GIT_SHA} -X main.dirty=${DIRTY}" -o manager main.go +ENV VERSION=${VERSION:-unknown} + +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags "-X main.version=${VERSION} -X main.gitSHA=${GIT_SHA} -X main.dirty=${DIRTY}" -o manager main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details diff --git a/Makefile b/Makefile index 82ca5e7..39bceb5 100644 --- a/Makefile +++ b/Makefile @@ -95,6 +95,7 @@ else GOBIN=$(shell go env GOBIN) endif +RELEASE_FILE = $(PROJECT_PATH)/make/release.mk all: build @@ -264,19 +265,19 @@ test-unit: clean-cov generate fmt vet ## Run Unit tests. build: GIT_SHA=$(shell git rev-parse HEAD || echo "unknown") build: DIRTY=$(shell $(PROJECT_PATH)/utils/check-git-dirty.sh || echo "unknown") build: generate fmt vet ## Build manager binary. - go build -ldflags "-X main.gitSHA=${GIT_SHA} -X main.dirty=${DIRTY}" -o bin/manager main.go + go build -ldflags "-X main.version=v$(VERSION) -X main.gitSHA=${GIT_SHA} -X main.dirty=${DIRTY}" -o bin/manager main.go run: export LOG_LEVEL = debug run: export LOG_MODE = development run: GIT_SHA=$(shell git rev-parse HEAD || echo "unknown") run: DIRTY=$(shell $(PROJECT_PATH)/utils/check-git-dirty.sh || echo "unknown") run: manifests generate fmt vet ## Run a controller from your host.) - go run -ldflags "-X main.gitSHA=${GIT_SHA} -X main.dirty=${DIRTY}" ./main.go + go run -ldflags "-X main.version=v$(VERSION) -X main.gitSHA=${GIT_SHA} -X main.dirty=${DIRTY}" ./main.go docker-build: GIT_SHA=$(shell git rev-parse HEAD || echo "unknown") docker-build: DIRTY=$(shell $(PROJECT_PATH)/utils/check-git-dirty.sh || echo "unknown") docker-build: ## Build docker image with the manager. - docker build --build-arg GIT_SHA=$(GIT_SHA) --build-arg DIRTY=$(DIRTY) --build-arg QUAY_IMAGE_EXPIRY=$(QUAY_IMAGE_EXPIRY) -t $(IMG) . + docker build --build-arg VERSION=v$(VERSION) --build-arg GIT_SHA=$(GIT_SHA) --build-arg DIRTY=$(DIRTY) --build-arg QUAY_IMAGE_EXPIRY=$(QUAY_IMAGE_EXPIRY) -t $(IMG) . docker-push: ## Push docker image with the manager. docker push $(IMG) @@ -369,8 +370,19 @@ bundle-build: ## Build the bundle image. bundle-push: ## Push the bundle image. $(MAKE) docker-push IMG=$(BUNDLE_IMG) +.PHONY: bundle-operator-image-url +bundle-operator-image-url: $(YQ) ## Read operator image reference URL from the manifest bundle. + @$(YQ) '.metadata.annotations.containerImage' bundle/manifests/limitador-operator.clusterserviceversion.yaml + +print-bundle-image: ## Pring bundle images. + @echo $(BUNDLE_IMG) + .PHONY: prepare-release +prepare-release: IMG_TAG=v$(VERSION) prepare-release: ## Prepare the manifests for OLM and Helm Chart for a release. + echo -e "#Release default values\\nIMG=$(IMAGE_TAG_BASE):$(IMG_TAG)\nBUNDLE_IMG=$(IMAGE_TAG_BASE)-bundle:$(IMG_TAG)\n\ + CATALOG_IMG=$(IMAGE_TAG_BASE)-catalog:$(IMG_TAG)\nCHANNELS=$(CHANNELS)\nBUNDLE_CHANNELS=--channels=$(CHANNELS)\n\ + VERSION=$(VERSION)" > $(RELEASE_FILE) $(MAKE) bundle VERSION=$(VERSION) \ LIMITADOR_VERSION=$(LIMITADOR_VERSION) \ $(MAKE) helm-build VERSION=$(VERSION) \ diff --git a/RELEASE.md b/RELEASE.md index a4705a2..02fe37b 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,8 +1,6 @@ -# How to release Limitador Operator +# Release -## Process - -To release a version _“v0.W.Z”_ of Limitador Operator in GitHub and Quay.io, follow these steps: +### Process 1. Pick a stable (released) version _“v0.X.Y”_ of the operand known to be compatible with operator’s image for _“v0.W.Z_”; if needed, [make a release of the operand first](https://github.com/Kuadrant/limitador/blob/main/RELEASE.md). @@ -14,18 +12,20 @@ To release a version _“v0.W.Z”_ of Limitador Operator in GitHub and Quay.io, * Commit SHA or branch name of the operator to release – usually: `main` * Operator version to release (without prefix) – i.e. `0.W.Z` * Limitador version the operator enables installations of (without prefix) – i.e. `0.X.Y` - * Operator replaced version (without prefix) – i.e. `0.P.Q` * If the release is a prerelease -3. Run the GHA [Build and push images](https://github.com/Kuadrant/limitador-operator/actions/workflows/build-images-base.yaml) - for the _“v0.W.Z”_ tag, specifying ‘Limitador version’ equals to _“0.X.Y”_. This will cause the - new images (bundle and catalog included) to be built and pushed to the corresponding repos in - [quay.io/kuadrant](https://quay.io/organization/kuadrant). +3. Verify that the build [release tag workflow](https://github.com/Kuadrant/dns-operator/actions/workflows/build-images-for-tag-release.yaml) is triggered and completes for the new tag + +4. Verify the new version can be installed from the catalog image, see [Verify OLM Deployment](#verify-olm-deployment) + +5. Release to the [community operator index catalogs](#community-operator-index-catalogs). + +### Community Operator Index Catalogs +- [Operatorhub Community Operators](https://github.com/k8s-operatorhub/community-operators) +- [Openshift Community Operators](http://github.com/redhat-openshift-ecosystem/community-operators-prod) -### Publishing the Operator in OpenShift Community Operators -Open a PR in the [OpenShift Community Operators repo](http://github.com/redhat-openshift-ecosystem/community-operators-prod) -([example](https://github.com/redhat-openshift-ecosystem/community-operators-prod/pull/1595) | +Open a PR on each index catalog ([example](https://github.com/redhat-openshift-ecosystem/community-operators-prod/pull/1595) | [docs](https://redhat-openshift-ecosystem.github.io/community-operators-prod/operator-release-process/)). The usual steps are: @@ -37,12 +37,3 @@ The usual steps are: * Copy the bundle files from `github.com/kuadrant/limitador-operator/tree/v0.W.Z/bundle` * Copy `github.com/kuadrant/limitador-operator/tree/v0.W.Z/bundle.Dockerfile` with the proper fix to the COPY commands (i.e. remove /bundle from the paths) - -### Publishing the Operator in Kubernetes Community Operators (OperatorHub.io) - -1. Open a PR in the [Kubernetes Community Operators repo](https://github.com/k8s-operatorhub/community-operators) - ([example](https://github.com/k8s-operatorhub/community-operators/pull/1655) | [docs](https://operatorhub.io/contribute)). - -2. The usual steps are the same as for the - [OpenShift Community Operators](https://docs.google.com/document/d/1tLveyv8Zwe0wKyfUTWOlEnFeMB5aVGqIVDUjVYWax0U/edit#heading=h.b5tapxn4sbk5) - hub. diff --git a/main.go b/main.go index fabb1f9..aa4ede2 100644 --- a/main.go +++ b/main.go @@ -38,18 +38,16 @@ import ( "github.com/kuadrant/limitador-operator/controllers" "github.com/kuadrant/limitador-operator/pkg/log" "github.com/kuadrant/limitador-operator/pkg/reconcilers" - //+kubebuilder:scaffold:imports - // import version - "github.com/kuadrant/limitador-operator/version" ) var ( scheme = k8sruntime.NewScheme() logLevel = env.GetString("LOG_LEVEL", "info") logMode = env.GetString("LOG_MODE", "production") - gitSHA string - dirty string + gitSHA string // pass ldflag here to display gitSHA hash + dirty string // must be string as passed in by ldflag to determine display . + version string // must be string as passed in by ldflag to determine display . ) func init() { @@ -72,7 +70,7 @@ func printControllerMetaInfo() { setupLog.Info(fmt.Sprintf("go version: %s", runtime.Version())) setupLog.Info(fmt.Sprintf("go os/arch: %s/%s", runtime.GOOS, runtime.GOARCH)) setupLog.Info("base logger", "log level", logLevel, "log mode", logMode) - setupLog.Info("", "version", version.Version, "commit", gitSHA, "dirty", dirty) + setupLog.Info("build information", "version", version, "commit", gitSHA, "dirty", dirty) } func main() { diff --git a/version/version.go b/version/version.go deleted file mode 100644 index 20e2284..0000000 --- a/version/version.go +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2021 Red Hat, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package version - -var ( - // This variable is dependent on what the current release is e.g. if it is v0.10.0 then this variable, outside of releases, will be v0.10.1-dev . - Version = "v0.12.0-dev" -)