Skip to content

Operator release manual #87

Operator release manual

Operator release manual #87

name: Operator release manual
on:
workflow_dispatch:
inputs:
release:
description: 'Force to run release'
required: true
default: '0'
delete:
description: 'Remove operator virtually from git (cockroachdb or cockroachdb/5.0.4) for debuging only'
required: false
default: ''
delete_for_renew:
description: 'Remove operator from index (allow/operator-recreate)'
required: true
default: '0'
index:
description: 'Target index (as a JSON list, e.g. ["latest", "latest-db"])'
required: true
default: '["latest"]'
list_of_operators:
description: 'List of operators to be synced in the index, list has to be devided by spaces (e.g. aqua ripsaw)'
required: true
default: ''
env:
OPP_DEBUG: 1
OPP_CONTAINER_OPT: "-t"
OPP_SCRIPT_URL: "https://raw.githubusercontent.com/redhat-openshift-ecosystem/community-operators-pipeline/ci/latest/ci/scripts/opp.sh"
OPP_SCRIPT_ENV_URL: "https://raw.githubusercontent.com/redhat-openshift-ecosystem/community-operators-pipeline/ci/latest/ci/scripts/opp-env.sh"
OPP_SCRIPT_ISS_URL: "https://raw.githubusercontent.com/redhat-openshift-ecosystem/community-operators-pipeline/ci/latest/ci/scripts/opp-iss.sh"
OPP_SCRIPT_CLEANUP_URL: "https://raw.githubusercontent.com/redhat-openshift-ecosystem/community-operators-pipeline/ci/latest/ci/scripts/opp-disk-cleanup-on-startup.sh"
OPP_SCRIPT_TRIGGER_OHIO_URL: "https://raw.githubusercontent.com/redhat-openshift-ecosystem/community-operators-pipeline/ci/latest/ci/scripts/opp-trigger-operatorhubio-ci.sh"
OPP_IMAGE: "quay.io/operator_testing/operator-test-playbooks:latest"
OPP_ANSIBLE_PULL_REPO: "https://github.com/redhat-openshift-ecosystem/operator-test-playbooks"
OPP_ANSIBLE_PULL_BRANCH: "upstream-community"
OPP_PROD: 1
OPP_MIRROR_LATEST_TAG: ""
OPP_PRODUCTION_TYPE: "k8s"
OPP_RELEASE_BUNDLE_REGISTRY: "quay.io"
OPP_RELEASE_BUNDLE_ORGANIZATION: "operatorhubio"
OPP_RELEASE_INDEX_REGISTRY: "quay.io"
OPP_RELEASE_INDEX_ORGANIZATION: "operatorhubio"
OPP_RELEASE_INDEX_NAME: "catalog_tmp"
OPP_MIRROR_INDEX_REGISTRY: "quay.io"
OPP_MIRROR_INDEX_ORGANIZATION: "operatorhubio"
OPP_MIRROR_INDEX_NAME: "catalog"
OPP_MIRROR_INDEX_ENABLED: "1"
OPP_MIRROR_INDEX_MULTIARCH_BASE: "quay.io/operator-framework/opm"
OPP_MULTIARCH_SUPPORTED_VERSIONS: "latest"
OPP_MIRROR_INDEX_MULTIARCH_POSTFIX: "s"
IIB_INPUT_REGISTRY_USER: "framework_automation"
OPP_REGISTRY_MIRROR_USER: "framework_automation"
OPP_THIS_REPO_BASE: "https://github.com"
OPP_THIS_REPO: "k8s-operatorhub/community-operators"
OPP_THIS_BRANCH: "main"
INDEX_PATH_TO_SIGN: "not-defined"
SIGNATURE_ENDPOINT: "https://not-defined"
OPP_REVIEWERS_ENABLED: 0
OPP_ALLOW_FORCE_RELEASE: ${{ github.event.inputs.release }}
OPP_REMOVE_OPERATOR_AFTER_CLONE_PATH: "${{ github.event.inputs.delete }}"
REGISTRY_RELEASE_API_TOKEN: ${{ secrets.REGISTRY_RELEASE_API_TOKEN }}
REGISTRY_MIRROR_PW: ${{ secrets.REGISTRY_MIRROR_PW }}
GODEBUG: x509ignoreCN=0
CI_OHIO_TRIGGER_TOKEN: ${{ secrets.CI_OHIO_TRIGGER_TOKEN }}
OHIO_REGISTRY_TOKEN: ${{ secrets.OHIO_REGISTRY_TOKEN }}
QUAY_APPREG_TOKEN: ${{ secrets.QUAY_APPREG_TOKEN }}
QUAY_COURIER_TOKEN: ${{ secrets.QUAY_COURIER_TOKEN }}
REPO_GHA_PAT: ${{ secrets.REPO_GHA_PAT }}
IIB_INPUT_REGISTRY_TOKEN: ${{ secrets.IIB_INPUT_REGISTRY_TOKEN }}
jobs:
pr-check:
name: "PR-traffic-light"
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- id: files
uses: masesgroup/retrieve-changed-files@v2
continue-on-error: true
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install dependencies
run: python -m pip install --upgrade pip yq
- name: Operator traffic light
id: op-traffic-light
env:
OPP_ADDED_MODIFIED_FILES: "${{ steps.files.outputs.added_modified }}"
OPP_MODIFIED_FILES: "${{ steps.files.outputs.modified }}"
OPP_RENAMED_FILES: "${{ steps.files.outputs.renamed }}"
OPP_REMOVED_FILES: "${{ steps.files.outputs.removed }}"
run: |
if [ -z "${{ github.event.inputs.list_of_operators }}" ]
then
echo "Found an empty input - list_of_operators [OK]"
else
OPP_MODIFIED_FILES=""
for operator_to_loop in ${{ github.event.inputs.list_of_operators }}; do
echo "Processing $operator_to_loop"
if [ -z "$OPP_MODIFIED_FILES" ]
then
echo "...inicializing OPP_MODIFIED_FILES"
OPP_MODIFIED_FILES="$(find operators/$operator_to_loop/ -type f -name "*.clusterserviceversion.yaml" | tail -n 1)"
else
echo "...extending OPP_MODIFIED_FILES"
OPP_MODIFIED_FILES="$OPP_MODIFIED_FILES $(find operators/$operator_to_loop/ -type f -name "*.clusterserviceversion.yaml" | tail -n 1)"
fi
done
fi
echo "OPP_MODIFIED_FILES=$OPP_MODIFIED_FILES"
echo "OPP_LABELS=$OPP_LABELS"
echo "Using script '$OPP_SCRIPT_ENV_URL' ..."
bash <(curl -sL $OPP_SCRIPT_ENV_URL)
- name: Block until there is no running workflow
if: steps.op-traffic-light.outputs.opp_release_ready == '1'
uses: softprops/turnstyle@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
outputs:
opp_test_ready: "${{ steps.op-traffic-light.outputs.opp_test_ready }}"
opp_release_ready: "${{ steps.op-traffic-light.outputs.opp_release_ready }}"
opp_stream: "${{ steps.op-traffic-light.outputs.opp_stream }}"
opp_name: "${{ steps.op-traffic-light.outputs.opp_name }}"
opp_version: "${{ steps.op-traffic-light.outputs.opp_version }}"
opp_ci_yaml_only: "${{ steps.op-traffic-light.outputs.opp_ci_yaml_only }}"
opp_ver_overwrite: "${{ steps.op-traffic-light.outputs.opp_ver_overwrite }}"
opp_op_delete: "${{ steps.op-traffic-light.outputs.opp_op_delete }}"
opp_recreate: "${{ steps.op-traffic-light.outputs.opp_recreate }}"
opp_is_new_operatror: "${{ steps.op-traffic-light.outputs.opp_is_new_operatror }}"
opp_release_delete_appreg: "${{ steps.op-traffic-light.outputs.opp_release_delete_appreg }}"
opp_pr_title: "${{ steps.op-traffic-light.outputs.opp_pr_title }}"
opp_auto_packagemanifest_cluster_version_label: "${{ steps.op-traffic-light.outputs.opp_auto_packagemanifest_cluster_version_label }}"
remove-k8s:
name: "Remove / k8s"
needs: pr-check
if: needs.pr-check.outputs.opp_release_ready == '1'
runs-on: ubuntu-latest
strategy:
matrix:
index-tag: ${{ fromJson(github.event.inputs.index) }}
fail-fast: false
steps:
- name: Remove operator from index
if: github.event.inputs.list_of_operators !='' && github.event.inputs.delete_for_renew == '1'
env:
OPP_LABELS: "${{ needs.pr-check.outputs.opp_labels }}"
OPP_AUTO_PACKAGEMANIFEST_CLUSTER_VERSION_LABEL: "${{ needs.pr-check.outputs.opp_auto_packagemanifest_cluster_version_label }}"
OPERATOR_INDEX_TAG: ${{ matrix.index-tag }}
run: |
for operator_to_delete in ${{ github.event.inputs.list_of_operators }}; do
echo "OPP_LABELS=$OPP_LABELS"
echo "op_delete_${OPERATOR_INDEX_TAG} operators/$operator_to_delete/dummy $OPP_THIS_REPO $OPP_THIS_BRANCH"
bash <(curl -sL $OPP_SCRIPT_URL) op_delete_${OPERATOR_INDEX_TAG} operators/$operator_to_delete/dummy $OPP_THIS_REPO $OPP_THIS_BRANCH
done
- name: Operator release (operator version overwrite)
if: needs.pr-check.outputs.opp_ci_yaml_only == '0' && needs.pr-check.outputs.opp_ver_overwrite == '1' && needs.pr-check.outputs.opp_name != '' && needs.pr-check.outputs.opp_version != ''
env:
OPP_LABELS: "${{ needs.pr-check.outputs.opp_labels }}"
OPP_AUTO_PACKAGEMANIFEST_CLUSTER_VERSION_LABEL: "${{ needs.pr-check.outputs.opp_auto_packagemanifest_cluster_version_label }}"
OPP_IIB_INSTALL: 0
OPERATOR_INDEX_TAG: ${{ matrix.index-tag }}
run: |
echo "OPP_LABELS=$OPP_LABELS"
FAKE_RC=false
FAKE_TYPE=$(echo $OPERATOR_INDEX_TAG | cut -d '-' -f 2)
echo "op_delete_${OPERATOR_INDEX_TAG} operators/${{ needs.pr-check.outputs.opp_name }}/${{ needs.pr-check.outputs.opp_version }} $OPP_THIS_REPO $OPP_THIS_BRANCH"
bash <(curl -sL $OPP_SCRIPT_URL) op_delete_${OPERATOR_INDEX_TAG} operators/${{ needs.pr-check.outputs.opp_name }}/${{ needs.pr-check.outputs.opp_version }} $OPP_THIS_REPO $OPP_THIS_BRANCH || $FAKE_RC
operators-k8s:
name: "Index check / k8s"
needs: [pr-check, remove-k8s ]
if: needs.pr-check.outputs.opp_release_ready == '1' && (needs.pr-check.outputs.opp_op_delete == '0' || needs.pr-check.outputs.opp_is_new_operatror == '1' || needs.pr-check.outputs.opp_recreate == '1' )
runs-on: ubuntu-latest
steps:
- name: List of missing operators
id: operators
env:
OPP_LABELS: "${{ needs.pr-check.outputs.opp_labels }}"
OPP_AUTO_PACKAGEMANIFEST_CLUSTER_VERSION_LABEL: "${{ needs.pr-check.outputs.opp_auto_packagemanifest_cluster_version_label }}"
OPP_IIB_INSTALL: 0
IIB_INPUT_REGISTRY_TOKEN: ${{ secrets.IIB_INPUT_REGISTRY_TOKEN }}
OPERATOR_INDEX_TAG: "orange_latest"
OPP_INDEX_CHECK_ONLY: 1
run: |
for index in $(echo '${{ github.event.inputs.index }}' | jq -r .[]); do
TARGET_INDEX_RAW=$(echo $index|cut -d '-' -f1)
TARGET_INDEX_UNDERLINE=$(echo $TARGET_INDEX_RAW|tr '.' '_')
export OPP_FORCE_OPERATORS_$TARGET_INDEX_UNDERLINE="${{ github.event.inputs.list_of_operators }}"
echo "opp_uncomplete_operators_$TARGET_INDEX_UNDERLINE=${{ github.event.inputs.list_of_operators }}" >> $GITHUB_OUTPUT
done
echo "opp_uncomplete_operators=${{ github.event.inputs.list_of_operators }}" >> $GITHUB_OUTPUT
- name: Index check
run: |
echo "Operators : ${{ steps.operators.outputs.opp_uncomplete_operators }}"
echo "Operators (latest) : ${{ steps.operators.outputs.opp_uncomplete_operators_latest }}"
- name: Operator info
id: op-info
env:
OPP_FORCE_OPERATORS: "${{ github.event.inputs.list_of_operators }}"
OPP_OP_INFO_PARALLEL: 1
OPP_OP_INFO_PARALLEL_BATCH: 20
OPP_AUTO_LABEL: 1
ANSIBLE_FORCE_COLOR: 1
ANSIBLE_DISPLAY_SKIPPED_HOSTS: 0
ANSIBLE_STDOUT_CALLBACK: "yaml"
TMPDIR: "/mnt/tmp"
run: |
sudo mkdir -p "${TMPDIR}"
sudo chmod 1777 "${TMPDIR}"
OPP_FORCE_OPERATORS=${OPP_FORCE_OPERATORS// /,}
echo $OPP_FORCE_OPERATORS
[ "$OPP_AUTO_LABEL" = '1' ] && ANSIBLE_ARGS="-e automatic_cluster_version_label=true" || ANSIBLE_ARGS="-e automatic_cluster_version_label=false"
[ "$OPP_OP_INFO_PARALLEL" = '1' ] && ANSIBLE_ARGS="$ANSIBLE_ARGS -e op_info_parallel=true -e op_info_parallel_batch=$OPP_OP_INFO_PARALLEL_BATCH" || ANSIBLE_ARGS="$ANSIBLE_ARGS -e op_info_parallel=false"
echo $ANSIBLE_ARGS
git clone $OPP_ANSIBLE_PULL_REPO -b $OPP_ANSIBLE_PULL_BRANCH operator-test-playbooks
cd operator-test-playbooks
ansible-playbook -i localhost, -e ansible_connection=local -e run_upstream=true -e run_prepare_catalog_repo_upstream=true -e catalog_repo=$OPP_THIS_REPO_BASE/$OPP_THIS_REPO -e catalog_repo_branch=$OPP_THIS_BRANCH upstream/local.yml --tags reset_tools,operator_info -e operator_base_dir=/tmp/community-operators-for-catalog/operators -e operators=$OPP_FORCE_OPERATORS -e cluster_type=$OPP_PRODUCTION_TYPE -e strict_cluster_version_labels=true -e production_registry_namespace=$OPP_RELEASE_BUNDLE_REGISTRY/$OPP_RELEASE_BUNDLE_ORGANIZATION $ANSIBLE_ARGS
- name: Upload operator_info
uses: actions/upload-artifact@v4
with:
name: operator_info
path: "/tmp/operator-test/op_info.yaml"
- name: Upload converted operators
uses: actions/upload-artifact@v4
with:
name: operators_converted
path: "/tmp/operator-test/operators"
- shell: bash
run: |
[ -f /tmp/operator-test/op_info.yaml ] && cat /tmp/operator-test/op_info.yaml || echo "opp_uncomplete_operators=" >> $GITHUB_OUTPUT
outputs:
opp_uncomplete_operators: "${{ steps.operators.outputs.opp_uncomplete_operators }}"
opp_uncomplete_operators_latest: "${{ steps.operators.outputs.opp_uncomplete_operators_latest }}"
bundles-k8s:
name: "Bundles / k8s"
needs: [ pr-check, remove-k8s, operators-k8s ]
if: needs.pr-check.outputs.opp_release_ready == '1' && needs.operators-k8s.outputs.opp_uncomplete_operators != ''
runs-on: ubuntu-latest
steps:
- name: Download operator_info
uses: actions/download-artifact@v4
with:
name: operator_info
path: /tmp/operator-test/
- name: Download converted operators
uses: actions/download-artifact@v4
with:
name: operators_converted
path: /tmp/operator-test/operators
- name: Build bundles
env:
OPP_LABELS: "${{ needs.pr-check.outputs.opp_labels }}"
OPP_AUTO_PACKAGEMANIFEST_CLUSTER_VERSION_LABEL: "${{ needs.pr-check.outputs.opp_auto_packagemanifest_cluster_version_label }}"
OPP_IIB_INSTALL: 0
OPERATOR_INDEX_TAG: latest
OPP_SKIP_INDEX: 1
OPP_SKIP_BUNDLES: 0
OPP_FORCE_OPERATORS: "${{ needs.operators-k8s.outputs.opp_uncomplete_operators }}"
run: |
echo "OPP_LABELS=$OPP_LABELS"
echo "OPP_FORCE_OPERATORS=$OPP_FORCE_OPERATORS"
FAKE_RC=false
FAKE_TYPE=$(echo $OPERATOR_INDEX_TAG | cut -d '-' -f 2)
echo "orange_${OPERATOR_INDEX_TAG} operators/sync $OPP_THIS_REPO $OPP_THIS_BRANCH"
bash <(curl -sL $OPP_SCRIPT_URL) orange_${OPERATOR_INDEX_TAG} operators/sync $OPP_THIS_REPO $OPP_THIS_BRANCH || $FAKE_RC
release-k8s:
name: "Index / k8s"
needs: [ pr-check, operators-k8s, bundles-k8s ]
if: needs.pr-check.outputs.opp_release_ready == '1' && needs.operators-k8s.outputs.opp_uncomplete_operators != ''
runs-on: ubuntu-latest
strategy:
matrix:
index-tag: ${{ fromJson(github.event.inputs.index) }}
fail-fast: false
steps:
- name: Download operator_info
uses: actions/download-artifact@v4
with:
name: operator_info
path: /tmp/operator-test/
- name: Download converted operators
uses: actions/download-artifact@v4
with:
name: operators_converted
path: /tmp/operator-test/operators
- name: Print space info (before)
run: |
du -h -d 3 /tmp | sort -h -r
df -h
docker images
- name: Index sync
env:
OPP_LABELS: "${{ needs.pr-check.outputs.opp_labels }}"
OPP_AUTO_PACKAGEMANIFEST_CLUSTER_VERSION_LABEL: "${{ needs.pr-check.outputs.opp_auto_packagemanifest_cluster_version_label }}"
OPP_IIB_INSTALL: 0
#OPP_MIRROR_INDEX_ENABLED: 0
OPP_FORCE_INDEX_UPDATE: 1
OPP_SKIP_BUNDLES: 1
IIB_INPUT_REGISTRY_TOKEN: ${{ secrets.IIB_INPUT_REGISTRY_TOKEN }}
OPERATOR_INDEX_TAG: ${{ matrix.index-tag }}
# OPP_FORCE_OPERATORS: "${{ needs.operators-k8s.outputs.opp_uncomplete_operators }}"
OPP_FORCE_OPERATORS: ""
run: |
echo "OPP_LABELS=$OPP_LABELS"
FAKE_RC=false
FAKE_TYPE=$(echo $OPERATOR_INDEX_TAG | cut -d '-' -f 2)
for index in $(echo '${{ github.event.inputs.index }}' | jq -r .[]); do
TARGET_INDEX_RAW=$(echo $index|cut -d '-' -f1)
TARGET_INDEX_UNDERLINE=$(echo $TARGET_INDEX_RAW|tr '.' '_')
export OPP_FORCE_OPERATORS_$TARGET_INDEX_UNDERLINE="${{ github.event.inputs.list_of_operators }}"
done
bash <(curl -sL $OPP_SCRIPT_CLEANUP_URL)
echo "orange_${OPERATOR_INDEX_TAG} operators/sync $OPP_THIS_REPO $OPP_THIS_BRANCH"
bash <(curl -sL $OPP_SCRIPT_URL) orange_${OPERATOR_INDEX_TAG} operators/sync $OPP_THIS_REPO $OPP_THIS_BRANCH || $FAKE_RC
- name: Print space info (after)
if: always()
run: |
docker exec -t op-test /bin/bash -c "du -h -d 3 /tmp | sort -h -r" || true
docker exec -t op-test /bin/bash -c "podman images ; df -h" || true
echo "local df:"
df -h
index-verify-k8s:
name: "Index Verify / k8s"
needs: [ pr-check, operators-k8s, bundles-k8s, release-k8s]
if: needs.pr-check.outputs.opp_release_ready == '1' && needs.operators-k8s.outputs.opp_uncomplete_operators != ''
runs-on: ubuntu-latest
strategy:
matrix:
index-tag: ${{ fromJson(github.event.inputs.index) }}
fail-fast: false
steps:
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.x'
- name: Install dependencies
run: python -m pip install --upgrade pip yq
- name: Index verify
id: index-verify
env:
OPP_CONTAINER_TOOL: podman
run: |
MY_TAG=${{ matrix.index-tag }}
MY_TAG=$(echo $MY_TAG | cut -d '-' -f 1)
MY_INDEXES="quay.io/operatorhubio/catalog_tmp:${MY_TAG}"
MY_INDEXES="$MY_INDEXES,quay.io/operatorhubio/catalog_tmp:${MY_TAG}s"
MY_INDEXES="$MY_INDEXES,quay.io/operatorhubio/catalog:${MY_TAG}"
echo "MY_INDEXES=$MY_INDEXES"
echo "$REGISTRY_MIRROR_PW" | $OPP_CONTAINER_TOOL login $OPP_MIRROR_INDEX_REGISTRY -u $OPP_REGISTRY_MIRROR_USER --password-stdin || { echo "Problem to login to '$OPP_MIRROR_INDEX_REGISTRY' !!!"; exit 1; }
ansible-pull -U $OPP_ANSIBLE_PULL_REPO -C $OPP_ANSIBLE_PULL_BRANCH -i localhost, -e run_upstream=true -e run_prepare_catalog_repo_upstream=false -e container_tool=$OPP_CONTAINER_TOOL upstream/local.yml --tags reset_tools,index_verify -e iv_indexes="$MY_INDEXES"
ohio-image-k8s:
name: "OHIO image / k8s"
needs: [ pr-check, release-k8s ]
if: needs.pr-check.outputs.opp_release_ready == '1'
runs-on: ubuntu-latest
env:
OHIO_INPUT_CATALOG_IMAGE: "quay.io/operatorhubio/catalog_tmp:latest"
OHIO_REGISTRY_IMAGE: "quay.io/operator-framework/upstream-community-operators:latest"
TMPDIR: "/mnt/tmp"
steps:
- name: Ohio image
env:
TMPDIR: "/mnt/tmp"
run: |
echo "ohio_image operators/sync $OPP_THIS_REPO $OPP_THIS_BRANCH"
bash <(curl -sL $OPP_SCRIPT_CLEANUP_URL)
bash <(curl -sL $OPP_SCRIPT_URL) ohio_image operators/sync $OPP_THIS_REPO $OPP_THIS_BRANCH
ohio-page-k8s:
name: "Release / operatorhub.io"
needs: ohio-image-k8s
if: needs.pr-check.outputs.opp_release_ready == '1'
runs-on: ubuntu-latest
env:
CI_OHIO_BRANCH: "latest"
REPO_GHA_PAT: ${{ secrets.REPO_GHA_PAT }}
steps:
- name: Ohio image
run: |
echo "$OPP_SCRIPT_TRIGGER_OHIO_URL ${CI_OHIO_BRANCH}"
bash <(curl -sL $OPP_SCRIPT_TRIGGER_OHIO_URL) ${CI_OHIO_BRANCH}
slack-notification:
name: "Monitoring notification"
needs: [ pr-check, remove-k8s, operators-k8s, release-k8s, index-verify-k8s, ohio-image-k8s, ohio-page-k8s ]
if: failure()
runs-on: ubuntu-latest
steps:
- name: Report Status to a Slack
uses: ravsamhq/notify-slack-action@master
with:
notification_title: 'Release pipeline failed: ${{ needs.pr-check.outputs.opp_pr_title }}'
token: ${{ secrets.GITHUB_TOKEN }}
message_format: "{emoji} *{workflow}* {status_message} in <{repo_url}|{repo}>. <{run_url}|View Failed Run>"
footer: 'monitoring'
status: 'failure'
notify_when: 'failure'
env:
SLACK_WEBHOOK_URL: ${{ secrets.ACTION_MONITORING_SLACK }}
continue-on-error: true