Skip to content

Commit 5c43e61

Browse files
committed
UI visual regression testing to cover UI widgets visibility
1 parent 1235fc8 commit 5c43e61

15 files changed

+4257
-2
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: UI notebooks tests
2+
3+
on: [pull_request]
4+
5+
concurrency:
6+
group: ${{ github.head_ref }}-${{ github.workflow }}
7+
cancel-in-progress: true
8+
9+
env:
10+
CODEFLARE_OPERATOR_IMG: "quay.io/project-codeflare/codeflare-operator:dev"
11+
12+
jobs:
13+
verify-0_basic_ray:
14+
runs-on: ubuntu-20.04-4core
15+
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
with:
20+
submodules: recursive
21+
22+
- name: Checkout common repo code
23+
uses: actions/checkout@v4
24+
with:
25+
repository: "project-codeflare/codeflare-common"
26+
ref: "main"
27+
path: "common"
28+
29+
- name: Checkout CodeFlare operator repository
30+
uses: actions/checkout@v4
31+
with:
32+
repository: project-codeflare/codeflare-operator
33+
path: codeflare-operator
34+
35+
- name: Set Go
36+
uses: actions/setup-go@v5
37+
with:
38+
go-version-file: "./codeflare-operator/go.mod"
39+
cache-dependency-path: "./codeflare-operator/go.sum"
40+
41+
- name: Set up gotestfmt
42+
uses: gotesttools/gotestfmt-action@v2
43+
with:
44+
token: ${{ secrets.GITHUB_TOKEN }}
45+
46+
- name: Set up specific Python version
47+
uses: actions/setup-python@v5
48+
with:
49+
python-version: "3.9"
50+
cache: "pip" # caching pip dependencies
51+
52+
- name: Setup and start KinD cluster
53+
uses: ./common/github-actions/kind
54+
55+
- name: Deploy CodeFlare stack
56+
id: deploy
57+
run: |
58+
cd codeflare-operator
59+
echo Setting up CodeFlare stack
60+
make setup-e2e
61+
echo Deploying CodeFlare operator
62+
make deploy -e IMG="${CODEFLARE_OPERATOR_IMG}" -e ENV="e2e"
63+
kubectl wait --timeout=120s --for=condition=Available=true deployment -n openshift-operators codeflare-operator-manager
64+
cd ..
65+
66+
- name: Setup Guided notebooks execution
67+
run: |
68+
echo "Installing papermill and dependencies..."
69+
pip install poetry ipython ipykernel
70+
poetry config virtualenvs.create false
71+
echo "Installing SDK..."
72+
poetry install --with test,docs
73+
74+
- name: Install Yarn dependencies
75+
run: |
76+
poetry run yarn install
77+
poetry run yarn playwright install chromium
78+
working-directory: ui-tests
79+
80+
- name: Fix 3_widget_example.ipynb notebook for test
81+
run: |
82+
# Remove login/logout cells, as KinD doesn't support authentication using token
83+
jq -r 'del(.cells[] | select(.source[] | contains("Create authentication object for user permissions")))' 3_widget_example.ipynb > 3_widget_example.ipynb.tmp && mv 3_widget_example.ipynb.tmp 3_widget_example.ipynb
84+
jq -r 'del(.cells[] | select(.source[] | contains("auth.logout()")))' 3_widget_example.ipynb > 3_widget_example.ipynb.tmp && mv 3_widget_example.ipynb.tmp 3_widget_example.ipynb
85+
# Set explicit namespace as SDK need it (currently) to resolve local queues
86+
sed -i "s/head_memory_limits=2,/head_memory_limits=2, namespace='default',/" 3_widget_example.ipynb
87+
working-directory: demo-notebooks/guided-demos
88+
89+
- name: Run UI notebook tests
90+
run: |
91+
set -euo pipefail
92+
93+
poetry run yarn test
94+
working-directory: ui-tests
95+
96+
- name: Upload Playwright Test assets
97+
if: always()
98+
uses: actions/upload-artifact@v4
99+
with:
100+
name: ipywidgets-test-assets
101+
path: |
102+
ui-tests/test-results
103+
104+
- name: Upload Playwright Test report
105+
if: always()
106+
uses: actions/upload-artifact@v4
107+
with:
108+
name: ipywidgets-test-report
109+
path: |
110+
ui-tests/playwright-report

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ Pipfile.lock
88
build/
99
tls-cluster-namespace
1010
quicktest.yaml
11+
node_modules
12+
.DS_Store
13+
ui-tests/playwright-report
14+
ui-tests/test-results
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "8d4a42f6",
6+
"metadata": {},
7+
"source": [
8+
"In this notebook, we will go through the basics of using the SDK to:\n",
9+
" - Spin up a Ray cluster with our desired resources\n",
10+
" - View the status and specs of our Ray cluster\n",
11+
" - Take down the Ray cluster when finished"
12+
]
13+
},
14+
{
15+
"cell_type": "code",
16+
"execution_count": null,
17+
"id": "b55bc3ea-4ce3-49bf-bb1f-e209de8ca47a",
18+
"metadata": {},
19+
"outputs": [],
20+
"source": [
21+
"# Import pieces from codeflare-sdk\n",
22+
"from codeflare_sdk import Cluster, ClusterConfiguration, TokenAuthentication"
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": null,
28+
"id": "614daa0c",
29+
"metadata": {},
30+
"outputs": [],
31+
"source": [
32+
"# Create authentication object for user permissions\n",
33+
"# IF unused, SDK will automatically check for default kubeconfig, then in-cluster config\n",
34+
"# KubeConfigFileAuthentication can also be used to specify kubeconfig path manually\n",
35+
"auth = TokenAuthentication(\n",
36+
" token = \"XXXXX\",\n",
37+
" server = \"XXXXX\",\n",
38+
" skip_tls=False\n",
39+
")\n",
40+
"auth.login()"
41+
]
42+
},
43+
{
44+
"cell_type": "markdown",
45+
"id": "bc27f84c",
46+
"metadata": {},
47+
"source": [
48+
"Here, we want to define our cluster by specifying the resources we require for our batch workload. Below, we define our cluster object (which generates a corresponding RayCluster).\n",
49+
"\n",
50+
"NOTE: 'quay.io/modh/ray:2.35.0-py39-cu121' is the default image used by the CodeFlare SDK for creating a RayCluster resource. \n",
51+
"If you have your own Ray image which suits your purposes, specify it in image field to override the default image."
52+
]
53+
},
54+
{
55+
"cell_type": "code",
56+
"execution_count": null,
57+
"id": "0f4bc870-091f-4e11-9642-cba145710159",
58+
"metadata": {},
59+
"outputs": [],
60+
"source": [
61+
"# Create and configure our cluster object\n",
62+
"# The SDK will try to find the name of your default local queue based on the annotation \"kueue.x-k8s.io/default-queue\": \"true\" unless you specify the local queue manually below\n",
63+
"cluster = Cluster(ClusterConfiguration(\n",
64+
" name='raytest', \n",
65+
" head_cpu_requests='500m',\n",
66+
" head_cpu_limits='500m',\n",
67+
" head_memory_requests=2,\n",
68+
" head_memory_limits=2,\n",
69+
" head_extended_resource_requests={'nvidia.com/gpu':0}, # For GPU enabled workloads set the head_extended_resource_requests and worker_extended_resource_requests\n",
70+
" worker_extended_resource_requests={'nvidia.com/gpu':0},\n",
71+
" num_workers=2,\n",
72+
" worker_cpu_requests='250m',\n",
73+
" worker_cpu_limits=1,\n",
74+
" worker_memory_requests=2,\n",
75+
" worker_memory_limits=2,\n",
76+
" # image=\"\", # Optional Field \n",
77+
" write_to_file=False, # When enabled Ray Cluster yaml files are written to /HOME/.codeflare/resources \n",
78+
" # local_queue=\"local-queue-name\" # Specify the local queue manually\n",
79+
"))"
80+
]
81+
},
82+
{
83+
"cell_type": "code",
84+
"execution_count": null,
85+
"id": "2d8e6ce3",
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"cluster.status()"
90+
]
91+
}
92+
],
93+
"metadata": {
94+
"kernelspec": {
95+
"display_name": "Python 3 (ipykernel)",
96+
"language": "python",
97+
"name": "python3"
98+
},
99+
"language_info": {
100+
"codemirror_mode": {
101+
"name": "ipython",
102+
"version": 3
103+
},
104+
"file_extension": ".py",
105+
"mimetype": "text/x-python",
106+
"name": "python",
107+
"nbconvert_exporter": "python",
108+
"pygments_lexer": "ipython3",
109+
"version": "3.9.19"
110+
},
111+
"vscode": {
112+
"interpreter": {
113+
"hash": "f9f85f796d01129d0dd105a088854619f454435301f6ffec2fea96ecbd9be4ac"
114+
}
115+
}
116+
},
117+
"nbformat": 4,
118+
"nbformat_minor": 5
119+
}

0 commit comments

Comments
 (0)