diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 87513b7cee1d..7cc5663e9f42 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -16,8 +16,6 @@ updates: interval: "monthly" time: "06:00" timezone: "America/Chicago" - commit-message: - prefix: "chore" labels: [] ignore: # Ignore patch updates for all dependencies diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b64c12359b4c..e12411acca60 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -25,7 +25,7 @@ jobs: docs: ${{ steps.filter.outputs.docs }} helm: ${{ steps.filter.outputs.helm }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 id: filter with: @@ -55,7 +55,7 @@ jobs: name: Run prettier check runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version @@ -72,7 +72,7 @@ jobs: needs: changes if: needs.changes.outputs.docs == 'true' steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version @@ -89,7 +89,7 @@ jobs: needs: changes if: needs.changes.outputs.helm == 'true' steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -103,7 +103,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version @@ -121,7 +121,7 @@ jobs: if: needs.changes.outputs.ci == 'true' steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Check workflow files run: | bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9 @@ -134,7 +134,7 @@ jobs: needs: changes if: needs.changes.outputs.code == 'true' steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version @@ -144,7 +144,7 @@ jobs: test/package-lock.json - run: SKIP_SUBMODULE_DEPS=1 npm ci - run: npm run test:unit - - uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5 + - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 if: success() with: token: ${{ secrets.CODECOV_TOKEN }} @@ -163,12 +163,12 @@ jobs: steps: - run: sudo apt update && sudo apt install -y libkrb5-dev - - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest + - uses: awalsh128/cache-apt-pkgs-action@681749ae568c81c2037cb9185e38b709b261bd2f # latest with: packages: quilt version: 1.0 - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: submodules: true - run: quilt push -a @@ -191,7 +191,7 @@ jobs: # embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild. - name: Fetch prebuilt linux-x64 Code package from cache id: cache-vscode - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: lib/vscode-reh-web-linux-x64 key: vscode-linux-x64-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }} @@ -219,7 +219,7 @@ jobs: if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true' steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version @@ -256,7 +256,7 @@ jobs: steps: - name: Cache Caddy - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 id: caddy-cache with: path: | @@ -269,7 +269,7 @@ jobs: mkdir -p ~/.cache/caddy tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version diff --git a/.github/workflows/installer.yaml b/.github/workflows/installer.yaml index a77a5fd61919..9b4ab9018ff1 100644 --- a/.github/workflows/installer.yaml +++ b/.github/workflows/installer.yaml @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Install code-server run: ./install.sh @@ -44,7 +44,7 @@ jobs: container: "alpine:3.17" steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Install curl run: apk add curl @@ -67,7 +67,7 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Install code-server run: ./install.sh diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 64355ee0dcd8..76a7c78533bc 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -33,7 +33,7 @@ jobs: run: | echo "VERSION=${TAG#v}" >> $GITHUB_ENV - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version-file: .node-version @@ -64,7 +64,7 @@ jobs: echo "VERSION=${TAG#v}" >> $GITHUB_ENV - name: Checkout code-server-aur repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: repository: "cdrci/code-server-aur" token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }} @@ -93,9 +93,9 @@ jobs: run: | git checkout -b update-version-${{ env.VERSION }} git add . - git commit -m "chore: updating version to ${{ env.VERSION }}" + git commit -m "Update to ${{ env.VERSION }}" git push -u origin $(git branch --show) - gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR + gh pr create --repo coder/code-server-aur --title "Update to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR docker: runs-on: ubuntu-latest @@ -108,9 +108,9 @@ jobs: run: | echo "VERSION=${TAG#v}" >> $GITHUB_ENV - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 - - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 + - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 with: @@ -149,7 +149,7 @@ jobs: run: | echo "VERSION=${TAG#v}" >> $GITHUB_ENV - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - run: ./ci/build/update-repo.sh @@ -164,4 +164,4 @@ jobs: gh pr create \ --repo coder/code-server \ --body-file .cache/checklist \ - --title "Update to $VERSION" + --title "Update Helm chart and changelog with $VERSION" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 31589fa7ffa5..ce69cd72c9f7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -59,7 +59,7 @@ jobs: steps: - run: sudo apt update && sudo apt install -y libkrb5-dev - - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest + - uses: awalsh128/cache-apt-pkgs-action@681749ae568c81c2037cb9185e38b709b261bd2f # latest with: packages: quilt version: 1.0 @@ -76,7 +76,7 @@ jobs: version=4${version:1} echo "VERSION=$version" >> $GITHUB_ENV - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: submodules: true - run: quilt push -a @@ -110,7 +110,7 @@ jobs: - run: | sed "/^## Unreleased/,/^## / ! d" CHANGELOG.md | head -n -2 | tail -n +3 > .cache/release-notes if: ${{ matrix.vscode_arch == 'x64' }} - - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 + - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 if: ${{ matrix.vscode_arch == 'x64' }} with: draft: true @@ -123,7 +123,7 @@ jobs: # Platform-specific release. - run: KEEP_MODULES=1 npm run release - run: npm run package - - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 + - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 with: draft: true discussion_category_name: "📣 Announcements" @@ -170,7 +170,7 @@ jobs: version=4${version:1} echo "VERSION=$version" >> $GITHUB_ENV - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: submodules: true - run: quilt push -a @@ -189,7 +189,7 @@ jobs: - run: npm run test:native - run: npm run package - - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1 + - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 with: draft: true discussion_category_name: "📣 Announcements" diff --git a/.github/workflows/scripts.yaml b/.github/workflows/scripts.yaml index 4ebef47ea875..1c671c48fa90 100644 --- a/.github/workflows/scripts.yaml +++ b/.github/workflows/scripts.yaml @@ -41,7 +41,7 @@ jobs: container: "alpine:3.17" steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Install test utilities run: apk add bats checkbashisms @@ -58,7 +58,7 @@ jobs: timeout-minutes: 5 steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Install lint utilities run: sudo apt install shellcheck diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml index ba4bcbba5da1..7671a094e6d5 100644 --- a/.github/workflows/security.yaml +++ b/.github/workflows/security.yaml @@ -25,7 +25,7 @@ jobs: timeout-minutes: 15 steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: fetch-depth: 0 @@ -46,7 +46,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout repo - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: fetch-depth: 0 @@ -62,7 +62,7 @@ jobs: severity: "HIGH,CRITICAL" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 with: sarif_file: "trivy-repo-results.sarif" @@ -76,17 +76,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 with: config-file: ./.github/codeql-config.yml languages: javascript - name: Autobuild - uses: github/codeql-action/autobuild@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4 + uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 diff --git a/.github/workflows/trivy-docker.yaml b/.github/workflows/trivy-docker.yaml index 98a8d8c4063f..26bf15886948 100644 --- a/.github/workflows/trivy-docker.yaml +++ b/.github/workflows/trivy-docker.yaml @@ -46,7 +46,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Run Trivy vulnerability scanner in image mode uses: aquasecurity/trivy-action@314ff8b43182423b84c50b1670b0e10f858f2d98 # latest @@ -58,6 +58,6 @@ jobs: severity: "HIGH,CRITICAL" - name: Upload Trivy scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4 with: sarif_file: "trivy-image-results.sarif" diff --git a/.github/workflows/update.yaml b/.github/workflows/update.yaml index 3ea12c5d9e07..461a31e1b40d 100644 --- a/.github/workflows/update.yaml +++ b/.github/workflows/update.yaml @@ -28,7 +28,7 @@ jobs: run: | echo "VERSION=${TAG#v}" >> $GITHUB_ENV - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: submodules: true @@ -47,7 +47,7 @@ jobs: echo done=false >> $GITHUB_OUTPUT fi - - uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest + - uses: awalsh128/cache-apt-pkgs-action@681749ae568c81c2037cb9185e38b709b261bd2f # latest if: steps.check.outputs.done == 'false' with: packages: quilt diff --git a/.node-version b/.node-version index 5bf4400f2292..1dd37d53743d 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -24.15.0 +24.17.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dbab3c87315..57416d3c64f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,54 @@ Code v99.99.999 ## Unreleased +## [4.128.0](https://github.com/coder/code-server/releases/tag/v4.128.0) - 2026-07-11 + +Code v1.128.0 + +### Changed + +- Update to Code 1.128.0 + +## [4.127.0](https://github.com/coder/code-server/releases/tag/v4.127.0) - 2026-07-02 + +Code v1.127.0 + +### Changed + +- Update to Code 1.127.0 + +## [4.126.0](https://github.com/coder/code-server/releases/tag/v4.126.0) - 2026-06-24 + +Code v1.126.0 + +### Changed + +- Update to Code 1.126.0 + +## [4.125.0](https://github.com/coder/code-server/releases/tag/v4.125.0) - 2026-06-18 + +Code v1.125.0 + +### Changed + +- Update to Code 1.125.0 + +## [4.124.2](https://github.com/coder/code-server/releases/tag/v4.124.2) - 2026-06-16 + +Code v1.124.2 + +### Security + +- Strip code-server's session token from the cookie before proxying to a local + port. Previously, when you used built-in password authentication, the cookie + would be sent to the local proxied port, which meant if the service was + malicious and not already running as your code-server user it could use the + cookie to log into code-server and execute commands as your code-server user. + +### Changed + +- Update to Code 1.124.2 + ## [4.123.0](https://github.com/coder/code-server/releases/tag/v4.123.0) - 2026-06-03 Code v1.123.0 diff --git a/ci/build/build-release.sh b/ci/build/build-release.sh index 30dcfef6399e..6dbc2784acbc 100755 --- a/ci/build/build-release.sh +++ b/ci/build/build-release.sh @@ -130,7 +130,7 @@ bundle_vscode() { # dependencies, since we want to ship this via NPM. # Also override the name to prevent vulnerability scanners from # misidentifying this package as VS Code (see #7071). - jq --slurp '.[0] * .[1] | .name = "code-oss-dev"' \ + jq --slurp '.[0] * .[1] | .name = "code-oss"' \ "$VSCODE_SRC_PATH/remote/package.json" \ "$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged" mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json" diff --git a/ci/build/update-vscode.sh b/ci/build/update-vscode.sh index 26a43cd9b4cb..bc4eddbe068c 100755 --- a/ci/build/update-vscode.sh +++ b/ci/build/update-vscode.sh @@ -42,6 +42,8 @@ function refresh_patches() { function update_node() { local node_version node_version=$(cat .node-version) + local target_node_version + target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"') if [[ $node_version == "$target_node_version" ]] ; then echo "Already set to $target_node_version" else @@ -116,9 +118,6 @@ function main() { source ./ci/lib.sh - local target_node_version - target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"') - declare -a steps # If version is not set, assume we are already at the target version and the @@ -141,7 +140,7 @@ function main() { fi steps+=( - "Set Node version to $target_node_version" "update_node" + "Update Node version" "update_node" "Update CSP webview hash" "update_csp" "Add changelog note" "add_changelog" ) diff --git a/ci/helm-chart/Chart.yaml b/ci/helm-chart/Chart.yaml index 60f9b1720cf8..6d1bda0f3678 100644 --- a/ci/helm-chart/Chart.yaml +++ b/ci/helm-chart/Chart.yaml @@ -15,9 +15,9 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 3.38.0 +version: 3.43.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. -appVersion: 4.123.0 +appVersion: 4.128.0 diff --git a/ci/helm-chart/values.yaml b/ci/helm-chart/values.yaml index 81f112ced5fd..05954e11926e 100644 --- a/ci/helm-chart/values.yaml +++ b/ci/helm-chart/values.yaml @@ -6,7 +6,7 @@ replicaCount: 1 image: repository: codercom/code-server - tag: '4.123.0' + tag: '4.128.0' pullPolicy: Always # Specifies one or more secrets to be used when pulling images from a diff --git a/docs/install.md b/docs/install.md index 30da4d415e77..edd256ba3072 100644 --- a/docs/install.md +++ b/docs/install.md @@ -101,9 +101,8 @@ _exact_ same commands presented in the rest of this document. We recommend installing with `npm` when: 1. You aren't using a machine with `amd64` or `arm64`. -2. You are installing code-server on Windows. -3. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21. -4. You're running Alpine Linux or are using a non-glibc libc. See +2. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21. +3. You're running Alpine Linux or are using a non-glibc libc. See [#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198) for more information. @@ -296,8 +295,7 @@ You can install code-server using the [Helm package manager](https://coder.com/d ## Windows We currently [do not publish Windows -releases](https://github.com/coder/code-server/issues/1397). We recommend -installing code-server onto Windows with [`npm`](#npm). +releases](https://github.com/coder/code-server/issues/1397). ## Raspberry Pi diff --git a/lib/vscode b/lib/vscode index 6a44c352bd24..fc3def6774c7 160000 --- a/lib/vscode +++ b/lib/vscode @@ -1 +1 @@ -Subproject commit 6a44c352bd24569c417e530095901b649960f9f8 +Subproject commit fc3def6774c76082adf699d366f31a557ce5573f diff --git a/package-lock.json b/package-lock.json index b3ef6a0f26cc..91807c30f6ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,12 +13,13 @@ "@coder/logger": "^3.0.1", "argon2": "^0.44.0", "compression": "^1.7.4", + "cookie": "^1.1.1", "cookie-parser": "^1.4.6", "env-paths": "^2.2.1", "express": "^5.0.1", "http-proxy": "^1.18.1", "httpolyglot": "^0.1.2", - "i18next": "^25.8.3", + "i18next": "^26.3.1", "js-yaml": "^4.1.0", "limiter": "^2.1.0", "pem": "^1.14.8", @@ -37,7 +38,6 @@ "@eslint/compat": "^1.2.0", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.12.0", - "@schemastore/package": "^0.0.10", "@types/compression": "^1.7.3", "@types/cookie-parser": "^1.4.4", "@types/eslint__js": "^8.42.3", @@ -57,7 +57,7 @@ "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.28.1", "eslint-plugin-prettier": "^5.0.0", - "globals": "^16.1.0", + "globals": "^17.6.0", "prettier": "3.8.3", "prettier-plugin-sh": "^0.18.0", "ts-node": "^10.9.1", @@ -68,15 +68,6 @@ "node": "22" } }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@coder/logger": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/@coder/logger/-/logger-3.0.1.tgz", @@ -446,35 +437,29 @@ "dev": true, "license": "MIT" }, - "node_modules/@schemastore/package": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/@schemastore/package/-/package-0.0.10.tgz", - "integrity": "sha512-D3LxMCnkgsb4LO5sDKf6E+yahM2SqpEHmkqMPDSJis5Cy/j2MgWo/g/iq0lECK0mrPWfx3hqKm2ZJlqxwbRJQA==", - "dev": true, - "license": "MIT" - }, "node_modules/@textlint/ast-node-types": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-12.6.1.tgz", - "integrity": "sha512-uzlJ+ZsCAyJm+lBi7j0UeBbj+Oy6w/VWoGJ3iHRHE5eZ8Z4iK66mq+PG/spupmbllLtz77OJbY89BYqgFyjXmA==", + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/ast-node-types/-/ast-node-types-15.7.1.tgz", + "integrity": "sha512-Wii5UgUKFEh9Uv6wbq1zr4/Kf+dtjiUuzPrrXzKp8H+ifkvKNzi23V4Nz+6wVyHQn5T28AFuc8VH8OtzvGYecA==", "dev": true, "license": "MIT" }, "node_modules/@textlint/markdown-to-ast": { - "version": "12.6.1", - "resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-12.6.1.tgz", - "integrity": "sha512-T0HO+VrU9VbLRiEx/kH4+gwGMHNMIGkp0Pok+p0I33saOOLyhfGvwOKQgvt2qkxzQEV2L5MtGB8EnW4r5d3CqQ==", + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/@textlint/markdown-to-ast/-/markdown-to-ast-15.7.1.tgz", + "integrity": "sha512-9DLSah7g6mYNHvO6pssLdFvFPAl3HHyEIm4RE5of/1QN9FXJXDgdOcVV3YpQmbYT/YntuIvOQiqOndCSPWTW2A==", "dev": true, "license": "MIT", "dependencies": { - "@textlint/ast-node-types": "^12.6.1", - "debug": "^4.3.4", + "@textlint/ast-node-types": "15.7.1", + "debug": "^4.4.3", "mdast-util-gfm-autolink-literal": "^0.1.3", + "neotraverse": "^0.6.18", "remark-footnotes": "^3.0.0", "remark-frontmatter": "^3.0.0", "remark-gfm": "^1.0.0", "remark-parse": "^9.0.0", - "traverse": "^0.6.7", + "structured-source": "^4.0.0", "unified": "^9.2.2" } }, @@ -770,20 +755,20 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", - "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz", + "integrity": "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/type-utils": "8.56.1", - "@typescript-eslint/utils": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/type-utils": "8.61.1", + "@typescript-eslint/utils": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -793,9 +778,9 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.56.1", + "@typescript-eslint/parser": "^8.61.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { @@ -809,16 +794,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", - "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.1.tgz", + "integrity": "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3" }, "engines": { @@ -830,18 +815,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", - "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.1.tgz", + "integrity": "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.1", - "@typescript-eslint/types": "^8.56.1", + "@typescript-eslint/tsconfig-utils": "^8.61.1", + "@typescript-eslint/types": "^8.61.1", "debug": "^4.4.3" }, "engines": { @@ -852,18 +837,18 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.1.tgz", + "integrity": "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -874,9 +859,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz", + "integrity": "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==", "dev": true, "license": "MIT", "engines": { @@ -887,21 +872,21 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", - "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.1.tgz", + "integrity": "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/utils": "8.61.1", "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -912,13 +897,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.1.tgz", + "integrity": "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==", "dev": true, "license": "MIT", "engines": { @@ -930,21 +915,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", - "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.1.tgz", + "integrity": "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.56.1", - "@typescript-eslint/tsconfig-utils": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", + "@typescript-eslint/project-service": "8.61.1", + "@typescript-eslint/tsconfig-utils": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" + "ts-api-utils": "^2.5.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -954,7 +939,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { @@ -968,9 +953,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { @@ -981,13 +966,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" @@ -997,16 +982,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.1.tgz", + "integrity": "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1017,17 +1002,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", - "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.1.tgz", + "integrity": "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/types": "8.61.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -1405,9 +1390,9 @@ } }, "node_modules/anchor-markdown-header": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.8.2.tgz", - "integrity": "sha512-ix0Hx6ARkHOsQRmt1++ZmjURq4Pr5MGXQJjh0lQ/l5jTpTURn4aqhbZ+AJMpZ/Sd3JiyNwi7KaeiF64OsMGCPg==", + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/anchor-markdown-header/-/anchor-markdown-header-0.8.4.tgz", + "integrity": "sha512-20eMBMpts7k5rXAAj67geSqc/tsexHZOZJDWQD214YcDuNtyizDa7Q77sYa5rkao2FwsQP1WKRt2X6mphwmhbg==", "dev": true, "license": "MIT", "dependencies": { @@ -1671,6 +1656,13 @@ "url": "https://opencollective.com/express" } }, + "node_modules/boundary": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", + "integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/brace-expansion": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", @@ -1936,12 +1928,16 @@ } }, "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/cookie-parser": { @@ -1957,6 +1953,15 @@ "node": ">= 0.8.0" } }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -2167,18 +2172,17 @@ } }, "node_modules/doctoc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/doctoc/-/doctoc-2.3.0.tgz", - "integrity": "sha512-duuDNVnRHE5mFGYlI+oDf1vguML8PIhKnbUCs7iKPHIEdzYhkCldk6MQeX3ZeXQStRtZxGspSHImtgOMQPIS4A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/doctoc/-/doctoc-2.5.0.tgz", + "integrity": "sha512-xWb2P8mQw9x+T9xPYToytRP0/bA68oexdsY0anMG72RdhZGTVPx6oHJfI57gbZe9LsOSfQUNNLwxSspdoTlJIQ==", "dev": true, "license": "MIT", "dependencies": { - "@textlint/markdown-to-ast": "^12.1.1", - "anchor-markdown-header": "^0.8.2", + "@textlint/markdown-to-ast": "^15.6.0", + "anchor-markdown-header": "^0.8.4", "htmlparser2": "^7.2.0", - "minimist": "^1.2.6", - "underscore": "^1.13.2", - "update-section": "^0.3.3" + "loglevel": "^1.9.2", + "minimist": "^1.2.6" }, "bin": { "doctoc": "doctoc.js" @@ -2953,6 +2957,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/express/node_modules/cookie-signature": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", @@ -3310,9 +3323,9 @@ } }, "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "version": "17.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", + "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "dev": true, "license": "MIT", "engines": { @@ -3532,29 +3545,26 @@ } }, "node_modules/i18next": { - "version": "25.8.13", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.13.tgz", - "integrity": "sha512-E0vzjBY1yM+nsFrtgkjLhST2NBkirkvOVoQa0MSldhsuZ3jUge7ZNpuwG0Cfc74zwo5ZwRzg3uOgT+McBn32iA==", + "version": "26.3.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz", + "integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==", "funding": [ { "type": "individual", - "url": "https://locize.com" + "url": "https://www.locize.com/i18next" }, { "type": "individual", - "url": "https://locize.com/i18next.html" + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" }, { "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + "url": "https://www.locize.com" } ], "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4" - }, "peerDependencies": { - "typescript": "^5" + "typescript": "^5 || ^6" }, "peerDependenciesMeta": { "typescript": { @@ -4130,9 +4140,19 @@ "license": "ISC" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4237,6 +4257,20 @@ "dev": true, "license": "MIT" }, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, "node_modules/longest-streak": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", @@ -4710,6 +4744,16 @@ "node": ">= 0.6" } }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, "node_modules/netmask": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", @@ -5339,9 +5383,9 @@ } }, "node_modules/remove-markdown": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.3.tgz", - "integrity": "sha512-Qvp2p0Q1irE7AaJO7QemJe04HdObHylJrG+q4hszvPlYp7q4EvfINpEIaIEFdB+3XTDp1h6fiyT60ae00gmRow==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.6.4.tgz", + "integrity": "sha512-BompiLClzjfh46irZmzv+1Q61jZYlKN3iq/hzae9EOUwf7ctr/5wpD4qwgn/FWDAYE18RORO7z/yr+HXZJCY8Q==", "dev": true, "license": "MIT" }, @@ -5904,6 +5948,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/structured-source": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/structured-source/-/structured-source-4.0.0.tgz", + "integrity": "sha512-qGzRFNJDjFieQkl/sVOI2dUjHKRyL9dAJi2gCPGJLbJHBIkyOHxjuocpIEfbLioX+qSJpvbYdT49/YCdMznKxA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boundary": "^2.0.0" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5972,24 +6026,6 @@ "node": ">=0.6" } }, - "node_modules/traverse": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.11.tgz", - "integrity": "sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==", - "dev": true, - "license": "MIT", - "dependencies": { - "gopd": "^1.2.0", - "typedarray.prototype.slice": "^1.0.5", - "which-typed-array": "^1.1.18" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/trough": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", @@ -6002,9 +6038,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -6182,29 +6218,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedarray.prototype.slice": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.5.tgz", - "integrity": "sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "math-intrinsics": "^1.1.0", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-offset": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -6220,16 +6233,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.1.tgz", - "integrity": "sha512-U4lM6pjmBX7J5wk4szltF7I1cGBHXZopnAXCMXb3+fZ3B/0Z3hq3wS/CCUB2NZBNAExK92mCU2tEohWuwVMsDQ==", + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.61.1.tgz", + "integrity": "sha512-V7PayAfJokV3pEHgN7/v03D1SpujhRfQtYLbLIiBfDDncdg4PAiRBfoS4cnCANK4jmAPncczi59QO3afiXUlNw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.56.1", - "@typescript-eslint/parser": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1" + "@typescript-eslint/eslint-plugin": "8.61.1", + "@typescript-eslint/parser": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/utils": "8.61.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6240,7 +6253,7 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/unbox-primitive": { @@ -6262,13 +6275,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/underscore": { - "version": "1.13.8", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", - "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", - "dev": true, - "license": "MIT" - }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -6403,13 +6409,6 @@ "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, - "node_modules/update-section": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/update-section/-/update-section-0.3.3.tgz", - "integrity": "sha512-BpRZMZpgXLuTiKeiu7kK0nIPwGdyrqrs6EDSaXtjD/aQ2T+qVo9a5hRC3HN3iJjCMxNT/VxoLGQ7E/OzE5ucnw==", - "dev": true, - "license": "MIT" - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -6613,9 +6612,9 @@ "license": "ISC" }, "node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", "license": "MIT", "engines": { "node": ">=10.0.0" diff --git a/package.json b/package.json index b229efb3f5e5..dbebbc7c370d 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "@eslint/compat": "^1.2.0", "@eslint/eslintrc": "^3.1.0", "@eslint/js": "^9.12.0", - "@schemastore/package": "^0.0.10", "@types/compression": "^1.7.3", "@types/cookie-parser": "^1.4.4", "@types/eslint__js": "^8.42.3", @@ -59,7 +58,7 @@ "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.28.1", "eslint-plugin-prettier": "^5.0.0", - "globals": "^16.1.0", + "globals": "^17.6.0", "prettier": "3.8.3", "prettier-plugin-sh": "^0.18.0", "ts-node": "^10.9.1", @@ -70,12 +69,13 @@ "@coder/logger": "^3.0.1", "argon2": "^0.44.0", "compression": "^1.7.4", + "cookie": "^1.1.1", "cookie-parser": "^1.4.6", "env-paths": "^2.2.1", "express": "^5.0.1", "http-proxy": "^1.18.1", "httpolyglot": "^0.1.2", - "i18next": "^25.8.3", + "i18next": "^26.3.1", "js-yaml": "^4.1.0", "limiter": "^2.1.0", "pem": "^1.14.8", diff --git a/patches/base-path.diff b/patches/base-path.diff index 234b8403c6c4..9191effe8ed5 100644 --- a/patches/base-path.diff +++ b/patches/base-path.diff @@ -146,7 +146,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts embedderIdentifier: 'server-distro', extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? { ...this._productService.extensionsGallery, -@@ -407,7 +414,9 @@ export class WebClientServer { +@@ -401,7 +408,9 @@ export class WebClientServer { WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '', WORKBENCH_WEB_BASE_URL: staticRoute, WORKBENCH_NLS_URL, @@ -157,7 +157,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts }; // DEV --------------------------------------------------------------------------------------- -@@ -444,7 +453,7 @@ export class WebClientServer { +@@ -438,7 +447,7 @@ export class WebClientServer { 'default-src \'self\';', 'img-src \'self\' https: data: blob:;', 'media-src \'self\';', @@ -166,7 +166,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts 'child-src \'self\';', `frame-src 'self' https://*.vscode-cdn.net data:;`, 'worker-src \'self\' data: blob:;', -@@ -517,3 +526,70 @@ export class WebClientServer { +@@ -511,3 +520,70 @@ export class WebClientServer { return void res.end(data); } } @@ -241,7 +241,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -66,6 +66,7 @@ export type ExtensionVirtualWorkspaceSup +@@ -85,6 +85,7 @@ export interface IAgentSdkProductConfig export interface IProductConfiguration { readonly codeServerVersion?: string diff --git a/patches/disable-builtin-ext-update.diff b/patches/disable-builtin-ext-update.diff index 96c916a16b5c..05f964dd5859 100644 --- a/patches/disable-builtin-ext-update.diff +++ b/patches/disable-builtin-ext-update.diff @@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts -@@ -344,6 +344,10 @@ export class Extension implements IExten +@@ -343,6 +343,10 @@ export class Extension implements IExten if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) { return false; } diff --git a/patches/display-language.diff b/patches/display-language.diff index 526272fe5775..3ff62227f3e8 100644 --- a/patches/display-language.diff +++ b/patches/display-language.diff @@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; import { ConfigurationService } from '../../platform/configuration/common/configurationService.js'; -@@ -359,6 +359,9 @@ export async function setupServerService +@@ -358,6 +358,9 @@ export async function setupServerService socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority))); @@ -161,7 +161,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts import { CharCode } from '../../base/common/charCode.js'; import { IExtensionManifest } from '../../platform/extensions/common/extensions.js'; import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js'; -@@ -405,14 +406,22 @@ export class WebClientServer { +@@ -399,14 +400,22 @@ export class WebClientServer { }; const cookies = cookie.parse(req.headers.cookie || ''); diff --git a/patches/external-file-actions.diff b/patches/external-file-actions.diff index 582384af6cee..abbfac2cb32a 100644 --- a/patches/external-file-actions.diff +++ b/patches/external-file-actions.diff @@ -112,7 +112,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -389,6 +389,8 @@ export class WebClientServer { +@@ -383,6 +383,8 @@ export class WebClientServer { serverBasePath: basePath, webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', userDataPath: this._environmentService.userDataPath, @@ -147,7 +147,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts @IProductService private readonly productService: IProductService, @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, @IEditorService private readonly editorService: IEditorService, -@@ -201,6 +201,10 @@ export class WorkbenchContextKeysHandler +@@ -202,6 +202,10 @@ export class WorkbenchContextKeysHandler this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService); this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized()); @@ -230,7 +230,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js'; import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js'; import { equalsIgnoreCase, format, startsWithIgnoreCase } from '../../../../base/common/strings.js'; -@@ -161,7 +161,7 @@ export class SimpleFileDialog extends Di +@@ -152,7 +152,7 @@ export class SimpleFileDialog extends Di @IFileDialogService private readonly fileDialogService: IFileDialogService, @IModelService private readonly modelService: IModelService, @ILanguageService private readonly languageService: ILanguageService, @@ -239,7 +239,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, @IPathService protected readonly pathService: IPathService, @IKeybindingService private readonly keybindingService: IKeybindingService, -@@ -392,21 +392,23 @@ export class SimpleFileDialog extends Di +@@ -362,21 +362,23 @@ export class SimpleFileDialog extends Di this.filePickBox.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path"); this.filePickBox.ok = true; this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic; diff --git a/patches/getting-started.diff b/patches/getting-started.diff index 7135955f6efe..9d50f8f47d35 100644 --- a/patches/getting-started.diff +++ b/patches/getting-started.diff @@ -201,7 +201,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -393,6 +393,7 @@ export class WebClientServer { +@@ -387,6 +387,7 @@ export class WebClientServer { userDataPath: this._environmentService.userDataPath, isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'], isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'], @@ -222,7 +222,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js'; -@@ -204,6 +204,7 @@ export class WorkbenchContextKeysHandler +@@ -205,6 +205,7 @@ export class WorkbenchContextKeysHandler // code-server IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true) IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true) diff --git a/patches/integration.diff b/patches/integration.diff index 44327d24e005..2d4507fe2bd2 100644 --- a/patches/integration.diff +++ b/patches/integration.diff @@ -164,7 +164,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts +++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts -@@ -65,6 +65,7 @@ import { IOpenerService } from '../../pl +@@ -64,6 +64,7 @@ import { IOpenerService } from '../../pl import { mixin, safeStringify } from '../../base/common/objects.js'; import { IndexedDB } from '../../base/browser/indexedDB.js'; import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js'; @@ -172,7 +172,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts import { IProgressService } from '../../platform/progress/common/progress.js'; import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js'; import { dirname, joinPath } from '../../base/common/resources.js'; -@@ -140,6 +141,9 @@ export class BrowserMain extends Disposa +@@ -139,6 +140,9 @@ export class BrowserMain extends Disposa // Startup const instantiationService = workbench.startup(); @@ -186,8 +186,8 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -65,6 +65,8 @@ export type ExtensionVirtualWorkspaceSup - }; +@@ -84,6 +84,8 @@ export interface IAgentSdkProductConfig + } export interface IProductConfiguration { + readonly codeServerVersion?: string @@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/server-main.ts =================================================================== --- code-server.orig/lib/vscode/src/server-main.ts +++ code-server/lib/vscode/src/server-main.ts -@@ -22,6 +22,9 @@ import { IServerAPI } from './vs/server/ +@@ -23,6 +23,9 @@ import { IServerAPI } from './vs/server/ perf.mark('code/server/start'); (globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now(); @@ -273,7 +273,16 @@ Index: code-server/lib/vscode/src/server-main.ts // Do a quick parse to determine if a server or the cli needs to be started const parsedArgs = minimist(process.argv.slice(2), { boolean: ['start-server', 'list-extensions', 'print-ip-address', 'help', 'version', 'accept-server-license-terms', 'update-extensions'], -@@ -150,6 +153,7 @@ if (shouldSpawnCli) { +@@ -50,7 +53,7 @@ if (shouldSpawnCli) { + mod.spawnCli(); + }); + } else { +- installServerProcessExitDiagnostics(); ++ installServerProcessExitDiagnostics(parsedArgs); + + let _remoteExtensionHostAgentServer: IServerAPI | null = null; + let _remoteExtensionHostAgentServerPromise: Promise | null = null; +@@ -153,6 +156,7 @@ if (shouldSpawnCli) { } }); } @@ -281,7 +290,16 @@ Index: code-server/lib/vscode/src/server-main.ts function sanitizeStringArg(val: unknown): string | undefined { if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array -@@ -283,3 +287,22 @@ function prompt(question: string): Promi +@@ -173,7 +177,7 @@ function sanitizeStringArg(val: unknown) + * provided) so they survive process teardown (an async stdio write from an + * `exit` handler does not). + */ +-function installServerProcessExitDiagnostics(): void { ++function installServerProcessExitDiagnostics(parsedArgs: minimist.ParsedArgs): void { + if (!process.env['VSCODE_SERVER_EXIT_DIAGNOSTICS']) { + return; + } +@@ -406,3 +410,22 @@ function prompt(question: string): Promi }); }); } diff --git a/patches/local-storage.diff b/patches/local-storage.diff index 986eb4dde3ba..87710698a9ca 100644 --- a/patches/local-storage.diff +++ b/patches/local-storage.diff @@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -384,6 +384,7 @@ export class WebClientServer { +@@ -378,6 +378,7 @@ export class WebClientServer { remoteAuthority, serverBasePath: basePath, webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre', diff --git a/patches/logout.diff b/patches/logout.diff index c21be0de9115..5af694506d6c 100644 --- a/patches/logout.diff +++ b/patches/logout.diff @@ -8,7 +8,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -68,6 +68,7 @@ export interface IProductConfiguration { +@@ -87,6 +87,7 @@ export interface IProductConfiguration { readonly codeServerVersion?: string readonly rootEndpoint?: string readonly updateEndpoint?: string diff --git a/patches/marketplace.diff b/patches/marketplace.diff index 37347d13b660..539ba28bb7ca 100644 --- a/patches/marketplace.diff +++ b/patches/marketplace.diff @@ -64,7 +64,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts + extensionsGallery: this._productService.extensionsGallery, }; - const proposedApi = this._environmentService.args['enable-proposed-api']; + if (!this._environmentService.isBuilt) { Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts diff --git a/patches/proxy-uri.diff b/patches/proxy-uri.diff index 9921cc23022a..ef98ae832064 100644 --- a/patches/proxy-uri.diff +++ b/patches/proxy-uri.diff @@ -30,7 +30,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -69,6 +69,7 @@ export interface IProductConfiguration { +@@ -88,6 +88,7 @@ export interface IProductConfiguration { readonly rootEndpoint?: string readonly updateEndpoint?: string readonly logoutEndpoint?: string diff --git a/patches/service-worker.diff b/patches/service-worker.diff index 9e048c3c66e6..0204d57dd904 100644 --- a/patches/service-worker.diff +++ b/patches/service-worker.diff @@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -70,6 +70,10 @@ export interface IProductConfiguration { +@@ -89,6 +89,10 @@ export interface IProductConfiguration { readonly updateEndpoint?: string readonly logoutEndpoint?: string readonly proxyEndpointTemplate?: string diff --git a/patches/sourcemaps.diff b/patches/sourcemaps.diff index 4c51aace765e..22ca7ef04323 100644 --- a/patches/sourcemaps.diff +++ b/patches/sourcemaps.diff @@ -6,7 +6,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.ts =================================================================== --- code-server.orig/lib/vscode/build/gulpfile.reh.ts +++ code-server/lib/vscode/build/gulpfile.reh.ts -@@ -296,10 +296,15 @@ function packageTask(type: string, platf +@@ -344,10 +344,15 @@ function packageTask(type: string, platf const destination = path.join(BUILD_ROOT, destinationFolderName); return () => { diff --git a/patches/telemetry.diff b/patches/telemetry.diff index 462d3ce01c77..cd17a28bbfcb 100644 --- a/patches/telemetry.diff +++ b/patches/telemetry.diff @@ -147,7 +147,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -74,6 +74,7 @@ export interface IProductConfiguration { +@@ -93,6 +93,7 @@ export interface IProductConfiguration { readonly path: string; readonly scope: string; } diff --git a/patches/trusted-domains.diff b/patches/trusted-domains.diff index 9d42246bda34..f6ca9dc5fc01 100644 --- a/patches/trusted-domains.diff +++ b/patches/trusted-domains.diff @@ -46,4 +46,4 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts + linkProtectionTrustedDomains, }; - const proposedApi = this._environmentService.args['enable-proposed-api']; + if (!this._environmentService.isBuilt) { diff --git a/patches/update-check.diff b/patches/update-check.diff index d668e4254c9f..6cadd81e3ef7 100644 --- a/patches/update-check.diff +++ b/patches/update-check.diff @@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/base/common/product.ts +++ code-server/lib/vscode/src/vs/base/common/product.ts -@@ -67,6 +67,7 @@ export type ExtensionVirtualWorkspaceSup +@@ -86,6 +86,7 @@ export interface IAgentSdkProductConfig export interface IProductConfiguration { readonly codeServerVersion?: string readonly rootEndpoint?: string @@ -101,14 +101,14 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts readonly version: string; readonly date?: string; -@@ -119,6 +120,7 @@ export interface IProductConfiguration { +@@ -138,6 +139,7 @@ export interface IProductConfiguration { readonly resourceUrlTemplate: string; readonly nlsBaseUrl: string; readonly accessSKUs?: string[]; + readonly authorizationHeaderToken?: string; }; - readonly mcpGallery?: { + readonly agentSdks?: { readonly [packageId: string]: IAgentSdkProductConfig }; Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts diff --git a/patches/webview.diff b/patches/webview.diff index a1ce247be496..fd5349d73198 100644 --- a/patches/webview.diff +++ b/patches/webview.diff @@ -54,7 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts =================================================================== --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts -@@ -380,6 +380,7 @@ export class WebClientServer { +@@ -374,6 +374,7 @@ export class WebClientServer { const workbenchWebConfiguration = { remoteAuthority, serverBasePath: basePath, @@ -70,8 +70,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index -+ content="default-src 'none'; script-src 'sha256-m1DlJtsIJd46QuWYNcsaYIG1xI+9FyjKQu+cfp+zq5Q=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> +- content="default-src 'none'; script-src 'sha256-nXjtuhBilO++r8hfxl5VjEScSmdm07wDAk6jw228DgM=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> ++ content="default-src 'none'; script-src 'sha256-A6/szVNdTzyi4hDa+9OLbzS8tSd2iUV4CqimLNWex2Y=' 'self'; frame-src 'self'; style-src 'unsafe-inline';"> { } }) +// Strip the code-server cookie if it exists to avoid transmitting the cookie +// to potentially malicious local ports. +proxy.on("proxyReq", (preq, req) => { + const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"]) + preq.setHeader( + "Cookie", + cookie.stringifyCookie({ + ...(req as Request).cookies, + [cookieSessionName]: undefined, + }), + ) +}) + // Intercept the response to rewrite absolute redirects against the base path. // Is disabled when the request has no base path which means /absproxy is in use. proxy.on("proxyRes", (res, req) => { diff --git a/test/e2e/codeServer.test.ts b/test/e2e/codeServer.test.ts index 0e04742ea31a..199298a1495e 100644 --- a/test/e2e/codeServer.test.ts +++ b/test/e2e/codeServer.test.ts @@ -32,7 +32,7 @@ describe("code-server", ["--disable-workspace-trust"], {}, () => { test("should show the Integrated Terminal", async ({ codeServerPage }) => { await codeServerPage.focusTerminal() - expect(await codeServerPage.page.isVisible("#terminal")).toBe(true) + await expect(codeServerPage.page.locator("#terminal")).toBeVisible() }) test("should open a file", async ({ codeServerPage }) => { diff --git a/test/e2e/downloads.test.ts b/test/e2e/downloads.test.ts index 0adcd68ff83d..f08e13b74e0a 100644 --- a/test/e2e/downloads.test.ts +++ b/test/e2e/downloads.test.ts @@ -18,7 +18,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => { // Action await codeServerPage.openContextMenu("text=unique-file.txt") - expect(await codeServerPage.page.isVisible("text=Download...")).toBe(true) + await expect(codeServerPage.page.locator("text=Download...")).toBeVisible() }) test("should see the 'Show Local' button on Save As", async ({ codeServerPage }) => { @@ -37,7 +37,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => { await codeServerPage.page.keyboard.type("Making some edits.") await codeServerPage.navigateMenus(["File", "Save As..."]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true) + await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible() }) test("should see the 'Show Local' button on Save File", async ({ codeServerPage }) => { @@ -46,14 +46,14 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => { await codeServerPage.waitForTab("Untitled-1") await codeServerPage.navigateMenus(["File", "Save"]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true) + await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible() }) test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => { // Action await codeServerPage.navigateMenus(["File", "Save Workspace As..."]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true) + await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible() }) }) @@ -72,7 +72,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d // Action await codeServerPage.openContextMenu("text=unique-file.txt") - expect(await codeServerPage.page.isVisible("text=Download...")).toBe(false) + await expect(codeServerPage.page.locator("text=Download...")).not.toBeVisible() }) test("should not see the 'Show Local' button on Save as", async ({ codeServerPage }) => { @@ -87,7 +87,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d await codeServerPage.openFile(fileName) await codeServerPage.page.click(".tab") await codeServerPage.navigateMenus(["File", "Save As..."]) - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false) + await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible() }) test("should not see the 'Show Local' button on Save File", async ({ codeServerPage }) => { @@ -96,13 +96,13 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d await codeServerPage.waitForTab("Untitled-1") await codeServerPage.navigateMenus(["File", "Save"]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false) + await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible() }) test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => { // Action await codeServerPage.navigateMenus(["File", "Save Workspace As..."]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false) + await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible() }) }) diff --git a/test/e2e/extensions.test.ts b/test/e2e/extensions.test.ts index ac56fcfec059..9861e0004e7b 100644 --- a/test/e2e/extensions.test.ts +++ b/test/e2e/extensions.test.ts @@ -13,7 +13,7 @@ function runTestExtensionTests() { // Remove end slash in address. const normalizedAddress = address.replace(/\/+$/, "") - await codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`) + await expect(codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)).toBeVisible() }) } diff --git a/test/e2e/github.test.ts b/test/e2e/github.test.ts index 403d3161a208..aa45886bd1f6 100644 --- a/test/e2e/github.test.ts +++ b/test/e2e/github.test.ts @@ -12,7 +12,7 @@ if (process.env.GITHUB_TOKEN) { await codeServerPage.page.click("text=Allow") // It should ask to select an account, one of which will be the one we // pre-injected. - expect(await codeServerPage.page.isVisible("text=Select an account")).toBe(false) + await expect(codeServerPage.page.locator("text=Select an account")).not.toBeVisible() }) }) @@ -26,7 +26,7 @@ if (process.env.GITHUB_TOKEN) { await codeServerPage.page.click("text=Allow") // Since there is no account it will ask directly for the token (because // we are on localhost; otherwise it would initiate the oauth flow). - expect(await codeServerPage.page.isVisible("text=GitHub Personal Access Token")).toBe(false) + await expect(codeServerPage.page.locator("text=GitHub Personal Access Token")).not.toBeVisible() }) }) } else { diff --git a/test/e2e/login.test.ts b/test/e2e/login.test.ts index 90ec1b8cdef9..2ce9ce8e8035 100644 --- a/test/e2e/login.test.ts +++ b/test/e2e/login.test.ts @@ -24,8 +24,8 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () => // Skip entering password // Click the submit button and login await codeServerPage.page.click(".submit") - await codeServerPage.page.waitForLoadState("networkidle") - expect(await codeServerPage.page.isVisible("text=Missing password")) + // The required input blocks empty submits, so the server-side error can't render. + await expect(codeServerPage.page.locator("input.password:invalid")).toBeVisible() }) test("should see an error message for incorrect password", async ({ codeServerPage }) => { @@ -34,28 +34,29 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () => // Click the submit button and login await codeServerPage.page.click(".submit") await codeServerPage.page.waitForLoadState("networkidle") - expect(await codeServerPage.page.isVisible("text=Incorrect password")) + await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible() }) test("should hit the rate limiter for too many unsuccessful logins", async ({ codeServerPage }) => { - // Type in password - await codeServerPage.page.fill(".password", "password123") + test.slow() // Click the submit button and login // The current RateLimiter allows 2 logins per minute plus // 12 logins per hour for a total of 14 // See: src/node/routes/login.ts for (let i = 1; i <= 14; i++) { + await codeServerPage.page.fill(".password", "password123") await codeServerPage.page.click(".submit") await codeServerPage.page.waitForLoadState("networkidle") // We double-check that the correct error message shows // which should be for incorrect password - expect(await codeServerPage.page.isVisible("text=Incorrect password")) + await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible() } // The 15th should fail for a different reason: // login rate + await codeServerPage.page.fill(".password", "password123") await codeServerPage.page.click(".submit") await codeServerPage.page.waitForLoadState("networkidle") - expect(await codeServerPage.page.isVisible("text=Login rate limited!")) + await expect(codeServerPage.page.locator("text=Login rate limited!")).toBeVisible() }) }) diff --git a/test/e2e/uploads.test.ts b/test/e2e/uploads.test.ts index 80df808a44e4..05bb9ffd98a3 100644 --- a/test/e2e/uploads.test.ts +++ b/test/e2e/uploads.test.ts @@ -18,14 +18,14 @@ describe("Uploads (enabled)", ["--disable-workspace-trust"], {}, () => { // Action await codeServerPage.openContextMenu('span:has-text("test-directory")') - expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(true) + await expect(codeServerPage.page.locator("text=Upload...")).toBeVisible() }) test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => { // Action await codeServerPage.navigateMenus(["File", "Open File..."]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true) + await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible() }) }) @@ -44,13 +44,13 @@ describe("Uploads (disabled)", ["--disable-workspace-trust", "--disable-file-upl // Action await codeServerPage.openContextMenu('span:has-text("test-directory")') - expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(false) + await expect(codeServerPage.page.locator("text=Upload...")).not.toBeVisible() }) test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => { // Action await codeServerPage.navigateMenus(["File", "Open File..."]) await codeServerPage.page.waitForSelector(".quick-input-widget") - expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false) + await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible() }) }) diff --git a/test/package-lock.json b/test/package-lock.json index 171c8d085db8..422c6c393fa4 100644 --- a/test/package-lock.json +++ b/test/package-lock.json @@ -7,7 +7,7 @@ "license": "MIT", "devDependencies": { "@jest-mock/express": "^1.4.5", - "@playwright/test": "^1.56.1", + "@playwright/test": "^1.61.0", "@types/jest": "^27.0.2", "@types/jsdom": "^16.2.13", "@types/node-fetch": "^2.5.8", @@ -18,7 +18,7 @@ "jest-fetch-mock": "^3.0.3", "jsdom": "^16.4.0", "node-fetch": "^2.6.7", - "playwright": "^1.59.1", + "playwright": "^1.61.0", "ts-jest": "^27.0.7", "wtfnode": "^0.9.1" } @@ -998,13 +998,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", - "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.0.tgz", + "integrity": "sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.56.1" + "playwright": "1.61.0" }, "bin": { "playwright": "cli.js" @@ -1013,53 +1013,6 @@ "node": ">=18" } }, - "node_modules/@playwright/test/node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/@playwright/test/node_modules/playwright": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", - "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.56.1" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/@playwright/test/node_modules/playwright-core": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", - "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -2336,17 +2289,17 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -2561,9 +2514,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "dev": true, "license": "MIT", "dependencies": { @@ -3602,16 +3555,16 @@ } }, "node_modules/jsdom/node_modules/form-data": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", - "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz", + "integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", + "hasown": "^2.0.4", "mime-types": "^2.1.35" }, "engines": { @@ -4114,13 +4067,13 @@ } }, "node_modules/playwright": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz", - "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==", + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.0.tgz", + "integrity": "sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.59.1" + "playwright-core": "1.61.0" }, "bin": { "playwright": "cli.js" @@ -4133,9 +4086,9 @@ } }, "node_modules/playwright-core": { - "version": "1.59.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz", - "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==", + "version": "1.61.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.0.tgz", + "integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/test/package.json b/test/package.json index 508876c785f2..46ae308fda52 100644 --- a/test/package.json +++ b/test/package.json @@ -3,7 +3,7 @@ "#": "We must put jest in a sub-directory otherwise VS Code somehow picks up the types and generates conflicts with mocha.", "devDependencies": { "@jest-mock/express": "^1.4.5", - "@playwright/test": "^1.56.1", + "@playwright/test": "^1.61.0", "@types/jest": "^27.0.2", "@types/jsdom": "^16.2.13", "@types/node-fetch": "^2.5.8", @@ -14,7 +14,7 @@ "jest-fetch-mock": "^3.0.3", "jsdom": "^16.4.0", "node-fetch": "^2.6.7", - "playwright": "^1.59.1", + "playwright": "^1.61.0", "ts-jest": "^27.0.7", "wtfnode": "^0.9.1" }, diff --git a/test/unit/node/heart.test.ts b/test/unit/node/heart.test.ts index 7ad0d21752f2..85b1945e3760 100644 --- a/test/unit/node/heart.test.ts +++ b/test/unit/node/heart.test.ts @@ -1,10 +1,9 @@ import { logger } from "@coder/logger" import { readFile, writeFile, stat, utimes } from "fs/promises" +import { setImmediate } from "timers" import { Heart } from "../../../src/node/heart" import { clean, mockLogger, tmpdir } from "../../utils/helpers" -const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo) - describe("Heart", () => { const testName = "heartTests" let testDir = "" @@ -15,12 +14,15 @@ describe("Heart", () => { await clean(testName) testDir = await tmpdir(testName) }) - beforeEach(() => { - heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true)) - }) + afterAll(() => { jest.restoreAllMocks() }) + + beforeEach(() => { + heart = new Heart(`${testDir}/shutdown.txt`, jest.fn().mockResolvedValue(true)) + }) + afterEach(() => { jest.resetAllMocks() jest.useRealTimers() @@ -28,6 +30,7 @@ describe("Heart", () => { heart.dispose() } }) + it("should write to a file when given a valid file path", async () => { // Set up heartbeat file with contents const text = "test" @@ -42,7 +45,7 @@ describe("Heart", () => { expect(fileContents).toBe(text) - heart = new Heart(pathToFile, mockIsActive(true)) + heart = new Heart(pathToFile, jest.fn().mockResolvedValue(true)) await heart.beat() // Check that the heart wrote to the heartbeatFilePath and overwrote our text const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" }) @@ -51,31 +54,30 @@ describe("Heart", () => { const fileStatusAfterEdit = await stat(pathToFile) expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0) }) + it("should log a warning when given an invalid file path", async () => { - heart = new Heart(`fakeDir/fake.txt`, mockIsActive(false)) + heart = new Heart(`fakeDir/fake.txt`, jest.fn().mockResolvedValue(false)) await heart.beat() expect(logger.warn).toHaveBeenCalled() }) + it("should be active after calling beat", async () => { await heart.beat() const isAlive = heart.alive() expect(isAlive).toBe(true) }) + it("should not be active after dispose is called", () => { heart.dispose() const isAlive = heart.alive() expect(isAlive).toBe(false) }) + it("should beat twice without warnings", async () => { - // Use fake timers so we can speed up setTimeout - jest.useFakeTimers() - heart = new Heart(`${testDir}/hello.txt`, mockIsActive(true)) + heart = new Heart(`${testDir}/hello.txt`, jest.fn().mockResolvedValue(true)) await heart.beat() - // we need to speed up clocks, timeouts - // call heartbeat again (and it won't be alive I think) - // then assert no warnings were called jest.runAllTimers() expect(logger.warn).not.toHaveBeenCalled() }) @@ -84,40 +86,48 @@ describe("Heart", () => { describe("heartbeatTimer", () => { const testName = "heartbeatTimer" let testDir = "" + beforeAll(async () => { await clean(testName) testDir = await tmpdir(testName) mockLogger() }) + afterAll(() => { jest.restoreAllMocks() }) + beforeEach(() => { jest.useFakeTimers() }) + afterEach(() => { jest.resetAllMocks() jest.clearAllTimers() jest.useRealTimers() }) + it("should call isActive when timeout expires", async () => { - const isActive = true - const mockIsActive = jest.fn().mockResolvedValue(isActive) + const mockIsActive = jest.fn().mockResolvedValue(true) const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive) await heart.beat() jest.advanceTimersByTime(60 * 1000) expect(mockIsActive).toHaveBeenCalled() }) + it("should log a warning when isActive rejects", async () => { - const errorMsg = "oh no" - const error = new Error(errorMsg) + const error = new Error("oh no") const mockIsActive = jest.fn().mockRejectedValue(error) const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive) await heart.beat() jest.advanceTimersByTime(60 * 1000) - expect(mockIsActive).toHaveBeenCalled() - expect(logger.warn).toHaveBeenCalledWith(errorMsg) + + // The timer callback waits on mockIsActive, so we need to yield to let the + // callback finish. + await new Promise((resolve) => setImmediate(resolve)) + + expect(logger.warn).toHaveBeenCalledWith(error.message) }) }) @@ -125,38 +135,54 @@ describe("stateChange", () => { const testName = "stateChange" let testDir = "" let heart: Heart + beforeAll(async () => { await clean(testName) testDir = await tmpdir(testName) mockLogger() }) + afterAll(() => { jest.restoreAllMocks() }) + + beforeEach(() => { + jest.useFakeTimers() + }) + afterEach(() => { jest.resetAllMocks() + jest.useRealTimers() if (heart) { heart.dispose() } }) + it("should change to alive after a beat", async () => { - heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true)) + const mockIsActive = jest.fn().mockResolvedValue(true) + heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive) const mockOnChange = jest.fn() heart.onChange(mockOnChange) + await heart.beat() expect(mockOnChange.mock.calls[0][0]).toBe("alive") }) - it.only("should change to expired when not active", async () => { - jest.useFakeTimers() - heart = new Heart(`${testDir}/shutdown.txt`, () => new Promise((resolve) => resolve(false))) + + it("should change to expired when not active", async () => { + const mockIsActive = jest.fn().mockResolvedValue(false) + heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive) const mockOnChange = jest.fn() heart.onChange(mockOnChange) + await heart.beat() + jest.advanceTimersByTime(60 * 1000) + expect(mockIsActive).toHaveBeenCalled() + + // The timer callback waits on the isActive promise, so we need to yield to + // let the callback finish. + await new Promise((resolve) => setImmediate(resolve)) - await jest.advanceTimersByTime(60 * 1000) expect(mockOnChange.mock.calls[1][0]).toBe("expired") - jest.clearAllTimers() - jest.useRealTimers() }) }) diff --git a/test/unit/node/proxy.test.ts b/test/unit/node/proxy.test.ts index b3509ed640df..94945cb94eaa 100644 --- a/test/unit/node/proxy.test.ts +++ b/test/unit/node/proxy.test.ts @@ -1,15 +1,12 @@ import * as express from "express" -import * as http from "http" -import nodeFetch from "node-fetch" import { HttpCode } from "../../../src/common/http" -import { proxy } from "../../../src/node/proxy" import { wss, Router as WsRouter } from "../../../src/node/wsRouter" -import { getAvailablePort, mockLogger } from "../../utils/helpers" +import { mockLogger } from "../../utils/helpers" import * as httpserver from "../../utils/httpserver" import * as integration from "../../utils/integration" describe("proxy", () => { - const nhooyrDevServer = new httpserver.HttpServer() + const proxyTarget = new httpserver.HttpServer() const wsApp = express.default() const wsRouter = WsRouter() let codeServer: httpserver.HttpServer | undefined @@ -19,21 +16,22 @@ describe("proxy", () => { beforeAll(async () => { wsApp.use("/", wsRouter.router) - await nhooyrDevServer.listen((req, res) => { + await proxyTarget.listen((req, res) => { e(req, res) }) - nhooyrDevServer.listenUpgrade(wsApp) - proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup` + proxyTarget.listenUpgrade(wsApp) + proxyPath = `/proxy/${proxyTarget.port()}/wsup` absProxyPath = proxyPath.replace("/proxy/", "/absproxy/") }) afterAll(async () => { - await nhooyrDevServer.dispose() + await proxyTarget.dispose() }) beforeEach(() => { e = express.default() mockLogger() + delete process.env.PASSWORD }) afterEach(async () => { @@ -283,65 +281,42 @@ describe("proxy", () => { const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" }) expect(resp.status).toBe(200) }) -}) -// NOTE@jsjoeio -// Both this test suite and the one above it are very similar -// The main difference is this one uses http and node-fetch -// and specifically tests the proxy in isolation vs. using -// the httpserver abstraction we've built. -// -// Leaving this as a separate test suite for now because -// we may consider refactoring the httpserver abstraction -// in the future. -// -// If you're writing a test specifically for code in -// src/node/proxy.ts, you should probably add it to -// this test suite. -describe("proxy (standalone)", () => { - let URL = "" - let PROXY_URL = "" - let testServer: http.Server - let proxyTarget: http.Server + it("should return a 500 when no target is running ", async () => { + const target = new httpserver.HttpServer() + await target.listen(() => {}) + const port = target.port() + target.dispose() + codeServer = await integration.setup(["--auth=none"], "") + const resp = await codeServer.fetch(`/proxy/${port}/wsup`) + expect(resp.status).toBe(HttpCode.ServerError) + expect(resp.statusText).toBe("Internal Server Error") + }) - beforeEach(async () => { - const PORT = await getAvailablePort() - const PROXY_PORT = await getAvailablePort() - URL = `http://localhost:${PORT}` - PROXY_URL = `http://localhost:${PROXY_PORT}` - // Define server and a proxy server - testServer = http.createServer((req, res) => { - proxy.web(req, res, { - target: PROXY_URL, - }) - }) + it("should strip token cookie", async () => { + const token = "my-super-secure-token" + process.env.HASHED_PASSWORD = token + codeServer = await integration.setup(["--auth=password"]) - proxyTarget = http.createServer((req, res) => { - res.writeHead(200, { "Content-Type": "text/plain" }) - res.end() + // Set up a listener that just prints the cookies it got. + e.get("/wsup/cookies", (req, res) => { + res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" }) + res.end(req.headers.cookie) }) - // Start both servers - proxyTarget.listen(PROXY_PORT) - testServer.listen(PORT) - }) - - afterEach(async () => { - testServer.close() - proxyTarget.close() - }) - - it("should return a 500 when proxy target errors ", async () => { - // Close the proxy target so that proxy errors - proxyTarget.close() - const errorResp = await nodeFetch(`${URL}/error`) - expect(errorResp.status).toBe(HttpCode.ServerError) - expect(errorResp.statusText).toBe("Internal Server Error") - }) + // Send the token along with other cookies which should be preserved. + // Encode one to make sure they are being re-encoded properly. + const value = "hello=there" + const encodedValue = encodeURIComponent(value) + const resp = await codeServer.fetch(proxyPath + "/cookies", { + headers: { + cookie: `cookie1=${encodedValue}; code-server-session=${token}; cookie2=hello;`, + }, + }) - it("should proxy correctly", async () => { - const resp = await nodeFetch(`${URL}/route`) + // The proxied listener should not have printed the code-server token. expect(resp.status).toBe(200) - expect(resp.statusText).toBe("OK") + const text = await resp.text() + expect(text).toBe(`cookie1=${encodedValue}; cookie2=hello`) }) })