Skip to content

feat(test): ui e2e testing, w/ pr cluster #3078

feat(test): ui e2e testing, w/ pr cluster

feat(test): ui e2e testing, w/ pr cluster #3078

Workflow file for this run

name: PR Workflow
on:
pull_request:
types:
- opened
- synchronize
defaults:
run:
working-directory: go/src/github.com/stackrox/infra
concurrency: pr-${{ github.ref }}
env:
CLUSTER_NAME: infra-pr-${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}
jobs:
lint:
uses: ./.github/workflows/lint.yaml
unit-tests:
uses: ./.github/workflows/unit-tests.yaml
build-and-push:
uses: ./.github/workflows/build-and-push.yaml
secrets: inherit
create-dev-cluster:
runs-on: ubuntu-latest
steps:
- uses: stackrox/actions/infra/create-cluster@v1
with:
flavor: gke-default
name: infra-pr-${{ github.event.pull_request.number }}
args: machine-type=e2-standard-4,nodes=3,gcp-image-type=ubuntu_containerd
lifespan: ${{ github.actor == 'dependabot[bot]' && '1h' || '24h' }}
wait: true
token: ${{ secrets.INFRA_TOKEN }}
comment-on-PR:
needs:
- build-and-push
- create-dev-cluster
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.4.9
steps:
- name: Checkout
uses: actions/checkout@v6
with:
path: go/src/github.com/stackrox/infra
- name: Add PR comment for deploy to dev
env:
GITHUB_TOKEN: ${{ secrets.RHACS_BOT_GITHUB_TOKEN }}
run: |
./scripts/add-PR-comment-for-deploy-to-dev.sh "${{ github.event.pull_request.html_url }}" "$CLUSTER_NAME"
deploy-and-test:
needs:
- build-and-push
- create-dev-cluster
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.4.9
outputs:
session-secret: ${{ steps.deploy.outputs.session-secret }}
env:
KUBECONFIG: /github/home/artifacts/kubeconfig
INFRA_TOKEN: ${{ secrets.INFRA_TOKEN }}
INFRACTL: bin/infractl -k -e localhost:8443
USE_GKE_GCLOUD_AUTH_PLUGIN: "True"
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
path: go/src/github.com/stackrox/infra
- uses: actions/setup-go@v6
with:
go-version-file: go/src/github.com/stackrox/infra/go.mod
- name: Authenticate to GCloud
uses: google-github-actions/auth@v3
with:
credentials_json: ${{ secrets.INFRA_CI_AUTOMATION_GCP_SA }}
- name: Set up Cloud SDK
uses: "google-github-actions/setup-gcloud@v3"
with:
install_components: "gke-gcloud-auth-plugin"
- name: Download production infractl
uses: stackrox/actions/infra/install-infractl@v1
- name: Download artifacts
run: |
/github/home/.local/bin/infractl artifacts "$CLUSTER_NAME" -d /github/home/artifacts >> "$GITHUB_STEP_SUMMARY"
- name: Wait for cluster to be ready
run: |
echo "Waiting for cluster API server to be ready..."
timeout 300 sh -c 'until kubectl get nodes >/dev/null 2>&1; do
echo "Waiting for cluster..."
sleep 5
done'
echo "Cluster is ready"
kubectl get nodes -o wide
- name: Deploy infra to dev cluster
id: deploy
run: |
# Generate random session secret for JWT signing
# This secret is used by both the server (for verification) and Cypress (for JWT generation)
SESSION_SECRET=$(openssl rand -base64 32 | tr -d '\n')
export SESSION_SECRET
echo "Generated random session secret for this PR cluster deployment"
ENVIRONMENT=development TEST_MODE=true make helm-deploy
sleep 10 # wait for old pods to disappear so the svc port-forward doesn't connect to them
kubectl -n infra port-forward svc/infra-server-service 8443:8443 > /dev/null 2>&1 &
sleep 10
kubectl -n infra logs -l app=infra-server --tail=-1
make pull-infractl-from-dev-server
kill %1
# Save session secret for UI E2E tests (job output for next job)
echo "session-secret=$SESSION_SECRET" >> "$GITHUB_OUTPUT"
# Also set as env var for steps in this job
echo "SESSION_SECRET=$SESSION_SECRET" >> "$GITHUB_ENV"
- name: Check the deployment
run: |
kubectl -n infra port-forward svc/infra-server-service 8443:8443 > /dev/null 2>&1 &
sleep 10
version="$($INFRACTL version --json)"
echo "$version"
client="$(echo "$version" | jq -r '.Client.Version')"
server="$(echo "$version" | jq -r '.Server.Version')"
if [[ "$client" == "$server" ]]; then
echo "Client and server versions match"
else
echo "Client and server versions are mismatched"
exit 1
fi
tag="$(make tag)"
if [[ "$client" == "$tag" ]]; then
echo "Infra and make tag match"
else
echo "Infra and make tag are mismatched (make tag: $tag)"
exit 1
fi
kill %1
- name: Install Argo CLI
run: |
ARGO_VERSION=$(grep "github.com/argoproj/argo-workflows/v3" go.mod | awk '{ print $2 }')
curl -sLO "https://github.com/argoproj/argo-workflows/releases/download/${ARGO_VERSION}/argo-linux-amd64.gz"
gunzip argo-linux-amd64.gz
chmod +x argo-linux-amd64
mv ./argo-linux-amd64 /usr/local/bin/argo
argo version
- name: Lint Argo workflows
# We're linting here, because Argo Lint requires a workflow server
run: |
make argo-workflow-lint
go-e2e-test:
needs:
- deploy-and-test
runs-on: ubuntu-latest
container:
image: quay.io/stackrox-io/apollo-ci:stackrox-test-0.4.9
env:
KUBECONFIG: /github/home/artifacts/kubeconfig
INFRA_TOKEN: ${{ secrets.INFRA_TOKEN_DEV }}
INFRACTL: bin/infractl -k -e localhost:8443
USE_GKE_GCLOUD_AUTH_PLUGIN: "True"
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
path: go/src/github.com/stackrox/infra
- uses: actions/setup-go@v6
with:
go-version-file: go/src/github.com/stackrox/infra/go.mod
- name: Authenticate to GCloud
uses: google-github-actions/auth@v3
with:
credentials_json: ${{ secrets.INFRA_CI_AUTOMATION_GCP_SA }}
- name: Set up Cloud SDK
uses: "google-github-actions/setup-gcloud@v3"
with:
install_components: "gke-gcloud-auth-plugin"
- name: Download production infractl
uses: stackrox/actions/infra/install-infractl@v1
- name: Download artifacts
run: |
/github/home/.local/bin/infractl artifacts "$CLUSTER_NAME" -d /github/home/artifacts >> "$GITHUB_STEP_SUMMARY"
- name: Verify cluster connectivity
run: |
echo "Verifying cluster is accessible..."
kubectl get nodes -o wide
- name: Run Go e2e tests
run: |
kubectl -n infra port-forward svc/infra-server-service 8443:8443 > /dev/null 2>&1 &
sleep 5
make go-e2e-tests
ui-e2e-test-pr-cluster:
needs:
- deploy-and-test
runs-on: ubuntu-latest
# Note: This job does NOT use the apollo-ci container to avoid path issues
env:
KUBECONFIG: /tmp/kubeconfig
INFRA_TOKEN: ${{ secrets.INFRA_TOKEN }}
USE_GKE_GCLOUD_AUTH_PLUGIN: "True"
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
path: go/src/github.com/stackrox/infra
- name: Authenticate to GCloud
uses: google-github-actions/auth@v3
with:
credentials_json: ${{ secrets.INFRA_CI_AUTOMATION_GCP_SA }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v3
with:
install_components: "gke-gcloud-auth-plugin"
- name: Download production infractl
uses: stackrox/actions/infra/install-infractl@v1
- name: Get kubeconfig for PR cluster
run: |
echo "Downloading kubeconfig for $CLUSTER_NAME..."
/home/runner/.local/bin/infractl artifacts "$CLUSTER_NAME" -d /tmp/artifacts
cp /tmp/artifacts/kubeconfig "$KUBECONFIG"
echo "Verifying cluster access..."
kubectl get nodes -o wide
- name: Wait for infra-server deployment
run: |
echo "Checking infra-server pods..."
kubectl get pods -n infra
kubectl wait --for=condition=ready pod -l app=infra-server -n infra --timeout=5m
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install UI dependencies
run: |
cd ui
npm install --legacy-peer-deps
- name: Start port-forward to PR cluster
run: |
kubectl -n infra port-forward svc/infra-server-service 8443:8443 >/dev/null 2>&1 &
PORT_FORWARD_PID=$!
echo "PORT_FORWARD_PID=$PORT_FORWARD_PID" >> "$GITHUB_ENV"
echo "Started port-forward with PID: $PORT_FORWARD_PID"
sleep 10
# Verify port-forward is working
echo "Verifying port-forward connectivity..."
timeout 30 sh -c 'until curl -k -f https://localhost:8443/v1/whoami 2>/dev/null; do
echo "Waiting for port-forward..."
sleep 2
done' || {
echo "Port-forward verification failed"
pgrep -a port-forward || true
exit 1
}
echo "Port-forward is working"
- name: Debug - Check flavors API
run: |
echo "Checking if flavors are available..."
# First try without auth (should fail with access denied)
echo "1. Testing without authentication:"
UNAUTH_RESPONSE=$(curl -k -s https://localhost:8443/v1/flavor/list || echo "API call failed")
echo "$UNAUTH_RESPONSE" | jq . || echo "$UNAUTH_RESPONSE"
# Check whoami endpoint
echo ""
echo "2. Testing /v1/whoami:"
WHOAMI=$(curl -k -s https://localhost:8443/v1/whoami || echo "whoami failed")
echo "$WHOAMI" | jq . || echo "$WHOAMI"
# The real issue is the UI itself - let's check if the flavors endpoint
# works at all. The UI must be getting an error from somewhere.
echo ""
echo "3. Checking flavors API (unauthenticated count):"
FLAVOR_COUNT=$(echo "$UNAUTH_RESPONSE" | jq '.flavors | length' 2>/dev/null || echo "0")
echo "Number of flavors available: $FLAVOR_COUNT"
if [ "$FLAVOR_COUNT" = "0" ]; then
echo "NOTE: Flavors API requires authentication"
echo "This is expected - Cypress tests use JWT authentication with randomly generated secret"
fi
- name: Run UI E2E tests
uses: cypress-io/github-action@v6
with:
working-directory: go/src/github.com/stackrox/infra/ui
install: false
start: npm run start
wait-on: 'http://localhost:3001'
wait-on-timeout: 60
command: npm run cypress:run:e2e
env:
BROWSER: none
PORT: 3001
# Backend is the PR cluster deployment accessed via port-forward
# This deployment uses ENVIRONMENT=development with real OIDC (NOT localDeploy=true)
INFRA_API_ENDPOINT: https://localhost:8443
# Session secret for JWT generation (matches what the server uses)
# Retrieved from deploy-and-test job output
CYPRESS_SESSION_SECRET: ${{ needs.deploy-and-test.outputs.session-secret }}
- name: Upload test artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: cypress-artifacts-pr-cluster-${{ github.event.pull_request.number }}
path: |
go/src/github.com/stackrox/infra/ui/cypress/videos
go/src/github.com/stackrox/infra/ui/cypress/screenshots
retention-days: 7
- name: Cleanup port-forward
if: always()
run: |
if [ -n "${{ env.PORT_FORWARD_PID }}" ]; then
echo "Cleaning up port-forward (PID: ${{ env.PORT_FORWARD_PID }})..."
kill ${{ env.PORT_FORWARD_PID }} 2>/dev/null || true
fi
pkill -f "kubectl port-forward.*8443:8443" 2>/dev/null || true