From a4f79a13677ec369931e735501b56c86c288b926 Mon Sep 17 00:00:00 2001 From: Valerii Svydenko Date: Tue, 16 Apr 2024 15:36:05 +0300 Subject: [PATCH] feat: set fixed versions for vsix extensions (#1062) * feat: set fixed versions for vsix extensions; add script to update versions Signed-off-by: Valeriy Svydenko * update doenload_vsix script Signed-off-by: Valeriy Svydenko * remove built-in git extension Signed-off-by: Valeriy Svydenko * add depended vscode.git extension Signed-off-by: Valeriy Svydenko * add github action to update versions Signed-off-by: Valeriy Svydenko * update workflow to check new versions each month Signed-off-by: Valeriy Svydenko --------- Signed-off-by: Valeriy Svydenko --- .github/workflows/update-vsix-versions.yaml | 58 +++ .../build/scripts/download_vsix.sh | 176 ++++----- .../scripts/update_extensions_versions.sh | 173 ++++++++ .../che-plugin-registry/openvsx-sync.json | 371 ++++++++++-------- 4 files changed, 516 insertions(+), 262 deletions(-) create mode 100644 .github/workflows/update-vsix-versions.yaml create mode 100755 dependencies/che-plugin-registry/build/scripts/update_extensions_versions.sh diff --git a/.github/workflows/update-vsix-versions.yaml b/.github/workflows/update-vsix-versions.yaml new file mode 100644 index 0000000000..3f0ee26f1b --- /dev/null +++ b/.github/workflows/update-vsix-versions.yaml @@ -0,0 +1,58 @@ +# +# Copyright (c) 2024 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# + +name: Check new versions of VSIX extensions + +on: + schedule: + - cron: '0 0 1 * *' # Run at midnight (00:00) on the 1st day of every month + +jobs: + Check-new-extensions-versions: + runs-on: ubuntu-20.04 + + steps: + + - name: Clone source code + uses: actions/checkout@v3 + with: + fetch-depth: 1 + token: ${{secrets.CRW_BUILD_TOKEN}} + + - name: Validate content + run: | + cd dependencies/che-plugin-registry/build/scripts + ./update_extensions_versions.sh + + - name: Verify Changed files + uses: tj-actions/verify-changed-files@v19 + id: verify-changed-files + with: + files: dependencies/che-plugin-registry/openvsx-sync.json + + - name: Create Pull Request + if: steps.verify-changed-files.outputs.files_changed == 'true' + run: | + # Set up git configuration + export GITHUB_TOKEN=${{ secrets.CRW_BUILD_TOKEN }} + git config user.email "nickboldt+devstudio-release@gmail.com" + git config user.name "devstudio-release" + + # Create a new branch + git checkout -b new-extension-version-branch + + # Add and commit changes + git add . + git commit -m "Auto-generated changes; update vsix extensions versions" + + # Push changes to the remote repository + git push origin new-extension-version-branch + + # Create a pull request + gh pr create --title "chore: Auto-generated PR to update extnesions versions" --body "This pull request was automatically generated by GitHub Actions" --base devspaces-3-rhel-8 diff --git a/dependencies/che-plugin-registry/build/scripts/download_vsix.sh b/dependencies/che-plugin-registry/build/scripts/download_vsix.sh index 2d35e32c39..1a944cc290 100755 --- a/dependencies/che-plugin-registry/build/scripts/download_vsix.sh +++ b/dependencies/che-plugin-registry/build/scripts/download_vsix.sh @@ -5,30 +5,32 @@ trap EXIT set -e set -o pipefail -downloadVsix=1 openvsxJson="/openvsx-server/openvsx-sync.json" -usage() -{ +usage() { echo "Usage: $0 -b devspaces-3.y-rhel-8 -j /path/to/openvsx-sync.json --no-download All arguments are optional. -b|--branch Specify a devspaces branch. Otherwise will be computed from local git directory --j|--json Specify a path for openvsx-sync.json. Default: /openvsx-server/openvsx-sync.json ---no-download Do not download vsix files, only update versions in the openvsx-sync.json" +-j|--json Specify a path for openvsx-sync.json. Default: /openvsx-server/openvsx-sync.json" exit } # commandline args while [[ "$#" -gt 0 ]]; do - case $1 in - '-b'|'--branch') scriptBranch="$2"; shift 1;; - '-j'|'--json') openvsxJson="$2"; shift 1;; - '--no-download') downloadVsix=0;; - '-h'|'--help') usage;; - esac - shift 1 + case $1 in + '-b' | '--branch') + scriptBranch="$2" + shift 1 + ;; + '-j' | '--json') + openvsxJson="$2" + shift 1 + ;; + '-h' | '--help') usage ;; + esac + shift 1 done RED="\e[31m" @@ -43,17 +45,16 @@ DEFAULT_EMOJI_FAIL="✘" # could be overriden with EMOJI_FAIL="[FAIL]" EMOJI_FAIL=${EMOJI_FAIL:-$DEFAULT_EMOJI_FAIL} function initTest() { - echo -n -e "${BOLD}\n${EMOJI_HEADER} ${1}${RESETSTYLE} ... " + echo -n -e "${BOLD}\n${EMOJI_HEADER} ${1}${RESETSTYLE} ... " } vsixMetadata="" #now global so it can be set/checked via function -getMetadata(){ +getMetadata() { vsixName=$1 key=$2 # check there is no error field in the metadata and retry if there is - for j in 1 2 3 4 5 - do + for j in 1 2 3 4 5; do vsixMetadata=$(curl -sLS "https://open-vsx.org/api/${vsixName}/${key}") if [[ $(echo "${vsixMetadata}" | jq -r ".error") != null ]]; then echo "Attempt $j/5: Error while getting metadata for ${vsixName} version ${key}" @@ -70,11 +71,10 @@ getMetadata(){ } versionsPage="" -getVersions(){ +getVersions() { vsixName=$1 # check the versions page is empty and retry if it is - for j in 1 2 3 4 5 - do + for j in 1 2 3 4 5; do versionsPage=$(curl -sLS "https://open-vsx.org/api/${vsixName}/versions?size=200") totalSize=$(echo "${versionsPage}" | jq -r ".totalSize") if [[ "$totalSize" != "null" && "$totalSize" -eq 0 ]]; then @@ -106,7 +106,7 @@ fi mkdir -p /tmp/vsix openVsxSyncFileContent=$(cat "$openvsxJson") numberOfExtensions=$(echo "${openVsxSyncFileContent}" | jq ". | length") -IFS=$'\n' +IFS=$'\n' for i in $(seq 0 "$((numberOfExtensions - 1))"); do vsixFullName=$(echo "${openVsxSyncFileContent}" | jq -r ".[$i].id") @@ -124,63 +124,35 @@ for i in $(seq 0 "$((numberOfExtensions - 1))"); do # grab metadata for the vsix file # if version wasn't set, use latest if [[ $vsixVersion == null ]]; then - getVersions "${vsixName}" + echo "Version is not set for ${vsixName}" + exit 1 + fi - # if version wasn't set in json, grab it from metadata and add it into the file - # get all versions of the extension - allVersions=$(echo "${versionsPage}" | jq -r '.versions') - if [[ "$allVersions" == "{}" ]]; then - echo "No versions found for ${vsixName}" - exit 1 - fi - key_value_pairs=$(echo "$allVersions" | jq -r 'to_entries[] | [ .key, .value ] | @tsv') - - # go through all versions of the extension to find the latest stable version that is compatible with the VS Code version - resultedVersion=null - while IFS=$'\t' read -r key value; do - # get metadata for the version - getMetadata "${vsixName}" "${key}" - - # check if the version is pre-release - preRelease=$(echo "${vsixMetadata}" | jq -r '.preRelease') - if [[ $preRelease == true ]]; then - echo "Skipping pre-release version ${value}" - continue - fi - - # extract the engine version from the json metadata - vscodeEngineVersion=$(echo "${vsixMetadata}" | jq -r '.engines.vscode') - # remove ^ from the engine version - vscodeEngineVersion="${vscodeEngineVersion//^/}" - # remove >= from the engine version - vscodeEngineVersion="${vscodeEngineVersion//>=/}" - # replace x by 0 in the engine version - vscodeEngineVersion="${vscodeEngineVersion//x/0}" - # check if the extension's engine version is compatible with the code version - # if the extension's engine version is ahead of the code version, check a next version of the extension - if [[ "$vscodeEngineVersion" = "$(echo -e "$vscodeEngineVersion\n$codeVersion" | sort -V | head -n1)" ]]; then - #VS Code version >= Engine version, can proceed." - resultedVersion=$(echo "${vsixMetadata}" | jq -r ".version") - break - else - echo "Skipping ${value}, it is not compatible with VS Code editor $codeVersion" - continue - fi - done <<< "$key_value_pairs" - - if [[ $resultedVersion == null ]]; then - echo "[ERROR] No stable version of $vsixFullName is compatible with VS Code editor verision $codeVersion; must exit!" - exit 1 - else - vsixVersion=$resultedVersion - fi + # get metadata for the version + getMetadata "${vsixName}" "${vsixVersion}" + + # check if the version is pre-release + preRelease=$(echo "${vsixMetadata}" | jq -r '.preRelease') + if [[ $preRelease == true ]]; then + echo "Version ${vsixVersion} is marked as pre-release for ${vsixName}, it should be stable one" + exit 1 + fi + + # extract the engine version from the json metadata + vscodeEngineVersion=$(echo "${vsixMetadata}" | jq -r '.engines.vscode') + # remove ^ from the engine version + vscodeEngineVersion="${vscodeEngineVersion//^/}" + # remove >= from the engine version + vscodeEngineVersion="${vscodeEngineVersion//>=/}" + # replace x by 0 in the engine version + vscodeEngineVersion="${vscodeEngineVersion//x/0}" + # check if the extension's engine version is compatible with the code version + # if the extension's engine version is ahead of the code version, print an error + if [[ "$vscodeEngineVersion" != "$(echo -e "$vscodeEngineVersion\n$codeVersion" | sort -V | head -n1)" ]]; then + echo "Version ${vsixVersion} of ${vsixName} is not compatible with VS Code editor $codeVersion" + exit 1 + fi - jq --argjson i "$i" --arg version "$vsixVersion" '.[$i] += { "version": $version }' "$openvsxJson" > tmp.json - mv tmp.json "$openvsxJson" - else - getMetadata "${vsixName}" "${vsixVersion}" - fi - # extract the download link from the json metadata vsixDownloadLink=$(echo "${vsixMetadata}" | jq -r '.files.download') # get universal download link @@ -196,32 +168,30 @@ for i in $(seq 0 "$((numberOfExtensions - 1))"); do fi fi - if [[ $downloadVsix = 1 ]]; then - echo "Downloading ${vsixDownloadLink} into ${vsixPublisher} folder..." - vsixFilename="/tmp/vsix/${vsixFullName}-${vsixVersion}.vsix" - # download the latest vsix file in the publisher directory - curl -sLS "${vsixDownloadLink}" -o "${vsixFilename}" - - initTest "Checking $vsixFilename" - - # Extract the supported version of VS Code engine from the package.json - vscodeEngineVersion=$(unzip -p "$vsixFilename" "extension/package.json" | jq -r '.engines.vscode') - - # remove ^ from the engine version - vscodeEngineVersion="${vscodeEngineVersion//^/}" - # remove >= from the engine version - vscodeEngineVersion="${vscodeEngineVersion//>=/}" - # replace x by 0 in the engine version - vscodeEngineVersion="${vscodeEngineVersion//x/0}" - # check if the extension's engine version is compatible with the code version - # if the extension's engine version is ahead of the code version, check a next version of the extension - if [[ "$vscodeEngineVersion" = "$(echo -e "$vscodeEngineVersion\n$codeVersion" | sort -V | head -n1)" ]]; then - #VS Code version >= Engine version, can proceed." - echo -e "${GREEN}${EMOJI_PASS}${RESETSTYLE} compatible." - else - echo -e "Extension requires a newer engine version than Che Code version ($codeVersion)." - echo -e "${RED}${EMOJI_FAIL}${RESETSTYLE} Test failed!" - exit 1 - fi + echo "Downloading ${vsixDownloadLink} into ${vsixPublisher} folder..." + vsixFilename="/tmp/vsix/${vsixFullName}-${vsixVersion}.vsix" + # download the latest vsix file in the publisher directory + curl -sLS "${vsixDownloadLink}" -o "${vsixFilename}" + + initTest "Checking $vsixFilename" + + # Extract the supported version of VS Code engine from the package.json + vscodeEngineVersion=$(unzip -p "$vsixFilename" "extension/package.json" | jq -r '.engines.vscode') + + # remove ^ from the engine version + vscodeEngineVersion="${vscodeEngineVersion//^/}" + # remove >= from the engine version + vscodeEngineVersion="${vscodeEngineVersion//>=/}" + # replace x by 0 in the engine version + vscodeEngineVersion="${vscodeEngineVersion//x/0}" + # check if the extension's engine version is compatible with the code version + # if the extension's engine version is ahead of the code version, check a next version of the extension + if [[ "$vscodeEngineVersion" = "$(echo -e "$vscodeEngineVersion\n$codeVersion" | sort -V | head -n1)" ]]; then + #VS Code version >= Engine version, can proceed." + echo -e "${GREEN}${EMOJI_PASS}${RESETSTYLE} compatible." + else + echo -e "Extension requires a newer engine version than Che Code version ($codeVersion)." + echo -e "${RED}${EMOJI_FAIL}${RESETSTYLE} Test failed!" + exit 1 fi -done; +done diff --git a/dependencies/che-plugin-registry/build/scripts/update_extensions_versions.sh b/dependencies/che-plugin-registry/build/scripts/update_extensions_versions.sh new file mode 100755 index 0000000000..12bef31ef9 --- /dev/null +++ b/dependencies/che-plugin-registry/build/scripts/update_extensions_versions.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# The script checks the available versions from openvsx.org +# and updates them in the list of extensions that are going to be included into the embedded plugin registry + +trap EXIT + +set -e +set -o pipefail + +GREEN="\e[32m" +RESETSTYLE="\e[0m" +BOLD="\e[1m" +DEFAULT_EMOJI_HEADER="🏃" # could be overiden with EMOJI_HEADER="-" +EMOJI_HEADER=${EMOJI_HEADER:-$DEFAULT_EMOJI_HEADER} +DEFAULT_EMOJI_PASS="✔" # could be overriden with EMOJI_PASS="[PASS]" +EMOJI_PASS=${EMOJI_PASS:-$DEFAULT_EMOJI_PASS} +DEFAULT_EMOJI_FAIL="✘" # could be overriden with EMOJI_FAIL="[FAIL]" +EMOJI_FAIL=${EMOJI_FAIL:-$DEFAULT_EMOJI_FAIL} + +function initMessage() { + echo -e "${BOLD}\n${EMOJI_HEADER} ${1}${RESETSTYLE}" +} + +echo -e "${BOLD}\n${EMOJI_HEADER}${EMOJI_HEADER}${EMOJI_HEADER} Check new versions for extensions from openvsx_sync.json: ${BASH_SOURCE[0]}${RESETSTYLE}" + +# Get version of the editor +scriptBranch=$(git rev-parse --abbrev-ref HEAD) +echo "Dev Spaces version=${scriptBranch}" +codeVersion=$(curl -sSlko- https://raw.githubusercontent.com/redhat-developer/devspaces-images/"${scriptBranch}"/devspaces-code/code/package.json | jq -r '.version') +echo "Che Code version=${codeVersion}" + +# Check if the information about the current branch is empty +if [[ -z "$scriptBranch" ]]; then + echo -e "The branch is not defined. It is not possible to get Che Code version." + exit 1 +fi + +################################################################ +vsixMetadata="" +getMetadata() { + vsixName=$1 + key=$2 + + # check there is no error field in the metadata and retry if there is + for j in 1 2 3 4 5; do + vsixMetadata=$(curl -sLS "https://open-vsx.org/api/${vsixName}/${key}") + if [[ $(echo "${vsixMetadata}" | jq -r ".error") != null ]]; then + echo "Attempt $j/5: Error while getting metadata for ${vsixName} version ${key}" + + if [[ $j -eq 5 ]]; then + echo "[ERROR] Maximum of 5 attempts reached - must exit!" + exit 1 + fi + continue + else + break + fi + done +} + +versionsPage="" +getVersions() { + vsixName=$1 + # check the versions page is empty and retry if it is + for j in 1 2 3 4 5; do + versionsPage=$(curl -sLS "https://open-vsx.org/api/${vsixName}/versions?size=200") + totalSize=$(echo "${versionsPage}" | jq -r ".totalSize") + if [[ "$totalSize" != "null" && "$totalSize" -eq 0 ]]; then + echo "Attempt $j/5: Error while getting versions for ${vsixName}" + + if [[ $j -eq 5 ]]; then + echo "[ERROR] Maximum of 5 attempts reached - must exit!" + exit 1 + fi + continue + else + break + fi + done +} +openvsxJson="../../openvsx-sync.json" +openVsxSyncFileContent=$(cat "${openvsxJson}") + +numberOfExtensions=$(echo "${openVsxSyncFileContent}" | jq ". | length") +echo "The number of extensions is $numberOfExtensions" +IFS=$'\n' + +for i in $(seq 0 "$((numberOfExtensions - 1))"); do + vsixFullName=$(echo "${openVsxSyncFileContent}" | jq -r ".[$i].id") + vsixUpdate=$(echo "${openVsxSyncFileContent}" | jq -r ".[$i].update") + if [[ $vsixUpdate == false ]]; then + echo -e "${BOLD}\nSkipping ${vsixFullName}${RESETSTYLE}" + continue + fi + vsixVersion=$(echo "${openVsxSyncFileContent}" | jq -r ".[$i].version") + vsixDownloadLink=$(echo "${openVsxSyncFileContent}" | jq -r ".[$i].download") + # replace the dot by / in the vsix name + vsixName=$(echo "${vsixFullName}" | sed 's/\./\//g') + + initMessage "Checking for a new version: $vsixFullName" + + # version should not be empty if download link was set + if [[ $vsixDownloadLink != null ]] && [[ -z "$vsixVersion" ]]; then + echo -e "Version should not be empty for $vsixFullName" + exit 1 + fi + + # if download wasn't set, try to fetch from openvsx.org + if [[ $vsixDownloadLink == null ]]; then + # grab metadata for the vsix file + getVersions "${vsixName}" + + # if version wasn't set in json, grab it from metadata and add it into the file + # get all versions of the extension + allVersions=$(echo "${versionsPage}" | jq -r '.versions') + if [[ "$allVersions" == "{}" ]]; then + echo "No versions found for ${vsixName}" + exit 1 + fi + key_value_pairs=$(echo "$allVersions" | jq -r 'to_entries[] | [ .key, .value ] | @tsv') + + # go through all versions of the extension to find the latest stable version that is compatible with the VS Code version + resultedVersion=null + while IFS=$'\t' read -r key value; do + # get metadata for the version + getMetadata "${vsixName}" "${key}" + + # check if the version is pre-release + preRelease=$(echo "${vsixMetadata}" | jq -r '.preRelease') + if [[ $preRelease == true ]]; then + echo "Skipping pre-release version ${value}" + continue + fi + + # extract the engine version from the json metadata + vscodeEngineVersion=$(echo "${vsixMetadata}" | jq -r '.engines.vscode') + # remove ^ from the engine version + vscodeEngineVersion="${vscodeEngineVersion//^/}" + # remove >= from the engine version + vscodeEngineVersion="${vscodeEngineVersion//>=/}" + # replace x by 0 in the engine version + vscodeEngineVersion="${vscodeEngineVersion//x/0}" + # check if the extension's engine version is compatible with the code version + # if the extension's engine version is ahead of the code version, check a next version of the extension + if [[ "$vscodeEngineVersion" = "$(echo -e "$vscodeEngineVersion\n$codeVersion" | sort -V | head -n1)" ]]; then + #VS Code version >= Engine version, can proceed." + resultedVersion=$(echo "${vsixMetadata}" | jq -r ".version") + break + else + echo "Skipping ${value}, it is not compatible with VS Code editor $codeVersion" + continue + fi + done <<<"$key_value_pairs" + + if [[ $resultedVersion == null ]]; then + echo "[ERROR] No stable version of $vsixFullName is compatible with VS Code editor verision $codeVersion; must exit!" + exit 1 + else + vsixVersion=$resultedVersion + fi + + jq --argjson i "$i" --arg version "$vsixVersion" '.[$i] += { "version": $version }' "$openvsxJson" >tmp.json + mv tmp.json "$openvsxJson" + fi + +done + +echo -e "${GREEN}${EMOJI_PASS}${RESETSTYLE} Finished checking new versions!" diff --git a/dependencies/che-plugin-registry/openvsx-sync.json b/dependencies/che-plugin-registry/openvsx-sync.json index 0ccfcbe504..7d73876678 100644 --- a/dependencies/che-plugin-registry/openvsx-sync.json +++ b/dependencies/che-plugin-registry/openvsx-sync.json @@ -1,161 +1,214 @@ [ - { - "id": "donjayamanne.githistory" - }, - { - "id": "yzane.markdown-pdf" - }, - { - "id": "DavidAnson.vscode-markdownlint" - }, - { - "id": "robocorp.robotframework-lsp" - }, - { - "id": "shardulm94.trailing-spaces" - }, - { - "id": "adamhartford.vscode-base64" - }, - { - "id": "usernamehw.indent-one-space" - }, - { - "id": "redhat.vscode-xml" - }, - { - "id": "redhat.vscode-yaml" - }, - { - "id": "vscode.github-authentication" - }, - { - "id": "GitHub.vscode-pull-request-github" - }, - { - "id": "vscode.typescript-language-features" - }, - { - "id": "llvm-vs-code-extensions.vscode-clangd" - }, - { - "id": "eclipse-cdt.cdt-gdb-vscode" - }, - { - "id": "bmewburn.vscode-intelephense-client" - }, - { - "id": "ms-python.python" - }, - { - "id": "ms-python.black-formatter" - }, - { - "id": "ms-python.isort" - }, - { - "id": "ms-toolsai.jupyter" - }, - { - "id": "ms-toolsai.jupyter-keymap" - }, - { - "id": "ms-toolsai.jupyter-renderers" - }, - { - "id": "ms-toolsai.vscode-jupyter-cell-tags" - }, - { - "id": "ms-toolsai.vscode-jupyter-slideshow" - }, - { - "id": "golang.Go" - }, - { - "id": "ms-kubernetes-tools.vscode-kubernetes-tools" - }, - { - "id": "redhat.java" - }, - { - "id": "vscjava.vscode-java-debug" - }, - { - "id": "vscjava.vscode-java-test" - }, - { - "id": "redhat.vscode-microprofile" - }, - { - "id": "vscode.html-language-features" - }, - { - "id": "redhat.vscode-quarkus" - }, - { - "id": "redhat.fabric8-analytics" - }, - { - "id": "redhat.vscode-redhat-account" - }, - { - "id": "redhat.vscode-openshift-connector" - }, - { - "id": "xdebug.php-debug" - }, - { - "id": "ms-dotnettools.vscode-dotnet-runtime" - }, - { - "id": "muhammad-sammy.csharp" - }, - { - "id": "SonarSource.sonarlint-vscode" - }, - { - "id": "vscode.git-base" - }, - { - "id": "vscode.git" - }, - { - "id": "dbaeumer.vscode-eslint" - }, - { - "id": "redhat.vscode-commons" - }, - { - "id": "redhat.vscode-tekton-pipelines" - }, - { - "id": "atlassian.atlascode" - }, - { - "id": "JFrog.jfrog-vscode-extension" - }, - { - "id": "SonatypeCommunity.vscode-iq-plugin" - }, - { - "id": "GitLab.gitlab-workflow" - }, - { - "id": "timonwong.shellcheck" - }, - { - "id": "redhat.ansible" - }, - { - "id": "vscode.npm" - }, - { - "id": "esbenp.prettier-vscode" - }, - { - "id": "eamodio.gitlens" - }, - { - "id": "Continue.continue" - } + { + "id": "donjayamanne.githistory", + "version": "0.6.20" + }, + { + "id": "yzane.markdown-pdf", + "version": "1.5.0" + }, + { + "id": "DavidAnson.vscode-markdownlint", + "version": "0.54.0" + }, + { + "id": "robocorp.robotframework-lsp", + "version": "1.11.0" + }, + { + "id": "shardulm94.trailing-spaces", + "version": "0.4.1" + }, + { + "id": "adamhartford.vscode-base64", + "version": "0.1.0" + }, + { + "id": "usernamehw.indent-one-space", + "version": "0.3.0" + }, + { + "id": "redhat.vscode-xml", + "version": "0.26.1" + }, + { + "id": "redhat.vscode-yaml", + "version": "1.14.0" + }, + { + "id": "vscode.github-authentication", + "version": "1.83.1" + }, + { + "id": "GitHub.vscode-pull-request-github", + "version": "0.86.0" + }, + { + "id": "vscode.typescript-language-features", + "version": "1.83.1" + }, + { + "id": "llvm-vs-code-extensions.vscode-clangd", + "version": "0.1.28" + }, + { + "id": "eclipse-cdt.cdt-gdb-vscode", + "version": "0.0.108" + }, + { + "id": "bmewburn.vscode-intelephense-client", + "version": "1.10.4" + }, + { + "id": "ms-python.python", + "version": "2024.2.1" + }, + { + "id": "ms-python.black-formatter", + "version": "2024.2.0" + }, + { + "id": "ms-python.isort", + "version": "2023.10.1" + }, + { + "id": "ms-toolsai.jupyter", + "version": "2023.9.100" + }, + { + "id": "ms-toolsai.jupyter-keymap", + "version": "1.1.2" + }, + { + "id": "ms-toolsai.jupyter-renderers", + "version": "1.0.17" + }, + { + "id": "ms-toolsai.vscode-jupyter-cell-tags", + "version": "0.1.9" + }, + { + "id": "ms-toolsai.vscode-jupyter-slideshow", + "version": "0.1.6" + }, + { + "id": "golang.Go", + "version": "0.41.2" + }, + { + "id": "ms-kubernetes-tools.vscode-kubernetes-tools", + "version": "1.3.16" + }, + { + "id": "redhat.java", + "version": "1.29.0" + }, + { + "id": "vscjava.vscode-java-debug", + "version": "0.57.0" + }, + { + "id": "vscjava.vscode-java-test", + "version": "0.41.0" + }, + { + "id": "redhat.vscode-microprofile", + "version": "0.11.0" + }, + { + "id": "vscode.html-language-features", + "version": "1.83.1" + }, + { + "id": "redhat.vscode-quarkus", + "version": "1.17.0" + }, + { + "id": "redhat.fabric8-analytics", + "version": "0.9.4" + }, + { + "id": "redhat.vscode-redhat-account", + "version": "0.2.0" + }, + { + "id": "redhat.vscode-openshift-connector", + "version": "1.12.0" + }, + { + "id": "xdebug.php-debug", + "version": "1.34.0" + }, + { + "id": "ms-dotnettools.vscode-dotnet-runtime", + "version": "2.0.3" + }, + { + "id": "muhammad-sammy.csharp", + "version": "2.22.5" + }, + { + "id": "SonarSource.sonarlint-vscode", + "version": "4.4.2" + }, + { + "id": "vscode.git-base", + "version": "1.83.1" + }, + { + "id": "vscode.git", + "version": "1.83.1" + }, + { + "id": "dbaeumer.vscode-eslint", + "version": "2.4.4" + }, + { + "id": "redhat.vscode-commons", + "version": "0.0.6" + }, + { + "id": "redhat.vscode-tekton-pipelines", + "version": "1.0.1" + }, + { + "id": "atlassian.atlascode", + "version": "3.0.10" + }, + { + "id": "JFrog.jfrog-vscode-extension", + "version": "2.9.6" + }, + { + "id": "SonatypeCommunity.vscode-iq-plugin", + "version": "1.3.4" + }, + { + "id": "GitLab.gitlab-workflow", + "version": "4.8.0" + }, + { + "id": "timonwong.shellcheck", + "version": "0.37.0" + }, + { + "id": "redhat.ansible", + "version": "24.4.0" + }, + { + "id": "vscode.npm", + "version": "1.83.1" + }, + { + "id": "esbenp.prettier-vscode", + "version": "10.4.0" + }, + { + "id": "eamodio.gitlens", + "version": "14.9.0" + }, + { + "id": "Continue.continue", + "version": "0.8.22" + } ]