Skip to content

(2) Test And Release #483

(2) Test And Release

(2) Test And Release #483

name: (2) Test And Release
on:
workflow_dispatch:
inputs:
RELEASE_VERSION:
description: "Release version in the form of X.Y.Z"
required: true
schedule:
- cron: "0 9 * * *"
env:
NAMESPACE: oc-test-operator-${{ github.run_id }}
PARDOT_ID: redhat
GAR_REGION: us-east1
GAR_PROJECT: hazelcast-33
GAR_REPO: hazelcast-platform-operator
GKE_ZONE: us-east1-b
AWS_REGION: us-east-1
jobs:
migration-test:
name: Run migration test
runs-on: ubuntu-latest
env:
CLUSTER_NAME: kind
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
HZ_LICENSE_KEY,CN/HZ_LICENSE_KEY
- name: Create Kind Config
run: |
cat <<EOT >> ./kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
EOT
- name: Create Kind Cluster
uses: helm/kind-action@v1.10.0
with:
config: ./kind-config.yaml
cluster_name: ${{ env.CLUSTER_NAME }}
- name: Install metallb
uses: nick-fields/retry@v3
with:
timeout_minutes: 5
max_attempts: 3
retry_on: error
command: |
kubectl create namespace ${NAMESPACE}
kubectl config set-context --current --namespace=$NAMESPACE
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
kubectl wait --for=condition=ready --timeout=60s -n metallb-system pod -l app=metallb
HOST_MIN=$(docker network inspect -f '{{json .IPAM.Config}}' ${{ env.CLUSTER_NAME }} | jq -r '.[0].Subnet' | sed -n 's/.0.0.16/.255.200/p')
HOST_MAX=$(docker network inspect -f '{{json .IPAM.Config}}' ${{ env.CLUSTER_NAME }} | jq -r '.[0].Subnet' | sed -n 's/.0.0.16/.255.250/p')
IP_RANGE=$HOST_MIN-$HOST_MAX
cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kind-pool
namespace: metallb-system
spec:
addresses:
- $IP_RANGE
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2
namespace: metallb-system
spec:
ipAddressPools:
- kind-pool
EOF
- name: Create Secrets
if: matrix.edition == 'ee'
run: |
kubectl create secret generic hazelcast-license-key \
--namespace ${NAMESPACE} \
--from-literal=license-key=${{ env.HZ_LICENSE_KEY }}
- name: Deploy and Run Migration test
run: |
LATEST_VERSION=$(curl -s https://artifacthub.io/api/v1/packages/helm/hazelcast/hazelcast-platform-operator | jq -r '.version')
STABLE_VERSION=$(curl -s https://artifacthub.io/api/v1/packages/helm/hazelcast/hazelcast-platform-operator | jq -r '.available_versions | map(select(.version | contains("snapshot") | not)) | .[0].version')
kubectl create secret generic hazelcast-license-key --from-literal=license-key=${{ env.HZ_LICENSE_KEY }}
helm repo add hazelcast https://hazelcast-charts.s3.amazonaws.com && \
helm repo update && \
helm install operator hazelcast/hazelcast-platform-operator --version=$STABLE_VERSION --set=installCRDs=true --set=phoneHomeEnabled=false --wait
echo "Checking Operator Deployment before upgrade"
kubectl rollout status deployment.apps/operator-hazelcast-platform-operator
echo "Checking Operator Pod before upgrade"
kubectl wait pods -l app.kubernetes.io/name=hazelcast-platform-operator --for condition=Ready --timeout=300s
kubectl apply -f - <<EOF
apiVersion: hazelcast.com/v1alpha1
kind: Hazelcast
metadata:
name: hazelcast
spec:
nativeMemory:
allocatorType: POOLED
size: 100M
clusterSize: 3
repository: "docker.io/hazelcast/hazelcast-enterprise"
exposeExternally:
discoveryServiceType: LoadBalancer
memberAccess: NodePortExternalIP
licenseKeySecret: hazelcast-license-key
persistence:
clusterDataRecoveryPolicy: "FullRecoveryOnly"
pvc:
accessModes: ["ReadWriteOnce"]
requestStorage: 10Mi
---
apiVersion: hazelcast.com/v1alpha1
kind: Map
metadata:
name: persistent
spec:
hazelcastResourceName: hazelcast
persistenceEnabled: false
backupCount: 4
nearCache:
inMemoryFormat: NATIVE
eviction:
evictionPolicy: LRU
maxSizePolicy: USED_NATIVE_MEMORY_SIZE
size: 5000
---
apiVersion: hazelcast.com/v1alpha1
kind: ManagementCenter
metadata:
name: managementcenter
spec:
repository: 'hazelcast/management-center'
hazelcastClusters:
- address: hazelcast
name: dev
EOF
echo "Checking Hazelcast CR before upgrade"
kubectl wait --for=jsonpath='{.status.phase}'=Running --timeout=300s hazelcast/hazelcast || (echo "Hazelcast CR Check Failed" && kubectl get hazelcasts.hazelcast.com hazelcast -o wide; exit 1;)
echo "Checking Map CR before upgrade"
kubectl wait --for=jsonpath='{.status.state}'=Success --timeout=300s map/persistent || (echo "Map CR Check Failed" && kubectl get maps.hazelcast.com persistent -o wide; exit 1;)
echo "Checking Management Center CR before upgrade"
kubectl wait --for=jsonpath='{.status.phase}'=Running --timeout=300s ManagementCenter/managementcenter || (echo "Management Center CR Check Failed" && kubectl get managementcenters.hazelcast.com managementcenter -o wide; exit 1;)
helm upgrade operator hazelcast/hazelcast-platform-operator --version=$LATEST_VERSION --set=installCRDs=true --set=phoneHomeEnabled=false --wait
echo "Checking Operator Pod after upgrade"
kubectl wait pods -l app.kubernetes.io/name=hazelcast-platform-operator --for condition=Ready --timeout=300s
echo "Checking Hazelcast CR after upgrade"
kubectl wait --for=jsonpath='{.status.phase}'=Running --timeout=300s hazelcast/hazelcast || (echo "Hazelcast CR Check Failed" && kubectl get hazelcasts.hazelcast.com hazelcast -o wide; exit 1;)
echo "Checking Map CR after upgrade"
kubectl wait --for=jsonpath='{.status.state}'=Success --timeout=300s map/persistent || (echo "Map CR Check Failed" && kubectl get maps.hazelcast.com persistent -o wide; exit 1;)
echo "Checking Management Center CR after upgrade"
kubectl wait --for=jsonpath='{.status.phase}'=Running --timeout=300s ManagementCenter/managementcenter || (echo "Management Center CR Check Failed" && kubectl get managementcenters.hazelcast.com managementcenter -o wide; exit 1;)
test_container:
name: Build and Test Container
defaults:
run:
shell: bash
runs-on: ubuntu-latest
outputs:
RELEASE_VERSION: ${{ steps.setup-envs.outputs.RELEASE_VERSION }}
CONTAINER_IMAGE: ${{ steps.setup-envs.outputs.CONTAINER_IMAGE }}
CONTAINER_IMAGE_DIGEST: ${{ steps.build-image.outputs.digest }}
REFS: ${{ steps.setup-envs.outputs.ref }}
steps:
- name: Checkout to hazelcast-operator
uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
PFLT_PYXIS_API_TOKEN,CN/PREFLIGHT_RHEL_API_KEY
GKE_SA_KEY,CN/GKE_SA_KEY
- name: Setup Preflight and Get Certification Project ID
uses: redhat-actions/openshift-tools-installer@v1
with:
preflight: "latest"
source: github
skip_cache: true
- name: Set Environment Variables And Job Outputs
id: setup-envs
run: |
if [[ ${{ github.event_name == 'schedule' }} == true ]]; then
echo "RELEASE_VERSION=1.0.0" >> $GITHUB_ENV
echo "RELEASE_VERSION=1.0.0" >> $GITHUB_OUTPUT
elif [[ ${{ github.event_name == 'workflow_dispatch' }} == true ]]; then
echo "RELEASE_VERSION=${{ github.event.inputs.RELEASE_VERSION }}" >> $GITHUB_ENV
echo "RELEASE_VERSION=${{ github.event.inputs.RELEASE_VERSION }}" >> $GITHUB_OUTPUT
echo "ref=refs/heads/${{ inputs.RELEASE_VERSION }}" >> $GITHUB_OUTPUT
fi
CONTAINER_IMAGE=${{ env.GAR_REGION }}-docker.pkg.dev/${{ env.GAR_PROJECT }}/${{ env.GAR_REPO }}/$(uuidgen):5d
echo "CONTAINER_IMAGE=${CONTAINER_IMAGE}" >> $GITHUB_ENV
echo "CONTAINER_IMAGE=${CONTAINER_IMAGE}" >> $GITHUB_OUTPUT
- name: Validate version
run: |
NUMBER='(0|[1-9][0-9]*)'
echo ${RELEASE_VERSION} | egrep "^$NUMBER.$NUMBER.$NUMBER?$"
- name: Set Up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3.3.0
with:
install: true
- name: Authenticate to GAR
uses: docker/login-action@v3
with:
registry: us-east1-docker.pkg.dev
username: _json_key
password: ${{ env.GKE_SA_KEY }}
- name: Build Image
id: build-image
uses: docker/build-push-action@v5.3.0
with:
context: .
builder: ${{ steps.buildx.outputs.name }}
build-args: |
version=${{github.sha}}
pardotID=dockerhub
file: Dockerfile
push: true
tags: ${{ steps.setup-envs.outputs.CONTAINER_IMAGE }}
cache-from: type=registry,ref=${{ env.GAR_REGION }}-docker.pkg.dev/${{ env.GAR_PROJECT }}/${{ env.GAR_REPO }}/${{ hashFiles('Dockerfile','main.go','api/**','controllers/**','internal/**','licenses/**','**/go.mod','**/go.sum') }}:14d
cache-to: type=registry,ref=${{ env.GAR_REGION }}-docker.pkg.dev/${{ env.GAR_PROJECT }}/${{ env.GAR_REPO }}/${{ hashFiles('Dockerfile','main.go','api/**','controllers/**','internal/**','licenses/**','**/go.mod','**/go.sum') }}:14d
- name: Initiating a Container Scan
run: |
echo "Running the container scan tests"
preflight check container $CONTAINER_IMAGE --platform amd64
grep -E -q "Preflight result: PASSED\"( |$)" preflight.log || exit 1
openscap_image_scan:
name: Run OpenSCAP Vulnerability Scan
needs: test_container
defaults:
run:
shell: bash
env:
CONTAINER_IMAGE: ${{ needs.test_container.outputs.CONTAINER_IMAGE }}
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
GKE_SA_KEY,CN/GKE_SA_KEY
OPENSCAP_SCANHOST,CN/OPENSCAP_SCANHOST
OPENSCAP_PRIVATE_KEY,CN/OPENSCAP_PRIVATE_KEY
OPENSCAP_FINGERPRINT,CN/OPENSCAP_FINGERPRINT
- name: Authenticate to GAR
uses: docker/login-action@v3
with:
registry: us-east1-docker.pkg.dev
username: _json_key
password: ${{ env.GKE_SA_KEY }}
- name: Run OpenSCAP Vulnerability Scan
id: vulnerabilityScan
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ env.OPENSCAP_SCANHOST }}
username: ec2-user
key: ${{ env.OPENSCAP_PRIVATE_KEY }}
envs: CONTAINER_IMAGE
script: |
sudo podman pull $CONTAINER_IMAGE
sudo oscap-podman $CONTAINER_IMAGE oval eval --report vulnerability_report.html rhel-8.oval.xml | grep -E 'true' && exit 1 || echo "Vulnerabilty scan passed"
- name: Download Scan Report
if: failure() && steps.vulnerabilityScan.outcome == 'failure'
uses: nicklasfrahm/scp-action@v1.0.1
with:
direction: download
host: ${{ env.OPENSCAP_SCANHOST }}
username: ec2-user
fingerprint: ${{ env.OPENSCAP_FINGERPRINT }}
key: ${{ env.OPENSCAP_PRIVATE_KEY }}
source: ~/vulnerability_report.html
target: vulnerability_report.html
- name: Save Scan Report As Artifact
uses: actions/upload-artifact@v3
if: failure() && steps.vulnerabilityScan.outcome == 'failure'
with:
name: vulnerability-report
path: vulnerability_report.html
build_bundle:
name: Build Bundle and Index Image
needs: [test_container, openscap_image_scan]
defaults:
run:
shell: bash
env:
CONTAINER_IMAGE: ${{ needs.test_container.outputs.CONTAINER_IMAGE }}
CONTAINER_IMAGE_DIGEST: ${{ needs.test_container.outputs.CONTAINER_IMAGE_DIGEST }}
RELEASE_VERSION: ${{ needs.test_container.outputs.RELEASE_VERSION }}
outputs:
BUNDLE_VERSION: ${{ steps.build-bundle-outputs.outputs.BUNDLE_VERSION }}
BUNDLE_IMAGE: ${{ steps.build-bundle-outputs.outputs.BUNDLE_IMAGE }}
BUNDLE_IMAGE_DIGEST: ${{ steps.push-bundle-image.outputs.BUNDLE_IMAGE_DIGEST }}
PFLT_INDEXIMAGE: ${{ steps.build-bundle-outputs.outputs.PFLT_INDEXIMAGE }}
runs-on: ubuntu-latest
steps:
- name: Checkout to hazelcast-operator
uses: actions/checkout@v4
- name: Setup Preflight and OPM Tools
uses: redhat-actions/openshift-tools-installer@v1
with:
preflight: "latest"
source: github
skip_cache: true
- uses: redhat-actions/openshift-tools-installer@v1
with:
opm: "latest"
skip_cache: true
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
GKE_SA_KEY,CN/GKE_SA_KEY
- name: Authenticate to GAR
uses: docker/login-action@v3
with:
registry: us-east1-docker.pkg.dev
username: _json_key
password: ${{ env.GKE_SA_KEY }}
- name: Set Environment Variables And Job Outputs
id: build-bundle-outputs
run: |
BUNDLE_VERSION=$( make print-bundle-version VERSION=${RELEASE_VERSION} )
BUNDLE_REPOSITORY=${{ env.GAR_REGION }}-docker.pkg.dev/${{ env.GAR_PROJECT }}/${{ env.GAR_REPO }}/$(uuidgen)
BUNDLE_IMAGE=$BUNDLE_REPOSITORY:5d
PFLT_INDEXIMAGE=$BUNDLE_REPOSITORY-index:5d
echo "BUNDLE_VERSION=${BUNDLE_VERSION}" >> $GITHUB_ENV
echo "BUNDLE_REPOSITORY=${BUNDLE_REPOSITORY}" >> $GITHUB_ENV
echo "BUNDLE_IMAGE=${BUNDLE_IMAGE}" >> $GITHUB_ENV
echo "PFLT_INDEXIMAGE=${PFLT_INDEXIMAGE}" >> $GITHUB_ENV
echo "BUNDLE_VERSION=${BUNDLE_VERSION}" >> $GITHUB_OUTPUT
echo "BUNDLE_IMAGE=${BUNDLE_IMAGE}" >> $GITHUB_OUTPUT
echo "PFLT_INDEXIMAGE=${PFLT_INDEXIMAGE}" >> $GITHUB_OUTPUT
- name: Build Bundle
run: |
IMAGE_NAME_DIGEST=${CONTAINER_IMAGE}@${CONTAINER_IMAGE_DIGEST}
make bundle IMG=${IMAGE_NAME_DIGEST} VERSION=${RELEASE_VERSION}
cat >> ./bundle/metadata/annotations.yaml <<EOF
# OpenShift annotations.
com.redhat.openshift.versions: v4.8
operators.operatorframework.io.bundle.channel.default.v1: alpha
EOF
- name: Upload Bundle Artifacts
uses: actions/upload-artifact@v3
with:
name: bundle-artifacts
path: ./bundle/
- name: Build and Push Bundle Image
id: push-bundle-image
run: |
docker build -f bundle.Dockerfile -t ${BUNDLE_IMAGE} .
docker push ${BUNDLE_IMAGE}
BUNDLE_IMAGE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' ${BUNDLE_IMAGE} | cut -d'@' -f2)
echo "BUNDLE_IMAGE_DIGEST=${BUNDLE_IMAGE_DIGEST}" >> $GITHUB_OUTPUT
- name: Create Bundle Index
run: |
opm index add --bundles ${BUNDLE_IMAGE} --tag ${PFLT_INDEXIMAGE}
podman push ${PFLT_INDEXIMAGE}
test_operator:
name: Test Operator Bundle
needs: build_bundle
runs-on: ubuntu-latest
env:
PFLT_INDEXIMAGE: ${{ needs.build_bundle.outputs.PFLT_INDEXIMAGE }}
BUNDLE_IMAGE: ${{ needs.build_bundle.outputs.BUNDLE_IMAGE }}
BUNDLE_IMAGE_DIGEST: ${{ needs.build_bundle.outputs.BUNDLE_IMAGE_DIGEST }}
KUBECONFIG: $HOME/.kube/config
steps:
- name: Checkout to hazelcast-operator
uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
PFLT_PYXIS_API_TOKEN,CN/PREFLIGHT_RHEL_API_KEY
GKE_SA_KEY,CN/GKE_SA_KEY
OCP_CLUSTER_URL,CN/OCP_CLUSTER_URL
OCP_USERNAME,CN/OCP_USERNAME
OCP_PASSWORD,CN/OCP_PASSWORD
- name: Setup Preflight and Operator SDK
uses: redhat-actions/openshift-tools-installer@v1
with:
preflight: "latest"
source: github
skip_cache: true
- uses: redhat-actions/openshift-tools-installer@v1
with:
operator-sdk: "latest"
source: github
skip_cache: true
- name: Authenticate to GAR
uses: docker/login-action@v3
with:
registry: us-east1-docker.pkg.dev
username: _json_key
password: ${{ env.GKE_SA_KEY }}
- name: Login to OCP and Create New Project
id: project_creation
run: |
oc login ${{ env.OCP_CLUSTER_URL }} -u=${{ env.OCP_USERNAME }} -p=${{ env.OCP_PASSWORD }} --insecure-skip-tls-verify
oc new-project ${NAMESPACE}
echo "exit_code=$?" >> $GITHUB_OUTPUT
- name: Initiating an Operator Bundle Scan
run: |
preflight check operator ${BUNDLE_IMAGE}@${BUNDLE_IMAGE_DIGEST}
grep -E -q "Preflight result: PASSED\"( |$)" preflight.log || exit 1
- name: Clean Up Openshift Namespace
if: always() && steps.project_creation.outputs.exit_code == 0
run: |
oc delete project ${NAMESPACE}
community_operators_test_suite:
needs: build_bundle
uses: ./.github/workflows/community-operator-tests.yaml
with:
BUNDLE_VERSION: ${{ needs.build_bundle.outputs.BUNDLE_VERSION }}
create_operator_tag:
if: needs.test_container.outputs.REFS == github.ref && github.ref != 'refs/heads/main'
needs: [ test_container, test_operator, community_operators_test_suite ]
name: Create Operator Tag
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
DEVOPS_GITHUB_TOKEN,CN/DEVOPS_GITHUB_TOKEN
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ env.DEVOPS_GITHUB_TOKEN }}
- name: Create a New Tag
run: |
TAG_VERSION=v${{ needs.test_container.outputs.RELEASE_VERSION }}
git tag ${TAG_VERSION}
git push origin ${TAG_VERSION}
publish_release:
if: needs.test_container.outputs.REFS == github.ref && github.ref != 'refs/heads/main'
needs: [migration-test, create_operator_tag, test_container, test_operator, community_operators_test_suite]
uses: ./.github/workflows/publish-release.yaml
with:
RELEASE_VERSION: ${{ needs.test_container.outputs.RELEASE_VERSION }}
secrets: inherit
clean_up_artifacts:
if: always()
needs: [ build_bundle, openscap_image_scan, community_operators_test_suite ]
runs-on: ubuntu-latest
name: Clean The Bundle Artifact and Test Image
steps:
- name: Delete Bundle Artifact
uses: geekyeggo/delete-artifact@v5
with:
name: |
bundle-artifacts
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4.0.2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
OPENSCAP_SCANHOST,CN/OPENSCAP_SCANHOST
OPENSCAP_PRIVATE_KEY,CN/OPENSCAP_PRIVATE_KEY
- name: Delete Test Image For Security Scan
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ env.OPENSCAP_SCANHOST }}
username: ec2-user
key: ${{ env.OPENSCAP_PRIVATE_KEY }}
script: sudo podman image prune -af