From 573d6b3bf95d6389a483f80474fbd586350bed78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20P=C3=BDrek?= Date: Thu, 30 Oct 2025 13:12:13 +0100 Subject: [PATCH 1/6] feat: add integration tests to CI --- .editorconfig | 4 ++++ .github/workflows/ci.yml | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/.editorconfig b/.editorconfig index 4f92a467d0..37bd57d7d6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,3 +15,7 @@ insert_final_newline = true [{.travis.yml,npm-shrinkwrap.json,package.json}] indent_style = space indent_size = 4 + +[.github/{workflows,actions}/*.yml] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f47be9fa91..9a230d495c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,6 +190,44 @@ jobs: - name: Run spell check run: npm run spell-check + integration-tests: + name: Integration Tests + runs-on: ubuntu-latest + timeout-minutes: 20 + permissions: + id-token: write + contents: read + packages: read + steps: + - name: Checkout + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + + - name: Setup Node.js + uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + with: + cache: 'npm' + node-version: ${{ env.NODE_VERSION }} + registry-url: 'https://npm.pkg.github.com' + scope: '@deepnote' + + - name: Setup Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: '3.12' + + - name: Install dependencies + run: npm ci --prefer-offline --no-audit + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Compile TypeScript + run: npm run compile + + - name: Run integration tests + run: xvfb-run -a -s "-screen 0 1024x768x24" npm run test:integration + # env: + # VSC_JUPYTER_CI_TEST_GREP: 'Deepnote Integration Tests' + audit-prod: name: Audit - Production runs-on: ubuntu-latest From 50a4122432603acd20b878b3941cc69bcc828b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20P=C3=BDrek?= Date: Thu, 30 Oct 2025 16:04:05 +0100 Subject: [PATCH 2/6] feat: make necessary changes to make E2E tests running --- src/notebooks/deepnote/deepnoteExplorerView.ts | 5 ++++- src/test/constants.node.ts | 2 +- src/test/constants.ts | 2 +- src/test/datascience/setupTestEnvs.sh | 6 +++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/notebooks/deepnote/deepnoteExplorerView.ts b/src/notebooks/deepnote/deepnoteExplorerView.ts index 07809e0876..e8f180e3fa 100644 --- a/src/notebooks/deepnote/deepnoteExplorerView.ts +++ b/src/notebooks/deepnote/deepnoteExplorerView.ts @@ -1,7 +1,8 @@ import { injectable, inject } from 'inversify'; import { commands, window, workspace, type TreeView, Uri, l10n } from 'vscode'; import * as yaml from 'js-yaml'; -import { convertIpynbFilesToDeepnoteFile } from '@deepnote/convert'; +// NOTE: Use dynamic import for '@deepnote/convert' to avoid activation failures in test hosts +// where the package may not be resolvable. We only import it when needed. import { IExtensionContext } from '../../platform/common/types'; import { IDeepnoteNotebookManager } from '../types'; @@ -357,6 +358,7 @@ export class DeepnoteExplorerView { const outputFileName = `${projectName}.deepnote`; const outputPath = Uri.joinPath(workspaceFolder.uri, outputFileName).path; + const { convertIpynbFilesToDeepnoteFile } = await import('@deepnote/convert'); await convertIpynbFilesToDeepnoteFile(inputFilePaths, { outputPath: outputPath, projectName: projectName @@ -429,6 +431,7 @@ export class DeepnoteExplorerView { // File doesn't exist, continue } + const { convertIpynbFilesToDeepnoteFile } = await import('@deepnote/convert'); await convertIpynbFilesToDeepnoteFile(inputFilePaths, { outputPath: outputUri.path, projectName: projectName diff --git a/src/test/constants.node.ts b/src/test/constants.node.ts index 7ef5609002..d080bb4710 100644 --- a/src/test/constants.node.ts +++ b/src/test/constants.node.ts @@ -16,7 +16,7 @@ export const EXTENSION_TEST_DIR_FOR_FILES = path.join( 'datascience', 'temp' ); -export const JVSC_EXTENSION_ID_FOR_TESTS = 'ms-toolsai.jupyter'; +export const JVSC_EXTENSION_ID_FOR_TESTS = 'Deepnote.vscode-deepnote'; export const SMOKE_TEST_EXTENSIONS_DIR = path.join( EXTENSION_ROOT_DIR_FOR_TESTS, diff --git a/src/test/constants.ts b/src/test/constants.ts index 82c2a0b38d..36000a5f9f 100644 --- a/src/test/constants.ts +++ b/src/test/constants.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -export const JVSC_EXTENSION_ID_FOR_TESTS = 'ms-toolsai.jupyter'; +export const JVSC_EXTENSION_ID_FOR_TESTS = 'Deepnote.vscode-deepnote'; export const PerformanceExtensionId = 'ms-toolsai.vscode-notebook-perf'; export type TestSettingsType = { diff --git a/src/test/datascience/setupTestEnvs.sh b/src/test/datascience/setupTestEnvs.sh index 67cc0bfb30..f15867bb37 100644 --- a/src/test/datascience/setupTestEnvs.sh +++ b/src/test/datascience/setupTestEnvs.sh @@ -7,7 +7,7 @@ python --version python -c "import sys;print(sys.executable)" uv pip install ipykernel python -m ipykernel install --user --name .venvkernel --display-name .venvkernel -uv pip uninstall jedi --yes +uv pip uninstall jedi uv pip install jedi==0.17.2 uv pip install ipywidgets==7.7.2 @@ -16,6 +16,6 @@ python --version python -c "import sys;print(sys.executable)" uv pip install ipykernel python -m ipykernel install --user --name .venvnokernel --display-name .venvnokernel -uv pip uninstall jedi --yes +uv pip uninstall jedi uv pip install jedi==0.17.2 -uv pip uninstall ipykernel --yes +uv pip uninstall ipykernel From 0602dab3431e8607695c9aaff1ffb045d41bfb88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20P=C3=BDrek?= Date: Thu, 30 Oct 2025 17:22:43 +0100 Subject: [PATCH 3/6] ci: improve integration tests --- .github/workflows/ci.yml | 76 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a230d495c..0bf807635d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,11 +193,17 @@ jobs: integration-tests: name: Integration Tests runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 30 permissions: id-token: write contents: read packages: read + env: + VSC_JUPYTER_FORCE_LOGGING: 'true' + VSC_PYTHON_FORCE_LOGGING: 'true' + VSC_JUPYTER_CI_TEST_VSC_CHANNEL: 'insiders' + DISABLE_INSIDERS_EXTENSION: 1 + PYTHON_VERSION: '3.12' steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 @@ -206,27 +212,83 @@ jobs: uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 with: cache: 'npm' - node-version: ${{ env.NODE_VERSION }} + node-version-file: '.nvmrc' registry-url: 'https://npm.pkg.github.com' scope: '@deepnote' - - name: Setup Python + - name: Setup Python ${{ env.PYTHON_VERSION }} uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + id: setupPythonVersion + with: + python-version: ${{ env.PYTHON_VERSION }} + + - name: Set CI Python Path + run: echo "CI_PYTHON_PATH=${{ steps.setupPythonVersion.outputs.python-path }}" >> $GITHUB_ENV + + # Cache pip dependencies + - name: Cache pip dependencies + uses: actions/cache@v4 with: - python-version: '3.12' + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ env.PYTHON_VERSION }}-${{ hashFiles('build/venv-test-ipywidgets8-requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip-${{ env.PYTHON_VERSION }}- - name: Install dependencies run: npm ci --prefer-offline --no-audit env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Install Python test requirements + run: | + python --version + python -c "import sys;print(sys.executable)" + python -m pip install --upgrade pip wheel + python -m pip --disable-pip-version-check install -r build/venv-test-ipywidgets8-requirements.txt + python -m pip install packaging + python ./pythonFiles/install_debugpy.py + python -m ipykernel install --user + + - name: Install screen capture dependencies + run: sudo apt-get update && sudo apt-get install --fix-missing imagemagick x11-xserver-utils + - name: Compile TypeScript run: npm run compile + env: + VSC_JUPYTER_CI_FAST_COMPILATION: 1 + + - name: Create temp folder for user data dir + run: | + echo "VSC_JUPYTER_USER_DATA_DIR=$(mktemp -d)" >> $GITHUB_ENV + echo ${{env.VSC_JUPYTER_USER_DATA_DIR}} is user data dir + + - name: Set xvfb parameters + run: echo "xvfbCommand=--server-args=\"-screen 0 1024x768x24\"" >> $GITHUB_ENV - name: Run integration tests - run: xvfb-run -a -s "-screen 0 1024x768x24" npm run test:integration - # env: - # VSC_JUPYTER_CI_TEST_GREP: 'Deepnote Integration Tests' + uses: GabrielBB/xvfb-action@b706e4e27b14669b486812790492dc50ca16b465 # v1.7 + with: + run: ${{ env.xvfbCommand }} npm run test:integration + env: + VSC_JUPYTER_FORCE_LOGGING: 1 + VSC_PYTHON_FORCE_LOGGING: 1 + VSC_JUPYTER_CI_TEST_VSC_CHANNEL: 'insiders' + + - name: Upload VS Code logs + uses: actions/upload-artifact@v4 + if: failure() + with: + name: VSCodeLogs-integration-tests + path: '${{env.VSC_JUPYTER_USER_DATA_DIR}}/logs/**/*' + retention-days: 7 + + - name: Upload test result files + uses: actions/upload-artifact@v4 + if: always() + with: + name: TestLogs-integration-tests + path: './logs/*' + retention-days: 7 audit-prod: name: Audit - Production From 20b2d29888d5ea28d68e7aa3f22615e59e18c26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20P=C3=BDrek?= Date: Thu, 30 Oct 2025 17:25:01 +0100 Subject: [PATCH 4/6] ci: use v6 actions/setup-node for integration tests --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0bf807635d..3174e6899a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -209,7 +209,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - name: Setup Node.js - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6 with: cache: 'npm' node-version-file: '.nvmrc' From aac009199d6192d0edb7ad4cb083c6fba94af079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20P=C3=BDrek?= Date: Thu, 30 Oct 2025 17:35:03 +0100 Subject: [PATCH 5/6] ci: harden the actions in integration tests --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3174e6899a..905ad40dcb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -227,7 +227,7 @@ jobs: # Cache pip dependencies - name: Cache pip dependencies - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ env.PYTHON_VERSION }}-${{ hashFiles('build/venv-test-ipywidgets8-requirements.txt') }} @@ -275,7 +275,7 @@ jobs: VSC_JUPYTER_CI_TEST_VSC_CHANNEL: 'insiders' - name: Upload VS Code logs - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 #v5 if: failure() with: name: VSCodeLogs-integration-tests @@ -283,7 +283,7 @@ jobs: retention-days: 7 - name: Upload test result files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 #v5 if: always() with: name: TestLogs-integration-tests From 0d582ab98a784246011fe33bc9b3859dd0b094f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20P=C3=BDrek?= Date: Thu, 30 Oct 2025 17:47:00 +0100 Subject: [PATCH 6/6] ci: run integration tests in matrix --- .github/workflows/ci.yml | 65 +++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 905ad40dcb..72b3113aaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,18 +192,37 @@ jobs: integration-tests: name: Integration Tests - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} timeout-minutes: 30 permissions: id-token: write contents: read packages: read + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + # os: [ubuntu-latest, windows-latest] # Windows commented out for now, can be re-enabled later + python: [python] + pythonVersion: ['3.12'] + tags: [ + '^[^@]+$|@mandatory|@kernelCore|@python|@jupyter', + '@widgets', + '@iw', + '@webview|@export|@lsp|@variableViewer', + '@debugger' + ] + # exclude: + # - os: windows-latest + # tags: '@widgets' + # - os: windows-latest + # tags: '@webview|@export|@lsp|@variableViewer' env: VSC_JUPYTER_FORCE_LOGGING: 'true' VSC_PYTHON_FORCE_LOGGING: 'true' VSC_JUPYTER_CI_TEST_VSC_CHANNEL: 'insiders' DISABLE_INSIDERS_EXTENSION: 1 - PYTHON_VERSION: '3.12' + PYTHON_VERSION: ${{ matrix.pythonVersion }} steps: - name: Checkout uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 @@ -216,11 +235,11 @@ jobs: registry-url: 'https://npm.pkg.github.com' scope: '@deepnote' - - name: Setup Python ${{ env.PYTHON_VERSION }} + - name: Setup Python ${{ matrix.pythonVersion }} uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 id: setupPythonVersion with: - python-version: ${{ env.PYTHON_VERSION }} + python-version: ${{ matrix.pythonVersion }} - name: Set CI Python Path run: echo "CI_PYTHON_PATH=${{ steps.setupPythonVersion.outputs.python-path }}" >> $GITHUB_ENV @@ -230,9 +249,9 @@ jobs: uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ env.PYTHON_VERSION }}-${{ hashFiles('build/venv-test-ipywidgets8-requirements.txt') }} + key: ${{ runner.os }}-pip-${{ matrix.pythonVersion }}-${{ hashFiles('build/venv-test-ipywidgets8-requirements.txt') }} restore-keys: | - ${{ runner.os }}-pip-${{ env.PYTHON_VERSION }}- + ${{ runner.os }}-pip-${{ matrix.pythonVersion }}- - name: Install dependencies run: npm ci --prefer-offline --no-audit @@ -252,16 +271,31 @@ jobs: - name: Install screen capture dependencies run: sudo apt-get update && sudo apt-get install --fix-missing imagemagick x11-xserver-utils + - name: Generate Tag Variable + run: echo "TAGSVAR=${{ matrix.tags }}" >> $GITHUB_ENV + + - name: Generate Friendly Variable + run: echo "TAGS_NAME=${TAGSVAR//[^a-zA-Z]/_}" >> $GITHUB_ENV + - name: Compile TypeScript run: npm run compile env: VSC_JUPYTER_CI_FAST_COMPILATION: 1 + VSC_JUPYTER_CI_TEST_GREP: ${{ matrix.tags }} - name: Create temp folder for user data dir run: | echo "VSC_JUPYTER_USER_DATA_DIR=$(mktemp -d)" >> $GITHUB_ENV echo ${{env.VSC_JUPYTER_USER_DATA_DIR}} is user data dir + # Windows-specific steps (commented out for now) + # - name: Create temp folder for user data dir (Windows) + # if: matrix.os == 'windows-latest' + # run: | + # echo "VSC_JUPYTER_USER_DATA_DIR=$env:USERPROFILE\AppData\Local\Temp" >> $Env:GITHUB_ENV + # echo ${{env.VSC_JUPYTER_USER_DATA_DIR}} is user data dir + # shell: pwsh + - name: Set xvfb parameters run: echo "xvfbCommand=--server-args=\"-screen 0 1024x768x24\"" >> $GITHUB_ENV @@ -273,12 +307,24 @@ jobs: VSC_JUPYTER_FORCE_LOGGING: 1 VSC_PYTHON_FORCE_LOGGING: 1 VSC_JUPYTER_CI_TEST_VSC_CHANNEL: 'insiders' + VSC_JUPYTER_CI_TEST_GREP: ${{ matrix.tags }} + + # Windows-specific test execution (commented out for now) + # - name: Run integration tests (Windows) + # if: matrix.os == 'windows-latest' + # run: npm run test:integration:windows + # env: + # VSC_JUPYTER_FORCE_LOGGING: 1 + # VSC_PYTHON_FORCE_LOGGING: 1 + # VSC_JUPYTER_CI_TEST_VSC_CHANNEL: 'insiders' + # VSC_JUPYTER_CI_TEST_GREP: ${{ matrix.tags }} + # VSC_PYTHON_LOG_FILE: ${{env.VSC_JUPYTER_USER_DATA_DIR}}/logs/python.log - name: Upload VS Code logs uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 #v5 if: failure() with: - name: VSCodeLogs-integration-tests + name: VSCodeLogs-${{ matrix.os }}-${{ matrix.pythonVersion }}-${{ env.TAGS_NAME }} path: '${{env.VSC_JUPYTER_USER_DATA_DIR}}/logs/**/*' retention-days: 7 @@ -286,10 +332,13 @@ jobs: uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 #v5 if: always() with: - name: TestLogs-integration-tests + name: TestLogs-${{ matrix.os }}-${{ matrix.pythonVersion }}-${{ env.TAGS_NAME }} path: './logs/*' retention-days: 7 + - name: Verify there are no unhandled errors + run: npx gulp verifyUnhandledErrors + audit-prod: name: Audit - Production runs-on: ubuntu-latest