Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
8fb5938
Add dto csv yaml back
waodim Dec 3, 2025
4a88314
Merge branch 'main' of github.com:Dynatrace/dynatrace-operator
waodim Dec 3, 2025
2d712be
Merge branch 'main' of github.com:Dynatrace/dynatrace-operator
waodim Dec 3, 2025
8ce7f0e
Add composite action to update csv bundles
waodim Dec 3, 2025
0141a3f
Add composite action to release workflow; Move GCR Deployer step
waodim Dec 3, 2025
00b6d54
Add helper scripts
waodim Dec 3, 2025
aa1934e
Add new actions to create forks for marketplaces
waodim Dec 3, 2025
6a71e3b
Fix missing new lines
waodim Dec 4, 2025
3c1148b
Fix actions to use digest instead of tag
waodim Dec 4, 2025
293a9e8
Move scripts to scripts/release/ and scripts/release/csv/
waodim Dec 4, 2025
2d991a0
Prepare for testing
waodim Dec 4, 2025
cb91b11
Revert "Prepare for testing"
waodim Dec 4, 2025
8083562
Remove set_property.py as it's not needed
waodim Dec 5, 2025
3419bc6
Update fork workflows
waodim Dec 5, 2025
167c3d5
Update finalize scripts
waodim Dec 5, 2025
aab93c4
Remove obsolete env vars
waodim Dec 5, 2025
2437856
Merge branch 'main' into migrate/concourse-to-gha
waodim Dec 5, 2025
0f9b9f1
Merge branch 'main' into migrate/concourse-to-gha
waodim Dec 9, 2025
eda26ad
Export args for make bundle command to env vars
waodim Dec 9, 2025
bcbbd3d
Remove unused command
waodim Dec 9, 2025
8361ccf
Fix leftovers in py scripts
waodim Dec 9, 2025
a527dfe
Fix bundle command
waodim Dec 9, 2025
69e76c4
Create generic fork creation step
waodim Dec 9, 2025
017c48d
Adapt file name
waodim Dec 9, 2025
47d6452
Merge branch 'main' into migrate/concourse-to-gha
waodim Dec 10, 2025
2f30507
Fix issues
waodim Dec 10, 2025
7d32673
Fix new lines; apply suggestions
waodim Dec 11, 2025
bc2fec1
Final test
waodim Dec 11, 2025
33db045
Revert "Final test"
waodim Dec 11, 2025
59ca577
Simplify sdk step
waodim Dec 11, 2025
6ffcc11
Merge branch 'main' into migrate/concourse-to-gha
waodim Dec 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions .github/actions/update-csv-bundles/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
name: "Update CSV bundles"
description: "Generate and finalize OLM CSV bundles for a given version"

