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 def1c5c8201b..e12411acca60 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -25,8 +25,8 @@ jobs:
docs: ${{ steps.filter.outputs.docs }}
helm: ${{ steps.filter.outputs.helm }}
steps:
- - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- - uses: dorny/paths-filter@d1c1ffe0248fe513906c8e24db8ea791d46f8590 # v3
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
+ - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
id: filter
with:
filters: |
@@ -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 a23c3f903e78..76a7c78533bc 100644
--- a/.github/workflows/publish.yaml
+++ b/.github/workflows/publish.yaml
@@ -33,12 +33,12 @@ 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
- - uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
+ - uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
with:
repository: "coder/code-server"
tag: ${{ env.TAG }}
@@ -64,12 +64,17 @@ 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 }}
ref: "master"
+ - name: Configure git
+ run: |
+ git config --global user.name cdrci
+ git config --global user.email opensource@coder.com
+
- name: Fetch and reset master
run: |
git remote add upstream https://github.com/coder/code-server-aur.git
@@ -77,11 +82,6 @@ jobs:
git reset --hard upstream/master
git push --force
- - name: Configure git
- run: |
- git config --global user.name cdrci
- git config --global user.email opensource@coder.com
-
- name: Validate package
uses: heyhusen/archlinux-package-action@c9f94059ccbebe8710d31d582f33ef4e84fe575c # v3.0.0
with:
@@ -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,27 +108,27 @@ 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@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
+ - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
+ - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
+ - uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
with:
repository: "coder/code-server"
tag: v${{ env.VERSION }}
fileName: "*.deb"
out-file-path: "release-packages"
- - uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
+ - uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
with:
repository: "coder/code-server"
tag: v${{ env.VERSION }}
@@ -136,3 +136,32 @@ jobs:
out-file-path: "release-packages"
- run: npm run publish:docker
+
+ repo:
+ runs-on: ubuntu-latest
+ env:
+ GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
+ TAG: ${{ inputs.version || github.ref_name }}
+ needs: docker
+
+ steps:
+ - name: Set version to tag without leading v
+ run: |
+ echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
+
+ - run: ./ci/build/update-repo.sh
+
+ - name: Open PR
+ run: |
+ git config --global user.name cdrci
+ git config --global user.email opensource@coder.com
+ git checkout -b "helm/$VERSION"
+ git add .
+ git commit -m "Update Helm chart and changelog with $VERSION"
+ git push -u origin "$(git branch --show)"
+ gh pr create \
+ --repo coder/code-server \
+ --body-file .cache/checklist \
+ --title "Update Helm chart and changelog with $VERSION"
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 4054b08febd1..ce69cd72c9f7 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -6,6 +6,11 @@ on:
version:
type: string
required: true
+ pull_request_target:
+ types:
+ - closed
+ branches:
+ - main
permissions:
contents: write # For creating releases.
@@ -21,6 +26,9 @@ jobs:
package-linux:
name: ${{ format('linux-{0}', matrix.vscode_arch) }}
runs-on: ubuntu-22.04
+ if: >-
+ (github.event_name == 'workflow_dispatch') ||
+ (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
strategy:
matrix:
@@ -31,15 +39,12 @@ jobs:
- npm_arch: arm64
vscode_arch: arm64
package_arch: arm64
- - npm_arch: arm
- vscode_arch: armhf
- package_arch: armv7l
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- TAG: ${{ inputs.version || github.ref_name }}
+ TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
# Set release package name.
ARCH: ${{ matrix.package_arch }}
# Cross-compile target.
@@ -54,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
@@ -64,11 +69,14 @@ jobs:
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
echo "$HOME/.local/bin" >> $GITHUB_PATH
- - name: Set version to tag without leading v
+ - name: Strip update/ and v from tag and set major version
run: |
- echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+ version=${TAG#update/}
+ version=${version#v}
+ 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
@@ -99,25 +107,36 @@ jobs:
if: ${{ matrix.vscode_arch == 'x64' }}
- run: tar -czf package.tar.gz release
if: ${{ matrix.vscode_arch == 'x64' }}
- - uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
+ - 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@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
if: ${{ matrix.vscode_arch == 'x64' }}
with:
draft: true
discussion_category_name: "📣 Announcements"
files: package.tar.gz
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
+ body_path: .cache/release-notes
# 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"
files: ./release-packages/*
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
package-macos:
name: ${{ matrix.vscode_target }}
runs-on: ${{ matrix.os }}
+ if: >-
+ (github.event_name == 'workflow_dispatch') ||
+ (github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
strategy:
matrix:
include:
@@ -128,7 +147,7 @@ jobs:
env:
VSCODE_TARGET: ${{ matrix.vscode_target }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- TAG: ${{ inputs.version || github.ref_name }}
+ TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
# Ensure native modules are built from source to avoid prebuilds.
npm_config_build_from_source: true
@@ -144,11 +163,14 @@ jobs:
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
echo "$HOME/.local/bin" >> $GITHUB_PATH
- - name: Set version to tag without leading v
+ - name: Strip update/ and v from tag and set major version
run: |
- echo "VERSION=${TAG#v}" >> $GITHUB_ENV
+ version=${TAG#update/}
+ version=${version#v}
+ 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
@@ -167,8 +189,10 @@ 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"
files: ./release-packages/*
+ tag_name: v${{ env.VERSION }}
+ name: v${{ env.VERSION }}
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 f27584dcf251..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,12 +46,12 @@ jobs:
runs-on: ubuntu-22.04
steps:
- name: Checkout repo
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
- uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478 # latest
+ uses: aquasecurity/trivy-action@314ff8b43182423b84c50b1670b0e10f858f2d98 # latest
with:
scan-type: "fs"
scan-ref: "."
@@ -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 b38bf8287468..26bf15886948 100644
--- a/.github/workflows/trivy-docker.yaml
+++ b/.github/workflows/trivy-docker.yaml
@@ -18,8 +18,6 @@ on:
- .github/workflows/trivy-docker.yaml
schedule:
- # Run at 10:15 am UTC (3:15am PT/5:15am CT)
- # Run at 0 minutes 0 hours of every day.
- cron: "15 10 * * *"
workflow_dispatch:
@@ -48,10 +46,10 @@ 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@97e0b3872f55f89b95b2f65b3dbab56962816478 # latest
+ uses: aquasecurity/trivy-action@314ff8b43182423b84c50b1670b0e10f858f2d98 # latest
with:
image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true
@@ -60,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 97878a4e5ad9..461a31e1b40d 100644
--- a/.github/workflows/update.yaml
+++ b/.github/workflows/update.yaml
@@ -7,7 +7,7 @@ on:
type: string
required: true
schedule:
- - cron: "23 * * * *"
+ - cron: "0 16,21 * * *"
jobs:
update:
@@ -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
@@ -63,10 +63,10 @@ jobs:
git config --global user.email opensource@coder.com
git checkout -b "update/$VERSION"
git add .
- git commit -m "Update VS Code to $VERSION"
+ git commit -m "Update Code to $VERSION"
git push -u origin "$(git branch --show)"
gh pr create \
--repo coder/code-server \
- --title "Update VS Code to $VERSION" \
+ --title "Update Code to $VERSION" \
--body-file .cache/checklist \
--draft
diff --git a/.node-version b/.node-version
index 32a2d7bd80d1..ca5c350055cc 100644
--- a/.node-version
+++ b/.node-version
@@ -1 +1 @@
-22.22.1
+24.18.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71ea8cbfc04c..f197b7bad3f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,13 +22,103 @@ Code v99.99.999
## Unreleased
-## [4.119.0](https://github.com/coder/code-server/releases/tag/v4.119.0) - 2026-05-07
+Code v1.129.0
-Code v1.119.0
+### Changed
+
+- Update to Code 1.129.0
+
+## [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
+
+### Changed
+
+- Update to Code 1.123.0
+- Microsoft dropped support for armhf remotes so there will no longer be any
+ builds for armhf.
+
+## [4.122.1](https://github.com/coder/code-server/releases/tag/v4.122.1) - 2026-06-02
+
+Code v1.122.1
+
+### Changed
+
+- Update to Code 1.122.1
+
+## [4.122.0](https://github.com/coder/code-server/releases/tag/v4.122.0) - 2026-05-29
+
+Code v1.122.0
+
+### Changed
+
+- Update to Code 1.122.0
+
+### Fixed
+
+- `--app-name` will now affect window titles within the editor (it is now used
+ as the value for `${appName}` in the title template) as well as some other
+ places like the help > about dialog.
+
+### Added
+
+- App name can now be set with the `CODE_SERVER_APP_NAME` environment variable.
+
+## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20
+
+Code v1.121.0
### Changed
-- Update to Code 1.119.0
+- Update to Code 1.121.0
## [4.118.0](https://github.com/coder/code-server/releases/tag/v4.118.0) - 2026-05-06
diff --git a/ci/build/build-release.sh b/ci/build/build-release.sh
index 9ded35f98ccb..6dbc2784acbc 100755
--- a/ci/build/build-release.sh
+++ b/ci/build/build-release.sh
@@ -128,7 +128,9 @@ bundle_vscode() {
# Merge the package.json for the web/remote server so we can include
# dependencies, since we want to ship this via NPM.
- jq --slurp '.[0] * .[1]' \
+ # Also override the name to prevent vulnerability scanners from
+ # misidentifying this package as VS Code (see #7071).
+ 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-repo.sh b/ci/build/update-repo.sh
new file mode 100755
index 000000000000..0f1924fa91a4
--- /dev/null
+++ b/ci/build/update-repo.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+
+set -Eeuo pipefail
+
+# Given versions $1 and $2 figure out the first component that is different
+# (major, minor, patch).
+function find_version_diff() {
+ # shellcheck disable=SC2206
+ local a=( ${1//./ } )
+ # shellcheck disable=SC2206
+ local b=( ${2//./ } )
+
+ if [[ ${a[0]} != "${b[0]}" ]] ; then
+ echo major
+ elif [[ ${a[1]} != "${b[1]}" ]] ; then
+ echo minor
+ else
+ echo patch
+ fi
+}
+
+# Bump $1 by the bump type (major, minor, patch) in $2.
+function bump_version() {
+ # shellcheck disable=SC2206
+ local a=( ${1//./ } )
+ case $2 in
+ major)
+ ((a[0]++))
+ a[1]=0
+ a[2]=0
+ ;;
+ minor)
+ ((a[1]++))
+ a[2]=0
+ ;;
+ *)
+ ((a[2]++))
+ ;;
+ esac
+ echo "${a[0]}.${a[1]}.${a[2]}"
+}
+
+function update_helm() {
+ local chart_version
+ chart_version=$(yq .version ci/helm-chart/Chart.yaml)
+ local app_version
+ app_version=$(yq .appVersion ci/helm-chart/Chart.yaml)
+ local image_version
+ image_version=$(yq .image.tag ci/helm-chart/values.yaml)
+
+ local bump_type
+ bump_type=$(find_version_diff "$app_version" "$version")
+ local chart_version_bump
+ chart_version_bump=$(bump_version "$chart_version" "$bump_type")
+
+ # Use sed to replace because yq will reformat.
+ echo "Bumping version from $chart_version to $chart_version_bump..."
+ sed -i.bak "s/^version: $chart_version\$/version: $chart_version_bump/" ci/helm-chart/Chart.yaml
+
+ echo "Bumping app version from $app_version to $version..."
+ sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml
+
+ echo "Bumping image version from $image_version to $version..."
+ sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml
+}
+
+function update_changelog() {
+ local date
+ date=$(printf '%(%Y-%m-%d)T\n' -1)
+ local link="https://github.com/coder/code-server/releases/tag/v$version"
+ sed -i.bak "s|## Unreleased|## Unreleased\n\n## [$version]($link) - $date|" CHANGELOG.md
+}
+
+function main() {
+ cd "$(dirname "${0}")/../.."
+
+ source ./ci/lib.sh
+
+ local version=${VERSION:-$(git describe --tags)}
+ version="${version#v}"
+
+ declare -a steps
+
+ steps+=(
+ "Update Helm chart" "update_helm"
+ "Update changelog" "update_changelog"
+ )
+
+ # Even if a step failed, still output the last checkmark.
+ run-steps "${steps[@]}" || true
+
+ # This step is always manual.
+ echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist
+}
+
+main "$@"
diff --git a/ci/build/update-vscode.sh b/ci/build/update-vscode.sh
index a0b290eb8869..32b7fc1a2d1f 100755
--- a/ci/build/update-vscode.sh
+++ b/ci/build/update-vscode.sh
@@ -2,13 +2,26 @@
set -Eeuo pipefail
-function remove_patches() {
+function unapply_patches() {
local -i exit_code=0
- quilt pop -af || exit_code=$?
+ quiet quilt pop -af 2>&1 || exit_code=$?
case $exit_code in
- # Sucessfully removed.
+ # Sucessfully unapplied.
0) ;;
- # No more patches to remove.
+ # No more patches to unapply.
+ 2) ;;
+ # Some error.
+ *) return $exit_code ;;
+ esac
+}
+
+function apply_patches() {
+ local -i exit_code=0
+ quiet quilt push -a 2>&1 || exit_code=$?
+ case $exit_code in
+ # Sucessfully applied.
+ 0) ;;
+ # No more patches to apply.
2) ;;
# Some error.
*) return $exit_code ;;
@@ -17,9 +30,10 @@ function remove_patches() {
function update_vscode() {
pushd lib/vscode
- if ! git checkout "$target_vscode_version" ; then
+ if ! git checkout 2>&1 "$target_vscode_version" ; then
echo "$target_vscode_version does not exist locally, fetching..."
- git fetch --all --prune
+ git fetch --all --prune --tags
+ echo "Checking out $target_vscode_version again..."
git checkout "$target_vscode_version"
fi
popd
@@ -27,9 +41,8 @@ function update_vscode() {
function refresh_patches() {
local -i exit_code=0
- while quilt push ; ! (( exit_code=$? )) ; do
- quilt refresh
- echo # Extra new line for separation.
+ while quiet quilt push 2>&1 ; ! (( exit_code=$? )) ; do
+ quilt refresh 2>&1
done
case $exit_code in
# No more patches to apply.
@@ -42,8 +55,10 @@ 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 "$node_version already matches $target_node_version"
+ echo "Already set to $target_node_version"
else
echo "Updating from $node_version to $target_node_version..."
echo "$target_node_version" > .node-version
@@ -54,63 +69,46 @@ function get-webview-script-hash() {
local html
html=$(<"$1")
local start_tag='"
html=${html##*"$start_tag"}
html=${html%%"$end_tag"*}
echo -n "$html" | openssl sha256 -binary | openssl base64
}
-function update_csp() {
- local -i exit_code=0
- # Move back to the webview patch so it can be refreshed.
- quilt pop webview || exit_code=$?
- case $exit_code in
- # Successfully moved.
- 0) ;;
- # Already at the patch.
- 2) ;;
- # Some error.
- *) return $exit_code ;;
- esac
- local file=lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
- local hash
- hash=$(get-webview-script-hash "$file")
- echo "Calculated hash as $hash"
- # Use octothorpe as a delimiter since the hash may contain a slash.
- sed -i.bak "s#script-src 'sha256-[^']\+'#script-src 'sha256-$hash'#" "$file"
- quilt refresh
- # Get patched back up.
- quilt push -a
+function delete_csp() {
+ quilt delete csp-hashes.diff
}
-function run() {
- local -i failed=0
- rm -f .cache/checklist
- while (( $# )) ; do
- local name=$1 ; shift
- local fn=$1 ; shift
- # Only run if an earlier step has not failed.
- if [[ $failed == 0 ]] ; then
- echo "[+] $name..."
- if $fn ; then
- echo "- [X] $name" >> .cache/checklist
- else
- ((failed++))
- fi
- fi
- # For all failed steps, write out an empty checkbox.
- if [[ $failed != 0 ]] ; then
- echo "- [ ] $name" >> .cache/checklist
- fi
+function update_csp() {
+ apply_patches
+
+ local files=(
+ ./lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+ ./lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ )
+
+ quilt new csp-hashes.diff
+
+ local file
+ for file in "${files[@]}" ; do
+ quilt add "$file"
+
+ local hash
+ hash=$(get-webview-script-hash "$file")
+ echo "Calculated hash as $hash"
+ # Use octothorpe as a delimiter since the hash may contain a slash.
+ sed -i.bak "s#'sha256-[^']\+'#'sha256-$hash'#" "$file"
done
- if [[ $failed != 0 ]] ; then
- return 1
- fi
+
+ quilt refresh
}
function add_changelog() {
local file=CHANGELOG.md
- if grep "Code $target_vscode_version" "$file" ; then
+ if grep --quiet "Code $target_vscode_version" "$file" ; then
echo "Changelog for $target_vscode_version already exists"
else
# TODO: This is not exactly robust. In particular, it needs to handle if
@@ -124,28 +122,38 @@ 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
- local target_vscode_version
- target_vscode_version="${VERSION#v}"
+ # Hashes are always regenerated to avoid having to resolve conflicts..
+ steps+=("Revert CSP hashes" "delete_csp")
- declare -a steps
- # Removing patches only needs to be done locally; in CI we start from a fresh
- # clone each time.
- if [[ ! ${CI-} ]] ; then
- steps+=("Remove patches" "remove_patches")
+ # If version is not set, assume we are already at the target version and the
+ # user is just trying to resolve conflics.
+ local target_vscode_version
+ if [[ ${VERSION-} ]] ; then
+ # Removing patches only needs to be done locally; in CI we start from a
+ # fresh clone each time.
+ if [[ ! ${CI-} ]] ; then
+ steps+=("Unapplying patches" "unapply_patches")
+ fi
+ target_vscode_version="${VERSION#v}"
+ steps+=(
+ "Update Code to $target_vscode_version" "update_vscode"
+ "Refresh Code patches" "refresh_patches"
+ )
+ else
+ target_vscode_version="$(git -C lib/vscode describe --tags --exact-match)"
+ echo "Detected Code version $target_vscode_version"
fi
steps+=(
- "Update VS Code to $target_vscode_version" "update_vscode"
- "Refresh VS Code patches" "refresh_patches"
- "Set Node version to $target_node_version" "update_node"
- "Update CSP webview hash" "update_csp"
+ "Update Node version" "update_node"
+ "Regenerate CSP hashes" "update_csp"
"Add changelog note" "add_changelog"
)
- run "${steps[@]}"
+ # Even if a step failed, still output the last checkmark.
+ run-steps "${steps[@]}" || true
# This step is always manual.
echo "- [ ] Verify changelog" >> .cache/checklist
diff --git a/ci/helm-chart/Chart.yaml b/ci/helm-chart/Chart.yaml
index 0d045ffc290b..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.35.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.116.0
+appVersion: 4.128.0
diff --git a/ci/helm-chart/values.yaml b/ci/helm-chart/values.yaml
index e4f62ba0f7c0..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.116.0'
+ tag: '4.128.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
diff --git a/ci/lib.sh b/ci/lib.sh
index 71a875c6914b..41b75d65ce85 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -78,6 +78,45 @@ nodeArch() {
echo "$cpu"
}
+run-steps() {
+ local -i failed=0
+ mkdir -p .cache
+ rm -f .cache/checklist
+ while (( $# )) ; do
+ local name=$1 ; shift
+ local fn=$1 ; shift
+ echo "$name..."
+ # Only run if an earlier step has not failed.
+ # For all failed steps, write out an empty checkbox.
+ if [[ $failed == 0 ]] ; then
+ if $fn | indent ; then
+ echo "- [X] $name" >> .cache/checklist
+ else
+ ((failed++))
+ echo "- [-] $name" >> .cache/checklist
+ echo "Failed" | indent
+ fi
+ else
+ echo "- [ ] $name" >> .cache/checklist
+ echo "Skipped" | indent
+ fi
+ done
+ if [[ $failed != 0 ]] ; then
+ return 1
+ fi
+}
+
+quiet() {
+ "$@" >/dev/null
+}
+
+indent() {
+ local count=2
+ local space
+ space=$(printf "%${count}s")
+ sed "s/^/$space| /g"
+}
+
# See gulpfile.reh.ts for available targets.
if [[ ! ${VSCODE_TARGET-} ]]; then
VSCODE_TARGET="$(nodeOS)-$(nodeArch)"
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 3a3705e6dc7b..a2087ff17672 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -93,17 +93,20 @@ commits first if you are doing this).
### Version updates to Code
-1. Remove any patches with `quilt pop -a`.
-2. Update the `lib/vscode` submodule to the desired upstream version branch.
- 1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
- 2. `git add lib && git commit -m "chore: update to Code "`
-3. Apply the patches one at a time (`quilt push`). If the application succeeds
- but the lines changed, update the patch with `quilt refresh`. If there are
- conflicts, then force apply with `quilt push -f`, manually add back the
- rejected code, then run `quilt refresh`.
-4. From the code-server **project root**, run `npm install`.
-5. Check the Node.js version that's used by Electron (which is shipped with VS
- Code. If necessary, update our version of Node.js to match.
+PRs will be automatically created with updates to VS Code. If a patch cannot be
+automatically resolved, it will be necessary to clone the branch, resolve the
+conflicts manually, and finish the update. To do this:
+
+1. Apply as many patches as possible `quilt push -a`.
+2. Once you hit a conflict, force apply with `quilt push -f`, manually add back
+ the rejected code, then run `quilt refresh`.
+3. Once all patches have been resolved, run `./ci/build/update.sh` to finish the
+ update process.
+4. Commit all changes, push them up to the branch, and update the checklist in
+ the PR description.
+
+Once the PR is ready, manually verify that the unreleased changelog section
+contains all the changes going into this version before merging.
### Patching Code
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 8b640eef5a6c..125df4672b8a 160000
--- a/lib/vscode
+++ b/lib/vscode
@@ -1 +1 @@
-Subproject commit 8b640eef5a6c6089c029249d48efa5c99adf7d51
+Subproject commit 125df4672b8a6a34975303c6b0baa124e560a4f7
diff --git a/package-lock.json b/package-lock.json
index 19a1b3057eaf..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,8 +57,8 @@
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0",
- "globals": "^16.1.0",
- "prettier": "3.6.2",
+ "globals": "^17.6.0",
+ "prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1",
"typescript": "^5.6.2",
@@ -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": {
@@ -1639,9 +1624,9 @@
"license": "MIT"
},
"node_modules/basic-ftp": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
- "integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+ "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
@@ -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": {
@@ -3637,9 +3647,9 @@
}
},
"node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz",
+ "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==",
"license": "MIT",
"engines": {
"node": ">= 12"
@@ -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",
@@ -5100,9 +5144,9 @@
}
},
"node_modules/prettier": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
- "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
+ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -5197,9 +5241,9 @@
}
},
"node_modules/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
+ "version": "6.15.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
+ "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@@ -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.19.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "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 4f01a218b2fa..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,8 +58,8 @@
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0",
- "globals": "^16.1.0",
- "prettier": "3.6.2",
+ "globals": "^17.6.0",
+ "prettier": "3.8.3",
"prettier-plugin-sh": "^0.18.0",
"ts-node": "^10.9.1",
"typescript": "^5.6.2",
@@ -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/app-name.diff b/patches/app-name.diff
new file mode 100644
index 000000000000..32cb90ed0c28
--- /dev/null
+++ b/patches/app-name.diff
@@ -0,0 +1,46 @@
+Apply --app-name to VS Code web page titles
+
+VS Code's `${appName}` title variable comes from `productService.nameLong` in the
+web client. code-server already injects per-request product configuration into
+VS Code's web bootstrap, so set `nameShort`/`nameLong` from the existing
+`--app-name` CLI arg there.
+
+This keeps the patch minimal and makes browser tab titles honor `--app-name`
+without changing unrelated product metadata.
+
+Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+===================================================================
+--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
++++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+@@ -24,6 +24,7 @@ export const serverOptions: OptionDescri
+ 'disable-getting-started-override': { type: 'boolean' },
+ 'locale': { type: 'string' },
+ 'link-protection-trusted-domains': { type: 'string[]' },
++ 'app-name': { type: 'string' },
+
+ /* ----- server setup ----- */
+
+@@ -124,6 +125,7 @@ export interface ServerParsedArgs {
+ 'disable-getting-started-override'?: boolean,
+ 'locale'?: string
+ 'link-protection-trusted-domains'?: string[],
++ 'app-name'?: string,
+
+ /* ----- server setup ----- */
+
+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
+@@ -366,8 +366,11 @@ export class WebClientServer {
+ linkProtectionTrustedDomains.push(...this._productService.linkProtectionTrustedDomains);
+ }
+
++ const appName = this._environmentService.args['app-name'];
+ const productConfiguration: Partial> = {
+ codeServerVersion: this._productService.codeServerVersion,
++ nameShort: appName,
++ nameLong: appName,
+ rootEndpoint: rootBase,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
diff --git a/patches/base-path.diff b/patches/base-path.diff
index 693afc8f4d5c..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
@@ -263,7 +263,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
}
private startListening(): void {
-@@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
+@@ -590,17 +591,6 @@ class WorkspaceProvider implements IWork
}
}
@@ -281,7 +281,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
(function () {
// Find config by checking for DOM
-@@ -604,8 +594,8 @@ function readCookie(name: string): strin
+@@ -610,8 +600,8 @@ function readCookie(name: string): strin
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}
diff --git a/patches/clipboard.diff b/patches/clipboard.diff
index d479070d68f8..d4658b231494 100644
--- a/patches/clipboard.diff
+++ b/patches/clipboard.diff
@@ -78,7 +78,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
-@@ -149,6 +149,7 @@ export interface NativeParsedArgs {
+@@ -146,6 +146,7 @@ export interface NativeParsedArgs {
'disable-chromium-sandbox'?: boolean;
sandbox?: boolean;
'enable-coi'?: boolean;
diff --git a/patches/copilot.diff b/patches/copilot.diff
index 8db68a1b7a23..c525d33a24fa 100644
--- a/patches/copilot.diff
+++ b/patches/copilot.diff
@@ -2,8 +2,8 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts
+++ code-server/lib/vscode/build/gulpfile.extensions.ts
-@@ -294,6 +294,29 @@ export const compileCopilotExtensionBuil
- gulp.task(compileCopilotExtensionBuildTask);
+@@ -291,6 +291,29 @@ export const compileCopilotExtensionBuil
+ task.task(compileCopilotExtensionBuildTask);
/**
+ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering
@@ -26,7 +26,7 @@ Index: code-server/lib/vscode/build/gulpfile.extensions.ts
+ return Promise.resolve();
+ })
+));
-+gulp.task(compileCopilotExtensionFullBuildTask);
++task.task(compileCopilotExtensionFullBuildTask);
+
+/**
* Compiles the extensions for the build.
@@ -36,15 +36,15 @@ Index: code-server/lib/vscode/build/lib/extensions.ts
===================================================================
--- code-server.orig/lib/vscode/build/lib/extensions.ts
+++ code-server/lib/vscode/build/lib/extensions.ts
-@@ -24,6 +24,7 @@ import { getProductionDependencies } fro
+@@ -21,6 +21,7 @@ import { getProductionDependencies } fro
import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
import { fetchUrls, fetchGithub } from './fetch.ts';
import { createTsgoStream, spawnTsgo } from './tsgo.ts';
+import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts';
- import vzip from 'gulp-vinyl-zip';
+ import watcher from './watch/index.ts';
import { createRequire } from 'module';
-@@ -487,6 +488,116 @@ export function packageCopilotExtensionS
+@@ -483,6 +484,116 @@ export function packageCopilotExtensionS
).pipe(util2.setExecutableBit(['**/*.sh']));
}
diff --git a/patches/csp-hashes.diff b/patches/csp-hashes.diff
new file mode 100644
index 000000000000..0202248875e8
--- /dev/null
+++ b/patches/csp-hashes.diff
@@ -0,0 +1,26 @@
+Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+===================================================================
+--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
++++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+@@ -5,7 +5,7 @@
+
+
+
++ content="default-src 'none'; script-src 'sha256-A6/szVNdTzyi4hDa+9OLbzS8tSd2iUV4CqimLNWex2Y=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+
+
+
+
+
diff --git a/patches/disable-builtin-ext-update.diff b/patches/disable-builtin-ext-update.diff
index 20af3023a47c..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
-@@ -342,6 +342,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 db433fd9933e..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';
-@@ -301,6 +301,9 @@ export async function setupServerService
+@@ -358,6 +358,9 @@ export async function setupServerService
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentServ
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
+++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
-@@ -112,7 +112,7 @@ export abstract class AbstractNativeEnvi
+@@ -98,7 +98,7 @@ export abstract class AbstractNativeEnvi
return URI.file(join(vscodePortable, 'argv.json'));
}
@@ -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 || '');
@@ -198,7 +198,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
-@@ -116,6 +117,7 @@ export interface ServerParsedArgs {
+@@ -120,6 +121,7 @@ export interface ServerParsedArgs {
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
'disable-getting-started-override'?: boolean,
diff --git a/patches/external-file-actions.diff b/patches/external-file-actions.diff
index 40d7b4c6d5fb..abbfac2cb32a 100644
--- a/patches/external-file-actions.diff
+++ b/patches/external-file-actions.diff
@@ -99,7 +99,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
-@@ -110,6 +112,8 @@ export interface ServerParsedArgs {
+@@ -114,6 +116,8 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
'auth'?: string;
@@ -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());
@@ -207,7 +207,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
-@@ -41,6 +41,9 @@ export const EmbedderIdentifierContext =
+@@ -40,6 +40,9 @@ export const EmbedderIdentifierContext =
export const InAutomationContext = new RawContextKey('inAutomation', false, localize('inAutomation', "Whether VS Code is running under automation/smoke test"));
@@ -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 205bbbaea3a7..9d50f8f47d35 100644
--- a/patches/getting-started.diff
+++ b/patches/getting-started.diff
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
import './gettingStartedColors.js';
-@@ -925,6 +925,72 @@ export class GettingStartedPage extends
+@@ -928,6 +928,72 @@ export class GettingStartedPage extends
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
);
@@ -101,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
const leftColumn = $('.categories-column.categories-column-left', {},);
const rightColumn = $('.categories-column.categories-column-right', {},);
-@@ -974,6 +1040,9 @@ export class GettingStartedPage extends
+@@ -977,6 +1043,9 @@ export class GettingStartedPage extends
recentList.setLimit(5);
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
}
@@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
-@@ -114,6 +115,7 @@ export interface ServerParsedArgs {
+@@ -118,6 +119,7 @@ export interface ServerParsedArgs {
'auth'?: string;
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
@@ -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)
@@ -234,7 +234,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
-@@ -43,6 +43,7 @@ export const InAutomationContext = new R
+@@ -42,6 +42,7 @@ export const InAutomationContext = new R
export const IsEnabledFileDownloads = new RawContextKey('isEnabledFileDownloads', true, true);
export const IsEnabledFileUploads = new RawContextKey('isEnabledFileUploads', true, 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 0c1f281a21ff..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
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
-@@ -108,6 +109,7 @@ export const serverOptions: OptionDescri
+@@ -112,6 +113,7 @@ export const serverOptions: OptionDescri
export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
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/proposed-api.diff b/patches/proposed-api.diff
index daf7169f1436..3b2286b043e7 100644
--- a/patches/proposed-api.diff
+++ b/patches/proposed-api.diff
@@ -10,18 +10,17 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
-@@ -321,10 +321,7 @@ function extensionDescriptionArrayToMap(
+@@ -324,6 +324,10 @@ function extensionDescriptionArrayToMap(
}
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
-- if (!extension.enabledApiProposals) {
-- return false;
-- }
-- return true;// extension.enabledApiProposals.includes(proposal);
-+ return true
- }
-
- export function checkProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): void {
++ return true;
++}
++
++export function _isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
+ if (!extension.enabledApiProposals) {
+ return false;
+ }
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
diff --git a/patches/proxy-uri.diff b/patches/proxy-uri.diff
index ca55153eeb87..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
@@ -104,7 +104,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.js';
-@@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
+@@ -612,6 +613,39 @@ class WorkspaceProvider implements IWork
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
diff --git a/patches/series b/patches/series
index 3935786a69b6..5b548e3900dd 100644
--- a/patches/series
+++ b/patches/series
@@ -23,3 +23,5 @@ display-language.diff
trusted-domains.diff
signature-verification.diff
copilot.diff
+app-name.diff
+csp-hashes.diff
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 d9c89634593c..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
-@@ -261,10 +261,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 c830e09b0614..cd17a28bbfcb 100644
--- a/patches/telemetry.diff
+++ b/patches/telemetry.diff
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
import { NullPolicyService } from '../../platform/policy/common/policy.js';
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
import { LoggerService } from '../../platform/log/node/loggerService.js';
-@@ -174,11 +176,23 @@ export async function setupServerService
+@@ -176,11 +178,23 @@ export async function setupServerService
const requestService = new RequestService('remote', configurationService, environmentService, logService);
services.set(IRequestService, requestService);
@@ -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 0444cada7e9e..f6ca9dc5fc01 100644
--- a/patches/trusted-domains.diff
+++ b/patches/trusted-domains.diff
@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
-@@ -118,6 +119,7 @@ export interface ServerParsedArgs {
+@@ -122,6 +123,7 @@ export interface ServerParsedArgs {
'disable-file-uploads'?: boolean;
'disable-getting-started-override'?: boolean,
'locale'?: string
@@ -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 dbbb7e31ae95..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
@@ -134,7 +134,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
-@@ -104,6 +106,8 @@ export const serverOptions: OptionDescri
+@@ -108,6 +110,8 @@ export const serverOptions: OptionDescri
};
export interface ServerParsedArgs {
diff --git a/patches/webview.diff b/patches/webview.diff
index 59fe37de2b04..e3d82c35839c 100644
--- a/patches/webview.diff
+++ b/patches/webview.diff
@@ -3,9 +3,6 @@ Serve webviews from the same origin
Normally webviews are served from vscode-webview.net but we would rather them be
self-hosted.
-When doing this CSP will block resources (for example when viewing images) so
-add 'self' to the CSP to fix that.
-
Additionally the service worker defaults to handling *all* requests made to the
current host but when self-hosting the webview this will end up including the
webview HTML itself which means these requests will fail since the communication
@@ -20,16 +17,6 @@ webview host is separate by default but we serve on the same host).
To test, open a few types of webviews (images, markdown, extension details, etc).
-Make sure to update the hash. To do so:
-1. run code-server
-2. open any webview (i.e. preview Markdown)
-3. see error in console and copy hash
-
-That will test the hash change in pre/index.html
-
-Double-check the console to make sure there are no console errors for the webWorkerExtensionHostIframe
-which also requires a hash change.
-
parentOriginHash changes
This fixes webviews from not working properly due to a change upstream.
@@ -41,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
-@@ -223,7 +223,7 @@ export class BrowserWorkbenchEnvironment
+@@ -226,7 +226,7 @@ export class BrowserWorkbenchEnvironment
@memoize
get webviewExternalEndpoint(): string {
@@ -54,7 +41,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,
@@ -66,15 +53,6 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
-@@ -5,7 +5,7 @@
-
-
-
-+ content="default-src 'none'; script-src 'sha256-m1DlJtsIJd46QuWYNcsaYIG1xI+9FyjKQu+cfp+zq5Q=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
-
-
-
-
-
-@@ -25,6 +25,13 @@
- // validation not requested
+@@ -34,6 +34,13 @@
+ }
return start();
}
+
diff --git a/src/node/cli.ts b/src/node/cli.ts
index ac4ee32f0deb..0946c8e04344 100644
--- a/src/node/cli.ts
+++ b/src/node/cli.ts
@@ -677,9 +677,7 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
}
args["proxy-domain"] = finalProxies
- if (!args["app-name"]) {
- args["app-name"] = "code-server"
- }
+ args["app-name"] ??= process.env.CODE_SERVER_APP_NAME || "code-server"
args._ = getResolvedPathsFromArgs(args)
diff --git a/src/node/constants.ts b/src/node/constants.ts
index bb6873dfa113..06281c6889cf 100644
--- a/src/node/constants.ts
+++ b/src/node/constants.ts
@@ -1,9 +1,13 @@
import { logger } from "@coder/logger"
-import type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"
import * as os from "os"
import * as path from "path"
-export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles {
+type PackageJson = {
+ version: string
+ commit: string
+}
+
+export function getPackageJson(relativePath: string): PackageJson {
let pkg = {}
try {
pkg = require(relativePath)
@@ -11,7 +15,7 @@ export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJso
logger.warn(error.message)
}
- return pkg
+ return pkg as PackageJson
}
export const rootPath = path.resolve(__dirname, "../..")
diff --git a/src/node/i18n/index.ts b/src/node/i18n/index.ts
index a7f9f17bccc4..e8186067ba98 100644
--- a/src/node/i18n/index.ts
+++ b/src/node/i18n/index.ts
@@ -54,7 +54,6 @@ init({
lowerCaseLng: true,
debug: process.env.NODE_ENV === "development",
resources: defaultResources,
- showSupportNotice: false,
})
export default i18next
diff --git a/src/node/proxy.ts b/src/node/proxy.ts
index afa964ae529b..8282729cc34d 100644
--- a/src/node/proxy.ts
+++ b/src/node/proxy.ts
@@ -1,5 +1,7 @@
+import * as cookie from "cookie"
+import type { Request } from "express"
import proxyServer from "http-proxy"
-import { HttpCode } from "../common/http"
+import { getCookieSessionName, HttpCode } from "../common/http"
export const proxy = proxyServer.createProxyServer({})
@@ -18,6 +20,19 @@ proxy.on("error", (error, _, res) => {
}
})
+// 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/appName.test.ts b/test/e2e/appName.test.ts
new file mode 100644
index 000000000000..a12795cb0b33
--- /dev/null
+++ b/test/e2e/appName.test.ts
@@ -0,0 +1,9 @@
+import { version } from "../../src/node/constants"
+import { describe, test, expect } from "./baseFixture"
+
+const appName = "testnäme"
+describe("--app-name", [`--app-name=${appName}`], {}, () => {
+ test("should use app-name for the title", async ({ codeServerPage }) => {
+ expect(await codeServerPage.page.title()).toContain(appName)
+ })
+})
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/playwright.config.ts b/test/playwright.config.ts
index 05d520f30b37..1de4b92ca3b6 100644
--- a/test/playwright.config.ts
+++ b/test/playwright.config.ts
@@ -5,10 +5,10 @@ import path from "path"
// The default configuration runs all tests in three browsers with workers equal
// to half the available threads. See 'npm run test:e2e --help' to customize
// from the command line. For example:
-// npm run test:e2e --workers 1 # Run with one worker
-// npm run test:e2e --project Chromium # Only run on Chromium
-// npm run test:e2e --grep login # Run tests matching "login"
-// PWDEBUG=1 npm run test:e2e # Run Playwright inspector
+// npm run test:e2e -- --workers 1 # Run with one worker
+// npm run test:e2e -- --project Chromium # Only run on Chromium
+// npm run test:e2e -- --grep login # Run tests matching "login"
+// PWDEBUG=1 npm run test:e2e # Run Playwright inspector
const config: PlaywrightTestConfig = {
testDir: path.join(__dirname, "e2e"), // Search for tests in this directory.
timeout: 60000, // Each test is given 60 seconds.
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`)
})
})