Playwright Tests #1262
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Playwright Tests | |
on: | |
workflow_dispatch: | |
inputs: | |
kubewarden: | |
description: Kubewarden version | |
type: choice | |
default: 'rc' | |
required: true | |
options: | |
- source | |
- rc | |
- released | |
rancher: | |
description: Rancher version | |
type: choice | |
default: 'released' | |
options: | |
- 'released' # released versions | |
- '~ 2.7' | |
- '~ 2.8' | |
- '~ 2.9' | |
- 'rc' # rc versions | |
- '~ 2.7-0' | |
- '~ 2.8-0' | |
- '~ 2.9-0' | |
k3s: | |
description: Kubernetes version | |
type: choice | |
default: 'v1.30' | |
required: true | |
options: | |
- v1.25 | |
- v1.26 | |
- v1.27 | |
- v1.28 | |
- v1.29 | |
- v1.30 | |
mode: | |
description: Installation mode | |
type: choice | |
default: 'base' | |
required: true | |
options: | |
- base | |
- fleet | |
- upgrade | |
testbase: | |
description: Run base tests | |
type: boolean | |
default: true | |
testpolicies: | |
description: Run policy tests | |
type: boolean | |
default: false | |
pull_request: | |
branches: main | |
paths: | |
- pkg/kubewarden/** | |
- package.json | |
workflow_run: | |
workflows: ["Build and Release Extension Charts"] | |
types: | |
- completed | |
schedule: | |
- cron: "0 21 * * *" | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
cancel-in-progress: true | |
env: | |
# Github -> Secrets and variables -> Actions -> New repository variable | |
KUBEWARDEN: ${{ inputs.kubewarden || 'rc' }} | |
K3D_VERSION: # 'v5.6.3' - optionally pin version | |
K3S_VERSION: ${{ inputs.k3s || 'v1.30' }} | |
K3D_CLUSTER_NAME: ${{ github.repository_owner }}-${{ github.event.repository.name }}-runner | |
# First value after the && must be truthy. Otherwise, the value after the || will always be returned | |
TESTBASE: ${{ github.event_name != 'workflow_dispatch' && true || inputs.testbase }} | |
TESTPOLICIES: ${{ inputs.testpolicies || false }} | |
# Enable QASE integration only for original repo | |
QASE: ${{ github.repository_owner == 'rancher' && github.event_name != 'pull_request' }} | |
defaults: | |
run: | |
shell: bash | |
jobs: | |
e2e: | |
strategy: | |
fail-fast: false | |
matrix: | |
rancher: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_run') && fromJSON('["2.7", "2.8", "2.9"]') || fromJSON(format('["{0}"]', inputs.rancher || 'released')) }} | |
mode: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_run') && fromJSON('["base", "upgrade", "fleet"]') || fromJSON(format('["{0}"]', inputs.mode || 'base')) }} | |
exclude: | |
# Run full tests on 2.8 since it's latest prime version | |
- rancher: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_run') && '2.7' }} | |
mode: upgrade | |
- rancher: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_run') && '2.7' }} | |
mode: fleet | |
- rancher: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_run') && '2.8' }} | |
mode: upgrade | |
- rancher: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_run') && '2.8' }} | |
mode: fleet | |
# Run schedule workflows only on original repo, not forks | |
if: | | |
(github.event_name != 'schedule' || github.repository_owner == 'rancher') && | |
(github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success') | |
runs-on: self-hosted | |
steps: | |
# ================================================================================================== | |
# Check out code | |
# Use local kuberlr to avoid version skew | |
# Test from maintenance branch for Rancher < 2.9 | |
- name: Find checkout branch ref | |
id: set-ref | |
run: echo "ref=$( [[ "${{matrix.rancher}}" == 2.[78]* ]] && echo 'release-1.6' || echo '')" | tee -a $GITHUB_OUTPUT | |
- uses: actions/checkout@v4 | |
with: | |
ref: ${{ steps.set-ref.outputs.ref }} | |
# ================================================================================================== | |
# Set up parameters and ENV | |
- name: Setup global ENV | |
run: | | |
# Override KUBEWARDEN for automated triggers | |
case ${{github.event_name}} in | |
pull_request) | |
KUBEWARDEN=source;; | |
schedule) | |
# Initial Rancher 2.10 is not prime = UI is not available from official charts | |
[[ "${{ matrix.rancher }}" == *2.10* ]] && KUBEWARDEN=rc || KUBEWARDEN=released;; | |
workflow_run) | |
KUBEWARDEN=rc;; | |
esac | |
# Rancher 2.7 chart requires kubeVersion: < 1.28.0-0 | |
[[ "${{ matrix.rancher }}" == *2.7* ]] && K3S_VERSION="v1.27" | |
# Rancher 2.8 chart requires kubeVersion: < 1.29.0-0 | |
[[ "${{ matrix.rancher }}" == *2.8* ]] && K3S_VERSION="v1.28" | |
# KW extension is prime since 2.8.3 | |
[[ "${{ matrix.rancher }}" == *2.[789]* ]] && REPO=rancher-prime || REPO=rancher-latest | |
# Complete partial K3S version from dockerhub v1.30 -> v1.30.5-k3s1 | |
if [[ ! $K3S_VERSION =~ ^v[0-9.]+-k3s[0-9]$ ]]; then | |
K3S_VERSION=$(curl -L -s "https://registry.hub.docker.com/v2/repositories/rancher/k3s/tags?page_size=20&name=$K3S_VERSION" | jq -re 'first(.results[].name | select(test("^v[0-9.]+-k3s[0-9]$")))') | |
fi | |
# Print matrix | |
echo "Event: ${{github.event_name}}" | |
echo "Mode: ${{matrix.mode}}" | |
echo "Rancher: ${{matrix.rancher}}" | |
echo K3S_VERSION="$K3S_VERSION" | tee -a $GITHUB_ENV | |
echo REPO="$REPO" | tee -a $GITHUB_ENV | |
echo KUBEWARDEN="$KUBEWARDEN" | tee -a $GITHUB_ENV | |
echo TESTBASE=$TESTBASE | |
echo TESTPOLICIES="$TESTPOLICIES" | tee -a $GITHUB_ENV | |
# ================================================================================================== | |
# Create k3d cluster and install rancher | |
- name: "Create kubernetes cluster" | |
run: | | |
TAG=${{ env.K3D_VERSION }} sudo --preserve-env=TAG k3d-install | |
k3d cluster create ${{ env.K3D_CLUSTER_NAME }} --agents 1 --image rancher/k3s:${{ env.K3S_VERSION }} | |
- name: Install Rancher | |
run: | | |
RANCHER_FQDN=$(k3d cluster list ${{ env.K3D_CLUSTER_NAME }} -o json | jq -r '[.[].nodes[] | select(.role == "server").IP.IP] | first').nip.io | |
# Wait for kube-system | |
for i in {1..20}; do | |
output=$(kubectl get pods --no-headers -o wide -n kube-system | grep -vw Completed || echo 'Fail') | |
grep -vE '([0-9]+)/\1 +Running' <<< $output || break | |
[ $i -ne 20 ] && sleep 10 || { echo "Godot: pods not running"; exit 1; } | |
done | |
# Install cert-manager | |
helm repo add jetstack https://charts.jetstack.io --force-update | |
helm upgrade -i --wait cert-manager jetstack/cert-manager -n cert-manager --create-namespace --set crds.enabled=true | |
# Translate to sematic version | |
[ "$RANCHER" == "rc" ] && RANCHER='*-0' | |
[ "$RANCHER" == "released" ] && RANCHER='*' | |
helm repo add --force-update rancher-latest https://releases.rancher.com/server-charts/latest | |
helm repo add --force-update rancher-alpha https://releases.rancher.com/server-charts/alpha | |
helm repo add --force-update rancher-prime https://charts.rancher.com/server-charts/prime | |
helm search repo $REPO/rancher ${RANCHER:+--version "$RANCHER"} | |
helm upgrade --install rancher $REPO/rancher --wait \ | |
--namespace cattle-system --create-namespace \ | |
--set hostname=$RANCHER_FQDN \ | |
--set bootstrapPassword=sa \ | |
--set replicas=1 \ | |
${RANCHER:+--version "$RANCHER"} | |
# Wait for rancher | |
for i in {1..20}; do | |
output=$(kubectl get pods --no-headers -o wide -n cattle-system -l app=rancher-webhook | grep -vw Completed || echo 'Wait: cattle-system')$'\n' | |
output+=$(kubectl get pods --no-headers -o wide -n cattle-system | grep -vw Completed || echo 'Wait: cattle-system')$'\n' | |
output+=$(kubectl get pods --no-headers -o wide -n cattle-fleet-system | grep -vw Completed || echo 'Wait: cattle-fleet-system')$'\n' | |
grep -vE '([0-9]+)/\1 +Running|^$' <<< $output || break | |
[ $i -ne 20 ] && sleep 30 || { echo "Godot: pods not running"; exit 1; } | |
done | |
echo "RANCHER_FQDN=$RANCHER_FQDN" | tee -a $GITHUB_ENV | |
env: | |
RANCHER: ${{ matrix.rancher }} | |
# ================================================================================================== | |
# Setup playwright ENV and run tests | |
# https://rancher.github.io/dashboard/testing/e2e-test#setup-for-local-tests | |
- uses: actions/setup-node@v4 | |
if: env.KUBEWARDEN == 'source' | |
with: | |
node-version: '16' | |
- name: Build Kubewarden extension | |
if: env.KUBEWARDEN == 'source' | |
run: | | |
yarn install --ignore-engines | |
VERSION=0.0.1 yarn build-pkg kubewarden | |
- uses: actions/setup-node@v4 | |
with: | |
node-version: '18' | |
- name: Install playwright | |
working-directory: tests | |
run: | | |
yarn install | |
yarn playwright install chromium # --with-deps not supported on opensuse | |
- name: Execute tests | |
timeout-minutes: 120 | |
working-directory: tests | |
run: | | |
# Policy tests are hitting artifacthub rate limits | |
# Filter to exclude policies except those starting with random letter | |
EXCLUDE=$(yarn playwright test "\/90-" --reporter=list --list | grep -o 'install: .' | cut -d' ' -f2 | sort -fRu | sed 1d | paste -sd '') | |
EXCLUDE="90-.*install: [$EXCLUDE]" | |
TFILTER="\/00" # Always run installation tests | |
[[ "$TESTBASE" == "true" ]] && TFILTER+=" \/[1-9]" # Schedule everything else as base test | |
[[ "$TESTPOLICIES" != "true" ]] && GFILTER="$EXCLUDE" # Limit number of tested policies | |
# List tests and execute | |
echo yarn playwright test ${TFILTER:-} ${GFILTER:+-gv "$GFILTER"} -x | |
yarn playwright test ${TFILTER:-} ${GFILTER:+-gv "$GFILTER"} -x | tee qase-report.log | |
env: | |
MODE: ${{ matrix.mode }} | |
RANCHER_URL: https://${{ env.RANCHER_FQDN }} | |
ORIGIN: ${{ env.KUBEWARDEN }} | |
QASE_MODE: ${{ env.QASE == 'true' && 'testops' || 'off' }} | |
QASE_TESTOPS_API_TOKEN: ${{ secrets.QASE_APITOKEN }} | |
QASE_TESTOPS_RUN_TITLE: "Run[${{github.event_name}}]: UI[${{ env.KUBEWARDEN }}] - MODE[${{ matrix.mode }}] - RANCHER[${{ matrix.rancher }}] " | |
QASE_TESTOPS_RUN_DESCRIPTION: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
# ================================================================================================== | |
# QASE Integration | |
# Delete previous run if we have new one | |
- name: Delete previous QASE run | |
if: ${{ env.QASE == 'true' && !cancelled() && github.run_attempt > 1 }} | |
run: | | |
gh run download ${{ github.run_id }} -n QASE_RUN_ID-${{ matrix.rancher }}-${{ matrix.mode }} ||: | |
if [ -f QASE_RUN_ID.txt ]; then | |
qid=$(< QASE_RUN_ID.txt) | |
curl --request DELETE --url https://api.qase.io/v1/run/KUBEWARDEN/$qid --header 'Token: ${{secrets.QASE_APITOKEN_MKRAVEC}}' --header 'accept: application/json' | |
fi | |
env: | |
GH_TOKEN: ${{ github.token }} | |
# Delete current run if it was canceled | |
- name: Find current QASE run | |
if: ${{ env.QASE == 'true' && always() && hashFiles('tests/qase-report.log') != '' }} | |
run: | | |
grep -Eom1 'qase:.* [Rr]un.* [0-9]+' tests/qase-report.log | awk '{print $NF}' | tee QASE_RUN_ID.txt | |
- name: Delete current QASE run if job was canceled | |
if: ${{ env.QASE == 'true' && cancelled() && hashFiles('tests/qase-report.log') != '' }} | |
run: | | |
qid=$(< QASE_RUN_ID.txt) | |
curl --request DELETE --url https://api.qase.io/v1/run/KUBEWARDEN/$qid --header 'Token: ${{secrets.QASE_APITOKEN_MKRAVEC}}' --header 'accept: application/json' | |
# Set current run ID | |
- name: Upload current QASE_RUN_ID | |
if: ${{ env.QASE == 'true' && !cancelled() }} | |
uses: actions/upload-artifact@v4 | |
with: | |
name: QASE_RUN_ID-${{ matrix.rancher }}-${{ matrix.mode }} | |
path: QASE_RUN_ID.txt | |
overwrite: true | |
if-no-files-found: ignore | |
# ================================================================================================== | |
# Artifacts & Summary | |
- uses: actions/upload-artifact@v4 | |
if: always() | |
with: | |
name: playwright-report-${{ matrix.rancher }}-${{ matrix.mode }} | |
path: tests/playwright-report/ | |
retention-days: 15 | |
- name: Clean Up | |
if: always() | |
run: | | |
k3d cluster delete ${{ env.K3D_CLUSTER_NAME }} |