Skip to content

Commit

Permalink
Merge pull request #1460 from finos/jupyter-tests
Browse files Browse the repository at this point in the history
Add Jupyterlab tests to CI
  • Loading branch information
texodus authored Jun 29, 2021
2 parents 54e987c + 54cb839 commit 7fa3d92
Show file tree
Hide file tree
Showing 21 changed files with 783 additions and 34 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,14 @@ rust/perspective-vieux/pkg
rust/perspective-vieux/target
rust/perspective-vieux/target2
.emsdk

docs/static/css/material.dark.css
docs/i18n/en.json
docs/static/js

rust/perspective-vieux/target.vscode
target.vscode

# jupyterlab test artifacts
packages/perspective-jupyterlab/test/config/jupyter/lab
packages/perspective-jupyterlab/test/config/jupyter/migrated
171 changes: 156 additions & 15 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ parameters:
architecture: 'x64'
displayName: 'Use Python $(python.version)'

- bash: python -m pip install --upgrade pip wheel setuptools jupyterlab numpy "pyarrow>=2" "black==20.8b1" flake8-black
- bash: python -m pip install --upgrade pip wheel setuptools "jupyterlab>=3.0.14" numpy "pyarrow>=2" "black==20.8b1" flake8-black
displayName: 'Install Python base dependencies'
condition: and(succeeded(), ne(variables['python.version'], '2.7'))

Expand Down Expand Up @@ -95,12 +95,6 @@ parameters:
env:
PSP_DOCKER: 1

- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testRunner: JUnit
testResultsFiles: 'junit.xml'

