diff --git a/.ci/cache_version_tags.sh b/.ci/cache_version_tags.sh new file mode 100644 index 0000000..aafb2dc --- /dev/null +++ b/.ci/cache_version_tags.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# +# Copyright Red Hat +# +# 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. + +VERSION_PATTERN="v[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?" +CONFIG_CSV='config/manifests/bases/registry-operator.clusterserviceversion.yaml' +CONFIG_MANAGER_KUSTOMIZE='config/manager/kustomization.yaml' +BUNDLE_CSV='bundle/manifests/registry-operator.clusterserviceversion.yaml' +YQ_CLI=${YQ_CLI:-yq} + +# error on unset variables +set -u + +${YQ_CLI} '.spec.version' ${CONFIG_CSV} > ${CACHED_CSV_VERSION} && \ +${YQ_CLI} '(.metadata.annotations.containerImage | split(":") | .[1])' ${CONFIG_CSV} > ${CACHED_CSV_CONTAINER_IMAGE_TAG} && \ +${YQ_CLI} "(.metadata.name | capture(\"(?P${VERSION_PATTERN})\") | .tag)" ${CONFIG_CSV} > ${CACHED_CSV_NAME_TAG} && \ +${YQ_CLI} '.spec.version' ${BUNDLE_CSV} > ${CACHED_BUNDLE_VERSION} && \ +${YQ_CLI} '(.metadata.annotations.containerImage | split(":") | .[1])' ${BUNDLE_CSV} > ${CACHED_BUNDLE_CONTAINER_IMAGE_TAG} && \ +${YQ_CLI} "(.metadata.name | capture(\"(?P${VERSION_PATTERN})\") | .tag)" ${BUNDLE_CSV} > ${CACHED_BUNDLE_NAME_TAG} && \ +${YQ_CLI} '.images[0].newTag' ${CONFIG_MANAGER_KUSTOMIZE} > ${CACHED_MANAGER_IMAGE_TAG} diff --git a/.ci/minikube_integration.sh b/.ci/minikube_integration.sh new file mode 100644 index 0000000..fd5f706 --- /dev/null +++ b/.ci/minikube_integration.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# +# Copyright Red Hat +# +# 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. + +# NOTE: This script assumes that minikube is installed and running, and using the docker driver on Linux +# Due to networking issues with the docker driver and ingress on macOS/Windows, this script must be run on Linux + +# Share docker env with Minikube +eval $(minikube docker-env) + +# error on unset variables +set -u +# print each command before executing it +set -x + +# Build the registry operator image +export IMG=${REGISTRY_OPERATOR} +make docker-build +if [ $? -ne 0 ]; then + echo "Error building registry operator image" + exit 1; +fi + +# Install cert-manager +make install-cert + +# Wait for the cert-manager to become ready +kubectl wait deploy/cert-manager --namespace cert-manager --for=condition=Available --timeout=600s +kubectl wait deploy/cert-manager-cainjector --namespace cert-manager --for=condition=Available --timeout=600s +kubectl wait deploy/cert-manager-webhook --namespace cert-manager --for=condition=Available --timeout=600s +if [ $? -ne 0 ]; then + echo "cert-manager-controller container logs:" + kubectl logs -l app=cert-manager --namespace cert-manager --container cert-manager-controller + echo "cert-manager-cainjector container logs:" + kubectl logs -l app=cainjector --namespace cert-manager --container cert-manager-cainjector + echo "cert-manager-webhook container logs:" + kubectl logs -l app=webhook --namespace cert-manager --container cert-manager-webhook + + # Return the description of every pod + kubectl describe pods --namespace cert-manager + exit 1 +fi + +# Install CRDs & deploy registry operator +make install && make deploy + +# Wait for the registry operator to become ready +kubectl wait deploy/registry-operator-controller-manager --namespace registry-operator-system --for=condition=Available --timeout=600s +if [ $? -ne 0 ]; then + echo "manager container logs:" + kubectl logs -l app=devfileregistry-operator --namespace registry-operator-system --container manager + echo "kube-rbac-proxy container logs:" + kubectl logs -l app=devfileregistry-operator --namespace registry-operator-system --container kube-rbac-proxy + + # Return the description of every pod + kubectl describe pods --namespace registry-operator-system + exit 1 +fi + +# wait 15 seconds for registry operator to get set up +sleep 15 + +# run integration test suite +make test-integration diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 801c02d..70b8fed 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,18 +23,18 @@ jobs: name: Check go sources runs-on: ubuntu-latest steps: + - + name: Check out code into the Go module directory + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 with: - go-version: 1.19 - - - name: Check out code into the Go module directory - uses: actions/checkout@v2 + go-version-file: 'go.mod' - name: Cache go modules id: cache-mod - uses: actions/cache@v2 + uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3.3.2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -86,7 +86,7 @@ jobs: run: make test - name: Upload coverage to Codecov - uses: codecov/codecov-action@v2.1.0 + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 - name: Run Gosec Security Scanner run: | @@ -99,7 +99,7 @@ jobs: fi - name: Upload SARIF file - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@74483a38d39275f33fcff5f35b679b5ca4a26a99 # 2.22.5 with: # Path to SARIF file relative to the root of the repository sarif_file: gosec.sarif @@ -110,7 +110,7 @@ jobs: steps: - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Check if operator docker build is working run: docker build -f Dockerfile . @@ -121,7 +121,7 @@ jobs: steps: - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Build the operator's bundle image run: make bundle-build diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 72499d3..5670664 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -22,14 +22,14 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout - uses: actions/checkout@v2.3.1 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 with: persist-credentials: false - name: Set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 with: - go-version: 1.19 + go-version-file: 'go.mod' - name: Run tests run: make test - name: Codecov - uses: codecov/codecov-action@v2.1.0 + uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4 diff --git a/.github/workflows/dockerimage-push.yaml b/.github/workflows/dockerimage-push.yaml index 92c59f8..a504c46 100644 --- a/.github/workflows/dockerimage-push.yaml +++ b/.github/workflows/dockerimage-push.yaml @@ -24,9 +24,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout registry-operator source code - uses: actions/checkout@v2 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Docker Build & Push - Registry Operator Image - uses: docker/build-push-action@v1.1.0 + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 with: username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} @@ -40,9 +40,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout registry-operator source code - uses: actions/checkout@v2 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Build and push the Registry Operator Bundle to quay.io - uses: docker/build-push-action@v1.1.0 + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 with: username: ${{ secrets.QUAY_USERNAME }} password: ${{ secrets.QUAY_PASSWORD }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..b242ea1 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,138 @@ +# +# Copyright Red Hat +# +# 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. +name: Release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+' + +env: + OPERATOR_SDK_DL_URL: https://github.com/operator-framework/operator-sdk/releases/download/v1.28.0 + OPERATOR_SDK_CLI: ./operator-sdk + +jobs: + version-check: + runs-on: ubuntu-latest + env: + CACHED_CSV_VERSION: .cache/csv_version.txt + CACHED_CSV_CONTAINER_IMAGE_TAG: .cache/csv_container_image_tag.txt + CACHED_CSV_NAME_TAG: .cache/csv_name_tag.txt + CACHED_BUNDLE_VERSION: .cache/bundle_version.txt + CACHED_BUNDLE_CONTAINER_IMAGE_TAG: .cache/bundle_container_image_tag.txt + CACHED_BUNDLE_NAME_TAG: .cache/bundle_name_tag.txt + CACHED_MANAGER_IMAGE_TAG: .cache/manager_image_tag.txt + steps: + - name: Checkout registry-operator source code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Download yq + run: curl -sL https://github.com/mikefarah/yq/releases/download/v4.34.2/yq_linux_amd64 -o yq && chmod +x yq + - name: Cache version tags + env: + YQ_CLI: ./yq + run: mkdir -p .cache && bash .ci/cache_version_tags.sh + - name: Check if VERSION and version tags match release tag + run: bash check_version.sh ${{ github.ref_name }} + k8s-integration-test: + strategy: + matrix: + version: [1.25, 1.26] + needs: version-check + runs-on: ubuntu-latest + steps: + - name: Checkout registry-operator source code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup Go environment + uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + with: + go-version-file: 'go.mod' + - name: Download operator-sdk + run: | + export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) + export OS=$(uname | awk '{print tolower($0)}') + + curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH} + - name: Verify the downloaded operator-sdk + run: | + export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) + export OS=$(uname | awk '{print tolower($0)}') + gpg --keyserver keyserver.ubuntu.com --recv-keys 052996E2A20B5C7E; + curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt; + curl -LO ${OPERATOR_SDK_DL_URL}/checksums.txt.asc; + gpg -u "Operator SDK (release) " --verify checksums.txt.asc; + grep operator-sdk_${OS}_${ARCH} checksums.txt | sha256sum -c - + - name: Setup operator-sdk + run: | + export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac) + export OS=$(uname | awk '{print tolower($0)}') + mv operator-sdk_${OS}_${ARCH} ${OPERATOR_SDK_CLI} + chmod +x ${OPERATOR_SDK_CLI} + - name: Setup Minikube + uses: manusa/actions-setup-minikube@3856c6fa039819f1c8e7e248b1fc5a8564e354c9 # v2.9.0 + with: + minikube version: 'v1.31.2' + kubernetes version: "${{ matrix.version }}" + driver: 'docker' + github token: ${{ secrets.GITHUB_TOKEN }} + start args: '--memory 4096 --cpus 2' + - name: Set manager image pull policy to Never + uses: mikefarah/yq@0b34c9a00de1c575a34eea05af1d956a525c4fc1 # v4.34.2 + with: + cmd: yq -i '(select(documentIndex == 1) | .spec.template.spec.containers[0].imagePullPolicy) = "Never"' 'config/manager/manager.yaml' + - name: Run integration testing on release image + env: + REGISTRY_OPERATOR: localhost/registry-operator:${{ github.ref_name }} + run: bash .ci/minikube_integration.sh + push-operator-image: + needs: + # uncomment and remove version-check when integration testing for k8s has been fixed + # https://github.com/devfile/api/issues/1313 + # - k8s-1-26-integration-test + # - k8s-1-25-integration-test + - version-check + runs-on: ubuntu-latest + steps: + - name: Checkout registry-operator source code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Docker Build & Push - Registry Operator Release Image + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} + registry: quay.io + repository: devfile/registry-operator + dockerfile: Dockerfile + tags: ${{ github.ref_name }} + push-operator-bundle: + needs: + # uncomment and remove version-check when integration testing for k8s has been fixed + # https://github.com/devfile/api/issues/1313 + # - k8s-1-26-integration-test + # - k8s-1-25-integration-test + - version-check + runs-on: ubuntu-latest + steps: + - name: Checkout registry-operator source code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Docker Build & Push - Registry Operator Bundle Release Image + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} + registry: quay.io + repository: devfile/registry-operator-bundle + dockerfile: bundle.Dockerfile + tags: ${{ github.ref_name }} diff --git a/.gitignore b/.gitignore index d97ffc5..b944d5c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ bin *.swp *.swo *~ + +# cache directory +.cache/ diff --git a/Makefile b/Makefile index 638bf99..a5acd32 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,9 @@ K8S_CLI := kubectl endif endif +# operator-sdk +OPERATOR_SDK_CLI ?= operator-sdk + # Setting SHELL to bash allows bash commands to be executed by recipes. # This is a requirement for 'setup-envtest.sh' in the test target. @@ -241,10 +244,10 @@ $(ENVTEST): $(LOCALBIN) # Generate bundle manifests and metadata, then validate generated files. .PHONY: bundle bundle: manifests - operator-sdk generate kustomize manifests -q + $(OPERATOR_SDK_CLI) generate kustomize manifests -q cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) - $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) - operator-sdk bundle validate ./bundle + $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK_CLI) generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + $(OPERATOR_SDK_CLI) bundle validate ./bundle # Build the bundle image. .PHONY: bundle-build diff --git a/check_version.sh b/check_version.sh new file mode 100644 index 0000000..3e96dba --- /dev/null +++ b/check_version.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +# +# Copyright Red Hat +# +# 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. + +CACHED_CSV_VERSION=${CACHED_CSV_VERSION:-'.cache/csv_version.txt'} +CACHED_CSV_CONTAINER_IMAGE_TAG=${CACHED_CSV_CONTAINER_IMAGE_TAG:-'.cache/csv_container_image_tag.txt'} +CACHED_CSV_NAME_TAG=${CACHED_CSV_NAME_TAG:-'.cache/csv_name_tag.txt'} +CACHED_BUNDLE_VERSION=${CACHED_BUNDLE_VERSION:-'.cache/bundle_version.txt'} +CACHED_BUNDLE_CONTAINER_IMAGE_TAG=${CACHED_BUNDLE_CONTAINER_IMAGE_TAG:-'.cache/bundle_container_image_tag.txt'} +CACHED_BUNDLE_NAME_TAG=${CACHED_BUNDLE_NAME_TAG:-'.cache/bundle_name_tag.txt'} +CACHED_MANAGER_IMAGE_TAG=${CACHED_MANAGER_IMAGE_TAG:-'.cache/manager_image_tag.txt'} + +ref_name=$1 +failed="false" + +if [ -z ${ref_name} ] +then + echo "expects release tag (ref_name): bash check_version.sh [is_ci=false]" + exit 1 +fi + +if [ "${CI}" != "true" ] +then + if [ -z $(command -v yq) ] && [ -z $(command -v ${YQ_CLI}) ] + then + echo "This script requires the yq tool." + exit 1 + fi + + # Make cache directory if not exists + mkdir -p .cache/ + + # Export variables + export CACHED_CSV_VERSION + export CACHED_CSV_CONTAINER_IMAGE_TAG + export CACHED_CSV_NAME_TAG + export CACHED_BUNDLE_VERSION + export CACHED_BUNDLE_CONTAINER_IMAGE_TAG + export CACHED_BUNDLE_NAME_TAG + export CACHED_MANAGER_IMAGE_TAG + + # Read references to release version under project files and cache them for checks + bash .ci/cache_version_tags.sh + if [ $? -ne 0 ] + then + exit 1 + fi +fi + +# error on unset variables +set -u + +## Check if all references to the release version match ## + +if [ "${ref_name}" != "v$(cat ./VERSION)" ] +then + echo "Release tag does not match VERSION: release tag = ${ref_name}, VERSION = v$(cat ./VERSION)" + failed="true" +fi + +if [ "${ref_name}" != "v$(cat ${CACHED_CSV_VERSION})" ] +then + echo "Release tag does not match csv version: release tag = ${ref_name}, csv version = v$(cat ${CACHED_CSV_VERSION})" + failed="true" +fi + +if [ "${ref_name}" != "$(cat ${CACHED_CSV_CONTAINER_IMAGE_TAG})" ] +then + echo "Release tag does not match csv container image tag: release tag = ${ref_name}, csv container image tag = $(cat ${CACHED_CSV_CONTAINER_IMAGE_TAG})" + failed="true" +fi + +if [ "${ref_name}" != "$(cat ${CACHED_CSV_NAME_TAG})" ] +then + echo "Release tag does not match csv name tag: release tag = ${ref_name}, csv name tag = $(cat ${CACHED_CSV_NAME_TAG})" + failed="true" +fi + +if [ "${ref_name}" != "v$(cat ${CACHED_BUNDLE_VERSION})" ] +then + echo "Release tag does not match bundle version: release tag = ${ref_name}, bundle version = v$(cat ${CACHED_BUNDLE_VERSION})" + failed="true" +fi + +if [ "${ref_name}" != "$(cat ${CACHED_BUNDLE_CONTAINER_IMAGE_TAG})" ] +then + echo "Release tag does not match bundle container image tag: release tag = ${ref_name}, bundle container image tag = $(cat ${CACHED_BUNDLE_CONTAINER_IMAGE_TAG})" + failed="true" +fi + +if [ "${ref_name}" != "$(cat ${CACHED_BUNDLE_NAME_TAG})" ] +then + echo "Release tag does not match bundle name tag: release tag = ${ref_name}, bundle name tag = $(cat ${CACHED_BUNDLE_NAME_TAG})" + failed="true" +fi + +if [ "${ref_name}" != "$(cat ${CACHED_MANAGER_IMAGE_TAG})" ] +then + echo "Release tag does not match manager image tag: release tag = ${ref_name}, manager image tag = $(cat ${CACHED_MANAGER_IMAGE_TAG})" + failed="true" +fi + +if [ ${failed} == "true" ] +then + echo "One or more checks failed!" + exit 1 +else + echo "All version tags match!" +fi