Skip to content

Commit 220f49b

Browse files
authored
Merge branch 'master' into phase3/e2e-copilot-fixes
2 parents 8fc34ec + a44de43 commit 220f49b

32 files changed

Lines changed: 2185 additions & 1509 deletions

.github/dependabot.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,26 @@ updates:
66
schedule:
77
# Check for updates to GitHub Actions every week
88
interval: "weekly"
9+
10+
# npm version updates (security updates run automatically regardless of this)
11+
- package-ecosystem: "npm"
12+
directory: "/"
13+
schedule:
14+
interval: "weekly"
15+
open-pull-requests-limit: 10
16+
# Wait a week after a release is published before opening a bump for it, so a
17+
# freshly published (or later yanked/compromised) version isn't picked up on
18+
# day zero.
19+
cooldown:
20+
default-days: 7
21+
groups:
22+
# Roll routine minor/patch bumps into one PR to keep the noise down
23+
minor-and-patch:
24+
update-types:
25+
- "minor"
26+
- "patch"
27+
ignore:
28+
# @types/node tracks the Node version Electron bundles (24 for Electron 42),
29+
# not the newest types, so skip major bumps here.
30+
- dependency-name: "@types/node"
31+
update-types: ["version-update:semver-major"]

.github/workflows/e2e.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,11 @@ jobs:
8383
ver=$(awk '$1=="-" && $2=="jupyterlab" {print $3}' env_installer/jlab_server.yaml)
8484
[[ "$ver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "unexpected jupyterlab pin '$ver' in jlab_server.yaml (want exact x.y.z)"; exit 1; }
8585
python3 -m venv "$RUNNER_TEMP/jlab-venv"
86-
"$RUNNER_TEMP/jlab-venv/bin/pip" install --quiet "jupyterlab==$ver"
86+
# jupyterlab pulls in ipykernel, so the venv already has a python3
87+
# kernel for the cell-run test. ipywidgets is one of the extensions the
88+
# app bundles (see jlab_server.yaml); install it so the widget-render
89+
# test can confirm a labextension actually draws through the WebContentsView.
90+
"$RUNNER_TEMP/jlab-venv/bin/pip" install --quiet "jupyterlab==$ver" ipywidgets
8791
echo "JLAB_TEST_PYTHON_PATH=$RUNNER_TEMP/jlab-venv/bin/python" >> "$GITHUB_ENV"
8892
# xvfb is Linux-only; on macOS the runner has a real display, so run the
8993
# suite directly. Same yarn test:e2e command on both legs.

.github/workflows/publish.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
2424
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
2525
with:
26-
node-version: '20.x'
26+
node-version: '24.x'
2727
cache: 'yarn'
2828
- run: yarn install --frozen-lockfile
2929
- run: yarn test:coverage
@@ -59,7 +59,7 @@ jobs:
5959
- name: Install node
6060
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
6161
with:
62-
node-version: '20.x'
62+
node-version: '24.x'
6363
cache: 'yarn'
6464

6565
- name: Install dependencies

.github/workflows/releasepr.yml

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ jobs:
1212
steps:
1313
- name: Checkout
1414
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
15-
15+
with:
16+
# Read-only checkout: the default token is never persisted into the git
17+
# config. The write-capable app token is only introduced at the push
18+
# step below.
19+
persist-credentials: false
20+
1621
- name: Get package info
1722
shell: bash
1823
id: package-info
@@ -34,18 +39,31 @@ jobs:
3439
return releaseWithTag ? 'true' : 'false'
3540
result-encoding: string
3641

37-
- name: Make changes to pull request
42+
- name: Create release pull request
3843
if: steps.pre-release-exists.outputs.result == 'true'
39-
run: date +%s > auto-release.log
44+
env:
45+
APP_VERSION: ${{ steps.package-info.outputs.version }}
46+
GH_TOKEN: ${{ secrets.JLAB_APP_TOKEN }}
47+
run: |
48+
set -eux
49+
# git checkout -b fails if the branch already exists, which keeps a
50+
# re-run from opening a duplicate release PR.
51+
BRANCH_NAME="release-v${APP_VERSION}"
52+
git checkout -b "${BRANCH_NAME}"
53+
git config user.name "JupyterLab Desktop Bot"
54+
git config user.email 'jupyterlab-bot@users.noreply.github.com'
4055
41-
- name: Create Release pull request
42-
if: steps.pre-release-exists.outputs.result == 'true'
43-
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6
44-
with:
45-
token: ${{ secrets.JLAB_APP_TOKEN }}
46-
commit-message: Update auto-release logs
47-
branch: release-v${{ steps.package-info.outputs.version}}
48-
title: 'Release v${{ steps.package-info.outputs.version}}'
49-
body: |
50-
Release v${{ steps.package-info.outputs.version}}
51-
draft: false
56+
date +%s > auto-release.log
57+
git add auto-release.log
58+
git commit -m "Update auto-release logs"
59+
# Checkout ran with persist-credentials: false. Wire the app token in
60+
# through gh's credential helper just for this push, so it never lands
61+
# in the git config or the command log; git push then uses GH_TOKEN.
62+
gh auth setup-git
63+
git push origin "HEAD:refs/heads/${BRANCH_NAME}"
64+
65+
gh pr create \
66+
--head "${BRANCH_NAME}" \
67+
--base "${GITHUB_REF_NAME}" \
68+
--title "Release v${APP_VERSION}" \
69+
--body "Release v${APP_VERSION}"

.github/workflows/sync_lab_release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ jobs:
9393
- name: Install Node
9494
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
9595
with:
96-
node-version: '20.x'
96+
node-version: '24.x'
9797

9898
- name: Install npm dependencies
9999
run: |

.github/workflows/zizmor.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Static analysis of the GitHub Actions workflows with zizmor.
2+
# https://github.com/zizmorcore/zizmor
3+
name: GitHub Actions security (zizmor)
4+
5+
on:
6+
push:
7+
branches: [master]
8+
pull_request:
9+
branches: ["**"]
10+
11+
permissions: {}
12+
13+
jobs:
14+
zizmor:
15+
name: zizmor
16+
runs-on: ubuntu-latest
17+
permissions:
18+
security-events: write # upload-sarif needs this to publish results
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
22+
with:
23+
persist-credentials: false
24+
25+
- name: Install uv
26+
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
27+
28+
- name: Run zizmor
29+
# Report only for now. The existing workflows still have findings to work
30+
# through, so this uploads results to the Security tab instead of failing
31+
# the build. Flip to a hard gate once they're cleared. No token is passed,
32+
# so zizmor runs offline (skips the online-only audits) and avoids the API
33+
# rate limits its docs warn about.
34+
continue-on-error: true
35+
run: uvx zizmor@1.25.2 --format=sarif . > results.sarif
36+
37+
- name: Upload SARIF
38+
uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1
39+
with:
40+
sarif_file: results.sarif
41+
category: zizmor

package.json

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"test:unit:watch": "vitest",
1111
"test:coverage": "vitest run --coverage",
1212
"test:e2e": "playwright test",
13-
"clean": "rimraf build dist",
13+
"clean": "node scripts/rm.js build dist",
1414
"watch:tsc": "tsc -w",
1515
"watch:assets": "node ./scripts/extract.js && node ./scripts/copyassets.js watch",
1616
"watch": "concurrently \"yarn watch:tsc\" \"yarn watch:assets\" ",
@@ -30,19 +30,19 @@
3030
"dist:osx-arm64-dev": "yarn build && CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --macos --arm64 --publish never",
3131
"dist:win-64": "yarn build && electron-builder --win --publish never",
3232
"dist:win-arm64": "yarn build && yarn electron-builder --arm64 --publish never",
33-
"update_workflow_conda_lock": "cd workflow_env && rimraf *.lock && conda-lock --kind explicit -f publish_env.yaml && cd -",
34-
"update_conda_lock": "cd env_installer && rimraf *.lock && conda-lock --kind explicit -f jlab_server.yaml && cd -",
35-
"clean_env_installer": "rimraf ./env_installer/jlab_server.tar.gz && rimraf ./env_installer/jlab_server",
33+
"update_workflow_conda_lock": "node scripts/rm.js workflow_env/*.lock && cd workflow_env && conda-lock --kind explicit -f publish_env.yaml && cd -",
34+
"update_conda_lock": "node scripts/rm.js env_installer/*.lock && cd env_installer && conda-lock --kind explicit -f jlab_server.yaml && cd -",
35+
"clean_env_installer": "node scripts/rm.js ./env_installer/jlab_server.tar.gz && node scripts/rm.js ./env_installer/jlab_server",
3636
"create_env_installer": "yarn clean_env_installer && conda-lock install --no-validate-platform --prefix ./env_installer/jlab_server ./env_installer/conda-${ENV_PLATFORM}.lock && yarn copy_extras_to_bundled_env && conda pack -p ./env_installer/jlab_server -o ./env_installer/jlab_server.tar.gz",
3737
"create_env_installer:linux-64": "ENV_PLATFORM=linux-64 yarn create_env_installer",
3838
"create_env_installer:linux-aarch64": "ENV_PLATFORM=linux-aarch64 yarn create_env_installer",
3939
"create_env_installer:osx-64": "ENV_PLATFORM=osx-64 yarn create_env_installer",
4040
"create_env_installer:osx-arm64": "ENV_PLATFORM=osx-arm64 yarn create_env_installer",
4141
"create_env_installer:win-64": "yarn clean_env_installer && conda-lock install --no-validate-platform --prefix ./env_installer/jlab_server ./env_installer/conda-win-64.lock && yarn copy_extras_to_bundled_env && conda pack -p ./env_installer/jlab_server -o ./env_installer/jlab_server.tar.gz",
42-
"extract_env_installer:osx": "cd ./env_installer && rimraf jlab_server_extracted && mkdir jlab_server_extracted && tar -xzf jlab_server.tar.gz -C jlab_server_extracted && cd -",
42+
"extract_env_installer:osx": "node scripts/rm.js env_installer/jlab_server_extracted && cd ./env_installer && mkdir jlab_server_extracted && tar -xzf jlab_server.tar.gz -C jlab_server_extracted && cd -",
4343
"extract_env_installer:osx-64": "yarn extract_env_installer:osx",
4444
"extract_env_installer:osx-arm64": "yarn extract_env_installer:osx",
45-
"compress_env_installer:osx": "rimraf ./env_installer/jlab_server.tar.gz && cd ./env_installer/jlab_server_extracted && tar -czf ../jlab_server.tar.gz . && cd -",
45+
"compress_env_installer:osx": "node scripts/rm.js ./env_installer/jlab_server.tar.gz && cd ./env_installer/jlab_server_extracted && tar -czf ../jlab_server.tar.gz . && cd -",
4646
"compress_env_installer:osx-64": "yarn compress_env_installer:osx",
4747
"compress_env_installer:osx-arm64": "yarn compress_env_installer:osx",
4848
"check_version_match": "node scripts/buildutil.js --check-version-match",
@@ -157,6 +157,7 @@
157157
"darkModeSupport": true,
158158
"hardenedRuntime": true,
159159
"gatekeeperAssess": false,
160+
"minimumSystemVersion": "12.0.0",
160161
"artifactName": "${productName}-${arch}.${ext}",
161162
"extraResources": [
162163
{
@@ -182,54 +183,49 @@
182183
"repository": "https://github.com/jupyterlab/jupyterlab-desktop",
183184
"license": "BSD-3-Clause",
184185
"devDependencies": {
186+
"@electron/notarize": "^3.1.1",
185187
"@eslint/js": "^10.0.1",
186188
"@jupyter-notebook/web-components": "0.9.1",
187-
"@leeoniya/ufuzzy": "1.0.14",
188-
"@playwright/test": "^1.59.1",
189-
"@types/ejs": "^3.1.0",
190-
"@types/js-yaml": "^4.0.3",
189+
"@leeoniya/ufuzzy": "1.0.19",
190+
"@playwright/test": "^1.61.0",
191+
"@types/ejs": "^3.1.5",
192+
"@types/js-yaml": "^4.0.9",
191193
"@types/node": "^24",
192-
"@types/semver": "^7.3.4",
193-
"@types/tar": "^6.1.5",
194-
"@types/yargs": "^17.0.18",
195-
"@vitest/coverage-v8": "^4.1.5",
196-
"electron": "^27.0.2",
197-
"electron-builder": "^24.9.1",
198-
"electron-notarize": "^1.2.2",
194+
"@types/semver": "^7.7.1",
195+
"@types/yargs": "^17.0.35",
196+
"@vitest/coverage-v8": "^4.1.9",
197+
"electron": "^42.4.0",
198+
"electron-builder": "^26.15.3",
199199
"electron-playwright-helpers": "^2.1.0",
200200
"eslint": "^10.5.0",
201201
"eslint-config-prettier": "^10.1.8",
202-
"fs-extra": "~9.1.0",
203202
"globals": "^17.6.0",
204-
"istextorbinary": "^6.0.0",
205-
"meow": "^6.0.1",
206-
"node-watch": "^0.7.4",
203+
"istextorbinary": "^9.5.0",
207204
"prettier": "~2.1.1",
208205
"read-package-tree": "^5.1.6",
209-
"rimraf": "~3.0.0",
210-
"shx": "^0.3.4",
206+
"shx": "^0.4.0",
211207
"typescript": "^6.0.0",
212-
"typescript-eslint": "^8.61.0",
213-
"vitest": "^4.1.5",
214-
"webpack": "^5.76.0",
208+
"typescript-eslint": "^8.61.1",
209+
"vitest": "^4.1.9",
210+
"webpack": "^5.107.2",
215211
"webpack-cli": "^4.5.0"
216212
},
217213
"resolutions": {
218214
"serialize-javascript": "^6.0.2",
219215
"micromatch": "^4.0.8"
220216
},
221217
"dependencies": {
222-
"@lumino/signaling": "^1.10.0",
223-
"ejs": "^3.1.10",
224-
"electron-log": "^4.4.8",
225-
"fast-xml-parser": "^5.8.0",
218+
"@lumino/signaling": "^2.1.5",
219+
"ejs": "^6.0.1",
220+
"electron-log": "^5.4.4",
221+
"fast-xml-parser": "^5.9.0",
226222
"fix-path": "^3.0.0",
227-
"js-yaml": "^4.1.0",
228-
"semver": "^7.5.4",
229-
"tar": "^6.2.1",
230-
"update-electron-app": "^2.0.1",
231-
"which": "^2.0.2",
232-
"winreg": "^1.2.4",
233-
"yargs": "^17.6.2"
223+
"js-yaml": "^5.2.0",
224+
"semver": "^7.8.4",
225+
"tar": "^7.5.16",
226+
"update-electron-app": "^3.2.0",
227+
"which": "^7.0.0",
228+
"winreg": "^1.2.5",
229+
"yargs": "^17.7.2"
234230
}
235231
}

scripts/buildutil.js

Lines changed: 24 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,33 @@
1-
const meow = require('meow');
2-
const fs = require('fs-extra');
1+
const { parseArgs } = require('util');
2+
const fs = require('fs');
33
const path = require('path');
44
const semver = require('semver');
55
const yaml = require('js-yaml');
66

7+
// Native replacements for the fs-extra helpers this script used.
8+
const readJSONSync = p => JSON.parse(fs.readFileSync(p, 'utf8'));
9+
const copySync = (src, dest) => fs.cpSync(src, dest, { recursive: true });
10+
711
const pkgjsonFilePath = path.resolve(__dirname, '../package.json');
812

9-
const cli = meow(
10-
`
11-
Usage
12-
$ node buildutil <options>
13-
14-
Options
15-
--check-version-match check for JupyterLab version match
16-
--update-binary-sign-list update binary list to sign for macOS
17-
--copy-extras-to-bundled-env copy extra files from extras to bundled environment installer
18-
--platform platform for --update-binary-sign-list. osx-64 or osx-arm64
19-
20-
Other options:
21-
--help show usage information
22-
--version show version information
23-
24-
Examples
25-
$ node buildutil --check-version-match
26-
`,
27-
{
28-
flags: {
29-
checkVersionMatch: {
30-
type: 'boolean',
31-
default: false
32-
},
33-
updateBinarySignList: {
34-
type: 'boolean',
35-
default: false
36-
},
37-
platform: {
38-
type: 'string',
39-
default: 'osx-64'
40-
}
41-
}
13+
// node buildutil <options>
14+
// --check-version-match check for JupyterLab version match
15+
// --update-binary-sign-list update binary list to sign for macOS
16+
// --copy-extras-to-bundled-env copy extras into the bundled environment
17+
// --platform <osx-64|osx-arm64> platform for --update-binary-sign-list
18+
const { values: flags } = parseArgs({
19+
options: {
20+
'check-version-match': { type: 'boolean', default: false },
21+
'update-binary-sign-list': { type: 'boolean', default: false },
22+
'copy-extras-to-bundled-env': { type: 'boolean', default: false },
23+
platform: { type: 'string', default: 'osx-64' }
4224
}
43-
);
25+
});
4426

45-
if (cli.flags.checkVersionMatch) {
27+
if (flags['check-version-match']) {
4628
// parse application version
4729
const pkgjsonFileData = fs.existsSync(pkgjsonFilePath)
48-
? fs.readJSONSync(pkgjsonFilePath)
30+
? readJSONSync(pkgjsonFilePath)
4931
: undefined;
5032
if (!pkgjsonFileData) {
5133
console.error('package.json not found!');
@@ -91,7 +73,7 @@ if (cli.flags.checkVersionMatch) {
9173
process.exit(0);
9274
}
9375

94-
if (cli.flags.updateBinarySignList) {
76+
if (flags['update-binary-sign-list']) {
9577
const { isBinary } = require('istextorbinary');
9678
const envInstallerDir = path.resolve('env_installer', 'jlab_server');
9779

@@ -172,10 +154,7 @@ if (cli.flags.updateBinarySignList) {
172154

173155
const binaries = findBinariesInDirectory(envInstallerDir);
174156
const fileContent = binaries.join('\n');
175-
const signListFile = path.join(
176-
'env_installer',
177-
`sign-${cli.flags.platform}.txt`
178-
);
157+
const signListFile = path.join('env_installer', `sign-${flags.platform}.txt`);
179158

180159
fs.writeFileSync(signListFile, `${fileContent}\n`);
181160

@@ -184,11 +163,11 @@ if (cli.flags.updateBinarySignList) {
184163
process.exit(0);
185164
}
186165

187-
if (cli.flags.copyExtrasToBundledEnv) {
166+
if (flags['copy-extras-to-bundled-env']) {
188167
const envExtrasDir = path.resolve('env_installer', 'extras');
189168
const envInstallerDir = path.resolve('env_installer', 'jlab_server');
190169

191-
fs.copySync(envExtrasDir, envInstallerDir, { recursive: true });
170+
copySync(envExtrasDir, envInstallerDir);
192171

193172
console.log(
194173
`Finished copying env extras from \n\t"${envExtrasDir}" to \n\t"${envInstallerDir}"`

0 commit comments

Comments
 (0)