- name: pythonBuildSteps
type: stepList
default:
Expand Down Expand Up @@ -154,19 +148,19 @@ parameters:
default:
# Build a python wheel for Manylinux
- bash: yarn _wheel_python --ci $(python_flag) $(manylinux_flag)
condition: and(succeeded(), ne(variables['manylinux_flag'], ''), or(startsWith(variables['build.sourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Schedule')))
condition: and(succeeded(), ne(variables['manylinux_flag'], ''))
displayName: 'Build Manylinux Wheel'
env:
PSP_DOCKER: 1

# Test the wheel
- bash: cd $(System.DefaultWorkingDirectory)/python/perspective/scripts && ./test_wheels.sh $(python_flag) $(manylinux_flag)
condition: and(succeeded(), ne(variables['manylinux_flag'], ''), or(startsWith(variables['build.sourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Schedule')))
condition: and(succeeded(), ne(variables['manylinux_flag'], ''))
displayName: 'Test Manylinux Wheel'

# Save the artifact to Azure storage
- task: PublishPipelineArtifact@1
condition: and(succeeded(), ne(variables['manylinux_flag'], ''), or(startsWith(variables['build.sourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Schedule')))
condition: and(succeeded(), ne(variables['manylinux_flag'], ''))
inputs:
targetPath: '$(System.DefaultWorkingDirectory)/python/perspective/wheelhouse/'
artifactName: '$(artifact_name)'
Expand Down Expand Up @@ -232,6 +226,51 @@ jobs:
targetPath: '$(System.DefaultWorkingDirectory)/packages/perspective-workspace/screenshots/'
artifactName: "perspective-workspace-$(Build.BuildNumber)"

# `yarn pack` the public packages so the Jupyterlab tests can use the
# already-built `dist` folder for perspective, perspective-viewer,
# perspective-viewer-datagrid and perspective-viewer-d3fc.

- bash: cd $(System.DefaultWorkingDirectory)/packages/perspective && yarn pack --filename=perspective-dist.tgz
displayName: "yarn pack perspective"

- bash: cd $(System.DefaultWorkingDirectory)/packages/perspective-viewer && yarn pack --filename=perspective-viewer-dist.tgz
displayName: "yarn pack perspective-viewer"

- bash: cd $(System.DefaultWorkingDirectory)/packages/perspective-viewer-datagrid && yarn pack --filename=perspective-viewer-datagrid-dist.tgz
displayName: "yarn pack perspective-viewer-datagrid"

- bash: cd $(System.DefaultWorkingDirectory)/packages/perspective-viewer-d3fc && yarn pack --filename=perspective-viewer-d3fc-dist.tgz
displayName: "yarn pack perspective-viewer-d3fc"

- bash: cd $(System.DefaultWorkingDirectory)/packages/perspective-jupyterlab && yarn pack --filename=perspective-jupyterlab-dist.tgz
displayName: "yarn pack perspective-jupyterlab"

# Upload the packed versions
- task: PublishPipelineArtifact@1
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/packages/perspective/perspective-dist.tgz"
artifactName: "perspective-dist"

- task: PublishPipelineArtifact@1
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/packages/perspective-viewer/perspective-viewer-dist.tgz"
artifactName: "perspective-viewer-dist"

- task: PublishPipelineArtifact@1
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/packages/perspective-viewer-datagrid/perspective-viewer-datagrid-dist.tgz"
artifactName: "perspective-viewer-datagrid-dist"

- task: PublishPipelineArtifact@1
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/packages/perspective-viewer-d3fc/perspective-viewer-d3fc-dist.tgz"
artifactName: "perspective-viewer-d3fc-dist"

- task: PublishPipelineArtifact@1
inputs:
targetPath: "$(System.DefaultWorkingDirectory)/packages/perspective-jupyterlab/perspective-jupyterlab-dist.tgz"
artifactName: "perspective-jupyterlab-dist"


- job: 'Linux'
pool:
Expand Down Expand Up @@ -294,7 +333,6 @@ jobs:
- ${{ parameters.pythonCoverageSteps }}
- ${{ parameters.pythonLinuxWheelSteps }}


- job: 'Windows'
pool:
vmImage: 'vs2017-win2016'
Expand All @@ -307,10 +345,6 @@ jobs:
artifact_name: 'cp37-cp37m-win64_amd'

${{ if or(startsWith(variables['build.sourceBranch'], 'refs/tags/v'), eq(variables['Build.Reason'], 'Schedule')) }}:
# Python36:
# python.version: '3.6'
# python_flag: '--python36'
# artifact_name: 'cp36-cp36m-win64_amd'
Python38:
python.version: '3.8'
python_flag: '--python38'
Expand Down Expand Up @@ -361,3 +395,110 @@ jobs:
- ${{ parameters.pythonBuildSteps }}
- ${{ parameters.pythonCoverageSteps }}
- ${{ parameters.pythonMacWheelSteps }}


- job: "Jupyterlab"
dependsOn: ["WebAssembly", "Linux"]
pool:
vmImage: "ubuntu-latest"
variables:
python.version: "3.7"
python_flag: ""
manylinux_flag: "--manylinux2010"
artifact_name: "cp37-cp37m-manylinux2010_x86_64"

steps:
# don't use InitSteps because we don't want to cache local puppeteer
- task: NodeTool@0
inputs:
versionSpec: '12.x'

- bash: npm install -g yarn
displayName: 'Install Yarn'

- bash: yarn --frozen-lockfile
displayName: "Install Deps"

- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
architecture: 'x64'
displayName: 'Use Python $(python.version)'

- bash: python -m pip install --upgrade pip wheel setuptools jupyterlab numpy "pyarrow>=2" "black==20.8b1" flake8-black
displayName: 'Install Python base dependencies'
condition: and(succeeded(), ne(variables['python.version'], '2.7'))

- bash: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
displayName: "Install wasm-pack"

- task: DownloadPipelineArtifact@2
displayName: "Download Python 3.7 Perspective Wheel"
inputs:
artifact: $(artifact_name)
path: $(System.DefaultWorkingDirectory)/wheel

- bash: python -m pip install $(System.DefaultWorkingDirectory)/wheel/*.whl
displayName: "Install perspective-python from wheel"

- bash: jupyter labextension install @jupyter-widgets/jupyterlab-manager
displayName: "Install Labextensions"

- bash: yarn add -W --dev puppeteer@9.0.0
displayName: "Install Puppeteer"

- task: DownloadPipelineArtifact@2
displayName: "Download perspective dist"
inputs:
artifact: "perspective-dist"
path: $(System.DefaultWorkingDirectory)

- task: DownloadPipelineArtifact@2
displayName: "Download perspective-viewer dist"
inputs:
artifact: "perspective-viewer-dist"
path: $(System.DefaultWorkingDirectory)

- task: DownloadPipelineArtifact@2
displayName: "Download perspective-viewer-datagrid dist"
inputs:
artifact: "perspective-viewer-datagrid-dist"
path: $(System.DefaultWorkingDirectory)

- task: DownloadPipelineArtifact@2
displayName: "Download perspective-viewer-d3fc dist"
inputs:
artifact: "perspective-viewer-d3fc-dist"
path: $(System.DefaultWorkingDirectory)

- task: DownloadPipelineArtifact@2
displayName: "Download perspective-jupyterlab dist"
inputs:
artifact: "perspective-jupyterlab-dist"
path: $(System.DefaultWorkingDirectory)

- bash: tar --strip-components=1 -xvf $(System.DefaultWorkingDirectory)/perspective-dist.tgz -C $(System.DefaultWorkingDirectory)/packages/perspective package
displayName: "Install perspective dist"

- bash: tar --strip-components=1 -xvf $(System.DefaultWorkingDirectory)/perspective-viewer-dist.tgz -C $(System.DefaultWorkingDirectory)/packages/perspective-viewer package
displayName: "Install perspective-viewer dist"

- bash: tar --strip-components=1 -xvf $(System.DefaultWorkingDirectory)/perspective-viewer-datagrid-dist.tgz -C $(System.DefaultWorkingDirectory)/packages/perspective-viewer-datagrid package
displayName: "Install perspective-viewer-datagrid dist"

- bash: tar --strip-components=1 -xvf $(System.DefaultWorkingDirectory)/perspective-viewer-d3fc-dist.tgz -C $(System.DefaultWorkingDirectory)/packages/perspective-viewer-d3fc package
displayName: "Install perspective-viewer-d3fc dist"

- bash: tar --strip-components=1 -xvf $(System.DefaultWorkingDirectory)/perspective-jupyterlab-dist.tgz -C $(System.DefaultWorkingDirectory)/packages/perspective-jupyterlab package
displayName: "Install perspective-jupyterlab dist"

- bash: jupyter labextension install $(System.DefaultWorkingDirectory)/packages/perspective-jupyterlab
displayName: "Install perspective-jupyterlab labextension"

- bash: yarn jlab_link
displayName: "Link local Perspective to Jupyterlab"

- bash: yarn test_js --jupyter --debug
displayName: "Run Jupyterlab tests"
env:
PACKAGE: perspective-jupyterlab
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
"setup": "node scripts/setup.js",
"docs": "node scripts/docs.js",
"test": "node scripts/test.js",
"test:jupyter": "yarn workspace @finos/perspective-jupyterlab test:jupyter",
"test_js": "node scripts/test_js.js",
"test_python": "node scripts/test_python.js",
"clean": "node scripts/clean.js",
Expand Down
3 changes: 3 additions & 0 deletions packages/perspective-jupyterlab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
"clean:screenshots": "rimraf \"screenshots/**/*.@(failed|diff).png\"",
"test:build": "cpx \"test/html/*\" dist/umd && cpx \"test/csv/*\" dist/umd && cpx \"test/css/*\" dist/umd && webpack --color --config src/config/webpack.config.js",
"test:run": "jest --rootDir=. --config=test/config/jest.config.js --color --verbose",
"test:jupyter:build": "cpx \"test/html/*\" dist/umd && cpx \"test/arrow/*\" dist/umd && cpx \"test/css/*\" dist/umd",
"test:jupyter:run": "__JUPYTERLAB_PORT__=6538 jest --rootDir=. --config=test/config/jupyter/jest.config.js --color --verbose",
"test": "npm-run-all test:build test:run",
"test:jupyter": "npm-run-all test:jupyter:build test:jupyter:run",
"build": "webpack --color --config src/config/plugin.config.js",
"clean": "rimraf dist",
"version": "yarn build"
Expand Down
Binary file not shown.
24 changes: 24 additions & 0 deletions packages/perspective-jupyterlab/test/config/jupyter/globalSetup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/******************************************************************************
*
* Copyright (c) 2019, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
const {start_jlab, kill_jlab} = require("./jlab_start");

module.exports = async function() {
await start_jlab();

// At this point, Jupyterlab has already been started by the main test
// runner, so all we need to do is set up the signal listeners to
// clean up the Jupyter process if we Ctrl-C.
process.on("SIGINT", kill_jlab);
process.on("SIGABRT", kill_jlab);

// execute the standard globalSetup.js which will set up the
// Puppeteer browser instance.
const setup = require(`@finos/perspective-test/src/js/globalSetup.js`);
await setup();
};
16 changes: 16 additions & 0 deletions packages/perspective-jupyterlab/test/config/jupyter/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/******************************************************************************
*
* Copyright (c) 2019, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
const main_config = require("@finos/perspective-test/jest.config.js");

module.exports = Object.assign(main_config, {
globalSetup: "<rootDir>/test/config/jupyter/globalSetup.js",
setupFilesAfterEnv: ["<rootDir>/test/config/jupyter/teardown.js"],
testMatch: ["<rootDir>/test/jupyter/*.spec.js"],
roots: ["test"]
});
87 changes: 87 additions & 0 deletions packages/perspective-jupyterlab/test/config/jupyter/jlab_start.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/******************************************************************************
*
* Copyright (c) 2019, the Perspective Authors.
*
* This file is part of the Perspective library, distributed under the terms of
* the Apache License 2.0. The full license can be found in the LICENSE file.
*
*/
const path = require("path");
const {get} = require("http");
const {spawn} = require("child_process");
const {execute} = require("../../../../../scripts/script_utils");

const PACKAGE_ROOT = path.join(__dirname, "..", "..", "..");

/**
* Kill the Jupyterlab process created by the tests.
*/
const kill_jlab = () => {
console.log("-- Cleaning up Jupyterlab process");
execute`ps aux | grep -i '[j]upyter-lab --no-browser' | awk '{print $2}' | xargs kill -9 && echo "[perspective-jupyterlab] JupyterLab process terminated"`;
};

exports.kill_jlab = kill_jlab;

/**
* Block until the Jupyterlab server is ready.
*/
const wait_for_jlab = async function() {
let num_errors = 0;
let loaded = false;

while (!loaded) {
get(`http://127.0.0.1:${process.env.__JUPYTERLAB_PORT__}/lab?`, res => {
if (res.statusCode !== 200) {
throw new Error(`${res.statusCode} not 200!`);
}

console.log(`Jupyterlab server has started on ${process.env.__JUPYTERLAB_PORT__}`);
loaded = true;
}).on("error", err => {
if (num_errors > 50) {
kill_jlab();
throw new Error(`Could not launch Jupyterlab: ${err}`);
}

num_errors++;
});

await new Promise(resolve => setTimeout(resolve, 500));
}
};

exports.start_jlab = function() {
/*
* Spawn the Jupyterlab server.
*/
try {
// Does not alter the global env, only the env for this process
process.env.JUPYTER_CONFIG_DIR = path.join(PACKAGE_ROOT, "test", "config", "jupyter");
process.env.JUPYTERLAB_SETTINGS_DIR = path.join(PACKAGE_ROOT, "test", "config", "jupyter", "user_settings");

// Start jupyterlab with a root to dist/umd where the notebooks will be.
process.chdir(path.join(PACKAGE_ROOT, "dist", "umd"));

console.log("Spawning Jupyterlab process");

// Jupyterlab is spawned with the default $PYTHONPATH of the shell it
// is running in. For local testing during devlopment you may need to
// run it with the $PYTHONPATH set to ./python/perspective
const proc = spawn("jupyter", ["lab", "--no-browser", `--port=${process.env.__JUPYTERLAB_PORT__}`, `--config=${process.env.JUPYTER_CONFIG_DIR}/jupyter_notebook_config.json`], {
env: {
...process.env
},
stdio: "inherit"
});

// Wait for Jupyterlab to start up
return wait_for_jlab().then(() => {
return proc;
});
} catch (e) {
console.error(e);
kill_jlab();
process.exit(1);
}
};
Loading

0 comments on commit 7fa3d92

Please sign in to comment.