From dbc615e33f21211f5ecc0c8997d5713a7c4b8162 Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Tue, 27 Feb 2024 08:10:40 +0000 Subject: [PATCH 1/9] workflow to upgrade JupyterLab dependencies --- .../upgrade-juypterlab-dependencies.yml | 86 +++++++++++++++++++ scripts/get-latest-lab-version.py | 44 ++++++++++ scripts/upgrade-lab-dependencies.py | 82 ++++++++++++++++++ 3 files changed, 212 insertions(+) create mode 100644 .github/workflows/upgrade-juypterlab-dependencies.yml create mode 100644 scripts/get-latest-lab-version.py create mode 100644 scripts/upgrade-lab-dependencies.py diff --git a/.github/workflows/upgrade-juypterlab-dependencies.yml b/.github/workflows/upgrade-juypterlab-dependencies.yml new file mode 100644 index 0000000000..39e380f164 --- /dev/null +++ b/.github/workflows/upgrade-juypterlab-dependencies.yml @@ -0,0 +1,86 @@ +name: Check for latest JupyterLab releases + +on: + schedule: + - cron: 30 17 * * * + workflow_dispatch: + inputs: + version: + description: 'JupyterLab version' + default: latest + required: true + type: string + +env: + version_tag: 'latest' + +permissions: + contents: write + pull-requests: write + +jobs: + check_for_lab_updates: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: Install required dependencies + run: | + python -m pip install requests + sudo apt-get install hub + + - name: Install Node + uses: actions/setup-node@v2 + with: + node-version: '20.x' + + - name: Install npm dependencies + run: | + npm install --global yarn + yarn install + + - name: Check for new releases and update + shell: bash + run: | + set -eux + for version in ${{ inputs.version || env.version_tag }} + do + export LATEST=$(python scripts/get-latest-lab-version.py --set-version $version) + done + + echo "latest=${LATEST}" >> $GITHUB_ENV + python scripts/upgrade-lab-dependencies.py --set-version ${LATEST} + if [[ ! -z "$(git status --porcelain package.json)" ]]; then + yarn install + fi + + - name: Create a PR + shell: bash + env: + GITHUB_USER: ${{ secrets.G_USER }} + GITHUB_TOKEN: ${{ secrets.G_TOKEN }} + run: | + set -eux + # if resulted in any change: + export LATEST=${{ env.latest }} + if [[ ! -z "$(git status --porcelain package.json)" ]]; then + export BRANCH_NAME=update-to-v${LATEST} + + # this will fail if the branch already exists which means we won't have duplicate PRs + git checkout -b "${BRANCH_NAME}" + git config user.name "JupyterLab Desktop Bot" + git config user.email 'jupyterlab-bot@users.noreply.github.com' + + git commit . -m "Update to JupyterLab v${LATEST}" + + git push --set-upstream origin "${BRANCH_NAME}" + hub pull-request -m "Update to JupyterLab v${LATEST}" \ + -m "New JupyterLab release [v${LATEST}](https://github.com/jupyterlab/jupyterlab/releases/tag/v${LATEST}) is available. Please review the lock file carefully.". + fi diff --git a/scripts/get-latest-lab-version.py b/scripts/get-latest-lab-version.py new file mode 100644 index 0000000000..b74be46169 --- /dev/null +++ b/scripts/get-latest-lab-version.py @@ -0,0 +1,44 @@ +from urllib.request import urlopen +import json +import argparse + + +REPOSITORY = "jupyterlab" +ORGANIZATION = "jupyterlab" + + +def extract_version_from_releases(releases, version_tag): + for release in releases: + tag_name = release['tag_name'] + if (version_tag == "latest"): + if(not release['prerelease'] and not release['draft']): + return tag_name + + elif (version_tag == tag_name): + return tag_name + return None + + +def find_version(owner, repository, version_tag): + """Find latest stable release on GitHub for given repository.""" + endpoint = f"https://api.github.com/repos/{owner}/{repository}/releases" + releases = json.loads(urlopen(endpoint).read()) + + version = extract_version_from_releases(releases,version_tag) + + if version is None: + raise ValueError('Invalid release tag') + if not version.startswith('v'): + raise ValueError('Unexpected release tag name format: does not start with v') + return version[1:] + +def main(): + parser = argparse.ArgumentParser(description='Update dependencies in package.json.') + parser.add_argument('--set-version', dest='version_tag', type=str, required=True, help='Set version tag') + + args = parser.parse_args() + print(find_version(owner=ORGANIZATION,repository=REPOSITORY,version_tag=args.version_tag)) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/scripts/upgrade-lab-dependencies.py b/scripts/upgrade-lab-dependencies.py new file mode 100644 index 0000000000..11dfa92106 --- /dev/null +++ b/scripts/upgrade-lab-dependencies.py @@ -0,0 +1,82 @@ +import json +import argparse +import requests + +PACKAGE_JSON_PATHS = [ + "app/package.json", + "buildutils/package.json", + "package.json", + "packages/application-extension/package.json", + "packages/application/package.json", + "packages/console-extension/package.json", + "packages/docmanager-extension/package.json", + "packages/documentsearch-extension/package.json", + "packages/help-extension/package.json", + "packages/lab-extension/package.json", + "packages/notebook-extension/package.json", + "packages/terminal-extension/package.json", + "packages/tree-extension/package.json", + "packages/tree/package.json", + "packages/ui-components/package.json", +] + +DEPENDENCY_NAME = "@jupyterlab" + +def update_package_json(new_version): + url = f'https://api.github.com/repos/{owner}/{repository}/releases' + + response = requests.get(url) + + if response.status_code != 200: + print(f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}") + return + + new_package_json = response.json() + + for path in PACKAGE_JSON_PATHS: + with open(path, 'r') as package_json_file: + existing_package_json = json.load(package_json_file) + + new_dependencies = {**new_package_json.get('devDependencies', {}), **new_package_json.get('resolutions', {})} + update_dependencies(existing_package_json, new_dependencies) + + with open(path, 'w') as file: + json.dump(existing_package_json, file, indent=2) + file.write('\n') + + +def update_dependencies(existing_json, new_json): + if(existing_json == None): + return + + section_paths = ['resolutions','dependencies', 'devDependencies'] + + for section in section_paths: + if(existing_json.get(section) == None): + continue + + updated = existing_json.get(section) + for package, version in existing_json.get(section).items(): + if(package.startswith(DEPENDENCY_NAME) and package in new_json): + # To maintaing the existing prefix ~ or ^ + if version[0] in ('^','~'): + updated[package] = version[0] + absolute_version(new_json[package]) + else: + updated[package] = absolute_version(new_json[package]) + +def absolute_version(version): + if len(version) > 0 and version[0] in ('^','~'): + return version[1:]; + return version; + + +def main(): + parser = argparse.ArgumentParser(description='Update dependencies in package.json.') + parser.add_argument('--set-version', dest='new_version', type=str, required=True, help='New version to set for JupyterLab dependencies') + + args = parser.parse_args() + update_package_json(args.new_version) + + +if(__name__ == "__main__"): + main() \ No newline at end of file From 2fb9d893040f3a1bea93a32b41f15d9d23f911ee Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Tue, 27 Feb 2024 08:28:56 +0000 Subject: [PATCH 2/9] Update upgrade-lab-dependencies.py --- scripts/upgrade-lab-dependencies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/upgrade-lab-dependencies.py b/scripts/upgrade-lab-dependencies.py index 11dfa92106..31b10fc309 100644 --- a/scripts/upgrade-lab-dependencies.py +++ b/scripts/upgrade-lab-dependencies.py @@ -23,7 +23,7 @@ DEPENDENCY_NAME = "@jupyterlab" def update_package_json(new_version): - url = f'https://api.github.com/repos/{owner}/{repository}/releases' + url = f'https://raw.githubusercontent.com/jupyterlab/jupyterlab/v{new_version}/jupyterlab/staging/package.json' response = requests.get(url) From 0538550ffb47b5bf5f4526f33e6dfe83d80a9bbc Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Tue, 27 Feb 2024 18:15:42 +0000 Subject: [PATCH 3/9] Prettier code for Test Lint check --- .../upgrade-juypterlab-dependencies.yml | 7 ++--- scripts/get-latest-lab-version.py | 29 +++++++++++-------- scripts/upgrade-lab-dependencies.py | 20 +++++++------ 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/.github/workflows/upgrade-juypterlab-dependencies.yml b/.github/workflows/upgrade-juypterlab-dependencies.yml index 39e380f164..5edfb91a18 100644 --- a/.github/workflows/upgrade-juypterlab-dependencies.yml +++ b/.github/workflows/upgrade-juypterlab-dependencies.yml @@ -33,7 +33,7 @@ jobs: - name: Install required dependencies run: | - python -m pip install requests + python -m pip install requests jupyterlab sudo apt-get install hub - name: Install Node @@ -43,8 +43,7 @@ jobs: - name: Install npm dependencies run: | - npm install --global yarn - yarn install + jlpm install - name: Check for new releases and update shell: bash @@ -58,7 +57,7 @@ jobs: echo "latest=${LATEST}" >> $GITHUB_ENV python scripts/upgrade-lab-dependencies.py --set-version ${LATEST} if [[ ! -z "$(git status --porcelain package.json)" ]]; then - yarn install + jlpm install fi - name: Create a PR diff --git a/scripts/get-latest-lab-version.py b/scripts/get-latest-lab-version.py index b74be46169..e94eb4e74c 100644 --- a/scripts/get-latest-lab-version.py +++ b/scripts/get-latest-lab-version.py @@ -1,7 +1,6 @@ -from urllib.request import urlopen -import json import argparse - +import requests +import sys REPOSITORY = "jupyterlab" ORGANIZATION = "jupyterlab" @@ -20,16 +19,20 @@ def extract_version_from_releases(releases, version_tag): def find_version(owner, repository, version_tag): - """Find latest stable release on GitHub for given repository.""" - endpoint = f"https://api.github.com/repos/{owner}/{repository}/releases" - releases = json.loads(urlopen(endpoint).read()) + url = f"https://api.github.com/repos/{owner}/{repository}/releases" + + response = requests.get(url, timeout=10) + + if response.status_code != 200: + error_message = f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" + raise requests.HTTPError(error_message) - version = extract_version_from_releases(releases,version_tag) + releases = response.json() + version = extract_version_from_releases(releases, version_tag) if version is None: - raise ValueError('Invalid release tag') - if not version.startswith('v'): - raise ValueError('Unexpected release tag name format: does not start with v') + error_message = 'Invalid release tag' + raise ValueError(error_message) return version[1:] def main(): @@ -37,8 +40,10 @@ def main(): parser.add_argument('--set-version', dest='version_tag', type=str, required=True, help='Set version tag') args = parser.parse_args() - print(find_version(owner=ORGANIZATION,repository=REPOSITORY,version_tag=args.version_tag)) - + + result = find_version(owner=ORGANIZATION, repository=REPOSITORY, version_tag=args.version_tag) + sys.stdout.write(result) + sys.stdout.flush() if __name__ == '__main__': main() \ No newline at end of file diff --git a/scripts/upgrade-lab-dependencies.py b/scripts/upgrade-lab-dependencies.py index 31b10fc309..787e468df5 100644 --- a/scripts/upgrade-lab-dependencies.py +++ b/scripts/upgrade-lab-dependencies.py @@ -1,5 +1,6 @@ -import json import argparse +import json +from pathlib import Path import requests PACKAGE_JSON_PATHS = [ @@ -25,40 +26,41 @@ def update_package_json(new_version): url = f'https://raw.githubusercontent.com/jupyterlab/jupyterlab/v{new_version}/jupyterlab/staging/package.json' - response = requests.get(url) + response = requests.get(url, timeout=10) if response.status_code != 200: - print(f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}") - return + error_message = f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" + raise requests.HTTPError(error_message) new_package_json = response.json() for path in PACKAGE_JSON_PATHS: - with open(path, 'r') as package_json_file: + file_path = Path(path) + with file_path.open(mode='r') as package_json_file: existing_package_json = json.load(package_json_file) new_dependencies = {**new_package_json.get('devDependencies', {}), **new_package_json.get('resolutions', {})} update_dependencies(existing_package_json, new_dependencies) - with open(path, 'w') as file: + with file_path.open(mode='w') as file: json.dump(existing_package_json, file, indent=2) file.write('\n') def update_dependencies(existing_json, new_json): - if(existing_json == None): + if(existing_json is None): return section_paths = ['resolutions','dependencies', 'devDependencies'] for section in section_paths: - if(existing_json.get(section) == None): + if(existing_json.get(section) is None): continue updated = existing_json.get(section) for package, version in existing_json.get(section).items(): if(package.startswith(DEPENDENCY_NAME) and package in new_json): - # To maintaing the existing prefix ~ or ^ + # To maintain the existing prefix ~ or ^ if version[0] in ('^','~'): updated[package] = version[0] + absolute_version(new_json[package]) else: From 4de74363e653be90f6fb88c67a576aa4e7920ffa Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Tue, 27 Feb 2024 18:25:23 +0000 Subject: [PATCH 4/9] Prettier code for Test Lint checks --- scripts/get-latest-lab-version.py | 35 +++++++++------- scripts/upgrade-lab-dependencies.py | 62 ++++++++++++++++++----------- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/scripts/get-latest-lab-version.py b/scripts/get-latest-lab-version.py index e94eb4e74c..f4772c2d7d 100644 --- a/scripts/get-latest-lab-version.py +++ b/scripts/get-latest-lab-version.py @@ -1,19 +1,20 @@ import argparse -import requests import sys +import requests + REPOSITORY = "jupyterlab" ORGANIZATION = "jupyterlab" def extract_version_from_releases(releases, version_tag): for release in releases: - tag_name = release['tag_name'] - if (version_tag == "latest"): - if(not release['prerelease'] and not release['draft']): + tag_name = release["tag_name"] + if version_tag == "latest": + if not release["prerelease"] and not release["draft"]: return tag_name - - elif (version_tag == tag_name): + + elif version_tag == tag_name: return tag_name return None @@ -22,28 +23,34 @@ def find_version(owner, repository, version_tag): url = f"https://api.github.com/repos/{owner}/{repository}/releases" response = requests.get(url, timeout=10) - + if response.status_code != 200: - error_message = f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" + error_message = ( + f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" + ) raise requests.HTTPError(error_message) releases = response.json() version = extract_version_from_releases(releases, version_tag) if version is None: - error_message = 'Invalid release tag' + error_message = "Invalid release tag" raise ValueError(error_message) return version[1:] + def main(): - parser = argparse.ArgumentParser(description='Update dependencies in package.json.') - parser.add_argument('--set-version', dest='version_tag', type=str, required=True, help='Set version tag') - + parser = argparse.ArgumentParser(description="Update dependencies in package.json.") + parser.add_argument( + "--set-version", dest="version_tag", type=str, required=True, help="Set version tag" + ) + args = parser.parse_args() result = find_version(owner=ORGANIZATION, repository=REPOSITORY, version_tag=args.version_tag) sys.stdout.write(result) sys.stdout.flush() -if __name__ == '__main__': - main() \ No newline at end of file + +if __name__ == "__main__": + main() diff --git a/scripts/upgrade-lab-dependencies.py b/scripts/upgrade-lab-dependencies.py index 787e468df5..14d31231d3 100644 --- a/scripts/upgrade-lab-dependencies.py +++ b/scripts/upgrade-lab-dependencies.py @@ -1,6 +1,7 @@ import argparse import json from pathlib import Path + import requests PACKAGE_JSON_PATHS = [ @@ -23,62 +24,75 @@ DEPENDENCY_NAME = "@jupyterlab" + def update_package_json(new_version): - url = f'https://raw.githubusercontent.com/jupyterlab/jupyterlab/v{new_version}/jupyterlab/staging/package.json' - + url = f"https://raw.githubusercontent.com/jupyterlab/jupyterlab/v{new_version}/jupyterlab/staging/package.json" + response = requests.get(url, timeout=10) - + if response.status_code != 200: - error_message = f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" + error_message = ( + f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" + ) raise requests.HTTPError(error_message) - + new_package_json = response.json() for path in PACKAGE_JSON_PATHS: file_path = Path(path) - with file_path.open(mode='r') as package_json_file: + with file_path.open(mode="r") as package_json_file: existing_package_json = json.load(package_json_file) - - new_dependencies = {**new_package_json.get('devDependencies', {}), **new_package_json.get('resolutions', {})} + + new_dependencies = { + **new_package_json.get("devDependencies", {}), + **new_package_json.get("resolutions", {}), + } update_dependencies(existing_package_json, new_dependencies) - with file_path.open(mode='w') as file: + with file_path.open(mode="w") as file: json.dump(existing_package_json, file, indent=2) - file.write('\n') + file.write("\n") def update_dependencies(existing_json, new_json): - if(existing_json is None): + if existing_json is None: return - - section_paths = ['resolutions','dependencies', 'devDependencies'] + + section_paths = ["resolutions", "dependencies", "devDependencies"] for section in section_paths: - if(existing_json.get(section) is None): + if existing_json.get(section) is None: continue updated = existing_json.get(section) for package, version in existing_json.get(section).items(): - if(package.startswith(DEPENDENCY_NAME) and package in new_json): + if package.startswith(DEPENDENCY_NAME) and package in new_json: # To maintain the existing prefix ~ or ^ - if version[0] in ('^','~'): + if version[0] in ("^", "~"): updated[package] = version[0] + absolute_version(new_json[package]) else: updated[package] = absolute_version(new_json[package]) + def absolute_version(version): - if len(version) > 0 and version[0] in ('^','~'): - return version[1:]; - return version; + if len(version) > 0 and version[0] in ("^", "~"): + return version[1:] + return version def main(): - parser = argparse.ArgumentParser(description='Update dependencies in package.json.') - parser.add_argument('--set-version', dest='new_version', type=str, required=True, help='New version to set for JupyterLab dependencies') - + parser = argparse.ArgumentParser(description="Update dependencies in package.json.") + parser.add_argument( + "--set-version", + dest="new_version", + type=str, + required=True, + help="New version to set for JupyterLab dependencies", + ) + args = parser.parse_args() update_package_json(args.new_version) -if(__name__ == "__main__"): - main() \ No newline at end of file +if __name__ == "__main__": + main() From 9d7ea27588a88431bd57f19375606163c305e41c Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Tue, 27 Feb 2024 18:29:16 +0000 Subject: [PATCH 5/9] Prettier code for Test Lint check --- .github/workflows/upgrade-juypterlab-dependencies.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/upgrade-juypterlab-dependencies.yml b/.github/workflows/upgrade-juypterlab-dependencies.yml index 5edfb91a18..bbf8638e60 100644 --- a/.github/workflows/upgrade-juypterlab-dependencies.yml +++ b/.github/workflows/upgrade-juypterlab-dependencies.yml @@ -4,7 +4,7 @@ on: schedule: - cron: 30 17 * * * workflow_dispatch: - inputs: + inputs: version: description: 'JupyterLab version' default: latest @@ -13,7 +13,7 @@ on: env: version_tag: 'latest' - + permissions: contents: write pull-requests: write @@ -49,8 +49,8 @@ jobs: shell: bash run: | set -eux - for version in ${{ inputs.version || env.version_tag }} - do + for version in ${{ inputs.version || env.version_tag }} + do export LATEST=$(python scripts/get-latest-lab-version.py --set-version $version) done @@ -79,7 +79,7 @@ jobs: git commit . -m "Update to JupyterLab v${LATEST}" - git push --set-upstream origin "${BRANCH_NAME}" + git push --set-upstream origin "${BRANCH_NAME}" hub pull-request -m "Update to JupyterLab v${LATEST}" \ -m "New JupyterLab release [v${LATEST}](https://github.com/jupyterlab/jupyterlab/releases/tag/v${LATEST}) is available. Please review the lock file carefully.". fi From 81e218a9a1a60b61cf23f0fcc315f22e48336a5e Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Sun, 31 Mar 2024 10:17:22 +0000 Subject: [PATCH 6/9] added ts scripts to upgrade lab dependencies --- .../upgrade-juypterlab-dependencies.yml | 37 ++++--- buildutils/src/get-latest-lab-version.ts | 49 ++++++++++ buildutils/src/upgrade-lab-dependencies.ts | 95 ++++++++++++++++++ scripts/get-latest-lab-version.py | 56 ----------- scripts/upgrade-lab-dependencies.py | 98 ------------------- 5 files changed, 166 insertions(+), 169 deletions(-) create mode 100644 buildutils/src/get-latest-lab-version.ts create mode 100644 buildutils/src/upgrade-lab-dependencies.ts delete mode 100644 scripts/get-latest-lab-version.py delete mode 100644 scripts/upgrade-lab-dependencies.py diff --git a/.github/workflows/upgrade-juypterlab-dependencies.yml b/.github/workflows/upgrade-juypterlab-dependencies.yml index bbf8638e60..987d16c85e 100644 --- a/.github/workflows/upgrade-juypterlab-dependencies.yml +++ b/.github/workflows/upgrade-juypterlab-dependencies.yml @@ -33,7 +33,7 @@ jobs: - name: Install required dependencies run: | - python -m pip install requests jupyterlab + python -m pip install jupyterlab sudo apt-get install hub - name: Install Node @@ -41,9 +41,10 @@ jobs: with: node-version: '20.x' - - name: Install npm dependencies + - name: Install npm dependencies and build buildutils run: | jlpm install + jlpm run build:utils - name: Check for new releases and update shell: bash @@ -51,11 +52,11 @@ jobs: set -eux for version in ${{ inputs.version || env.version_tag }} do - export LATEST=$(python scripts/get-latest-lab-version.py --set-version $version) + export LATEST=$(node buildutils/lib/get-latest-lab-version.js --set-version $version) done echo "latest=${LATEST}" >> $GITHUB_ENV - python scripts/upgrade-lab-dependencies.py --set-version ${LATEST} + node buildutils/lib/upgrade-lab-dependencies.js --set-version ${LATEST} if [[ ! -z "$(git status --porcelain package.json)" ]]; then jlpm install fi @@ -67,19 +68,25 @@ jobs: GITHUB_TOKEN: ${{ secrets.G_TOKEN }} run: | set -eux - # if resulted in any change: + export LATEST=${{ env.latest }} - if [[ ! -z "$(git status --porcelain package.json)" ]]; then - export BRANCH_NAME=update-to-v${LATEST} + export BRANCH_NAME=update-to-v${LATEST} - # this will fail if the branch already exists which means we won't have duplicate PRs - git checkout -b "${BRANCH_NAME}" - git config user.name "JupyterLab Desktop Bot" - git config user.email 'jupyterlab-bot@users.noreply.github.com' + # if resulted in any change: + if [[ ! -z "$(git status --porcelain package.json)" ]]; then + # if branch already exists. + if git ls-remote --heads origin | grep "refs/heads/${BRANCH_NAME}$" > /dev/null; then + echo "Branch '${BRANCH_NAME}' exists." + else + # new branch is created + git checkout -b "${BRANCH_NAME}" + git config user.name "Jupyter Bot" + git config user.email 'jupyterlab-bot@users.noreply.github.com' - git commit . -m "Update to JupyterLab v${LATEST}" + git commit . -m "Update to JupyterLab v${LATEST}" - git push --set-upstream origin "${BRANCH_NAME}" - hub pull-request -m "Update to JupyterLab v${LATEST}" \ - -m "New JupyterLab release [v${LATEST}](https://github.com/jupyterlab/jupyterlab/releases/tag/v${LATEST}) is available. Please review the lock file carefully.". + git push --set-upstream origin "${BRANCH_NAME}" + hub pull-request -m "Update to JupyterLab v${LATEST}" \ + -m "New JupyterLab release [v${LATEST}](https://github.com/jupyterlab/jupyterlab/releases/tag/v${LATEST}) is available. Please review the lock file carefully.". + fi fi diff --git a/buildutils/src/get-latest-lab-version.ts b/buildutils/src/get-latest-lab-version.ts new file mode 100644 index 0000000000..46d99c97f0 --- /dev/null +++ b/buildutils/src/get-latest-lab-version.ts @@ -0,0 +1,49 @@ +function extractVersionFromReleases(releases: any, versionTag: string): string | null { + for (const release of releases) { + const tagName: string = release['tag_name']; + if (versionTag === "latest") { + if (!release['prerelease'] && !release['draft']) { + return tagName; + } + } else if (versionTag === tagName) { + return tagName; + } + } + return null; +} + +async function findVersion(versionTag: string): Promise<string> { + const url: string = `https://api.github.com/repos/jupyterlab/jupyterlab/releases`; + const response = await fetch(url); + if (!response.ok) { + const error_message: string = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; + throw new Error(error_message); + } + const releases: any = await response.json(); + const version: string | null = extractVersionFromReleases(releases, versionTag); + if (version === null) { + const error_message: string = "Invalid release tag"; + throw new Error(error_message); + } + return version.substring(1); +} + + +async function getLatestLabVersion(): Promise<void> { + const args: string[] = process.argv.slice(2); + if (args.length !== 2 || args[0] !== '--set-version') { + console.error('Usage: node script.js --set-version <version>'); + process.exit(1); + } + const version_tag: string = args[1]; + + try { + const result: string = await findVersion(version_tag); + console.log(result); + } catch (error:any) { + console.error('Error:', error.message); + process.exit(1); + } +} + +getLatestLabVersion(); diff --git a/buildutils/src/upgrade-lab-dependencies.ts b/buildutils/src/upgrade-lab-dependencies.ts new file mode 100644 index 0000000000..1fde1ce299 --- /dev/null +++ b/buildutils/src/upgrade-lab-dependencies.ts @@ -0,0 +1,95 @@ +import fs from 'fs'; +import path from 'path'; + +const PACKAGE_JSON_PATHS: string[] = [ + "app/package.json", + "buildutils/package.json", + "package.json", + "packages/application-extension/package.json", + "packages/application/package.json", + "packages/console-extension/package.json", + "packages/docmanager-extension/package.json", + "packages/documentsearch-extension/package.json", + "packages/help-extension/package.json", + "packages/lab-extension/package.json", + "packages/notebook-extension/package.json", + "packages/terminal-extension/package.json", + "packages/tree-extension/package.json", + "packages/tree/package.json", + "packages/ui-components/package.json", +]; + +const DEPENDENCY_GROUP: string = "@jupyterlab"; + +async function updatePackageJson(newVersion: string): Promise<void> { + const url: string = `https://raw.githubusercontent.com/jupyterlab/jupyterlab/v${newVersion}/jupyterlab/staging/package.json`; + const response = await fetch(url); + + if (!response.ok) { + const errorMessage: string = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; + throw new Error(errorMessage); + } + + const newPackageJson = await response.json(); + + for (const packageJsonPath of PACKAGE_JSON_PATHS) { + const filePath: string = path.resolve(packageJsonPath); + const existingPackageJson = JSON.parse(fs.readFileSync(filePath, 'utf-8')); + + const newDependencies = { + ...newPackageJson.devDependencies, + ...newPackageJson.resolutions + }; + + updateDependencyVersion(existingPackageJson, newDependencies); + + fs.writeFileSync(filePath, JSON.stringify(existingPackageJson, null, 2)); + } +} + +function updateDependencyVersion(existingJson: any, newJson: any): void { + if (!existingJson) { + return; + } + + const sectionPaths: string[] = ["resolutions", "dependencies", "devDependencies"]; + + for (const section of sectionPaths) { + if (!existingJson[section]) { + continue; + } + + const updated = existingJson[section]; + + for (const [pkg, version] of Object.entries<string>(existingJson[section])) { + if (pkg.startsWith(DEPENDENCY_GROUP) && pkg in newJson) { + if (version[0] === '^' || version[0] === '~') { + updated[pkg] = version[0] + absoluteVersion(newJson[pkg]); + } else { + updated[pkg] = absoluteVersion(newJson[pkg]); + } + } + } + } +} + +function absoluteVersion(version: string): string { + if (version.length > 0 && (version[0] === '^' || version[0] === '~')) { + return version.substring(1); + } + return version; +} + +async function upgradeLabDependencies(): Promise<void> { + const args: string[] = process.argv.slice(2); + + if (args.length !== 2 || args[0] !== '--set-version') { + console.error('Usage: node script.js --set-version <version>'); + process.exit(1); + } + + const newVersion: string = args[1]; + await updatePackageJson(newVersion); +} + +upgradeLabDependencies(); diff --git a/scripts/get-latest-lab-version.py b/scripts/get-latest-lab-version.py deleted file mode 100644 index f4772c2d7d..0000000000 --- a/scripts/get-latest-lab-version.py +++ /dev/null @@ -1,56 +0,0 @@ -import argparse -import sys - -import requests - -REPOSITORY = "jupyterlab" -ORGANIZATION = "jupyterlab" - - -def extract_version_from_releases(releases, version_tag): - for release in releases: - tag_name = release["tag_name"] - if version_tag == "latest": - if not release["prerelease"] and not release["draft"]: - return tag_name - - elif version_tag == tag_name: - return tag_name - return None - - -def find_version(owner, repository, version_tag): - url = f"https://api.github.com/repos/{owner}/{repository}/releases" - - response = requests.get(url, timeout=10) - - if response.status_code != 200: - error_message = ( - f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" - ) - raise requests.HTTPError(error_message) - - releases = response.json() - version = extract_version_from_releases(releases, version_tag) - - if version is None: - error_message = "Invalid release tag" - raise ValueError(error_message) - return version[1:] - - -def main(): - parser = argparse.ArgumentParser(description="Update dependencies in package.json.") - parser.add_argument( - "--set-version", dest="version_tag", type=str, required=True, help="Set version tag" - ) - - args = parser.parse_args() - - result = find_version(owner=ORGANIZATION, repository=REPOSITORY, version_tag=args.version_tag) - sys.stdout.write(result) - sys.stdout.flush() - - -if __name__ == "__main__": - main() diff --git a/scripts/upgrade-lab-dependencies.py b/scripts/upgrade-lab-dependencies.py deleted file mode 100644 index 14d31231d3..0000000000 --- a/scripts/upgrade-lab-dependencies.py +++ /dev/null @@ -1,98 +0,0 @@ -import argparse -import json -from pathlib import Path - -import requests - -PACKAGE_JSON_PATHS = [ - "app/package.json", - "buildutils/package.json", - "package.json", - "packages/application-extension/package.json", - "packages/application/package.json", - "packages/console-extension/package.json", - "packages/docmanager-extension/package.json", - "packages/documentsearch-extension/package.json", - "packages/help-extension/package.json", - "packages/lab-extension/package.json", - "packages/notebook-extension/package.json", - "packages/terminal-extension/package.json", - "packages/tree-extension/package.json", - "packages/tree/package.json", - "packages/ui-components/package.json", -] - -DEPENDENCY_NAME = "@jupyterlab" - - -def update_package_json(new_version): - url = f"https://raw.githubusercontent.com/jupyterlab/jupyterlab/v{new_version}/jupyterlab/staging/package.json" - - response = requests.get(url, timeout=10) - - if response.status_code != 200: - error_message = ( - f"Failed to fetch package.json from {url}. HTTP status code: {response.status_code}" - ) - raise requests.HTTPError(error_message) - - new_package_json = response.json() - - for path in PACKAGE_JSON_PATHS: - file_path = Path(path) - with file_path.open(mode="r") as package_json_file: - existing_package_json = json.load(package_json_file) - - new_dependencies = { - **new_package_json.get("devDependencies", {}), - **new_package_json.get("resolutions", {}), - } - update_dependencies(existing_package_json, new_dependencies) - - with file_path.open(mode="w") as file: - json.dump(existing_package_json, file, indent=2) - file.write("\n") - - -def update_dependencies(existing_json, new_json): - if existing_json is None: - return - - section_paths = ["resolutions", "dependencies", "devDependencies"] - - for section in section_paths: - if existing_json.get(section) is None: - continue - - updated = existing_json.get(section) - for package, version in existing_json.get(section).items(): - if package.startswith(DEPENDENCY_NAME) and package in new_json: - # To maintain the existing prefix ~ or ^ - if version[0] in ("^", "~"): - updated[package] = version[0] + absolute_version(new_json[package]) - else: - updated[package] = absolute_version(new_json[package]) - - -def absolute_version(version): - if len(version) > 0 and version[0] in ("^", "~"): - return version[1:] - return version - - -def main(): - parser = argparse.ArgumentParser(description="Update dependencies in package.json.") - parser.add_argument( - "--set-version", - dest="new_version", - type=str, - required=True, - help="New version to set for JupyterLab dependencies", - ) - - args = parser.parse_args() - update_package_json(args.new_version) - - -if __name__ == "__main__": - main() From 2154f0f039e9a5f3b8c42f94934dc8f6023b7ecd Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Sun, 31 Mar 2024 10:32:43 +0000 Subject: [PATCH 7/9] Prettier code for test lint check --- buildutils/src/get-latest-lab-version.ts | 81 +++++++------ buildutils/src/upgrade-lab-dependencies.ts | 130 +++++++++++---------- 2 files changed, 111 insertions(+), 100 deletions(-) diff --git a/buildutils/src/get-latest-lab-version.ts b/buildutils/src/get-latest-lab-version.ts index 46d99c97f0..166e035a59 100644 --- a/buildutils/src/get-latest-lab-version.ts +++ b/buildutils/src/get-latest-lab-version.ts @@ -1,49 +1,54 @@ -function extractVersionFromReleases(releases: any, versionTag: string): string | null { - for (const release of releases) { - const tagName: string = release['tag_name']; - if (versionTag === "latest") { - if (!release['prerelease'] && !release['draft']) { - return tagName; - } - } else if (versionTag === tagName) { - return tagName; - } +function extractVersionFromReleases( + releases: any, + versionTag: string +): string | null { + for (const release of releases) { + const tagName: string = release['tag_name']; + if (versionTag === 'latest') { + if (!release['prerelease'] && !release['draft']) { + return tagName; + } + } else if (versionTag === tagName) { + return tagName; } - return null; + } + return null; } async function findVersion(versionTag: string): Promise<string> { - const url: string = `https://api.github.com/repos/jupyterlab/jupyterlab/releases`; - const response = await fetch(url); - if (!response.ok) { - const error_message: string = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; - throw new Error(error_message); - } - const releases: any = await response.json(); - const version: string | null = extractVersionFromReleases(releases, versionTag); - if (version === null) { - const error_message: string = "Invalid release tag"; - throw new Error(error_message); - } - return version.substring(1); + const url = 'https://api.github.com/repos/jupyterlab/jupyterlab/releases'; + const response = await fetch(url); + if (!response.ok) { + const error_message = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; + throw new Error(error_message); + } + const releases: any = await response.json(); + const version: string | null = extractVersionFromReleases( + releases, + versionTag + ); + if (version === null) { + const error_message = 'Invalid release tag'; + throw new Error(error_message); + } + return version.substring(1); } - async function getLatestLabVersion(): Promise<void> { - const args: string[] = process.argv.slice(2); - if (args.length !== 2 || args[0] !== '--set-version') { - console.error('Usage: node script.js --set-version <version>'); - process.exit(1); - } - const version_tag: string = args[1]; + const args: string[] = process.argv.slice(2); + if (args.length !== 2 || args[0] !== '--set-version') { + console.error('Usage: node script.js --set-version <version>'); + process.exit(1); + } + const version_tag: string = args[1]; - try { - const result: string = await findVersion(version_tag); - console.log(result); - } catch (error:any) { - console.error('Error:', error.message); - process.exit(1); - } + try { + const result: string = await findVersion(version_tag); + console.log(result); + } catch (error: any) { + console.error('Error:', error.message); + process.exit(1); + } } getLatestLabVersion(); diff --git a/buildutils/src/upgrade-lab-dependencies.ts b/buildutils/src/upgrade-lab-dependencies.ts index 1fde1ce299..570f2d2417 100644 --- a/buildutils/src/upgrade-lab-dependencies.ts +++ b/buildutils/src/upgrade-lab-dependencies.ts @@ -2,94 +2,100 @@ import fs from 'fs'; import path from 'path'; const PACKAGE_JSON_PATHS: string[] = [ - "app/package.json", - "buildutils/package.json", - "package.json", - "packages/application-extension/package.json", - "packages/application/package.json", - "packages/console-extension/package.json", - "packages/docmanager-extension/package.json", - "packages/documentsearch-extension/package.json", - "packages/help-extension/package.json", - "packages/lab-extension/package.json", - "packages/notebook-extension/package.json", - "packages/terminal-extension/package.json", - "packages/tree-extension/package.json", - "packages/tree/package.json", - "packages/ui-components/package.json", + 'app/package.json', + 'buildutils/package.json', + 'package.json', + 'packages/application-extension/package.json', + 'packages/application/package.json', + 'packages/console-extension/package.json', + 'packages/docmanager-extension/package.json', + 'packages/documentsearch-extension/package.json', + 'packages/help-extension/package.json', + 'packages/lab-extension/package.json', + 'packages/notebook-extension/package.json', + 'packages/terminal-extension/package.json', + 'packages/tree-extension/package.json', + 'packages/tree/package.json', + 'packages/ui-components/package.json', ]; -const DEPENDENCY_GROUP: string = "@jupyterlab"; +const DEPENDENCY_GROUP = '@jupyterlab'; async function updatePackageJson(newVersion: string): Promise<void> { - const url: string = `https://raw.githubusercontent.com/jupyterlab/jupyterlab/v${newVersion}/jupyterlab/staging/package.json`; - const response = await fetch(url); + const url = `https://raw.githubusercontent.com/jupyterlab/jupyterlab/v${newVersion}/jupyterlab/staging/package.json`; + const response = await fetch(url); - if (!response.ok) { - const errorMessage: string = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; - throw new Error(errorMessage); - } + if (!response.ok) { + const errorMessage = `Failed to fetch package.json from ${url}. HTTP status code: ${response.status}`; + throw new Error(errorMessage); + } - const newPackageJson = await response.json(); + const newPackageJson = await response.json(); - for (const packageJsonPath of PACKAGE_JSON_PATHS) { - const filePath: string = path.resolve(packageJsonPath); - const existingPackageJson = JSON.parse(fs.readFileSync(filePath, 'utf-8')); + for (const packageJsonPath of PACKAGE_JSON_PATHS) { + const filePath: string = path.resolve(packageJsonPath); + const existingPackageJson = JSON.parse(fs.readFileSync(filePath, 'utf-8')); - const newDependencies = { - ...newPackageJson.devDependencies, - ...newPackageJson.resolutions - }; + const newDependencies = { + ...newPackageJson.devDependencies, + ...newPackageJson.resolutions, + }; - updateDependencyVersion(existingPackageJson, newDependencies); + updateDependencyVersion(existingPackageJson, newDependencies); - fs.writeFileSync(filePath, JSON.stringify(existingPackageJson, null, 2)); - } + fs.writeFileSync(filePath, JSON.stringify(existingPackageJson, null, 2)); + } } function updateDependencyVersion(existingJson: any, newJson: any): void { - if (!existingJson) { - return; + if (!existingJson) { + return; + } + + const sectionPaths: string[] = [ + 'resolutions', + 'dependencies', + 'devDependencies', + ]; + + for (const section of sectionPaths) { + if (!existingJson[section]) { + continue; } - const sectionPaths: string[] = ["resolutions", "dependencies", "devDependencies"]; + const updated = existingJson[section]; - for (const section of sectionPaths) { - if (!existingJson[section]) { - continue; - } - - const updated = existingJson[section]; - - for (const [pkg, version] of Object.entries<string>(existingJson[section])) { - if (pkg.startsWith(DEPENDENCY_GROUP) && pkg in newJson) { - if (version[0] === '^' || version[0] === '~') { - updated[pkg] = version[0] + absoluteVersion(newJson[pkg]); - } else { - updated[pkg] = absoluteVersion(newJson[pkg]); - } - } + for (const [pkg, version] of Object.entries<string>( + existingJson[section] + )) { + if (pkg.startsWith(DEPENDENCY_GROUP) && pkg in newJson) { + if (version[0] === '^' || version[0] === '~') { + updated[pkg] = version[0] + absoluteVersion(newJson[pkg]); + } else { + updated[pkg] = absoluteVersion(newJson[pkg]); } + } } + } } function absoluteVersion(version: string): string { - if (version.length > 0 && (version[0] === '^' || version[0] === '~')) { - return version.substring(1); - } - return version; + if (version.length > 0 && (version[0] === '^' || version[0] === '~')) { + return version.substring(1); + } + return version; } async function upgradeLabDependencies(): Promise<void> { - const args: string[] = process.argv.slice(2); + const args: string[] = process.argv.slice(2); - if (args.length !== 2 || args[0] !== '--set-version') { - console.error('Usage: node script.js --set-version <version>'); - process.exit(1); - } + if (args.length !== 2 || args[0] !== '--set-version') { + console.error('Usage: node script.js --set-version <version>'); + process.exit(1); + } - const newVersion: string = args[1]; - await updatePackageJson(newVersion); + const newVersion: string = args[1]; + await updatePackageJson(newVersion); } upgradeLabDependencies(); From 026ed8b7e2152a59ee5bbdcef3516c555a8f5d4a Mon Sep 17 00:00:00 2001 From: Vishnutheep B <vishnutheep@gmail.com> Date: Tue, 27 Aug 2024 17:20:12 +0530 Subject: [PATCH 8/9] Update buildutils/src/upgrade-lab-dependencies.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: MichaĆ Krassowski <5832902+krassowski@users.noreply.github.com> --- buildutils/src/upgrade-lab-dependencies.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildutils/src/upgrade-lab-dependencies.ts b/buildutils/src/upgrade-lab-dependencies.ts index 570f2d2417..003243f8a8 100644 --- a/buildutils/src/upgrade-lab-dependencies.ts +++ b/buildutils/src/upgrade-lab-dependencies.ts @@ -43,7 +43,7 @@ async function updatePackageJson(newVersion: string): Promise<void> { updateDependencyVersion(existingPackageJson, newDependencies); - fs.writeFileSync(filePath, JSON.stringify(existingPackageJson, null, 2)); + fs.writeFileSync(filePath, JSON.stringify(existingPackageJson, null, 2) + '\n'); } } From f4ef24391f0747c84601022eac8a9a98381e8f6d Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup <jeremy.tuloup@gmail.com> Date: Thu, 19 Dec 2024 20:11:11 +0100 Subject: [PATCH 9/9] Lint --- buildutils/src/upgrade-lab-dependencies.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/buildutils/src/upgrade-lab-dependencies.ts b/buildutils/src/upgrade-lab-dependencies.ts index 003243f8a8..36242c8af8 100644 --- a/buildutils/src/upgrade-lab-dependencies.ts +++ b/buildutils/src/upgrade-lab-dependencies.ts @@ -43,7 +43,10 @@ async function updatePackageJson(newVersion: string): Promise<void> { updateDependencyVersion(existingPackageJson, newDependencies); - fs.writeFileSync(filePath, JSON.stringify(existingPackageJson, null, 2) + '\n'); + fs.writeFileSync( + filePath, + JSON.stringify(existingPackageJson, null, 2) + '\n' + ); } }