Skip to content

Fix Node.js CI pipeline failures and stabilize GitHub Actions workflow #385

Fix Node.js CI pipeline failures and stabilize GitHub Actions workflow

Fix Node.js CI pipeline failures and stabilize GitHub Actions workflow #385

Workflow file for this run

name: Vertica CI
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ master ]
pull_request:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
env:
V_HOST: localhost
V_PORT: 5433
V_USER: dbadmin
V_DATABASE: vdb
KC_REALM: test
KC_USER: oauth_user
KC_PASSWORD: password
KC_CLIENT_ID: vertica
KC_CLIENT_SECRET: P9f8350QQIUhFfK1GF5sMhq4Dm3P6Sbs
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node:
- '12'
- '14'
- '16'
- '18'
- '20'
name: Node.js ${{ matrix.node }}
steps:
# ---------------------------
# Checkout and setup
# ---------------------------
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: yarn
- name: build
run: yarn
- name: bootstrap
run: yarn lerna bootstrap
# ---------------------------
# Kubernetes (KinD) + Helm setup
# ---------------------------
- name: Set up Kubernetes (KinD)
uses: helm/kind-action@v1.8.0
with:
cluster_name: vertica-ci
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 Setup
# ---------------------------
- 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=2m
kubectl get pods -n minio -o wide || true
kubectl get svc -n minio || true
- 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"
kubectl get secret communal-creds -n my-verticadb-operator -o yaml || true
# ---------------------------
# 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 <<'EOF' | kubectl apply -f -
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
communal:
path: s3://vertica-fleeting/vertica-nodejs/
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
- name: Wait for Vertica readiness
timeout-minutes: 10
run: |
NS=my-verticadb-operator
SS=verticadb-sample-defaultsubcluster
POD=${SS}-0
for i in {1..30}; do
kubectl get pod ${POD} -n ${NS} && break || sleep 10
done
kubectl wait --for=condition=Ready pod/${POD} -n ${NS} --timeout=5m
# ---------------------------
# Keycloak + OAuth setup
# ---------------------------
- name: Deploy Keycloak
run: |
kubectl create ns keycloak
cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: keycloak
namespace: keycloak
spec:
replicas: 1
selector:
matchLabels:
app: keycloak
template:
metadata:
labels:
app: keycloak
spec:
containers:
- name: keycloak
image: quay.io/keycloak/keycloak:23.0.4
args: ["start-dev"]
env:
- name: KEYCLOAK_ADMIN
value: admin
- name: KEYCLOAK_ADMIN_PASSWORD
value: admin
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 20
periodSeconds: 5
failureThreshold: 6
---
apiVersion: v1
kind: Service
metadata:
name: keycloak
namespace: keycloak
spec:
selector:
app: keycloak
ports:
- port: 8080
targetPort: 8080
EOF
- name: Wait for Keycloak readiness
run: |
kubectl -n keycloak rollout status deploy/keycloak --timeout=2m
kubectl -n keycloak get pods -o wide
- name: Configure Keycloak realm, client, and user
run: |
kubectl -n keycloak exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh config credentials \
--server http://localhost:8080 --realm master \
--user admin --password admin
kubectl -n keycloak exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh create realms -s realm=${KC_REALM} -s enabled=true
kubectl -n keycloak exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh update realms/${KC_REALM} -s accessTokenLifespan=3600
kubectl -n keycloak exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh create clients -r ${KC_REALM} \
-s clientId="${KC_CLIENT_ID}" -s enabled=true \
-s secret="${KC_CLIENT_SECRET}" \
-s 'redirectUris=["*"]' \
-s directAccessGrantsEnabled=true
kubectl -n keycloak exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh create users -r ${KC_REALM} \
-s username=${KC_USER} -s enabled=true
kubectl -n keycloak exec deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh set-password -r ${KC_REALM} \
--username ${KC_USER} --new-password ${KC_PASSWORD}
- name: Configure Vertica Authentication
run: |
NS=my-verticadb-operator
POD=verticadb-sample-defaultsubcluster-0
kubectl -n ${NS} exec ${POD} -c server -- bash -c "
/opt/vertica/bin/vsql -U dbadmin -c \"
CREATE AUTHENTICATION v_oauth METHOD 'oauth' HOST '0.0.0.0/0';
ALTER AUTHENTICATION v_oauth SET client_id = '${KC_CLIENT_ID}';
ALTER AUTHENTICATION v_oauth SET client_secret = '${KC_CLIENT_SECRET}';
ALTER AUTHENTICATION v_oauth SET discovery_url = 'http://keycloak.keycloak.svc.cluster.local:8080/realms/${KC_REALM}/.well-known/openid-configuration';
ALTER AUTHENTICATION v_oauth SET introspect_url = 'http://keycloak.keycloak.svc.cluster.local:8080/realms/${KC_REALM}/protocol/openid-connect/token/introspect';
CREATE USER ${KC_USER};
GRANT AUTHENTICATION v_oauth TO ${KC_USER};
GRANT ALL ON SCHEMA PUBLIC TO ${KC_USER};
CREATE AUTHENTICATION v_dbadmin_hash METHOD 'hash' HOST '0.0.0.0/0';
ALTER AUTHENTICATION v_dbadmin_hash PRIORITY 10000;
GRANT AUTHENTICATION v_dbadmin_hash TO dbadmin;
\"
"
# ---------------------------
# Port forwarding for local tests
# ---------------------------
- name: Set up port forwarding
run: |
NS=my-verticadb-operator
# Port-forward Vertica (5433)
kubectl -n ${NS} port-forward svc/verticadb-sample-defaultsubcluster 5433:5433 &
# Port-forward Keycloak (8080)
kubectl -n keycloak port-forward svc/keycloak 8080:8080 &
# Wait for port-forwards to be ready
sleep 5
# Verify connectivity
nc -zv localhost 5433 || echo "Warning: Vertica port-forward not ready"
nc -zv localhost 8080 || echo "Warning: Keycloak port-forward not ready"
# ---------------------------
# Retrieve OAuth access token
# ---------------------------
- name: Retrieve OAuth access token
run: |
TOKEN=""
for i in {1..10}; do
echo "Attempt $i..."
RAW=$(curl -s -X POST \
"http://localhost:8080/realms/${KC_REALM}/protocol/openid-connect/token" \
-d "client_id=${KC_CLIENT_ID}" \
-d "username=${KC_USER}" \
-d "password=${KC_PASSWORD}" \
-d "grant_type=password" \
-d "client_secret=${KC_CLIENT_SECRET}") || true
if ! printf '%s' "$RAW" | python3 -c 'import sys,json; json.load(sys.stdin)' >/dev/null 2>&1; then
echo "Token endpoint did not return valid JSON:"
printf '%s\n' "$RAW"
sleep 5
continue
fi
TOKEN=$(printf '%s' "$RAW" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("access_token", ""))') || true
if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ] && [ "$TOKEN" != "" ]; then
echo "Access token retrieved successfully (length: ${#TOKEN})"
echo "$TOKEN" > access_token.txt
break
fi
echo "Token fetch failed, Keycloak may not be ready yet."
sleep 5
if [ "$i" -eq 10 ]; then
echo "Failed to fetch access token after multiple retries."
exit 1
fi
done
# ---------------------------
# Test steps
# ---------------------------
- name: test-v-connection-string
run: |
cd packages/v-connection-string
yarn test
- name: test-v-pool
run: |
cd packages/v-pool
yarn test
- name: test-v-protocol
run: |
cd packages/v-protocol
yarn test
- name: test-vertica-nodejs
run: |
export VTEST_OAUTH_ACCESS_TOKEN=$(cat access_token.txt 2>/dev/null || echo "")
cd packages/vertica-nodejs
yarn test
# ---------------------------
# Cleanup
# ---------------------------
- name: Cleanup Kubernetes resources
if: always()
run: |
echo "Starting cleanup..."
echo "Deleting Keycloak..."
kubectl delete deployment keycloak -n keycloak --ignore-not-found || true
kubectl delete service keycloak -n keycloak --ignore-not-found || true
kubectl delete ns keycloak --ignore-not-found || true
echo "Deleting VerticaDB and Operator..."
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
echo "Deleting MinIO..."
kubectl delete -f minio.yaml --ignore-not-found || true
kubectl delete ns minio --ignore-not-found || true
echo "Kubernetes resources cleanup done."
- name: Delete KinD cluster
if: always()
run: |
echo "Deleting KinD cluster..."
kind delete cluster --name vertica-ci || true
echo "KinD cluster removed successfully"