1+ name : ' Build Extension'
2+ description : ' Build and test a JupyterLab extension'
3+ inputs :
4+ example :
5+ description : ' The example to build'
6+ required : true
7+ run-ui-tests :
8+ description : ' Whether to run UI tests'
9+ required : false
10+ default : ' false'
11+
12+ runs :
13+ using : ' composite'
14+ steps :
15+ - name : Path filter
16+ id : filter
17+ uses : dorny/paths-filter@v2
18+ with :
19+ filters : |
20+ extension:
21+ - '${{ inputs.example }}/**'
22+ - name : Cache lerna
23+ if : steps.filter.outputs.extension == 'true'
24+ uses : actions/cache@v4
25+ with :
26+ path : ' **/node_modules'
27+ key : ${{ runner.os }}-lerna-${{ hashFiles('**/package.json') }}
28+ restore-keys : ${{ runner.os }}-lerna-
29+ - name : Check config files
30+ if : steps.filter.outputs.extension == 'true'
31+ run : |
32+ diff ../hello-world/setup.py setup.py
33+ diff ../hello-world/tsconfig.json tsconfig.json
34+ diff ../hello-world/.yarnrc.yml .yarnrc.yml
35+ diff ../hello-world/ui-tests/jupyter_server_test_config.py ./ui-tests/jupyter_server_test_config.py
36+ diff ../hello-world/ui-tests/playwright.config.js ./ui-tests/playwright.config.js
37+ shell : bash
38+ working-directory : ${{ inputs.example }}
39+ - name : Install node
40+ if : steps.filter.outputs.extension == 'true'
41+ uses : actions/setup-node@v4
42+ with :
43+ node-version : ' 18.x'
44+ - name : Install Python
45+ if : steps.filter.outputs.extension == 'true'
46+ uses : actions/setup-python@v5
47+ with :
48+ python-version : ' 3.11'
49+ architecture : ' x64'
50+ - name : Get pip cache dir
51+ if : steps.filter.outputs.extension == 'true'
52+ id : pip-cache
53+ run : |
54+ echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT
55+ shell : bash
56+ - name : Cache pip
57+ if : steps.filter.outputs.extension == 'true'
58+ uses : actions/cache@v4
59+ with :
60+ path : ${{ steps.pip-cache.outputs.dir }}
61+ key : ${{ runner.os }}-pip-${{ hashFiles('environment.yml') }}
62+ restore-keys : |
63+ ${{ runner.os }}-pip-
64+ - name : Install the Python dependencies
65+ if : steps.filter.outputs.extension == 'true'
66+ run : |
67+ python -m pip install --upgrade pip "jupyterlab>=4.0.0"
68+ shell : bash
69+ # This is challenging to test in collaboration;
70+ # got trouble with the file ID service and the uncontrolled auto-save
71+ # - if: steps.filter.outputs.extension == 'true' && inputs.example == 'clap-button-message'
72+ # run: |
73+ # python -m pip install jupyter-collaboration
74+ - name : Build the extension
75+ if : steps.filter.outputs.extension == 'true'
76+ run : |
77+ # Same commands as in TL;DR to ensure it works
78+ touch yarn.lock
79+ pip install -e . -v
80+ jupyter labextension develop . --overwrite
81+ shell : bash
82+ working-directory : ${{ inputs.example }}
83+ - name : Lint the files
84+ if : steps.filter.outputs.extension == 'true'
85+ run : jlpm run lint:check
86+ shell : bash
87+ working-directory : ${{ inputs.example }}
88+ - name : Check extension installation
89+ if : steps.filter.outputs.extension == 'true'
90+ run : |
91+ jupyter labextension list 2>&1 | tee labextension.list
92+ cat labextension.list | grep -ie "@jupyterlab-examples/*.*OK"
93+ shell : bash
94+ working-directory : ${{ inputs.example }}
95+ # clap-button-message example will have one plugin failing as it is requiring a
96+ # Jupyter Notebook specific token. This is expected. Hence we need to skip this
97+ # test for that example
98+ - name : Browser check
99+ if : steps.filter.outputs.extension == 'true' && inputs.example != 'clap-button-message'
100+ run : |
101+ python -m jupyterlab.browser_check
102+ shell : bash
103+
104+ - name : Install galata
105+ if : steps.filter.outputs.extension == 'true' && inputs.run-ui-tests == 'true'
106+ working-directory : ${{ inputs.example }}/ui-tests
107+ env :
108+ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD : 1
109+ run : jlpm install
110+ shell : bash
111+ - name : Set up browser cache
112+ if : steps.filter.outputs.extension == 'true' && inputs.run-ui-tests == 'true'
113+ uses : actions/cache@v4
114+ with :
115+ path : |
116+ ${{ github.workspace }}/pw-browsers
117+ key : ${{ runner.os }}-${{ hashFiles('yarn.lock') }}
118+ - name : Install browser
119+ if : steps.filter.outputs.extension == 'true' && inputs.run-ui-tests == 'true'
120+ run : jlpm playwright install chromium
121+ working-directory : ${{ inputs.example }}/ui-tests
122+ shell : bash
123+ - name : Install kernel-output dependencies
124+ if : steps.filter.outputs.extension == 'true' && inputs.example == 'kernel-output'
125+ run : pip install numpy pandas
126+ shell : bash
127+ - name : Integration tests
128+ if : steps.filter.outputs.extension == 'true' && inputs.run-ui-tests == 'true'
129+ working-directory : ${{ inputs.example }}/ui-tests
130+ run : jlpm playwright test
131+ shell : bash
132+ - name : Upload UI Test artifacts
133+ if : steps.filter.outputs.extension == 'true' && inputs.run-ui-tests == 'true' && always()
134+ uses : actions/upload-artifact@v4
135+ with :
136+ name : ${{ inputs.example }}-ui-test-output
137+ path : |
138+ ${{ inputs.example }}/ui-tests/test-results
139+ - name : Uninstall extension
140+ if : steps.filter.outputs.extension == 'true' && (runner.os == 'Linux' || runner.os == 'macOS')
141+ run : |
142+ export NAME=`python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['name'])"`
143+ pip uninstall -y ${NAME}
144+ shell : bash
145+ working-directory : ${{ inputs.example }}
0 commit comments