Skip to content

ci: skip secret-dependent steps on fork PRs and add optional Vertica license gating #775

ci: skip secret-dependent steps on fork PRs and add optional Vertica license gating

ci: skip secret-dependent steps on fork PRs and add optional Vertica license gating #775

Workflow file for this run

name: CI and Codecov
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
# Determine whether a Vertica license is available. The VerticaDB operator
# requires a non-empty licenseSecret, and secrets are not exposed to fork PRs,
# so the coverage job only runs when VERTICA_LICENSE is present.
license-check:
runs-on: ubuntu-latest
outputs:
run_licensed: ${{ steps.check.outputs.run_licensed }}
steps:
- name: Check Vertica license availability
id: check
env:
VERTICA_LICENSE: ${{ secrets.VERTICA_LICENSE }}
run: |
if [ -z "${VERTICA_LICENSE:-}" ]; then
echo "::notice::VERTICA_LICENSE is unavailable (e.g. fork PR). Skipping the coverage job."
echo "run_licensed=false" >> "$GITHUB_OUTPUT"
else
echo "run_licensed=true" >> "$GITHUB_OUTPUT"
fi
codecov:
name: Codecov Workflow
needs: license-check
if: needs.license-check.outputs.run_licensed == 'true'
runs-on: ubuntu-latest
# Coverage needs a live Vertica brought up via the operator on KinD, which is
# heavy on hosted runners. Marked non-blocking so the coverage signal stays
# visible without failing the pipeline; remove once consistently green.
continue-on-error: true
steps:
- name: Installing graphviz package
run: sudo apt-get update && sudo apt-get install -y graphviz
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
# ---------------------------
# Kubernetes (KinD) + Helm setup
# The standalone opentext/vertica-ce image was removed from Docker Hub, so
# Vertica is brought up via the VerticaDB operator on KinD (CE mode).
# ---------------------------
- name: Set up Kubernetes (KinD)
uses: helm/kind-action@v1.8.0
with:
cluster_name: vertica-codecov
node_image: kindest/node:v1.29.0
- name: Set up Helm
uses: azure/setup-helm@v3
with:
version: "3.11.3"
- name: Add Helm repositories
run: |
helm repo add vertica-charts https://vertica.github.io/charts
helm repo add bitnami https://charts.bitnami.com/bitnami || true
helm repo update
# ---------------------------
# MinIO (communal storage required by the operator)
# ---------------------------
- name: Install MinIO
run: |
kubectl create ns minio
cat <<'EOF' > minio.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: minio
namespace: minio
spec:
replicas: 1
selector:
matchLabels:
app: minio
template:
metadata:
labels:
app: minio
spec:
containers:
- name: minio
image: minio/minio:latest
args: ["server", "/data"]
env:
- name: MINIO_ROOT_USER
value: "minioadmin"
- name: MINIO_ROOT_PASSWORD
value: "minioadmin"
ports:
- containerPort: 9000
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: minio
namespace: minio
spec:
selector:
app: minio
ports:
- port: 9000
targetPort: 9000
EOF
kubectl apply -f minio.yaml
kubectl -n minio rollout status deployment/minio --timeout=5m
- name: Ensure MinIO bucket exists
run: |
kubectl run mc-client --rm -i --restart=Never \
--image=minio/mc:latest \
-n minio \
--command -- bash -c "
mc alias set localminio http://minio.minio.svc.cluster.local:9000 minioadmin minioadmin && \
mc mb --ignore-existing localminio/vertica-fleeting && \
mc ls localminio
"
- name: Create MinIO Secret
run: |
kubectl create ns my-verticadb-operator
kubectl delete secret communal-creds -n my-verticadb-operator --ignore-not-found
kubectl create secret generic communal-creds \
-n my-verticadb-operator \
--from-literal=accesskey="minioadmin" \
--from-literal=secretkey="minioadmin"
# ---------------------------
# Vertica license (this job only runs when VERTICA_LICENSE is available)
# ---------------------------
- name: Create Vertica license secret
env:
VERTICA_LICENSE: ${{ secrets.VERTICA_LICENSE }}
run: |
set -uo pipefail
if printf '%s' "${VERTICA_LICENSE}" | base64 -d > /tmp/license.dat 2>/dev/null && [ -s /tmp/license.dat ]; then
echo "Decoded VERTICA_LICENSE as base64."
else
printf '%s' "${VERTICA_LICENSE}" > /tmp/license.dat
echo "Using VERTICA_LICENSE as raw license content."
fi
if [ ! -s /tmp/license.dat ]; then
echo "::error::Resulting license file is empty. Check the 'VERTICA_LICENSE' secret value."
rm -f /tmp/license.dat
exit 1
fi
kubectl delete secret vertica-license -n my-verticadb-operator --ignore-not-found
kubectl create secret generic vertica-license \
-n my-verticadb-operator \
--from-file=license.dat=/tmp/license.dat
rm -f /tmp/license.dat
# ---------------------------
# Vertica operator + DB deployment
# ---------------------------
- name: Install Vertica Operator
run: |
cat <<'EOF' > operator-values.yaml
installCRDs: true
controller:
extraEnv:
- name: AWS_REGION
value: "us-east-1"
- name: AWS_DEFAULT_REGION
value: "us-east-1"
EOF
helm upgrade --install vdb-op vertica-charts/verticadb-operator \
-n my-verticadb-operator -f operator-values.yaml --wait --timeout 10m
kubectl -n my-verticadb-operator get pods -o wide || true
- name: Deploy VerticaDB
run: |
cat > /tmp/verticadb.yaml <<'EOF'
apiVersion: vertica.com/v1
kind: VerticaDB
metadata:
name: verticadb-sample
namespace: my-verticadb-operator
annotations:
vertica.com/k-safety: "0"
spec:
image: opentext/vertica-k8s:latest
dbName: vdb
initPolicy: Create
licenseSecret: vertica-license
communal:
path: s3://vertica-fleeting/verticapy-codecov/
credentialSecret: communal-creds
endpoint: http://minio.minio.svc.cluster.local:9000
region: us-east-1
local:
dataPath: /data
depotPath: /depot
subclusters:
- name: defaultsubcluster
size: 1
EOF
echo "--- VerticaDB manifest ---"
cat /tmp/verticadb.yaml
kubectl apply -f /tmp/verticadb.yaml
- name: Wait for Vertica readiness
run: |
NS=my-verticadb-operator
SS=verticadb-sample-defaultsubcluster
POD=${SS}-0
for i in $(seq 1 60); do
kubectl get pod ${POD} -n ${NS} >/dev/null 2>&1 && break || sleep 10
done
if ! kubectl wait --for=condition=Ready pod/${POD} -n ${NS} --timeout=15m; then
echo "::error::Vertica pod ${POD} did not become Ready. Dumping diagnostics."
kubectl -n ${NS} get verticadb -o wide || true
kubectl -n ${NS} get pods -o wide || true
kubectl -n ${NS} describe pod ${POD} || true
kubectl -n ${NS} logs ${POD} -c server --tail=200 || true
exit 1
fi
kubectl -n ${NS} get pods -o wide || true
# ---------------------------
# Coverage (tox with --cov via kubectl port-forward)
# ---------------------------
- name: Install dependencies
run: pip install tox
- name: Run tests with coverage
run: |
set -uo pipefail
NS=my-verticadb-operator
SVC=verticadb-sample-defaultsubcluster
for i in {1..30}; do
addrs=$(kubectl -n ${NS} get endpoints ${SVC} \
-o jsonpath='{.subsets[*].addresses[*].ip}' 2>/dev/null || true)
[ -n "$addrs" ] && break || sleep 5
done
kubectl -n ${NS} port-forward svc/${SVC} 5433:5433 > /tmp/pf.log 2>&1 &
PF_PID=$!
trap 'kill ${PF_PID} 2>/dev/null || true' EXIT
for i in {1..30}; do
if (exec 3<>/dev/tcp/127.0.0.1/5433) 2>/dev/null; then
exec 3>&-
echo "Vertica reachable on localhost:5433"
break
fi
sleep 2
done
export VP_TEST_HOST=localhost
export VP_TEST_PORT=5433
export VP_TEST_USER=dbadmin
export VP_TEST_PASSWORD=""
export VP_TEST_DATABASE=vdb
tox -e py311 -- --cov=./ --cov-report=xml
- name: Check Codecov token availability
id: codecov-check
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: |
is_fork="${{ github.event.pull_request.head.repo.fork }}"
if [ "$is_fork" = "true" ] && [ -z "${CODECOV_TOKEN:-}" ]; then
echo "::notice::Fork PR detected — CODECOV_TOKEN secret is unavailable. Skipping coverage upload."
echo "run_codecov=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# For internal PRs and pushes, the token must be present
if [ -z "${CODECOV_TOKEN:-}" ]; then
echo "::error::GitHub secret 'CODECOV_TOKEN' is not set or is empty. Configure it under repo Settings > Secrets and variables > Actions."
exit 1
fi
echo "run_codecov=true" >> "$GITHUB_OUTPUT"
- name: Upload coverage to Codecov
if: steps.codecov-check.outputs.run_codecov == 'true'
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
flags: unittests
# ---------------------------
# Teardown
# ---------------------------
- name: Cleanup Kubernetes resources
if: always()
run: |
kubectl delete verticadb verticadb-sample -n my-verticadb-operator --ignore-not-found || true
helm uninstall vdb-op -n my-verticadb-operator || true
kubectl delete ns my-verticadb-operator --ignore-not-found || true
kubectl delete -f minio.yaml --ignore-not-found || true
kubectl delete ns minio --ignore-not-found || true
- name: Delete KinD cluster
if: always()
run: |
kind delete cluster --name vertica-codecov || true