inputs:
version:
description: "Version without v-prefix"
required: true
token:
description: "GitHub token to create PRs"
required: true
changelog-path:
description: "Path to the changelog file"
required: false

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
run: |
VERSION="${{ inputs.version }}"
MAJOR_MINOR="${VERSION%.*}"
echo "major_minor=${MAJOR_MINOR}" >> "$GITHUB_OUTPUT"
- name: Checkout release branch
uses: actions/checkout@v4
with:
ref: release-${{ steps.vars.outputs.major_minor }}
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: "${{ github.workspace }}/go.mod"
- name: Setting properties
shell: bash
env:
CHANGELOG_CONTENT: ${{ inputs.changelog-path }}
DIGEST: ${{ inputs.digest }}
VERSION: ${{ inputs.version }}
run: |
VERSION="${VERSION}"
echo "Setting version to v${VERSION} in files"
./.github/scripts/set_property.py --file "config/helm/chart/default/Chart.yaml" --property "appVersion" --value "v${VERSION}"
./.github/scripts/set_property.py --file "config/helm/chart/default/Chart.yaml" --property "version" --value "${VERSION}"
cat <<EOF > "config/helm/chart/default/Chart.yaml.tmp"
# Copyright 2020 Dynatrace LLC
# 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.
EOF
cat "config/helm/chart/default/Chart.yaml" >> "config/helm/chart/default/Chart.yaml.tmp"
mv "config/helm/chart/default/Chart.yaml.tmp" "config/helm/chart/default/Chart.yaml"
echo "Setting version in schema.yaml"
./.github/scripts/set_property.py \
--file "config/helm/schema.yaml" \
--property "x-google-marketplace.publishedVersion" \
--value "${VERSION}"
echo "Setting changelog in schema.yaml"
./.github/scripts/set_property.py \
--file "config/helm/schema.yaml" \
--property "x-google-marketplace.publishedVersionMetadata.releaseNote" \
--value-from-file "${CHANGELOG_CONTENT}"
echo "Adding copyright notice to schema.yaml"
cat <<EOF > "config/helm/schema.yaml.tmp"
# Copyright 2020 Dynatrace LLC
# 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.
EOF
cat "config/helm/schema.yaml" >> "config/helm/schema.yaml.tmp"
mv "config/helm/schema.yaml.tmp" "config/helm/schema.yaml"
echo "Setting version in application.yaml"
sed -i \
"s/ version: \"[0-9]+\.[0-9]+\.[0-9]+\"/ version: \"${VERSION}\"/" \
"config/helm/chart/default/templates/application.yaml"
- name: Install operator-sdk v1.36.0
shell: bash
env:
VERSION: ${{ inputs.version }}
run: |
GOBIN="$(go env GOPATH)/bin"
mkdir -p "$GOBIN"
echo "Installing operator-sdk v1.36.0 into $GOBIN"
curl -OJL \
"https://github.com/operator-framework/operator-sdk/releases/download/v1.36.0/operator-sdk_linux_amd64"
chmod +x operator-sdk_linux_amd64
mv operator-sdk_linux_amd64 ${GOBIN}/operator-sdk
"${GOBIN}/operator-sdk" version
echo "GOBIN=$GOBIN" >> $GITHUB_ENV
- name: Generate OLM bundles (openshift)
shell: bash
env:
VERSION: ${{ inputs.version }}
run: |
VERSION="${VERSION}"
mkdir -p config/olm/openshift/bases
make bundle PLATFORM=openshift VERSION="${VERSION}" CHANNELS=stable DEFAULT_CHANNEL=stable OLM_IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator:v${VERSION}" IMAGE="registry.connect.redhat.com/dynatrace/dynatrace-operator"
- name: Generate OLM bundles (kubernetes)
shell: bash
env:
VERSION: ${{ inputs.version }}
run: |
VERSION="${VERSION}"
make bundle PLATFORM=kubernetes VERSION="${VERSION}" CHANNELS=stable DEFAULT_CHANNEL=stable IMAGE="docker.io/dynatrace/dynatrace-operator" OLM_IMAGE="docker.io/dynatrace/dynatrace-operator:v${VERSION}"
- name: Finalize CSV files
shell: bash
env:
VERSION: ${{ inputs.version }}
run: |
VERSION="${VERSION}"
echo "Finalizing CSV files for Kubernetes"
./.github/scripts/finalize_csv_files.py \
--platform "kubernetes" \
--version "${VERSION}" \
--changelog "${{ inputs.changelog-path }}" \
--token "${GITHUB_TOKEN}"
echo "Finalizing CSV files for Openshift"
./.github/scripts/finalize_csv_files.py \
--platform "openshift" \
--version "${VERSION}" \
--changelog "${{ inputs.changelog-path }}" \
--token "${GITHUB_TOKEN}"
- name: Create CSV update PR
uses: peter-evans/create-pull-request@v7
env:
VERSION: ${{ inputs.version }}
with:
base: release-${{ steps.vars.outputs.major_minor }}
branch: csv-${{ steps.vars.outputs.major_minor}}
delete-branch: true
add-paths: |
config/olm/**
config/deploy/kubernetes/kustomization.yaml
config/deploy/openshift/kustomization.yaml
config/manifests/bases/**
config/helm/**
commit-message: "chore: update OLM bundles for v${{ env.VERSION }}"
signoff: true
title: "Update OLM CSV bundles for v${{ env.VERSION }}"
body: |
This PR updates the OLM bundles/CSVs on `release-${{ steps.vars.outputs.major_minor }}` for version `v${{ env.VERSION }}`.
68 changes: 68 additions & 0 deletions .github/scripts/finalize_csv_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env python3
import argparse
import sys
import datetime
import yaml


def print_usage():
print("Usage: finalize_csv_files <platform> <version>")
print("\tplatform:\tOne of 'kubernetes' or 'openshift'")
print("\tversion:\tVersion string in the form of x.y.z for which the CSV files should be finalized ")


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")
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")
argument_parser.add_argument("--token", type=str, required=True,
help="The token used to query the GitHub API")
argument_parser.add_argument("--repository", type=str, required=False, default="Dynatrace/dynatrace-operator",
help="The repository for which the releases are queried to find the current version."
"Defaults to Dynatrace/dynatrace-operator")
args = argument_parser.parse_args()

platform = args.platform
version = args.version
repository = args.repository
token = args.token
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)
77 changes: 77 additions & 0 deletions .github/scripts/make-release-csv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/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

# Setting changed array since I am unsure if python assigns arrays by reference or value
deployment["spec"]["template"]["containers"] = containers

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)

# Setting changed array since I am unsure if python assigns arrays by reference or value
csv["spec"]["install"]["spec"]["deployments"] = deployments

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)

24 changes: 24 additions & 0 deletions .github/scripts/release/directory_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
import argparse

from version.collection import get_latest_version_from_collection

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))
Loading