diff --git a/.github/actions/update-csv-bundles/action.yml b/.github/actions/update-csv-bundles/action.yml new file mode 100644 index 0000000000..f0c02aee57 --- /dev/null +++ b/.github/actions/update-csv-bundles/action.yml @@ -0,0 +1,137 @@ +name: "Update CSV bundles" +description: "Generate and finalize OLM CSV bundles for a given version" + +inputs: + version: + description: "Version without v-prefix" + required: true + changelog-path: + description: "Path to the changelog file" + required: true + app-id: + description: "GitHub App ID for creating release PR" + required: true + private-key: + description: "GitHub App private key for creating release PR" + required: true + +outputs: + major_minor: + description: "Major.minor part of the version" + value: ${{ steps.vars.outputs.major_minor }} + +runs: + using: "composite" + steps: + - name: Derive release branch name + id: vars + shell: bash + env: + VERSION: ${{ inputs.version }} + run: | + MAJOR_MINOR="${VERSION%.*}" + echo "major_minor=${MAJOR_MINOR}" >> "$GITHUB_OUTPUT" + - name: Checkout release branch + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + ref: release-${{ steps.vars.outputs.major_minor }} + fetch-depth: 0 + clean: false + - name: Setting properties + shell: bash + env: + CHANGELOG_CONTENT: ${{ inputs.changelog-path }} + DIGEST: ${{ inputs.digest }} + VERSION: ${{ inputs.version }} + run: | + echo "Setting version to v${VERSION} in files" + yq -i ".appVersion = \"$VERSION\"" config/helm/chart/default/Chart.yaml + yq -i ".version = \"$VERSION\"" config/helm/chart/default/Chart.yaml + + echo "Setting version in schema.yaml" + yq -i \ + ".x-google-marketplace.publishedVersion = \"$VERSION\"" \ + "config/helm/schema.yaml" + + echo "Setting changelog in schema.yaml" + + yq -i \ + ".x-google-marketplace.publishedVersionMetadata.releaseNote = load_str(env(CHANGELOG_CONTENT))" \ + "config/helm/schema.yaml" + - name: Install operator-sdk + shell: bash + env: + OPERATOR_SDK_VERSION: v1.36.0 + VERSION: ${{ inputs.version }} + run: | + curl -OJL \ + "https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk_linux_amd64" + chmod +x operator-sdk_linux_amd64 + mv operator-sdk_linux_amd64 /usr/local/bin/operator-sdk + echo "Downloaded operator-sdk" + - name: Check Operator SDK + shell: bash + id: check-step + run: | + operator-sdk version + - name: Generate OLM bundles (openshift) + shell: bash + env: + VERSION: ${{ inputs.version }} + PLATFORM: openshift + CHANNELS: stable + DEFAULT_CHANNEL: stable + IMAGE: registry.connect.redhat.com/dynatrace/dynatrace-operator + OLM_IMAGE: registry.connect.redhat.com/dynatrace/dynatrace-operator:v${{ inputs.version }} + run: | + make bundle + - name: Generate OLM bundles (kubernetes) + shell: bash + env: + VERSION: ${{ inputs.version }} + PLATFORM: kubernetes + CHANNELS: stable + DEFAULT_CHANNEL: stable + IMAGE: docker.io/dynatrace/dynatrace-operator + OLM_IMAGE: docker.io/dynatrace/dynatrace-operator:v${{ inputs.version }} + run: | + make bundle + - name: Finalize CSV files + shell: bash + env: + VERSION: ${{ inputs.version }} + run: | + + echo "Finalizing CSV files for Kubernetes" + ./.github/scripts/release/csv/finalize_csv_files.py \ + --platform "kubernetes" \ + --version "${VERSION}" \ + + echo "Finalizing CSV files for Openshift" + ./.github/scripts/release/csv/finalize_csv_files.py \ + --platform "openshift" \ + --version "${VERSION}" \ + - name: Create GitHub app token + uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: create-github-app-token + with: + app-id: ${{ inputs.app-id }} + private-key: ${{ inputs.private-key }} + - name: Create CSV update PR + uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9 + with: + base: release-${{ steps.vars.outputs.major_minor }} + branch: csv-${{ steps.vars.outputs.major_minor}} + token: ${{ steps.create-github-app-token.token }} + delete-branch: true + add-paths: | + config/olm/** + config/deploy/kubernetes/kustomization.yaml + config/deploy/openshift/kustomization.yaml + config/manifests/bases/** + config/helm/** + commit-message: "[Automatic] Update OLM bundles for v${{ inputs.version }}" + signoff: true + title: "[Automatic] Update OLM CSV bundles for v${{ inputs.version }}" + body: | + This PR updates the OLM bundles/CSVs on `release-${{ steps.vars.outputs.major_minor }}` for version `v${{ inputs.version }}`. diff --git a/.github/scripts/release/csv/finalize_csv_files.py b/.github/scripts/release/csv/finalize_csv_files.py new file mode 100755 index 0000000000..61d70d5b28 --- /dev/null +++ b/.github/scripts/release/csv/finalize_csv_files.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +import argparse +import sys +import datetime +import yaml + + +def read_yaml(path): + with open(path, "r") as yaml_file: + try: + data = yaml.safe_load(yaml_file) + except yaml.YAMLError as e: + print(f"Could not load file: {e}") + return None + return data + + +def write_yaml(data, path): + with open(path, "w") as file: + yaml.dump(data, file, default_flow_style=False, sort_keys=False) + + +if __name__ == "__main__": + argument_parser = argparse.ArgumentParser(description="Finalize CSV files by automatically setting the createdAt annotation and olm.skipRange") + argument_parser.add_argument("--platform", type=str, required=True, choices=["openshift", "kubernetes"], + help="Sets the platform for which the CSV files are finalized") + argument_parser.add_argument("--version", type=str, required=True, + help="Sets the version for which the CSV files are finalized") + + args = argument_parser.parse_args() + + platform = args.platform + version = args.version + csv_filepath = \ + f"config/olm/{platform}/{version}/manifests/" \ + f"dynatrace-operator.clusterserviceversion.yaml" + kustomize_filepath = f"config/olm/{platform}/kustomization.yaml" + + csv = read_yaml(csv_filepath) + kustomize = read_yaml(kustomize_filepath) + + if csv is None or kustomize is None: + sys.exit(1) + + kustomize.pop("images", None) + csv["metadata"]["annotations"]["createdAt"] = datetime.datetime.now().isoformat() + + for deployment_index, deployment in enumerate(csv["spec"]["install"]["spec"]["deployments"]): + for container_index, container in enumerate(deployment["spec"]["template"]["spec"]["containers"]): + deployment["spec"]["template"]["spec"]["containers"][container_index] = container + csv["spec"]["install"]["spec"]["deployments"][deployment_index] = deployment + + csv["metadata"]["annotations"]["olm.skipRange"] = f"<{version}" + + write_yaml(csv, csv_filepath) + write_yaml(kustomize, kustomize_filepath) diff --git a/.github/scripts/release/csv/make_release_csv.py b/.github/scripts/release/csv/make_release_csv.py new file mode 100755 index 0000000000..4044abde74 --- /dev/null +++ b/.github/scripts/release/csv/make_release_csv.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import argparse +import yaml + +def prepare_for_RHCC(csv): + csv["metadata"]["annotations"]["marketplace.openshift.io/remote-workflow"] = \ + "https://marketplace.redhat.com/en-us/operators/dynatrace-operator-rhmp/pricing?utm_source=openshift_console" + csv["metadata"]["annotations"]["marketplace.openshift.io/support-workflow"] = \ + "https://marketplace.redhat.com/en-us/operators/dynatrace-operator-rhmp/support?utm_source=openshift_console" + + return csv + +def configure_deployment(deployment, image, marketplace): + containers = deployment["spec"]["template"]["spec"]["containers"] + for container_index in range(len(containers)): + containers[container_index]["image"] = image + + if deployment["name"] == "dynatrace-operator": + formattedMarketplace = "operatorhub" + "-" + marketplace + deployment["spec"]["template"]["metadata"]["labels"]["dynatrace.com/install-source"] = formattedMarketplace + + return deployment + +if __name__ == "__main__": + argument_parser = argparse.ArgumentParser() + argument_parser.add_argument("path", type=str) + argument_parser.add_argument("--image", type=str, required=True) + argument_parser.add_argument("--isRHCC", type=bool, default=False) + argument_parser.add_argument("--marketplace", type=str, required=True) + + arguments = argument_parser.parse_args() + csv_path = arguments.path + image = arguments.image + isRHCC = arguments.isRHCC + marketplace = arguments.marketplace + + with open(csv_path, 'r') as csv_file: + csv = yaml.safe_load(csv_file) + + if isRHCC: + csv = prepare_for_RHCC(csv) + + csv["metadata"]["annotations"]["containerImage"] = image + + deployments = csv["spec"]["install"]["spec"]["deployments"] + for deployment_index in range(len(deployments)): + deployments[deployment_index] = configure_deployment(deployments[deployment_index], image, marketplace) + + csv["metadata"]["annotations"]["operators.openshift.io/valid-subscription"] = \ + '[\"Dynatrace Platform Subscription (DPS)\",\"Dynatrace Classic License\"]' + + csv["metadata"]["annotations"]["features.operators.openshift.io/disconnected"] = "true" + csv["metadata"]["annotations"]["features.operators.openshift.io/proxy-aware"] = "true" + csv["metadata"]["annotations"]["features.operators.openshift.io/fips-compliant"] = "false" + csv["metadata"]["annotations"]["features.operators.openshift.io/tls-profiles"] = "false" + csv["metadata"]["annotations"]["features.operators.openshift.io/token-auth-aws"] = "false" + csv["metadata"]["annotations"]["features.operators.openshift.io/token-auth-azure"] = "false" + csv["metadata"]["annotations"]["features.operators.openshift.io/token-auth-gcp"] = "false" + + + csv["spec"]["relatedImages"] = [ + { + "name": "dynatrace-operator", + "image": image + } + ] + + with open(csv_path, "w") as csv_file: + yaml.safe_dump(csv, csv_file, sort_keys=False) + diff --git a/.github/scripts/release/directory_version.py b/.github/scripts/release/directory_version.py new file mode 100755 index 0000000000..2955315182 --- /dev/null +++ b/.github/scripts/release/directory_version.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +import argparse + + +def _compare_normalized_version_arrays(a, b): + a_is_parseable = True + b_is_parseable = True + for i in range(0, 3): + version_num_a = 0 + version_num_b = 0 + + try: + version_num_a = int(a[i]) + except ValueError: + a_is_parseable = False + try: + version_num_b = int(b[i]) + except ValueError: + b_is_parseable = False + + if not a_is_parseable and not b_is_parseable: + return 0 + elif not a_is_parseable: + return -1 + elif not b_is_parseable: + return 1 + + if version_num_a > version_num_b: + return 1 + elif version_num_b > version_num_a: + return -1 + return 0 + + +def normalize_version(version): + version_array = _split_semantic_version(version) + version_array = _normalize_version_array(version_array) + return ".".join(version_array) + + +def _split_semantic_version(version): + return version.split(".") + + +def _normalize_version_array(version_array): + while len(version_array) < 3: + version_array.append("0") + return version_array[0:3] + + +def get_latest_version_from_collection(version_collection): + if len(version_collection) <= 0: + return "" + + if len(version_collection) == 1: + return version_collection[0] + + latest_version = "" + for version in version_collection: + latest = _normalize_version_array(_split_semantic_version(latest_version)) + current = _normalize_version_array(_split_semantic_version(version)) + comparison = _compare_normalized_version_arrays(latest, current) + + if comparison < 0: + latest_version = version + + return normalize_version(latest_version) + + +if __name__ == "__main__": + argument_parser = argparse.ArgumentParser( + description="Returns the latest version from a list of strings in the semver format") + argument_parser.add_argument("versions", + help="Newline separated list of versions. E.g. the output of 'ls -d */'. " + "Trailing slashes will be removed for your convenience", + type=str) + arguments = argument_parser.parse_args() + + versions_string = arguments.versions + version_dirs = versions_string.split("\n") + versions = [] + + for version_dir in version_dirs: + if version_dir.endswith("/"): + version_dir = version_dir[:-1] + versions.append(version_dir.split("/")[-1]) + + print(get_latest_version_from_collection(versions)) diff --git a/.github/workflows/create-marketplaces-forks.yaml b/.github/workflows/create-marketplaces-forks.yaml new file mode 100644 index 0000000000..af1a9bafaa --- /dev/null +++ b/.github/workflows/create-marketplaces-forks.yaml @@ -0,0 +1,234 @@ +name: Create forks for marketplaces + +on: + pull_request: + types: closed + branches: + - release-* +jobs: + create-forks: + if: > + github.event.pull_request.merged == true && + startsWith(github.event.pull_request.head.ref, 'csv-') && + startsWith(github.event.pull_request.base.ref, 'release-') + runs-on: ubuntu-24.04 + strategy: + matrix: + include: + - marketplace: community + original_repo: k8s-operatorhub/community-operators + fork_repo: dt-team-kubernetes/community-operators + - marketplace: community-prod + original_repo: redhat-openshift-ecosystem/community-operators-prod + fork_repo: dt-team-kubernetes/community-operators-prod + - marketplace: certified + original_repo: redhat-openshift-ecosystem/certified-operators + fork_repo: dt-team-kubernetes/certified-operators + - marketplace: redhat + original_repo: redhat-openshift-ecosystem/redhat-marketplace-operators + fork_repo: dt-team-kubernetes/redhat-marketplace-operators + env: + ORIGINAL_REPOSITORY_URL: ${{ matrix.original_repo }} + FORK_REPOSITORY_URL: ${{ matrix.fork_repo }} + MARKETPLACE: ${{ matrix.marketplace }} + steps: + - name: Checkout dynatrace-operator at base branch (team user) + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + ref: ${{ github.event.pull_request.base.ref }} + fetch-depth: 0 + token: ${{ secrets.TEAM_USER_TOKEN }} + - name: Configure git identity + run: | + git config --global user.name "${{ secrets.TEAM_USER_NAME }}" + git config --global user.email "${{ secrets.TEAM_USER_EMAIL }}" + - name: Install Python deps + run: | + pip install -r hack/requirements.txt + - name: Derive version and branch name + id: meta + run: | + set -euo pipefail + base_ref='${{ github.event.pull_request.base.ref }}' + echo "Base ref: $base_ref" + + versions_dirs="$(ls -d config/olm/kubernetes/*/ 2>/dev/null || true)" + if [ -z "$versions_dirs" ]; then + echo "ERROR: No bundle directories found under config/olm/kubernetes" + ls -R config/olm || true + exit 1 + fi + + version="$(python .github/scripts/release/directory_version.py "${versions_dirs}")" + echo "Detected bundle version: $version" + echo "version=$version" >> "$GITHUB_OUTPUT" + echo "branch=$base_ref" >> "$GITHUB_OUTPUT" + - name: Clone and setup fork repository + env: + VERSION: ${{ steps.meta.outputs.version }} + TEAM_TOKEN: ${{ secrets.TEAM_USER_TOKEN }} + run: | + set -euo pipefail + + fork_clone_url="https://github.com/${FORK_REPOSITORY_URL}.git" + fork_clone_url_with_token="${fork_clone_url/https:\/\//https:\/\/x-access-token:${TEAM_TOKEN}@}" + + echo "Cloning fork ${FORK_REPOSITORY_URL}" + git clone "${fork_clone_url_with_token}" fork-repo + cd fork-repo + + upstream_repo="${ORIGINAL_REPOSITORY_URL}" + git remote add upstream "https://github.com/${upstream_repo}.git" || true + git fetch upstream + + branch_name="dynatrace-operator-${VERSION}" + git checkout -B "${branch_name}" "upstream/main" + + echo "FORK_REPO_DIR=$(pwd)" >> "$GITHUB_ENV" + echo "BRANCH_NAME=${branch_name}" >> "$GITHUB_ENV" + - name: Prepare bundle files for ${{ env.MARKETPLACE }} + env: + VERSION: ${{ steps.meta.outputs.version }} + run: | + set -euo pipefail + cd "${FORK_REPO_DIR}" + + # Determine bundle source (kubernetes for community, openshift for others) + if [ "${MARKETPLACE}" = "community" ]; then + bundle_source="kubernetes" + else + bundle_source="openshift" + fi + + # Setup operator directory + if [ "${MARKETPLACE}" = "redhat" ]; then + operator_dir="operators/dynatrace-operator-rhmp/${VERSION}" + else + operator_dir="operators/dynatrace-operator/${VERSION}" + fi + + mkdir -p "${operator_dir}/manifests" + mkdir -p "${operator_dir}/metadata" + + # Copy bundle files + cp -rf "../config/olm/${bundle_source}/${VERSION}/manifests" "${operator_dir}/" + cp -rf "../config/olm/${bundle_source}/${VERSION}/metadata" "${operator_dir}/" + + # Create Dockerfile for community marketplaces + if [ "${MARKETPLACE}" = "community" ] || [ "${MARKETPLACE}" = "community-prod" ]; then + echo "Creating Dockerfile for ${MARKETPLACE}" + origin_dockerfile="../config/olm/kubernetes/bundle-${VERSION}.Dockerfile" + target_dockerfile="${operator_dir}/Dockerfile" + sed -n "\|COPY ${VERSION}/manifests /manifests/|q;p" "${origin_dockerfile}" > "${target_dockerfile}" + echo "COPY manifests /manifests/" >> "${target_dockerfile}" + echo "COPY metadata /metadata/" >> "${target_dockerfile}" + fi + + # Update package annotation for redhat + if [ "${MARKETPLACE}" = "redhat" ]; then + sed -i \ + "s/ operators.operatorframework.io.bundle.package.v1: dynatrace-operator/ operators.operatorframework.io.bundle.package.v1: dynatrace-operator-rhmp/" \ + "${operator_dir}/metadata/annotations.yaml" + fi + + # Determine last existing version and set spec.replaces + if [ "${MARKETPLACE}" = "redhat" ]; then + last_version="$(python ../.github/scripts/release/directory_version.py "$(ls -d operators/dynatrace-operator-rhmp/*/)" 2>/dev/null || true)" + else + last_version="$(python ../.github/scripts/release/directory_version.py "$(ls -d operators/dynatrace-operator/*/)" 2>/dev/null || true)" + fi + + csv_file="${operator_dir}/manifests/dynatrace-operator.clusterserviceversion.yaml" + + if [ -n "${last_version}" ]; then + if [ "${MARKETPLACE}" = "redhat" ]; then + yq -i ".spec.replaces = \"dynatrace-operator-rhmp.v${last_version}\"" "${csv_file}" + else + yq -i ".spec.replaces = \"dynatrace-operator.v${last_version}\"" "${csv_file}" + fi + else + yq e -i 'del(.spec.replaces)' "${csv_file}" + fi + - name: Set IMAGE and prepare CSVs for ${{ env.MARKETPLACE }} + env: + VERSION: ${{ steps.meta.outputs.version }} + RHCC_USERNAME: ${{ secrets.RHCC_USERNAME }} + RHCC_PASSWORD: ${{ secrets.RHCC_PASSWORD }} + run: | + set -euo pipefail + cd "${FORK_REPO_DIR}" + + # Set IMAGE based on marketplace + case "${MARKETPLACE}" in + community) + image_digest=$(skopeo inspect "docker://docker.io/dynatrace/dynatrace-operator:v${VERSION}" | jq -r '.Digest') + IMAGE="docker.io/dynatrace/dynatrace-operator@${image_digest}" + ;; + community-prod) + image_digest=$(skopeo inspect --username "${RHCC_USERNAME}" --password "${RHCC_PASSWORD}" "docker://registry.connect.redhat.com/dynatrace/dynatrace-operator:v${VERSION}" | jq -r '.Digest') + IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator@${image_digest}" + ;; + certified) + image_digest=$(skopeo inspect --username "${RHCC_USERNAME}" --password "${RHCC_PASSWORD}" "docker://registry.connect.redhat.com/dynatrace/dynatrace-operator:v${VERSION}" | jq -r '.Digest') + IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator@${image_digest}" + ;; + redhat) + image_digest=$(skopeo inspect --username "${RHCC_USERNAME}" --password "${RHCC_PASSWORD}" "docker://registry.connect.redhat.com/dynatrace/dynatrace-operator:v${VERSION}" | jq -r '.Digest') + IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator@${image_digest}" + ;; + *) + echo "Unknown marketplace: ${MARKETPLACE}" + exit 1 + ;; + esac + + # Prepare CSV files + if [ "${MARKETPLACE}" = "redhat" ]; then + csv_file="operators/dynatrace-operator-rhmp/${VERSION}/manifests/dynatrace-operator.clusterserviceversion.yaml" + python ../.github/scripts/release/csv/make_release_csv.py \ + "${csv_file}" \ + --image "${IMAGE}" \ + --marketplace "${MARKETPLACE}" \ + --isRHCC true + else + csv_file="operators/dynatrace-operator/${VERSION}/manifests/dynatrace-operator.clusterserviceversion.yaml" + python ../.github/scripts/release/csv/make_release_csv.py \ + "${csv_file}" \ + --image "${IMAGE}" \ + --marketplace "${MARKETPLACE}" + fi + - name: Post-process CSV for redhat marketplace + if: matrix.marketplace == 'redhat' + env: + VERSION: ${{ steps.meta.outputs.version }} + run: | + cd "${FORK_REPO_DIR}" + + # Rename CSV file + mv "operators/dynatrace-operator-rhmp/${VERSION}/manifests/dynatrace-operator.clusterserviceversion.yaml" \ + "operators/dynatrace-operator-rhmp/${VERSION}/manifests/dynatrace-operator-rhmp.clusterserviceversion.yaml" + + # Update metadata.name + yq -i \ + ".metadata.name = \"dynatrace-operator-rhmp.v${VERSION}\"" \ + "operators/dynatrace-operator-rhmp/${VERSION}/manifests/dynatrace-operator-rhmp.clusterserviceversion.yaml" + - name: Push changes to fork branch + env: + VERSION: ${{ steps.meta.outputs.version }} + run: | + cd "${FORK_REPO_DIR}" + + git add -A + if git diff-index --quiet HEAD; then + echo "No changes to commit; nothing to push for ${MARKETPLACE}." + exit 0 + fi + + if [ "${MARKETPLACE}" = "redhat" ]; then + operator_name="dynatrace-operator-rhmp" + else + operator_name="dynatrace-operator" + fi + + git commit -s -m "operator ${operator_name} (${VERSION})" + git push origin "${BRANCH_NAME}" diff --git a/.github/workflows/gcr-deployer-image.yaml b/.github/workflows/gcr-deployer-image.yaml new file mode 100644 index 0000000000..33743a1bee --- /dev/null +++ b/.github/workflows/gcr-deployer-image.yaml @@ -0,0 +1,64 @@ +name: GCR Deployer image +on: + pull_request: + branches: + - release-* + types: + - closed + +env: + GOOGLE_MARKETPLACE_ANNOTATION: com.googleapis.cloudmarketplace.product.service.name=services/dynatrace-operator-dynatrace-marketplace-prod.cloudpartnerservices.goog + PLATFORMS: linux/amd64,linux/arm64,linux/ppc64le,linux/s390x + DEPLOYER_PLATFORMS: linux/amd64 + + +jobs: + prepare: + if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'csv-') && startsWith(github.event.pull_request.base.ref, 'release-') + name: Prepare properties + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - name: Prepare build parameters + id: prep + run: | + hack/build/ci/prepare-build-variables.sh + outputs: + labels: ${{ steps.prep.outputs.docker_image_labels }} + version: ${{ steps.prep.outputs.docker_image_tag }} + version_without_prefix: ${{ steps.prep.outputs.docker_image_tag_without_prefix }} + + build-gcr-deployer: + if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'csv-') && startsWith(github.event.pull_request.base.ref, 'release-') + name: Build GCR deployer image + environment: Release + runs-on: ubuntu-24.04 + needs: [ prepare ] + env: + IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version }} + IMAGE_NO_PREFIX: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} + steps: + - name: Checkout + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - name: Login to Docker Hub + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 + with: + registry: gcr.io + username: ${{ secrets.GCR_USERNAME }} + password: ${{ secrets.GCR_JSON_KEY }} + - name: Set up QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # 3.10.0 + - name: Build and push + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # 6.18.0 + with: + platforms: ${{ env.DEPLOYER_PLATFORMS }} + provenance: false + context: ./config/helm + file: ./config/helm/Dockerfile + push: true + tags: ${{ env.IMAGE }},${{ env.IMAGE_NO_PREFIX }} + annotations: | + ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c48bfb7c92..7f14e81a28 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -153,39 +153,6 @@ jobs: signing-key: ${{ secrets.COSIGN_PRIVATE_KEY }} signing-password: ${{ secrets.COSIGN_PASSWORD }} - build-gcr-deployer: - name: Build GCR deployer image - environment: Release - runs-on: ubuntu-24.04 - needs: [ prepare ] - env: - IMAGE: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version }} - IMAGE_NO_PREFIX: gcr.io/${{ secrets.GCR_REPOSITORY_DEPLOYER }}:${{ needs.prepare.outputs.version_without_prefix }} - steps: - - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - name: Login to Docker Hub - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - registry: gcr.io - username: ${{ secrets.GCR_USERNAME }} - password: ${{ secrets.GCR_JSON_KEY }} - - name: Set up QEMU - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # 3.11.1 - - name: Build and push - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # 6.18.0 - with: - platforms: ${{ env.DEPLOYER_PLATFORMS }} - provenance: false - context: ./config/helm - file: ./config/helm/Dockerfile - push: true - tags: ${{ env.IMAGE }},${{ env.IMAGE_NO_PREFIX }} - annotations: | - ${{ env.GOOGLE_MARKETPLACE_ANNOTATION }} - run-preflight-rhcc: name: Run preflight for rhcc environment: Release @@ -332,6 +299,12 @@ jobs: prerelease: false draft: true fail_on_unmatched_files: true + - name: Upload Changelog as artifact + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: changelog + path: CHANGELOG.md + if-no-files-found: warn - name: Update index helm file if: ${{ !contains(github.ref, '-rc.') }} env: @@ -364,3 +337,24 @@ jobs: Helm upgrade to and install of `${{ github.ref }}` works. ## Checklist - [x] PR is labeled accordingly + + update-csv-bundles: + needs: prepare + runs-on: ubuntu-24.04 + if: ${{ !contains(github.ref, '-rc.') }} + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - name: Download changelog + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + with: + name: changelog + path: changelog_artifact + - uses: ./.github/actions/update-csv-bundles + with: + version: ${{ needs.prepare.outputs.version_without_prefix }} + changelog-path: ./changelog_artifact/CHANGELOG.md + app-id: ${{ secrets.RELEASE_APP_ID }} + private-key: ${{ secrets.RELEASE_APP_KEY }}