Compare commits

..

No commits in common. "main" and "v4.92.2" have entirely different histories.

143 changed files with 9318 additions and 14712 deletions

43
.eslintrc.yaml Normal file
View file

@ -0,0 +1,43 @@
parser: "@typescript-eslint/parser"
env:
browser: true
es6: true # Map, etc.
jest: true
node: true
parserOptions:
ecmaVersion: 2018
sourceType: module
extends:
- eslint:recommended
- plugin:@typescript-eslint/recommended
- plugin:import/recommended
- plugin:import/typescript
- plugin:prettier/recommended
# Prettier should always be last
# Removes eslint rules that conflict with prettier.
- prettier
rules:
# Sometimes you need to add args to implement a function signature even
# if they are unused.
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }]
# For overloads.
no-dupe-class-members: off
"@typescript-eslint/no-use-before-define": off
"@typescript-eslint/no-non-null-assertion": off
"@typescript-eslint/ban-types": off
"@typescript-eslint/no-var-requires": off
"@typescript-eslint/explicit-module-boundary-types": off
"@typescript-eslint/no-explicit-any": off
"@typescript-eslint/no-extra-semi": off
eqeqeq: error
import/order:
[error, { alphabetize: { order: "asc" }, groups: [["builtin", "external", "internal"], "parent", "sibling"] }]
no-async-promise-executor: off
settings:
import/resolver:
typescript:
alwaysTryTypes: true

View file

@ -1,2 +0,0 @@
# Prettier 3.4.2
9b0340a09276f93c054d705d1b9a5f24cc5dbc97

View file

@ -20,8 +20,6 @@ body:
- **Remote OS**: Ubuntu
- **Remote Architecture**: amd64
- **`code-server --version`**: 4.0.1
Please do not just put "latest" for the version.
value: |
- Web Browser:
- Local OS:
@ -64,7 +62,7 @@ body:
id: logs
attributes:
label: Logs
description: Run code-server with the --verbose flag and then paste any relevant logs from the server, from the browser console and/or the browser network tab. For issues with installation, include installation logs (i.e. output of `npm install -g code-server`).
description: Run code-server with the --verbose flag and then paste any relevant logs from the server, from the browser console and/or the browser network tab. For issues with installation, include installation logs (i.e. output of `yarn global add code-server`).
render: shell
- type: textarea
@ -86,18 +84,6 @@ body:
validations:
required: true
- type: dropdown
attributes:
label: Does this bug reproduce in VS Code web?
description: If the bug reproduces in VS Code web, submit the issue upstream instead (https://github.com/microsoft/vscode). You can run VS Code web with `code serve-web`.
options:
- Yes, this is also broken in VS Code web
- No, this works as expected in VS Code web
- This cannot be tested in VS Code web
- I did not test VS Code web
validations:
required: true
- type: dropdown
attributes:
label: Does this bug reproduce in GitHub Codespaces?

View file

@ -0,0 +1,17 @@
<!-- Note: this variable $CODE_SERVER_VERSION_TO_UPDATE will be set when you run the release-prep.sh script with `yarn release:prep` -->
This PR is to generate a new release of `code-server` at `$CODE_SERVER_VERSION_TO_UPDATE`
## Screenshot
TODO
## TODOs
Follow "Publishing a release" steps in `ci/README.md`
<!-- Note some of these steps below are redundant since they're listed in the "Publishing a release" docs -->
- [ ] update `CHANGELOG.md`
- [ ] manually run "Draft release" workflow after merging this PR
- [ ] merge PR opened in [code-server-aur](https://github.com/coder/code-server-aur)

View file

@ -19,181 +19,241 @@ concurrency:
# this ensures that it only executes if all previous jobs succeeded.
# if: steps.cache-node-modules.outputs.cache-hit != 'true'
# will skip running `npm install` if it successfully fetched from cache
# will skip running `yarn install` if it successfully fetched from cache
jobs:
changes:
runs-on: ubuntu-latest
outputs:
ci: ${{ steps.filter.outputs.ci }}
code: ${{ steps.filter.outputs.code }}
deps: ${{ steps.filter.outputs.deps }}
docs: ${{ steps.filter.outputs.docs }}
helm: ${{ steps.filter.outputs.helm }}
steps:
- name: Checkout repo
uses: actions/checkout@v6
- name: Check changed files
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
ci:
- ".github/**"
- "ci/**"
docs:
- "docs/**"
- "README.md"
- "CHANGELOG.md"
helm:
- "ci/helm-chart/**"
code:
- "src/**"
- "test/**"
deps:
- "lib/**"
- "patches/**"
- "package-lock.json"
- "test/package-lock.json"
- id: debug
run: |
echo "${{ toJSON(steps.filter )}}"
prettier:
name: Run prettier check
runs-on: ubuntu-22.04
name: Format with Prettier
runs-on: ubuntu-20.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- name: Checkout repo
uses: actions/checkout@v4
- name: Run prettier with actionsx/prettier
uses: actionsx/prettier@v3
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npx prettier --check .
args: --check --loglevel=warn .
doctoc:
name: Doctoc markdown files
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
timeout-minutes: 5
needs: changes
if: needs.changes.outputs.docs == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- name: Checkout repo
uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
docs/**
- name: Install Node.js
if: steps.changed-files.outputs.any_changed == 'true'
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run doctoc
cache: "yarn"
- name: Install doctoc
run: yarn global add doctoc@2.2.1
- name: Run doctoc
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn doctoc
lint-helm:
name: Lint Helm chart
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
timeout-minutes: 5
needs: changes
if: needs.changes.outputs.helm == 'true'
steps:
- uses: actions/checkout@v6
- uses: azure/setup-helm@v4
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
ci/helm-chart/**
- name: Install helm
if: steps.changed-files.outputs.any_changed == 'true'
uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- run: helm plugin install https://github.com/instrumenta/helm-kubeval
- run: helm kubeval ci/helm-chart
- name: Install helm kubeval plugin
if: steps.changed-files.outputs.any_changed == 'true'
run: helm plugin install https://github.com/instrumenta/helm-kubeval
- name: Lint Helm chart
if: steps.changed-files.outputs.any_changed == 'true'
run: helm kubeval ci/helm-chart
lint-ts:
name: Lint TypeScript files
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
timeout-minutes: 5
needs: changes
if: needs.changes.outputs.code == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
**/*.ts
**/*.js
files_ignore: |
lib/vscode/**
- name: Install Node.js
if: steps.changed-files.outputs.any_changed == 'true'
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run lint:ts
- name: Fetch dependencies from cache
if: steps.changed-files.outputs.any_changed == 'true'
id: cache-node-modules
uses: actions/cache@v4
with:
path: "**/node_modules"
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true' && steps.cache-node-modules.outputs.cache-hit != 'true'
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
- name: Lint TypeScript files
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn lint:ts
lint-actions:
name: Lint GitHub Actions
runs-on: ubuntu-latest
needs: changes
if: needs.changes.outputs.ci == 'true'
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Check workflow files
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
./actionlint -color -shellcheck= -ignore "softprops/action-gh-release"
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.1
./actionlint -color -shellcheck= -ignore "set-output"
shell: bash
test-unit:
name: Run unit tests
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
timeout-minutes: 5
needs: changes
if: needs.changes.outputs.code == 'true'
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
**/*.ts
files_ignore: |
lib/vscode/**
- name: Install Node.js
if: steps.changed-files.outputs.any_changed == 'true'
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run test:unit
- uses: codecov/codecov-action@v5
if: success()
- name: Fetch dependencies from cache
if: steps.changed-files.outputs.any_changed == 'true'
id: cache-node-modules
uses: actions/cache@v4
with:
path: "**/node_modules"
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true' && steps.cache-node-modules.outputs.cache-hit != 'true'
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
- name: Run unit tests
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn test:unit
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
if: success()
build:
name: Build code-server
runs-on: ubuntu-22.04
timeout-minutes: 70
runs-on: ubuntu-20.04
timeout-minutes: 60
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
DISABLE_V8_COMPILE_CACHE: 1
steps:
- uses: actions/checkout@v6
- name: Checkout repo
uses: actions/checkout@v4
with:
submodules: true
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: awalsh128/cache-apt-pkgs-action@latest
- name: Install system dependencies
run: sudo apt update && sudo apt install -y libkrb5-dev
- name: Install quilt
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: quilt
version: 1.0
- run: quilt push -a
- uses: actions/setup-node@v6
- name: Patch Code
run: quilt push -a
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- run: npm run build
- name: Fetch dependencies from cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: "**/node_modules"
key: yarn-build-code-server-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-code-server-
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile
- name: Build code-server
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: yarn build
# Get Code's git hash. When this changes it means the content is
# different and we need to rebuild.
- name: Get latest lib/vscode rev
id: vscode-rev
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
# We need to rebuild when we have a new version of Code, when any of
# the patches changed, or when the code-server version changes (since
# it gets embedded into the code). Use VSCODE_CACHE_VERSION to
@ -204,86 +264,134 @@ jobs:
with:
path: lib/vscode-reh-web-*
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
- name: Build vscode
env:
VERSION: "0.0.0"
if: steps.cache-vscode.outputs.cache-hit != 'true'
run: |
pushd lib/vscode
npm ci
popd
npm run build:vscode
run: yarn build:vscode
# The release package does not contain any native modules
# and is neutral to architecture/os/libc version.
- run: npm run release
- name: Create release package
run: yarn release
if: success()
# https://github.com/actions/upload-artifact/issues/38
- run: tar -czf package.tar.gz release
- uses: actions/upload-artifact@v4
- name: Compress release package
run: tar -czf package.tar.gz release
- name: Upload npm package artifact
uses: actions/upload-artifact@v4
with:
name: npm-package
path: ./package.tar.gz
test-e2e:
name: Run e2e tests
runs-on: ubuntu-22.04
needs: build
runs-on: ubuntu-20.04
timeout-minutes: 25
needs: [changes, build]
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
steps:
- uses: actions/checkout@v6
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: actions/setup-node@v6
- name: Checkout repo
uses: actions/checkout@v4
- name: Install system dependencies
run: sudo apt update && sudo apt install -y libkrb5-dev
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- uses: actions/download-artifact@v5
- name: Fetch dependencies from cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: "**/node_modules"
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-
- name: Download npm package
uses: actions/download-artifact@v4
with:
name: npm-package
- run: tar -xzf package.tar.gz
- run: cd release && npm install --unsafe-perm --omit=dev
- name: Decompress npm package
run: tar -xzf package.tar.gz
- name: Install release package dependencies
run: cd release && npm install --unsafe-perm --omit=dev
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
- name: Install Playwright OS dependencies
run: |
./test/node_modules/.bin/playwright install-deps
./test/node_modules/.bin/playwright install
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
- uses: actions/upload-artifact@v4
- name: Run end-to-end tests
run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: failed-test-videos
path: ./test/test-results
- run: rm -rf ./release ./test/test-results
- name: Remove release packages and test artifacts
run: rm -rf ./release ./test/test-results
test-e2e-proxy:
name: Run e2e tests behind proxy
runs-on: ubuntu-22.04
needs: build
runs-on: ubuntu-20.04
timeout-minutes: 25
needs: [changes, build]
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
steps:
- uses: actions/checkout@v6
- run: sudo apt update && sudo apt install -y libkrb5-dev
- uses: actions/setup-node@v6
- name: Checkout repo
uses: actions/checkout@v4
- name: Install system dependencies
run: sudo apt update && sudo apt install -y libkrb5-dev
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- uses: actions/download-artifact@v5
- name: Fetch dependencies from cache
id: cache-node-modules
uses: actions/cache@v4
with:
path: "**/node_modules"
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-
- name: Download npm package
uses: actions/download-artifact@v4
with:
name: npm-package
- run: tar -xzf package.tar.gz
- run: cd release && npm install --unsafe-perm --omit=dev
- name: Decompress npm package
run: tar -xzf package.tar.gz
- name: Install release package dependencies
run: cd release && npm install --unsafe-perm --omit=dev
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
- name: Install Playwright OS dependencies
run: |
./test/node_modules/.bin/playwright install-deps
./test/node_modules/.bin/playwright install
- name: Cache Caddy
uses: actions/cache@v4
id: caddy-cache
@ -291,6 +399,7 @@ jobs:
path: |
~/.cache/caddy
key: cache-caddy-2.5.2
- name: Install Caddy
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -299,13 +408,23 @@ jobs:
gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
mkdir -p ~/.cache/caddy
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
- run: ~/.cache/caddy/caddy start --config ./ci/Caddyfile
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
if: always()
- uses: actions/upload-artifact@v4
- name: Start Caddy
run: sudo ~/.cache/caddy/caddy start --config ./ci/Caddyfile
- name: Run end-to-end tests
run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e:proxy --global-timeout 840000
- name: Stop Caddy
if: always()
run: sudo ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: failed-test-videos-proxy
path: ./test/test-results
- name: Remove release packages and test artifacts
run: rm -rf ./release ./test/test-results

View file

@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install code-server
run: ./install.sh
@ -44,7 +44,7 @@ jobs:
container: "alpine:3.17"
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install curl
run: apk add curl
@ -67,7 +67,7 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install code-server
run: ./install.sh

View file

@ -21,39 +21,78 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# NOTE: this job requires curl, jq and yarn
# All of them are included in ubuntu-latest.
npm:
runs-on: ubuntu-latest
steps:
- name: Checkout code-server
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: "yarn"
- name: Download npm package from release artifacts
uses: robinraju/release-downloader@v1.12
uses: robinraju/release-downloader@v1.11
with:
repository: "coder/code-server"
tag: ${{ github.event.inputs.version || github.ref_name }}
fileName: "package.tar.gz"
out-file-path: "release-npm-package"
# Strip out the v (v4.9.1 -> 4.9.1).
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ github.event.inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- run: npm run publish:npm
- name: Publish npm package and tag with "latest"
run: yarn publish:npm
env:
VERSION: ${{ env.VERSION }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_ENVIRONMENT: "production"
homebrew:
needs: npm
runs-on: ubuntu-latest
steps:
# Ensure things are up to date
# Suggested by homebrew maintainers
# https://github.com/Homebrew/discussions/discussions/1532#discussioncomment-782633
- name: Set up Homebrew
id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Checkout code-server
uses: actions/checkout@v4
- name: Configure git
run: |
git config --global user.name cdrci
git config --global user.email opensource@coder.com
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ github.event.inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Bump code-server homebrew version
env:
VERSION: ${{ env.VERSION }}
HOMEBREW_GITHUB_API_TOKEN: ${{secrets.HOMEBREW_GITHUB_API_TOKEN}}
run: ./ci/steps/brew-bump.sh
aur:
needs: npm
runs-on: ubuntu-latest
timeout-minutes: 10
env:
@ -62,13 +101,13 @@ jobs:
steps:
# We need to checkout code-server so we can get the version
- name: Checkout code-server
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
path: "./code-server"
- name: Checkout code-server-aur repo
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
repository: "cdrci/code-server-aur"
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
@ -85,14 +124,15 @@ jobs:
git config --global user.name cdrci
git config --global user.email opensource@coder.com
# Strip out the v (v4.9.1 -> 4.9.1).
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ github.event.inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Validate package
uses: heyhusen/archlinux-package-action@v2.4.0
uses: heyhusen/archlinux-package-action@v2.2.1
env:
VERSION: ${{ env.VERSION }}
with:
@ -111,12 +151,11 @@ jobs:
git commit -m "chore: updating version 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
docker:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- name: Checkout code-server
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@ -137,14 +176,15 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Strip out the v (v4.9.1 -> 4.9.1).
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ github.event.inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Download deb artifacts
uses: robinraju/release-downloader@v1.12
uses: robinraju/release-downloader@v1.11
with:
repository: "coder/code-server"
tag: v${{ env.VERSION }}
@ -152,7 +192,7 @@ jobs:
out-file-path: "release-packages"
- name: Download rpm artifacts
uses: robinraju/release-downloader@v1.12
uses: robinraju/release-downloader@v1.11
with:
repository: "coder/code-server"
tag: v${{ env.VERSION }}

View file

@ -19,27 +19,103 @@ concurrency:
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
package-linux-cross:
name: ${{ matrix.prefix }}
# TODO: cache building yarn --production
# possibly 2m30s of savings(?)
# this requires refactoring our release scripts
package-linux-amd64:
name: x86-64 Linux build
runs-on: ubuntu-latest
timeout-minutes: 15
needs: npm-version
container: "python:3.8-slim-buster"
container: "centos:8"
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
- name: Install development tools
run: |
cd /etc/yum.repos.d/
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
yum install -y gcc-c++ make jq rsync python3 libsecret-devel krb5-devel
- name: Install nfpm and envsubst
run: |
mkdir -p ~/.local/bin
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.22.2/nfpm_2.22.2_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
curl -sSfL https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst
chmod +x envsubst
mv envsubst ~/.local/bin
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install yarn
run: npm install -g yarn
- name: Download npm package
uses: actions/download-artifact@v4
with:
name: npm-release-package
- name: Decompress npm package
run: tar -xzf package.tar.gz
- name: Build standalone release
run: npm run release:standalone
- name: Install test dependencies
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
- name: Run integration tests on standalone release
run: yarn test:integration
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
if: success()
continue-on-error: true
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Build packages with nfpm
env:
VERSION: ${{ env.VERSION }}
run: yarn package
- uses: softprops/action-gh-release@v2
with:
draft: true
discussion_category_name: "📣 Announcements"
files: ./release-packages/*
package-linux-cross:
name: Linux cross-compile builds
runs-on: ubuntu-latest
timeout-minutes: 15
needs: npm-version
container: "debian:buster"
strategy:
matrix:
include:
- prefix: x86_64-linux-gnu
npm_arch: x64
apt_arch: amd64
package_arch: amd64
- prefix: aarch64-linux-gnu
npm_arch: arm64
apt_arch: arm64
package_arch: arm64
- prefix: arm-linux-gnueabihf
npm_arch: armv7l
apt_arch: armhf
package_arch: armv7l
env:
AR: ${{ format('{0}-ar', matrix.prefix) }}
@ -53,29 +129,23 @@ jobs:
PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
TARGET_ARCH: ${{ matrix.apt_arch }}
npm_config_arch: ${{ matrix.npm_arch }}
PKG_ARCH: ${{ matrix.package_arch }}
# Not building from source results in an x86_64 argon2, as if
# npm_config_arch is being ignored.
npm_config_build_from_source: true
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- name: Install cross-compiler and system dependencies
run: |
sed -i 's/deb\.debian\.org/archive.debian.org/g' /etc/apt/sources.list
dpkg --add-architecture $TARGET_ARCH
apt update && apt install -y --no-install-recommends \
apt-get update && apt-get install -y --no-install-recommends \
crossbuild-essential-$TARGET_ARCH \
libx11-dev:$TARGET_ARCH \
libx11-xcb-dev:$TARGET_ARCH \
@ -85,8 +155,6 @@ jobs:
ca-certificates \
curl wget rsync gettext-base
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- name: Install nfpm
run: |
mkdir -p ~/.local/bin
@ -94,12 +162,15 @@ jobs:
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package
- run: tar -xzf package.tar.gz
- run: npm run release:standalone
- name: Decompress npm package
run: tar -xzf package.tar.gz
- name: Build standalone release
run: npm run release:standalone
- name: Replace node with cross-compile equivalent
run: |
@ -108,17 +179,19 @@ jobs:
tar -xf node-${node_version}-linux-${npm_config_arch}.tar.xz node-${node_version}-linux-${npm_config_arch}/bin/node --strip-components=2
mv ./node ./release-standalone/lib/node
# Strip out the v (v4.9.1 -> 4.9.1).
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- env:
- name: Build packages with nfpm
env:
VERSION: ${{ env.VERSION }}
run: npm run package $PKG_ARCH
run: npm run package ${npm_config_arch}
- uses: softprops/action-gh-release@v1
- uses: softprops/action-gh-release@v2
with:
draft: true
discussion_category_name: "📣 Announcements"
@ -126,87 +199,17 @@ jobs:
package-macos-amd64:
name: x86-64 macOS build
runs-on: macos-15-intel
timeout-minutes: 15
needs: npm-version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout repo
uses: actions/checkout@v6
- name: Install Node.js
uses: actions/setup-node@v6
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- name: Install nfpm
run: |
mkdir -p ~/.local/bin
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
# The version of node-gyp we use depends on distutils but it was removed
# in Python 3.12. It seems to be fixed in the latest node-gyp so when we
# next update Node we can probably remove this. For now, install
# setuptools since it contains distutils.
- run: brew install python-setuptools
- name: Download npm package
uses: actions/download-artifact@v5
with:
name: npm-release-package
- run: tar -xzf package.tar.gz
- run: npm run release:standalone
- run: npm run test:native
# Strip out the v (v4.9.1 -> 4.9.1).
- name: Get and set VERSION
run: |
TAG="${{ inputs.version || github.ref_name }}"
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Build packages with nfpm
env:
VERSION: ${{ env.VERSION }}
run: npm run package
- uses: softprops/action-gh-release@v1
with:
draft: true
discussion_category_name: "📣 Announcements"
files: ./release-packages/*
package-macos-arm64:
name: arm64 macOS build
runs-on: macos-latest
timeout-minutes: 15
needs: npm-version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
cache-dependency-path: |
package-lock.json
test/package-lock.json
- run: SKIP_SUBMODULE_DEPS=1 npm ci
- name: Install nfpm
run: |
@ -218,18 +221,28 @@ jobs:
# in Python 3.12. It seems to be fixed in the latest node-gyp so when we
# next update Node we can probably remove this. For now, install
# setuptools since it contains distutils.
- run: brew install python-setuptools
- name: Install Python utilities
run: brew install python-setuptools
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package
- run: tar -xzf package.tar.gz
- run: npm run release:standalone
- run: npm run test:native
- name: Decompress npm package
run: tar -xzf package.tar.gz
# Strip out the v (v4.9.1 -> 4.9.1).
- name: Build standalone release
run: npm run release:standalone
- name: Install test dependencies
run: SKIP_SUBMODULE_DEPS=1 yarn install
- name: Run native module tests on standalone release
run: yarn test:native
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ inputs.version || github.ref_name }}"
@ -238,9 +251,9 @@ jobs:
- name: Build packages with nfpm
env:
VERSION: ${{ env.VERSION }}
run: npm run package
run: yarn package
- uses: softprops/action-gh-release@v1
- uses: softprops/action-gh-release@v2
with:
draft: true
discussion_category_name: "📣 Announcements"
@ -253,11 +266,11 @@ jobs:
needs: npm-version
steps:
- name: Download npm package
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
name: npm-release-package
- uses: softprops/action-gh-release@v1
- uses: softprops/action-gh-release@v2
with:
draft: true
discussion_category_name: "📣 Announcements"
@ -269,7 +282,7 @@ jobs:
timeout-minutes: 15
steps:
- name: Download artifacts
uses: dawidd6/action-download-artifact@v11
uses: dawidd6/action-download-artifact@v6
id: download
with:
branch: ${{ github.ref }}
@ -279,9 +292,11 @@ jobs:
check_artifacts: false
if_no_artifact_found: fail
- run: tar -xzf package.tar.gz
- name: Decompress npm package
run: tar -xzf package.tar.gz
# Strip out the v (v4.9.1 -> 4.9.1).
# NOTE@jsjoeio - we do this so we can strip out the v
# i.e. v4.9.1 -> 4.9.1
- name: Get and set VERSION
run: |
TAG="${{ inputs.version || github.ref_name }}"
@ -300,7 +315,8 @@ jobs:
# Ensure it has the same permissions as before
chmod 644 release/lib/vscode/product.json
- run: tar -czf package.tar.gz release
- name: Compress release package
run: tar -czf package.tar.gz release
- name: Upload npm package artifact
uses: actions/upload-artifact@v4

View file

@ -41,7 +41,7 @@ jobs:
container: "alpine:3.17"
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install test utilities
run: apk add bats checkbashisms
@ -58,7 +58,7 @@ jobs:
timeout-minutes: 5
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Install lint utilities
run: sudo apt install shellcheck

View file

@ -25,17 +25,21 @@ jobs:
timeout-minutes: 15
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version-file: .node-version
- name: Audit yarn for vulnerabilities
run: yarn audit
if: success()
- name: Audit npm for vulnerabilities
run: npm audit
run: npm shrinkwrap && npm audit
if: success()
trivy-scan-repo:
@ -43,15 +47,15 @@ jobs:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8
with:
scan-type: "fs"
scan-ref: "."
@ -72,11 +76,11 @@ jobs:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/autobuild to send a status report
name: Analyze with CodeQL
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View file

@ -44,14 +44,14 @@ concurrency:
jobs:
trivy-scan-image:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8
with:
image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true

View file

@ -1 +1 @@
22.20.0
20.11.1

View file

@ -7,4 +7,3 @@ helm-chart
test/scripts
test/e2e/extensions/test-extension
.pc
package-lock.json

View file

@ -5,7 +5,7 @@
{
"file": "package.json",
"line": 31,
"description": "## Commands\n\nTo start developing, make sure you have Node 16+ and the [required dependencies](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) installed. Then, run the following commands:\n\n1. Install dependencies:\n>> npm\n\n3. Start development mode (and watch for changes):\n>> npm run watch"
"description": "## Commands\n\nTo start developing, make sure you have Node 16+ and the [required dependencies](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) installed. Then, run the following commands:\n\n1. Install dependencies:\n>> yarn\n\n3. Start development mode (and watch for changes):\n>> yarn watch"
},
{
"file": "src/node/app.ts",
@ -20,7 +20,7 @@
{
"file": "src/node/app.ts",
"line": 62,
"description": "## That's it!\n\n\nThat's all there is to it! When this tour ends, your terminal session may stop, but just use `npm run watch` to start developing from here on out!\n\n\nIf you haven't already, be sure to check out these resources:\n- [Tour: Contributing](command:codetour.startTourByTitle?[\"Contributing\"])\n- [Docs: FAQ.md](https://github.com/coder/code-server/blob/main/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md)\n- [Community: GitHub Discussions](https://github.com/coder/code-server/discussions)\n- [Community: Slack](https://community.coder.com)"
"description": "## That's it!\n\n\nThat's all there is to it! When this tour ends, your terminal session may stop, but just use `yarn watch` to start developing from here on out!\n\n\nIf you haven't already, be sure to check out these resources:\n- [Tour: Contributing](command:codetour.startTourByTitle?[\"Contributing\"])\n- [Docs: FAQ.md](https://github.com/coder/code-server/blob/main/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md)\n- [Community: GitHub Discussions](https://github.com/coder/code-server/discussions)\n- [Community: Slack](https://community.coder.com)"
}
]
}
}

View file

@ -22,298 +22,6 @@ Code v99.99.999
## Unreleased
## [4.104.2](https://github.com/coder/code-server/releases/tag/v4.104.2) - 2025-09-26
Code v1.104.2
### Changed
- Update to Code 1.104.2.
## [4.104.1](https://github.com/coder/code-server/releases/tag/v4.104.1) - 2025-09-19
Code v1.104.1
### Changed
- Update to Code 1.104.1.
## [4.104.0](https://github.com/coder/code-server/releases/tag/v4.104.0) - 2025-09-15
Code v1.104.0
### Fixed
- Fix "extension not found" errors from Open VSX when trying to install the
latest version of an extension.
### Changed
- Update to Code 1.104.0.
## [4.103.2](https://github.com/coder/code-server/releases/tag/v4.103.2) - 2025-08-25
Code v1.103.2
### Changed
- Update to Code 1.103.2.
## [4.103.1](https://github.com/coder/code-server/releases/tag/v4.103.1) - 2025-08-15
Code v1.103.1
### Changed
- Update to Code 1.103.1.
## [4.103.0](https://github.com/coder/code-server/releases/tag/v4.103.0) - 2025-08-12
Code v1.103.0
### Changed
- Update to Code 1.103.0.
## [4.102.2](https://github.com/coder/code-server/releases/tag/v4.102.2) - 2025-07-24
Code v1.102.2
### Changed
- Update to Code 1.102.2.
## [4.102.1](https://github.com/coder/code-server/releases/tag/v4.102.1) - 2025-07-17
Code v1.102.1
### Changed
- Update to Code 1.102.1.
## [4.102.0](https://github.com/coder/code-server/releases/tag/v4.102.0) - 2025-07-16
Code v1.102.0
### Changed
- Update to Code 1.102.0.
### Added
- Custom strings can be configured using the `--i18n` flag set to a JSON
file. This can be used for either translation (and can be used alongside
`--locale`) or for customizing the strings. See
[./src/node/i18n/locales/en.json](./src/node/i18n/locales/en.json) for the
available keys.
## [4.101.2](https://github.com/coder/code-server/releases/tag/v4.101.2) - 2025-06-25
Code v1.101.2
### Changed
- Update to Code 1.101.2.
### Fixed
- Fix web views not loading due to 401 when requesting the service worker.
## [4.101.1](https://github.com/coder/code-server/releases/tag/v4.101.1) - 2025-06-20
Code v1.101.1
### Changed
- Update to Code 1.101.1.
## [4.101.0](https://github.com/coder/code-server/releases/tag/v4.101.0) - 2025-06-20
Code v1.101.0
### Changed
- Update to Code 1.101.0.
## [4.100.3](https://github.com/coder/code-server/releases/tag/v4.100.3) - 2025-06-03
Code v1.100.3
### Changed
- Update to Code 1.100.3.
## [4.100.2](https://github.com/coder/code-server/releases/tag/v4.100.2) - 2025-05-15
Code v1.100.2
### Changed
- Update to Code 1.100.2.
## [4.100.1](https://github.com/coder/code-server/releases/tag/v4.100.1) - 2025-05-13
Code v1.100.1
### Changed
- Update to Code 1.100.1.
## [4.100.0](https://github.com/coder/code-server/releases/tag/v4.100.0) - 2025-05-12
Code v1.100.0
### Added
- Trusted domains for links can now be set at run-time by configuring
`linkProtectionTrustedDomains` in the `lib/vscode/product.json` file or via
the `--link-protection-trusted-domains` flag.
### Changed
- Update to Code 1.100.0.
- Disable extension signature verification, which previously was skipped by
default (the package used for verification is not available to OSS builds of
VS Code) but now reportedly throws hard errors making it impossible to install
extensions.
### Fixed
- Flags with repeatable options now work via the config file.
## [4.99.4](https://github.com/coder/code-server/releases/tag/v4.99.4) - 2025-05-02
Code v1.99.3
### Security
- Validate that ports in the path proxy are numbers, to prevent proxying to
arbitrary domains.
## [4.99.3](https://github.com/coder/code-server/releases/tag/v4.99.3) - 2025-04-17
Code v1.99.3
### Added
- Added `--skip-auth-preflight` flag to let preflight requests through the
proxy.
### Changed
- Update to Code 1.99.3.
## [4.99.2](https://github.com/coder/code-server/releases/tag/v4.99.2) - 2025-04-10
Code v1.99.2
### Changed
- Update to Code 1.99.2.
## [4.99.1](https://github.com/coder/code-server/releases/tag/v4.99.1) - 2025-04-08
Code v1.99.1
### Changed
- Update to Code 1.99.1.
## [4.99.0](https://github.com/coder/code-server/releases/tag/v4.99.0) - 2025-04-07
Code v1.99.0
### Changed
- Update to Code 1.99.0.
## [4.98.0](https://github.com/coder/code-server/releases/tag/v4.98.0) - 2025-03-07
Code v1.98.0
### Changed
- Update to Code 1.98.0.
## [4.97.2](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-02-18
Code v1.97.2
### Added
- Added back macOS amd64 builds.
### Changed
- Update to Code 1.97.2.
- Softened dark mode login page colors.
## [4.96.4](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-01-20
Code v1.96.4
### Changed
- Update to Code 1.96.4.
## [4.96.2](https://github.com/coder/code-server/releases/tag/v4.96.2) - 2024-12-20
Code v1.96.2
### Changed
- Update to Code 1.96.2.
## [4.96.1](https://github.com/coder/code-server/releases/tag/v4.96.1) - 2024-12-18
Code v1.96.1
### Added
- Dark color scheme for login and error pages.
### Changed
- Update to Code 1.96.1.
## [4.95.3](https://github.com/coder/code-server/releases/tag/v4.95.3) - 2024-11-18
Code v1.95.3
### Changed
- Update to Code 1.95.3.
## [4.95.2](https://github.com/coder/code-server/releases/tag/v4.95.2) - 2024-11-12
Code v1.95.2
### Changed
- Update to Code 1.95.2.
## [4.95.1](https://github.com/coder/code-server/releases/tag/v4.95.1) - 2024-11-06
Code v1.95.1
### Changed
- Update to Code 1.95.1.
## [4.93.1](https://github.com/coder/code-server/releases/tag/v4.93.1) - 2024-09-23
Code v1.93.1
### Changed
- Updated to Code 1.93.1.
### Added
- Added `--abs-proxy-base-path` flag for when code-server is not at the root.
## [4.92.2](https://github.com/coder/code-server/releases/tag/v4.92.2) - 2024-08-19
Code v1.92.2
### Breaking changes
@ -863,6 +571,7 @@ Code v1.68.1
would be accessible at `my.domain/proxy/8000/` without any authentication.
If all of the following apply to you please update as soon as possible:
- You run code-server with the built-in password authentication.
- You run unprotected HTTP services on ports accessible by code-server.

View file

@ -16,18 +16,18 @@ This directory contains scripts used for the development of code-server.
- [./ci/dev/image](./dev/image)
- See [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md) for docs on the development container.
- [./ci/dev/fmt.sh](./dev/fmt.sh) (`npm run fmt`)
- [./ci/dev/fmt.sh](./dev/fmt.sh) (`yarn fmt`)
- Runs formatters.
- [./ci/dev/lint.sh](./dev/lint.sh) (`npm run lint`)
- [./ci/dev/lint.sh](./dev/lint.sh) (`yarn lint`)
- Runs linters.
- [./ci/dev/test-unit.sh](./dev/test-unit.sh) (`npm run test:unit`)
- [./ci/dev/test-unit.sh](./dev/test-unit.sh) (`yarn test:unit`)
- Runs unit tests.
- [./ci/dev/test-e2e.sh](./dev/test-e2e.sh) (`npm run test:e2e`)
- [./ci/dev/test-e2e.sh](./dev/test-e2e.sh) (`yarn test:e2e`)
- Runs end-to-end tests.
- [./ci/dev/watch.ts](./dev/watch.ts) (`npm run watch`)
- [./ci/dev/watch.ts](./dev/watch.ts) (`yarn watch`)
- Starts a process to build and launch code-server and restart on any code changes.
- Example usage in [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md).
- [./ci/dev/gen_icons.sh](./dev/gen_icons.sh) (`npm run icons`)
- [./ci/dev/gen_icons.sh](./dev/gen_icons.sh) (`yarn icons`)
- Generates the various icons from a single `.svg` favicon in
`src/browser/media/favicon.svg`.
- Requires [imagemagick](https://imagemagick.org/index.php)
@ -37,20 +37,20 @@ This directory contains scripts used for the development of code-server.
This directory contains the scripts used to build and release code-server.
You can disable minification by setting `MINIFY=`.
- [./ci/build/build-code-server.sh](./build/build-code-server.sh) (`npm run build`)
- [./ci/build/build-code-server.sh](./build/build-code-server.sh) (`yarn build`)
- Builds code-server into `./out` and bundles the frontend into `./dist`.
- [./ci/build/build-vscode.sh](./build/build-vscode.sh) (`npm run build:vscode`)
- [./ci/build/build-vscode.sh](./build/build-vscode.sh) (`yarn build:vscode`)
- Builds vscode into `./lib/vscode/out-vscode`.
- [./ci/build/build-release.sh](./build/build-release.sh) (`npm run release`)
- [./ci/build/build-release.sh](./build/build-release.sh) (`yarn release`)
- Bundles the output of the above two scripts into a single node module at `./release`.
- [./ci/build/clean.sh](./build/clean.sh) (`npm run clean`)
- [./ci/build/clean.sh](./build/clean.sh) (`yarn clean`)
- Removes all build artifacts.
- Useful to do a clean build.
- [./ci/build/code-server.sh](./build/code-server.sh)
- Copied into standalone releases to run code-server with the bundled node binary.
- [./ci/build/test-standalone-release.sh](./build/test-standalone-release.sh) (`npm run test:standalone-release`)
- [./ci/build/test-standalone-release.sh](./build/test-standalone-release.sh) (`yarn test:standalone-release`)
- Ensures code-server in the `./release-standalone` directory works by installing an extension.
- [./ci/build/build-packages.sh](./build/build-packages.sh) (`npm run package`)
- [./ci/build/build-packages.sh](./build/build-packages.sh) (`yarn package`)
- Packages `./release-standalone` into a `.tar.gz` archive in `./release-packages`.
- If on linux, [nfpm](https://github.com/goreleaser/nfpm) is used to generate `.deb` and `.rpm`.
- [./ci/build/nfpm.yaml](./build/nfpm.yaml)
@ -59,15 +59,15 @@ You can disable minification by setting `MINIFY=`.
- Entrypoint script for code-server for `.deb` and `.rpm`.
- [./ci/build/code-server.service](./build/code-server.service)
- systemd user service packaged into the `.deb` and `.rpm`.
- [./ci/build/release-github-draft.sh](./build/release-github-draft.sh) (`npm run release:github-draft`)
- [./ci/build/release-github-draft.sh](./build/release-github-draft.sh) (`yarn release:github-draft`)
- Uses [gh](https://github.com/cli/cli) to create a draft release with a template description.
- [./ci/build/release-github-assets.sh](./build/release-github-assets.sh) (`npm run release:github-assets`)
- [./ci/build/release-github-assets.sh](./build/release-github-assets.sh) (`yarn release:github-assets`)
- Downloads the release-package artifacts for the current commit from CI.
- Uses [gh](https://github.com/cli/cli) to upload the artifacts to the release
specified in `package.json`.
- [./ci/build/npm-postinstall.sh](./build/npm-postinstall.sh)
- Post install script for the npm package.
- Bundled by`npm run release`.
- Bundled by`yarn release`.
## release-image
@ -87,15 +87,15 @@ This directory contains the scripts used in CI.
Helps avoid clobbering the CI configuration.
- [./steps/fmt.sh](./steps/fmt.sh)
- Runs `npm run fmt`.
- Runs `yarn fmt`.
- [./steps/lint.sh](./steps/lint.sh)
- Runs `npm run lint`.
- Runs `yarn lint`.
- [./steps/test-unit.sh](./steps/test-unit.sh)
- Runs `npm run test:unit`.
- Runs `yarn test:unit`.
- [./steps/test-integration.sh](./steps/test-integration.sh)
- Runs `npm run test:integration`.
- Runs `yarn test:integration`.
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
- Runs `npm run test:e2e`.
- Runs `yarn test:e2e`.
- [./steps/release.sh](./steps/release.sh)
- Runs the release process.
- Generates the npm package at `./release`.

View file

@ -1,10 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
# Given a platform-specific release found in ./release-standalone, generate an
# compressed archives and bundles (as appropriate for the platform) named after
# the platform's architecture and OS and place them in ./release-packages and
# ./release-gcp.
# Packages code-server for the current OS and architecture into ./release-packages.
# This script assumes that a standalone release is built already into ./release-standalone
main() {
cd "$(dirname "${0}")/../.."

View file

@ -1,16 +1,13 @@
#!/usr/bin/env bash
set -euo pipefail
# Once both code-server and VS Code have been built, use this script to copy
# them into a single directory (./release), prepare the package.json and
# product.json, and add shrinkwraps. This results in a generic NPM package that
# we published to NPM and also use to compile platform-specific packages.
# This script requires vscode to be built with matching MINIFY.
# MINIFY controls whether minified VS Code is bundled. It must match the value
# used when VS Code was built.
# MINIFY controls whether minified vscode is bundled.
MINIFY="${MINIFY-true}"
# node_modules are not copied by default. Set KEEP_MODULES=1 to copy them.
# KEEP_MODULES controls whether the script cleans all node_modules requiring a yarn install
# to run first.
KEEP_MODULES="${KEEP_MODULES-0}"
main() {
@ -44,8 +41,12 @@ bundle_code_server() {
rsync src/browser/pages/*.css "$RELEASE_PATH/src/browser/pages"
rsync src/browser/robots.txt "$RELEASE_PATH/src/browser"
# Add typings for plugins
mkdir -p "$RELEASE_PATH/typings"
rsync typings/pluginapi.d.ts "$RELEASE_PATH/typings"
# Adds the commit to package.json
jq --slurp '(.[0] | del(.scripts,.jest,.devDependencies)) * .[1]' package.json <(
jq --slurp '.[0] * .[1]' package.json <(
cat << EOF
{
"commit": "$(git rev-parse HEAD)",
@ -87,50 +88,49 @@ bundle_vscode() {
rsync "${rsync_opts[@]}" ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"
# 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]' \
# Use the package.json for the web/remote server. It does not have the right
# version though so pull that from the main package.json.
jq --slurp '.[0] * {version: .[1].version}' \
"$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"
cp "$VSCODE_SRC_PATH/remote/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/npm-shrinkwrap.json"
"$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
mv "$VSCODE_SRC_PATH/remote/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/npm-shrinkwrap.json"
# Include global extension dependencies as well.
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
cp "$VSCODE_SRC_PATH/extensions/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/extensions/npm-shrinkwrap.json"
mv "$VSCODE_SRC_PATH/extensions/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/extensions/npm-shrinkwrap.json"
rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
}
create_shrinkwraps() {
# package-lock.json files (used to ensure deterministic versions of
# dependencies) are not packaged when publishing to the NPM registry.
#
# To ensure deterministic dependency versions (even when code-server is
# installed with NPM), we create an npm-shrinkwrap.json file from the
# currently installed node_modules. This ensures the versions used from
# development (that the package-lock.json guarantees) are also the ones
# installed by end-users. These will include devDependencies, but those will
# be ignored when installing globally (for code-server), and because we use
# --omit=dev (for VS Code).
# yarn.lock or package-lock.json files (used to ensure deterministic versions of dependencies) are
# not packaged when publishing to the NPM registry.
# To ensure deterministic dependency versions (even when code-server is installed with NPM), we create
# an npm-shrinkwrap.json file from the currently installed node_modules. This ensures the versions used
# from development (that the yarn.lock guarantees) are also the ones installed by end-users.
# These will include devDependencies, but those will be ignored when installing globally (for code-server), and
# because we use --omit=dev when installing vscode.
# We first generate the shrinkwrap file for code-server itself - which is the
# current directory.
cp package-lock.json package-lock.json.temp
npm shrinkwrap
mv package-lock.json.temp package-lock.json
# We first generate the shrinkwrap file for code-server itself - which is the current directory
create_shrinkwrap_keeping_yarn_lock
# Then the shrinkwrap files for the bundled VS Code.
# Then the shrinkwrap files for the bundled VSCode
pushd "$VSCODE_SRC_PATH/remote/"
cp package-lock.json package-lock.json.temp
npm shrinkwrap
mv package-lock.json.temp package-lock.json
create_shrinkwrap_keeping_yarn_lock
popd
pushd "$VSCODE_SRC_PATH/extensions/"
cp package-lock.json package-lock.json.temp
npm shrinkwrap
mv package-lock.json.temp package-lock.json
create_shrinkwrap_keeping_yarn_lock
popd
}
create_shrinkwrap_keeping_yarn_lock() {
# HACK@edvincent: Generating a shrinkwrap alters the yarn.lock which we don't want (with NPM URLs rather than the Yarn URLs)
# But to generate a valid shrinkwrap, it has to exist... So we copy it to then restore it
cp yarn.lock yarn.lock.temp
npm shrinkwrap
cp yarn.lock.temp yarn.lock
rm yarn.lock.temp
}
main "$@"

View file

@ -1,10 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
# Once we have an NPM package, use this script to copy it to a separate
# directory (./release-standalone) and install the dependencies. This new
# directory can then be packaged as a platform-specific release.
main() {
cd "$(dirname "${0}")/../.."
@ -13,10 +9,11 @@ main() {
rsync "$RELEASE_PATH/" "$RELEASE_PATH-standalone"
RELEASE_PATH+=-standalone
# Package managers may shim their own "node" wrapper into the PATH, so run
# node and ask it for its true path.
# We cannot get the path to Node from $PATH (for example via `which node`)
# because Yarn shims a script called `node` and we would end up just copying
# that script. Instead we run Node and have it print its actual path.
local node_path
node_path="$(node -p process.execPath)"
node_path="$(node <<< 'console.info(process.execPath)')"
mkdir -p "$RELEASE_PATH/bin"
mkdir -p "$RELEASE_PATH/lib"

View file

@ -54,7 +54,7 @@ main() {
if [[ ! ${VERSION-} ]]; then
echo "VERSION not set. Please set before running this script:"
echo "VERSION='0.0.0' npm run build:vscode"
echo "VERSION='0.0.0' yarn build:vscode"
exit 1
fi
@ -112,9 +112,7 @@ EOF
# this because we have an NPM package that could be installed on any platform.
# The correct platform dependencies and scripts will be installed as part of
# the post-install during `npm install` or when building a standalone release.
node --max-old-space-size=16384 --optimize-for-size \
./node_modules/gulp/bin/gulp.js \
"vscode-reh-web-linux-x64${MINIFY:+-min}"
yarn gulp "vscode-reh-web-linux-x64${MINIFY:+-min}"
# Reset so if you develop after building you will not be stuck with the wrong
# commit (the dev client will use `oss-dev` but the dev server will still use

View file

@ -76,8 +76,8 @@ main() {
echo "USE AT YOUR OWN RISK!"
fi
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then
echo "ERROR: code-server currently requires node v22."
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-20}" ]; then
echo "ERROR: code-server currently requires node v20."
if [ -n "$FORCE_NODE_VERSION" ]; then
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
fi
@ -117,11 +117,14 @@ main() {
install_with_yarn_or_npm() {
echo "User agent: ${npm_config_user_agent-none}"
# For development we enforce npm, but for installing the package as an
# end-user we want to keep using whatever package manager is in use.
# NOTE@edvincent: We want to keep using the package manager that the end-user was using to install the package.
# This also ensures that when *we* run `yarn` in the development process, the yarn.lock file is used.
case "${npm_config_user_agent-}" in
npm*)
if ! npm install --unsafe-perm --omit=dev; then
# HACK: NPM's use of semver doesn't like resolving some peerDependencies that vscode (upstream) brings in the form of pre-releases.
# The legacy behavior doesn't complain about pre-releases being used, falling back to that for now.
# See https://github.com//pull/5071
if ! npm install --unsafe-perm --legacy-peer-deps --omit=dev; then
return 1
fi
;;

View file

@ -18,7 +18,7 @@ main() {
echo "Files need generation or are formatted incorrectly:"
git -c color.ui=always status | grep --color=no '\[31m'
echo "Please run the following locally:"
echo " npm run doctoc"
echo " yarn doctoc"
exit 1
fi
}

View file

@ -1,50 +1,44 @@
#!/bin/sh
set -eu
# Generate icons from a single favicon.svg. favicon.svg should have no fill
# colors set.
main() {
cd src/browser/media
# We need .ico for backwards compatibility. The other two are the only icon
# sizes required by Chrome and we use them for stuff like apple-touch-icon as
# well. https://web.dev/add-manifest/
# We need .ico for backwards compatibility.
# The other two are the only icon sizes required by Chrome and
# we use them for stuff like apple-touch-icon as well.
# https://web.dev/add-manifest/
#
# This should be enough and we can always add more if there are problems.
#
# -quiet to avoid https://github.com/ImageMagick/ImageMagick/issues/884
# -background defaults to white but we want it transparent.
# -density somehow makes the image both sharper and smaller in file size.
#
# https://imagemagick.org/script/command-line-options.php#background
convert -quiet -background transparent \
-resize 256x256 -density 256x256 \
favicon.svg favicon.ico
convert -quiet -background transparent -resize 256x256 favicon.svg favicon.ico
# We do not generate the pwa-icon from the favicon as they are slightly different
# designs and sizes.
# See favicon.afdesign and #2401 for details on the differences.
convert -quiet -background transparent -resize 192x192 pwa-icon.png pwa-icon-192.png
convert -quiet -background transparent -resize 512x512 pwa-icon.png pwa-icon-512.png
# Generate PWA icons. There should be enough padding to support masking.
convert -quiet -border 60x60 -bordercolor white -background white \
-resize 192x192 -density 192x192 \
favicon.svg pwa-icon-maskable-192.png
convert -quiet -border 160x160 -bordercolor white -background white \
-resize 512x512 -density 512x512 \
favicon.svg pwa-icon-maskable-512.png
# We use -quiet above to avoid https://github.com/ImageMagick/ImageMagick/issues/884
# Generate non-maskable PWA icons.
magick pwa-icon-maskable-192.png \
\( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 50,50" \) \
-channel-fx "| gray=>alpha" \
pwa-icon-192.png
magick pwa-icon-maskable-512.png \
\( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 100,100" \) \
-channel-fx "| gray=>alpha" \
pwa-icon-512.png
# The following adds dark mode support for the favicon as
# favicon-dark-support.svg There is no similar capability for pwas or .ico so
# we can only add support to the svg.
favicon_dark_style="<style>@media (prefers-color-scheme: dark) {* { fill: white; }}</style>"
cp favicon.svg favicon-dark-support.svg
sed "s%<path%$favicon_dark_style\n <path%" favicon.svg > favicon-dark-support.svg
# The following adds dark mode support for the favicon as favicon-dark-support.svg
# There is no similar capability for pwas or .ico so we can only add support to the svg.
favicon_dark_style="<style>
@media (prefers-color-scheme: dark) {
* {
fill: white;
}
}
</style>"
# See https://stackoverflow.com/a/22901380/4283659
# This escapes all newlines so that sed will accept them.
favicon_dark_style="$(printf "%s\n" "$favicon_dark_style" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g')"
sed "$(
cat -n << EOF
s%<rect id="favicon"%$favicon_dark_style<rect id="favicon"%
EOF
)" favicon.svg > favicon-dark-support.svg
}
main "$@"

View file

@ -3,13 +3,14 @@ set -euo pipefail
# Install dependencies in $1.
install-deps() {
local args=()
local args=(install)
if [[ ${CI-} ]]; then
args+=(ci)
else
args+=(install)
args+=(--frozen-lockfile)
fi
# If there is no package.json then npm will look upward and end up installing
if [[ "$1" == "lib/vscode" ]]; then
args+=(--no-default-rc)
fi
# If there is no package.json then yarn will look upward and end up installing
# from the root resulting in an infinite loop (this can happen if you have not
# checked out the submodule yet for example).
if [[ ! -f "$1/package.json" ]]; then
@ -18,7 +19,7 @@ install-deps() {
fi
pushd "$1"
echo "Installing dependencies for $PWD"
npm "${args[@]}"
yarn "${args[@]}"
popd
}

View file

@ -1,3 +0,0 @@
if (process.env.npm_execpath.includes("yarn")) {
throw new Error("`yarn` is no longer supported; please use `npm install` instead")
}

View file

@ -2,9 +2,9 @@
set -euo pipefail
help() {
echo >&2 " You can build with 'npm run watch' or you can build a release"
echo >&2 " For example: 'npm run build && npm run build:vscode && KEEP_MODULES=1 npm run release'"
echo >&2 " Then 'CODE_SERVER_TEST_ENTRY=./release npm run test:e2e'"
echo >&2 " You can build with 'yarn watch' or you can build a release"
echo >&2 " For example: 'yarn build && yarn build:vscode && KEEP_MODULES=1 yarn release'"
echo >&2 " Then 'CODE_SERVER_TEST_ENTRY=./release yarn test:e2e'"
echo >&2 " You can manually run that release with 'node ./release'"
}
@ -15,7 +15,7 @@ main() {
pushd test/e2e/extensions/test-extension
echo "Building test extension"
npm run build
yarn build
popd
local dir="$PWD"
@ -44,7 +44,7 @@ main() {
fi
cd test
./node_modules/.bin/playwright test "$@"
yarn playwright test "$@"
}
main "$@"

View file

@ -2,9 +2,9 @@
set -euo pipefail
help() {
echo >&2 " You can build the standalone release with 'npm run release:standalone'"
echo >&2 " You can build the standalone release with 'yarn release:standalone'"
echo >&2 " Or you can pass in a custom path."
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' yarn test:integration"
}
# Make sure a code-server release works. You can pass in the path otherwise it
@ -33,7 +33,7 @@ main() {
exit 1
fi
CODE_SERVER_PATH="$path" ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
CODE_SERVER_PATH="$path" CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
}
main "$@"

View file

@ -2,9 +2,9 @@
set -euo pipefail
help() {
echo >&2 " You can build the standalone release with 'npm run release:standalone'"
echo >&2 " You can build the standalone release with 'yarn release:standalone'"
echo >&2 " Or you can pass in a custom path."
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' yarn test:integration"
}
# Make sure a code-server release works. You can pass in the path otherwise it

View file

@ -6,10 +6,15 @@ main() {
source ./ci/lib.sh
echo "Building test plugin"
pushd test/unit/node/test-plugin
make -s out/index.js
popd
# We must keep jest in a sub-directory. See ../../test/package.json for more
# information. We must also run it from the root otherwise coverage will not
# include our source files.
./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts"
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts" --testPathIgnorePatterns "./test/unit/node/test-plugin"
}
main "$@"

View file

@ -45,11 +45,9 @@ class Watcher {
private readonly compilers: DevelopmentCompilers = {
codeServer: spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath }),
vscode: spawn("npm", ["run", "watch"], { cwd: this.paths.vscodeDir }),
vscodeWebExtensions: spawn("npm", ["run", "watch-web"], { cwd: this.paths.vscodeDir }),
plugins: this.paths.pluginDir
? spawn("npm", ["run", "build", "--watch"], { cwd: this.paths.pluginDir })
: undefined,
vscode: spawn("yarn", ["watch"], { cwd: this.paths.vscodeDir }),
vscodeWebExtensions: spawn("yarn", ["watch-web"], { cwd: this.paths.vscodeDir }),
plugins: this.paths.pluginDir ? spawn("yarn", ["build", "--watch"], { cwd: this.paths.pluginDir }) : undefined,
}
public async initialize(): Promise<void> {

View file

@ -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.31.2
version: 3.22.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.104.2
appVersion: 4.91.0

View file

@ -7,11 +7,8 @@ metadata:
helm.sh/chart: {{ include "code-server.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- if .Values.annotations }}
annotations: {{- toYaml .Values.annotations | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.replicaCount | default 1 }}
replicas: 1
strategy:
type: Recreate
selector:
@ -38,9 +35,8 @@ spec:
securityContext:
fsGroup: {{ .Values.securityContext.fsGroup }}
{{- end }}
{{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) .Values.extraInitContainers }}
initContainers:
{{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
initContainers:
- name: init-chmod-data
image: busybox:latest
imagePullPolicy: IfNotPresent
@ -54,7 +50,6 @@ spec:
volumeMounts:
- name: data
mountPath: /home/coder
{{- end }}
{{- if .Values.extraInitContainers }}
{{ tpl .Values.extraInitContainers . | indent 6}}
{{- end }}

View file

@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.104.2'
tag: '4.91.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
@ -19,9 +19,6 @@ nameOverride: ""
fullnameOverride: ""
hostnameOverride: ""
# The existing secret to use for code-server authentication in the frontend. the password is stored in the secret under the key `password`
# existingSecret: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
@ -31,9 +28,6 @@ serviceAccount:
# If not set and create is true, a name is generated using the fullname template
name: ""
# Specifies annotations for deployment
annotations: {}
podAnnotations: {}
podSecurityContext: {}
@ -78,9 +72,8 @@ extraArgs: []
extraVars: []
# - name: DISABLE_TELEMETRY
# value: "true"
# if dind is desired:
# - name: DOCKER_HOST
# value: "tcp://localhost:2376"
# value: "tcp://localhost:2375"
##
## Init containers parameters:
@ -143,39 +136,25 @@ lifecycle:
# - -c
# - curl -s -L SOME_SCRIPT | bash
# for dind, the following may be helpful
# postStart:
# exec:
# command:
# - /bin/sh
# - -c
# - |
# sudo apt-get update \
# && sudo apt-get install -y docker.io
## Enable an Specify container in extraContainers.
## This is meant to allow adding code-server dependencies, like docker-dind.
extraContainers: |
# If docker-dind is used, DOCKER_HOST env is mandatory to set in "extraVars"
# - name: docker-dind
# image: docker:28.3.2-dind
# imagePullPolicy: IfNotPresent
# resources:
# requests:
# cpu: 1
# ephemeral-storage: "50Gi"
# memory: 10Gi
# securityContext:
# privileged: true
# procMount: Default
# env:
# - name: DOCKER_TLS_CERTDIR
# value: "" # disable TLS setup
# command:
# - dockerd
# - --host=unix:///var/run/docker.sock
# - --host=tcp://0.0.0.0:2376
#- name: docker-dind
# image: docker:19.03-dind
# imagePullPolicy: IfNotPresent
# resources:
# requests:
# cpu: 250m
# memory: 256M
# securityContext:
# privileged: true
# procMount: Default
# env:
# - name: DOCKER_TLS_CERTDIR
# value: ""
# - name: DOCKER_DRIVER
# value: "overlay2"
extraInitContainers: |
# - name: customization

View file

@ -31,10 +31,7 @@ RUN sed -i "s/# en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen \
&& locale-gen
ENV LANG=en_US.UTF-8
RUN if grep -q 1000 /etc/passwd; then \
userdel -r "$(id -un 1000)"; \
fi \
&& adduser --gecos '' --disabled-password coder \
RUN adduser --gecos '' --disabled-password coder \
&& echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
RUN ARCH="$(dpkg --print-architecture)" \

View file

@ -7,7 +7,7 @@ eval "$(fixuid -q)"
if [ "${DOCKER_USER-}" ]; then
USER="$DOCKER_USER"
if [ -z "$(id -u "$DOCKER_USER" 2>/dev/null)" ]; then
if [ "$DOCKER_USER" != "$(whoami)" ]; then
echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
# Unfortunately we cannot change $HOME as we cannot move any bind mounts
# nor can we bind mount $HOME into a new home as that requires a privileged container.

View file

@ -53,11 +53,11 @@ main() {
# This string is used to determine how we should tag the npm release.
# Environment can be one of three choices:
# "development" - this means we tag with the PR number, allowing
# a developer to install this version with `npm install code-server@<pr-number>`
# a developer to install this version with `yarn add code-server@<pr-number>`
# "staging" - this means we tag with `beta`, allowing
# a developer to install this version with `npm install code-server@beta`
# a developer to install this version with `yarn add code-server@beta`
# "production" - this means we tag with `latest` (default), allowing
# a developer to install this version with `npm install code-server@latest`
# a developer to install this version with `yarn add code-server@latest`
if ! is_env_var_set "NPM_ENVIRONMENT"; then
echo "NPM_ENVIRONMENT is not set."
echo "Determining in script based on GITHUB environment variables."
@ -86,7 +86,7 @@ main() {
if [[ "$NPM_ENVIRONMENT" == "production" ]]; then
NPM_VERSION="$VERSION"
# This means the npm version will be published as "stable"
# and installed when a user runs `npm install code-server`
# and installed when a user runs `yarn install code-server`
NPM_TAG="latest"
else
COMMIT_SHA="$GITHUB_SHA"
@ -94,7 +94,7 @@ main() {
if [[ "$NPM_ENVIRONMENT" == "staging" ]]; then
NPM_VERSION="$VERSION-beta-$COMMIT_SHA"
# This means the npm version will be tagged with "beta"
# and installed when a user runs `npm install code-server@beta`
# and installed when a user runs `yarn install code-server@beta`
NPM_TAG="beta"
PACKAGE_NAME="@coder/code-server-pr"
fi
@ -105,7 +105,7 @@ main() {
NPM_VERSION="$VERSION-$PR_NUMBER-$COMMIT_SHA"
PACKAGE_NAME="@coder/code-server-pr"
# This means the npm version will be tagged with "<pr number>"
# and installed when a user runs `npm install code-server@<pr number>`
# and installed when a user runs `yarn install code-server@<pr number>`
NPM_TAG="$PR_NUMBER"
fi
@ -120,7 +120,10 @@ main() {
# Example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
# Example: "version": "4.0.1-beta-ad7b23cfe6ffd72914e34781ef7721b129a23040"
pushd release
# NOTE@jsjoeio
# I originally tried to use `yarn version` but ran into issues and abandoned it.
npm version "$NPM_VERSION"
# NOTE@jsjoeio
# Use the development package name
# This is so we don't clutter the code-server versions on npm
# with development versions.
@ -131,6 +134,7 @@ main() {
popd
fi
# NOTE@jsjoeio
# We need to make sure we haven't already published the version.
# If we get error, continue with script because we want to publish
# If version is valid, we check if we're publishing the same one
@ -140,10 +144,10 @@ main() {
return
fi
# NOTE@jsjoeio
# Since the dev builds are scoped to @coder
# We pass --access public to ensure npm knows it's not private.
cd release
npm publish --tag "$NPM_TAG" --access public
yarn publish --non-interactive release --tag "$NPM_TAG" --access public
}
main "$@"

View file

@ -32,10 +32,10 @@ The prerequisites for contributing to code-server are almost the same as those
for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Here is what is needed:
- `node` v22.x
- `node` v20.x
- `git` v2.x or greater
- [`git-lfs`](https://git-lfs.github.com)
- [`npm`](https://www.npmjs.com/)
- [`yarn`](https://classic.yarnpkg.com/en/)
- Used to install JS packages and run scripts
- [`nfpm`](https://nfpm.goreleaser.com/)
- Used to build `.deb` and `.rpm` packages
@ -70,8 +70,8 @@ for more information.
1. `git clone https://github.com/coder/code-server.git` - Clone `code-server`
2. `git submodule update --init` - Clone `vscode` submodule
3. `quilt push -a` - Apply patches to the `vscode` submodule.
4. `npm install` - Install dependencies
5. `npm run watch` - Launch code-server localhost:8080. code-server will be live
4. `yarn` - Install dependencies
5. `yarn watch` - Launch code-server localhost:8080. code-server will be live
reloaded when changes are made; the browser needs to be refreshed manually.
When pulling down changes that include modifications to the patches you will
@ -102,7 +102,7 @@ commits first if you are doing this).
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`.
4. From the code-server **project root**, run `yarn 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.
@ -127,14 +127,14 @@ You can build a full production as follows:
```shell
git submodule update --init
quilt push -a
npm install
npm run build
VERSION=0.0.0 npm run build:vscode
npm run release
yarn install
yarn build
VERSION=0.0.0 yarn build:vscode
yarn release
```
This does not keep `node_modules`. If you want them to be kept, use
`KEEP_MODULES=1 npm run release`
`KEEP_MODULES=1 yarn release`
Run your build:
@ -148,9 +148,9 @@ node .
Then, to build the release package:
```shell
npm run release:standalone
npm run test:integration
npm run package
yarn release:standalone
yarn test:integration
yarn package
```
> On Linux, the currently running distro will become the minimum supported
@ -170,9 +170,9 @@ writing, we do this for the following platforms/architectures:
- Linux armhf.rpm
- macOS arm64.tar.gz
Currently, these are compiled in CI using the `npm run release:standalone`
command in the `release.yaml` workflow. We then upload them to the draft release
and distribute via GitHub Releases.
Currently, these are compiled in CI using the `yarn release:standalone` command
in the `release.yaml` workflow. We then upload them to the draft release and
distribute via GitHub Releases.
### Troubleshooting
@ -226,7 +226,7 @@ We use these to test anything related to our scripts (most of which live under
### Integration tests
These are a work in progress. We build code-server and run tests with `npm run
These are a work in progress. We build code-server and run tests with `yarn
test:integration`, which ensures that code-server builds work on their
respective platforms.

View file

@ -31,7 +31,6 @@
- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
- [What's the difference between code-server and OpenVSCode-Server?](#whats-the-difference-between-code-server-and-openvscode-server)
- [What's the difference between code-server and GitHub Codespaces?](#whats-the-difference-between-code-server-and-github-codespaces)
- [What's the difference between code-server and VS Code web?](#whats-the-difference-between-code-server-and-vs-code-web)
- [Does code-server have any security login validation?](#does-code-server-have-any-security-login-validation)
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
- [How do I change the port?](#how-do-i-change-the-port)
@ -323,8 +322,12 @@ As long as there is an active browser connection, code-server touches
`~/.local/share/code-server/heartbeat` once a minute.
If you want to shutdown code-server if there hasn't been an active connection
after a predetermined amount of time, you can use the --idle-timeout-seconds flag
or set an `CODE_SERVER_IDLE_TIMEOUT_SECONDS` environment variable.
after a predetermined amount of time, you can do so by checking continuously for
the last modified time on the heartbeat file. If it is older than X minutes (or
whatever amount of time you'd like), you can kill code-server.
Eventually, [#1636](https://github.com/coder/code-server/issues/1636) will make
this process better.
## How do I change the password?
@ -380,9 +383,6 @@ mount into `/home/coder/myproject` from inside the `code-server` container. You
need to make sure the Docker daemon's `/home/coder/myproject` is the same as the
one mounted inside the `code-server` container, and the mount will work.
If you want Docker enabled when deploying on Kubernetes, look at the `values.yaml`
file for the 3 fields: `extraVars`, `lifecycle.postStart`, and `extraContainers`.
## How do I disable telemetry?
Use the `--disable-telemetry` flag to disable telemetry.
@ -440,8 +440,6 @@ Specific changes include:
- The ability to use your own marketplace and collect your own telemetry
- Built-in proxy for accessing ports on the remote machine integrated into
VS Code's ports panel
- Settings are stored on disk like desktop VS Code, instead of in browser
storage (note that state is still stored in browser storage).
- Wrapper process that spawns VS Code on-demand and has a separate CLI
- Notification when updates are available
- [Some other things](https://github.com/coder/code-server/tree/main/patches)
@ -450,12 +448,6 @@ Some of these changes appear very unlikely to ever be adopted by Microsoft.
Some may make their way upstream, further closing the gap, but at the moment it
looks like there will always be some subtle differences.
## What's the difference between code-server and VS Code web?
VS Code web (which can be ran using `code serve-web`) has the same differences
as the Codespaces section above. VS Code web can be a better choice if you need
access to the official Microsoft marketplace.
## Does code-server have any security login validation?
code-server supports setting a single password and limits logins to two per

View file

@ -90,7 +90,7 @@ Our testing structure is laid out under our [Contributing docs](https://coder.co
If you're ever looking to add more tests, here are a few ways to get started:
- run `npm run test:unit` and look at the coverage chart. You'll see all the
- run `yarn test:unit` and look at the coverage chart. You'll see all the
uncovered lines. This is a good place to start.
- look at `test/scripts` to see which scripts are tested. We can always use more
tests there.

View file

@ -1,6 +1,6 @@
# code-server
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/coder/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://coder.com/community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![Discord](https://img.shields.io/discord/747933592273027093)](https://discord.com/invite/coder) [![codecov](https://codecov.io/gh/coder/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/coder/code-server) [![See latest](https://img.shields.io/static/v1?label=Docs&message=see%20latest&color=blue)](https://coder.com/docs/code-server/latest)
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/coder/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://coder.com/community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/coder/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/coder/code-server) [![See latest](https://img.shields.io/static/v1?label=Docs&message=see%20latest&color=blue)](https://coder.com/docs/code-server/latest)
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
access it in the browser.
@ -24,7 +24,7 @@ on how to set up a Google VM on which you can install code-server.
## Getting started
There are five ways to get started:
There are four ways to get started:
1. Using the [install
script](https://github.com/coder/code-server/blob/main/install.sh), which
@ -35,9 +35,6 @@ There are five ways to get started:
3. Deploy code-server to your team with [coder/coder](https://cdr.co/coder-github)
4. Using our one-click buttons and guides to [deploy code-server to a cloud
provider](https://github.com/coder/deploy-code-server) ⚡
5. Using the [code-server feature for
devcontainers](https://github.com/coder/devcontainer-features/blob/main/src/code-server/README.md),
if you already use devcontainers in your project.
If you use the install script, you can preview what occurs during the install
process:

View file

@ -17,8 +17,8 @@ We use the following tools to help us stay on top of vulnerability mitigation.
- Comprehensive vulnerability scanner that runs on PRs into the default
branch and scans both our container image and repository code (see
`trivy-scan-repo` and `trivy-scan-image` jobs in `build.yaml`)
- `npm audit`
- Audits NPM dependencies.
- `yarn audit` and `npm audit`
- Audits Yarn/NPM dependencies.
## Supported Versions

View file

@ -11,11 +11,11 @@ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
```
6. Exit the terminal using `exit` and then reopen the terminal
7. Install and use Node.js 22:
7. Install and use Node.js 20:
```shell
nvm install 22
nvm use 22
nvm install 18
nvm use 18
```
8. Install code-server globally on device with: `npm install --global code-server`

View file

@ -20,11 +20,6 @@
- [Proxying to a Vue app](#proxying-to-a-vue-app)
- [Proxying to an Angular app](#proxying-to-an-angular-app)
- [Proxying to a Svelte app](#proxying-to-a-svelte-app)
- [Prefixing `/absproxy/<port>` with a path](#prefixing-absproxyport-with-a-path)
- [Preflight requests](#preflight-requests)
- [Internationalization and customization](#internationalization-and-customization)
- [Available keys and placeholders](#available-keys-and-placeholders)
- [Legacy flag](#legacy-flag)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
@ -123,22 +118,22 @@ access code-server on an iPad or do not want to use SSH port forwarding.
1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic.
2. You'll need a domain name (if you don't have one, you can purchase one from
1. You'll need a domain name (if you don't have one, you can purchase one from
[Google Domains](https://domains.google.com) or the domain service of your
choice). Once you have a domain name, add an A record to your domain that contains your
choice)). Once you have a domain name, add an A record to your domain that contains your
instance's IP address.
3. Install [Caddy](https://caddyserver.com/docs/download#debian-ubuntu-raspbian):
1. Install [Caddy](https://caddyserver.com/docs/download#debian-ubuntu-raspbian):
```console
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```
```console
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```
4. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this:
1. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this:
```text
mydomain.com {
@ -157,7 +152,7 @@ access code-server on an iPad or do not want to use SSH port forwarding.
Remember to replace `mydomain.com` with your domain name!
5. Reload Caddy:
1. Reload Caddy:
```console
sudo systemctl reload caddy
@ -168,22 +163,21 @@ At this point, you should be able to access code-server via
### Using Let's Encrypt with NGINX
1. This option requires that the remote machine be exposed to the internet. Make
sure that your instance allows HTTP/HTTPS traffic.
1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic.
2. You'll need a domain name (if you don't have one, you can purchase one from
1. You'll need a domain name (if you don't have one, you can purchase one from
[Google Domains](https://domains.google.com) or the domain service of your
choice). Once you have a domain name, add an A record to your domain that contains your
choice)). Once you have a domain name, add an A record to your domain that contains your
instance's IP address.
3. Install NGINX:
1. Install NGINX:
```bash
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
```
4. Update `/etc/nginx/sites-available/code-server` using sudo with the following
1. Update `/etc/nginx/sites-available/code-server` using sudo with the following
configuration:
```text
@ -204,11 +198,13 @@ At this point, you should be able to access code-server via
Be sure to replace `mydomain.com` with your domain name!
5. Enable the config:
1. Enable the config:
```console
sudo ln -s ../sites-available/code-server /etc/nginx/sites-enabled/code-server
sudo certbot --non-interactive --redirect --agree-tos --nginx -d mydomain.com -m me@example.com
```
Be sure to replace `me@example.com` with your actual email.
At this point, you should be able to access code-server via
@ -274,9 +270,9 @@ should see OSSStatus: 9836 in the browser console.
If you want to use external authentication mechanism (e.g., Sign in with
Google), you can do this with a reverse proxy such as:
- [Pomerium](https://www.pomerium.com/docs/guides/code-server.html)
- [oauth2-proxy](https://oauth2-proxy.github.io/oauth2-proxy/)
- [Cloudflare Access](https://www.cloudflare.com/zero-trust/products/access/)
- [Pomerium](https://www.pomerium.io/guides/code-server.html)
- [oauth2_proxy](https://github.com/pusher/oauth2_proxy)
- [Cloudflare Access](https://teams.cloudflare.com/access)
## HTTPS and self-signed certificates
@ -295,9 +291,7 @@ redirect all HTTP requests to HTTPS.
> You can use [Let's Encrypt](https://letsencrypt.org/) to get a TLS certificate
> for free.
Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it
will change the address displayed in the green section of code-server in the
bottom left to show the correct address.
Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it will change the address displayed in the green section of code-server in the bottom left to show the correct address.
## Accessing web services
@ -383,16 +377,14 @@ PUBLIC_URL=/absproxy/3000 \
BROWSER=none yarn start
```
You should then be able to visit
`https://my-code-server-address.io/absproxy/3000` to see your app exposed
through code-server.
You should then be able to visit `https://my-code-server-address.io/absproxy/3000` to see your app exposed through
code-server!
> We highly recommend using the subdomain approach instead to avoid this class of issue.
### Proxying to a Vue app
Similar to the situation with React apps, you have to make a few modifications
to proxy a Vue app.
Similar to the situation with React apps, you have to make a few modifications to proxy a Vue app.
1. add `vue.config.js`
2. update the values to match this (you can use any free port):
@ -413,8 +405,7 @@ Read more about `publicPath` in the [Vue.js docs](https://cli.vuejs.org/config/#
### Proxying to an Angular app
In order to use code-server's built-in proxy with Angular, you need to make the
following changes in your app:
In order to use code-server's built-in proxy with Angular, you need to make the following changes in your app:
1. use `<base href="./.">` in `src/index.html`
2. add `--serve-path /absproxy/4200` to `ng serve` in your `package.json`
@ -423,8 +414,7 @@ For additional context, see [this GitHub Discussion](https://github.com/coder/co
### Proxying to a Svelte app
In order to use code-server's built-in proxy with Svelte, you need to make the
following changes in your app:
In order to use code-server's built-in proxy with Svelte, you need to make the following changes in your app:
1. Add `svelte.config.js` if you don't already have one
2. Update the values to match this (you can use any free port):
@ -442,71 +432,3 @@ const config = {
3. Access app at `<code-server-root>/absproxy/5173/` e.g. `http://localhost:8080/absproxy/5173/
For additional context, see [this Github Issue](https://github.com/sveltejs/kit/issues/2958)
### Prefixing `/absproxy/<port>` with a path
This is a case where you need to serve an application via `absproxy` as
explained above while serving code-server itself from a path other than the root
in your domain.
For example: `http://my-code-server.com/user/123/workspace/my-app`. To achieve
this result:
1. Start code-server with the switch `--abs-proxy-base-path=/user/123/workspace`
2. Follow one of the instructions above for your framework.
### Preflight requests
By default, if you have auth enabled, code-server will authenticate all proxied
requests including preflight requests. This can cause issues because preflight
requests do not typically include credentials. To allow all preflight requests
through the proxy without authentication, use `--skip-auth-preflight`.
## Internationalization and customization
code-server allows you to provide a JSON file to configure certain strings. This
can be used for both internationalization and customization.
Create a JSON file with your custom strings:
```json
{
"WELCOME": "Welcome to {{app}}",
"LOGIN_TITLE": "{{app}} Access Portal",
"LOGIN_BELOW": "Please log in to continue",
"PASSWORD_PLACEHOLDER": "Enter Password"
}
```
Then reference the file:
```shell
code-server --i18n /path/to/custom-strings.json
```
Or this can be done in the config file:
```yaml
i18n: /path/to/custom-strings.json
```
You can combine this with the `--locale` flag to configure language support for
both code-server and VS Code in cases where code-server has no support but VS
Code does. If you are using this for internationalization, please consider
sending us a pull request to contribute it to `src/node/i18n/locales`.
### Available keys and placeholders
Refer to [../src/node/i18n/locales/en.json](../src/node/i18n/locales/en.json)
for a full list of the available keys for translations. Note that the only
placeholders supported for each key are the ones used in the default string.
The `--app-name` flag controls the `{{app}}` placeholder in templates. If you
want to change the name, you can either:
1. Set `--app-name` (potentially alongside `--i18n`)
2. Use `--i18n` and hardcode the name in your strings
### Legacy flag
The `--welcome-text` flag is now deprecated. Use the `WELCOME` key instead.

View file

@ -82,11 +82,13 @@ _exact_ same commands presented in the rest of this document.
- For Arch Linux, code-server will install the AUR package.
- For any unrecognized Linux operating system, code-server will install the
latest standalone release into `~/.local`.
- Ensure that you add `~/.local/bin` to your `$PATH` to run code-server.
- For macOS, code-server will install the Homebrew package (if you don't have
Homebrew installed, code-server will install the latest standalone release
into `~/.local`).
- Ensure that you add `~/.local/bin` to your `$PATH` to run code-server.
- For FreeBSD, code-server will install the [npm package](#npm) with `npm`

View file

@ -30,7 +30,7 @@ includes installing instructions based on your operating system.
## Node.js version
We use the same major version of Node.js shipped with Code's remote, which is
currently `22.x`. VS Code also [lists Node.js
currently `20.x`. VS Code also [lists Node.js
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Using other versions of Node.js [may lead to unexpected
@ -62,7 +62,8 @@ Proceed to [installing](#installing)
## Alpine
```bash
apk add alpine-sdk bash libstdc++ libc6-compat python3 krb5-dev
apk add alpine-sdk bash libstdc++ libc6-compat
npm config set python python3
```
Proceed to [installing](#installing)
@ -78,7 +79,7 @@ Proceed to [installing](#installing)
## FreeBSD
```sh
pkg install -y git python npm-node22 pkgconf
pkg install -y git python npm-node20 pkgconf
pkg install -y libinotify
```

View file

@ -57,7 +57,7 @@ npm config set python python3
node -v
```
you will get Node version `v22`
you will get Node version `v20`
5. Now install code-server following our guide on [installing with npm](./npm.md)

View file

@ -1,84 +0,0 @@
import { fixupConfigRules } from "@eslint/compat"
import globals from "globals"
import tsParser from "@typescript-eslint/parser"
import path from "node:path"
import { fileURLToPath } from "node:url"
import js from "@eslint/js"
import { FlatCompat } from "@eslint/eslintrc"
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
})
export default [
...fixupConfigRules(
compat.extends(
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"plugin:prettier/recommended",
"prettier",
),
),
{
languageOptions: {
globals: {
...globals.browser,
...globals.jest,
...globals.node,
},
parser: tsParser,
ecmaVersion: 2018,
sourceType: "module",
},
settings: {
"import/resolver": {
typescript: {
alwaysTryTypes: true,
},
},
},
rules: {
"@typescript-eslint/no-unused-vars": [
"error",
{
args: "none",
},
],
"no-dupe-class-members": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extra-semi": "off",
"@typescript-eslint/no-require-imports": "off",
"@typescript-eslint/no-unused-vars": "off", // TODO: Fix these.
"@typescript-eslint/no-empty-object-type": "off",
eqeqeq: "error",
"import/order": [
"error",
{
alphabetize: {
order: "asc",
},
groups: [["builtin", "external", "internal"], "parent", "sibling"],
},
],
"no-async-promise-executor": "off",
},
},
]

View file

@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
@ -20,18 +20,15 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1739303263,
"narHash": "sha256-c/Z/6gZLN8BIpYh1B3qMzEn0TArjf4F2lmy59lDLVBM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "6cc4213488e886db863878a1e3dc26cc932d38b8",
"type": "github"
"lastModified": 1716137900,
"narHash": "sha256-sowPU+tLQv8GlqtVtsXioTKeaQvlMz/pefcdwg8MvfM=",
"path": "/nix/store/r8nhgnkxacbnf4kv8kdi8b6ks3k9b16i-source",
"rev": "6c0b7a92c30122196a761b440ac0d46d3d9954f1",
"type": "path"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {

View file

@ -1,30 +1,18 @@
{
description = "code-server";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable-small";
flake-utils.url = "github:numtide/flake-utils";
};
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem
(system:
let pkgs = nixpkgs.legacyPackages.${system};
nodejs = pkgs.nodejs_22;
nodejs = pkgs.nodejs_20;
yarn' = pkgs.yarn.override { inherit nodejs; };
in {
devShells.default = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
imagemagick
nodejs
python3
pkg-config
git
rsync
jq
moreutils
quilt
bats
openssl
nodejs yarn' python3 pkg-config git rsync jq moreutils quilt bats openssl
];
buildInputs = with pkgs; (lib.optionals (!stdenv.isDarwin) [ libsecret libkrb5 ]
++ (with xorg; [ libX11 libxkbfile ])

View file

@ -461,9 +461,9 @@ npm_fallback() {
# Determine if we have standalone releases on GitHub for the system's arch.
has_standalone() {
case $ARCH in
arm64) return 0 ;;
# We only have arm64 for macOS.
amd64)
amd64) return 0 ;;
# We only have amd64 for macOS.
arm64)
[ "$(distro)" != macos ]
return
;;

@ -1 +1 @@
Subproject commit bf9252a2fb45be6893dd8870c0bf37e2e1766d61
Subproject commit fee1edb8d6d72a0ddff41e5f71a671c23ed924b9

6750
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -23,49 +23,44 @@
"test:native": "./ci/dev/test-native.sh",
"test:scripts": "./ci/dev/test-scripts.sh",
"package": "./ci/build/build-packages.sh",
"prettier": "prettier --write --log-level=warn --cache .",
"preinstall": "node ./ci/dev/preinstall.js",
"prettier": "prettier --write --loglevel=warn --cache .",
"postinstall": "./ci/dev/postinstall.sh",
"publish:npm": "./ci/steps/publish-npm.sh",
"publish:docker": "./ci/steps/docker-buildx-push.sh",
"fmt": "npm run prettier && ./ci/dev/doctoc.sh",
"fmt": "yarn prettier && ./ci/dev/doctoc.sh",
"lint:scripts": "./ci/dev/lint-scripts.sh",
"lint:ts": "eslint --max-warnings=0 --fix $(git ls-files '*.ts' '*.js' | grep -v 'lib/vscode')",
"test": "echo 'Run npm run test:unit or npm run test:e2e' && exit 1",
"test": "echo 'Run yarn test:unit or yarn test:e2e' && exit 1",
"watch": "VSCODE_DEV=1 VSCODE_IPC_HOOK_CLI= NODE_OPTIONS='--max_old_space_size=32384 --trace-warnings' ts-node ./ci/dev/watch.ts",
"icons": "./ci/dev/gen_icons.sh"
},
"main": "out/node/entry.js",
"devDependencies": {
"@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",
"@types/express": "^5.0.0",
"@types/express": "^4.17.17",
"@types/http-proxy": "1.17.7",
"@types/js-yaml": "^4.0.6",
"@types/node": "22.x",
"@types/node": "20.x",
"@types/pem": "^1.14.1",
"@types/proxy-from-env": "^1.0.1",
"@types/safe-compare": "^1.1.0",
"@types/semver": "^7.5.2",
"@types/trusted-types": "^2.0.4",
"@types/ws": "^8.5.5",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^6.7.2",
"doctoc": "^2.2.1",
"eslint": "^9.12.0",
"eslint": "^8.49.0",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-import-resolver-typescript": "^3.6.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-prettier": "^5.0.0",
"globals": "^16.1.0",
"prettier": "3.6.2",
"prettier": "^3.0.3",
"prettier-plugin-sh": "^0.14.0",
"ts-node": "^10.9.1",
"typescript": "^5.6.2",
"typescript-eslint": "^8.8.0"
"typescript": "^5.2.2"
},
"dependencies": {
"@coder/logger": "^3.0.1",
@ -73,23 +68,24 @@
"compression": "^1.7.4",
"cookie-parser": "^1.4.6",
"env-paths": "^2.2.1",
"express": "^5.0.1",
"express": "5.0.0-beta.3",
"http-proxy": "^1.18.1",
"httpolyglot": "^0.1.2",
"i18next": "^25.3.0",
"i18next": "^23.5.1",
"js-yaml": "^4.1.0",
"limiter": "^2.1.0",
"pem": "^1.14.8",
"proxy-agent": "^6.3.1",
"qs": "6.14.0",
"qs": "6.12.1",
"rotating-file-stream": "^3.1.1",
"safe-buffer": "^5.2.1",
"safe-compare": "^1.1.4",
"semver": "^7.5.4",
"ws": "^8.14.2",
"xdg-basedir": "^4.0.0"
},
"resolutions": {
"@types/node": "22.x"
"@types/node": "20.x"
},
"bin": {
"code-server": "out/node/entry.js"
@ -104,7 +100,8 @@
"remote-development"
],
"engines": {
"node": "22"
"node": "20",
"yarn": "1"
},
"jest": {
"transform": {

View file

@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
+++ code-server/lib/vscode/src/vs/base/common/network.ts
@@ -237,7 +237,9 @@ class RemoteAuthoritiesImpl {
@@ -212,7 +212,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
authority: `${host}:${port}`,
@ -46,18 +46,18 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
+ <link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
<style id="vscode-css-modules" type="text/css" media="screen"></style>
</head>
@@ -39,7 +39,7 @@
<!-- Startup (do not modify order of script tags!) -->
<body aria-label="">
@@ -39,7 +39,7 @@
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/webPackagePaths.js"></script>
<script>
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
</script>
<script>
Object.keys(self.webPackagePaths).map(function (key, index) {
self.webPackagePaths[key] = `${baseUrl}/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
});
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@ -83,54 +83,49 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
+ <link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
</head>
@@ -36,7 +36,7 @@
<!-- Startup (do not modify order of script tags!) -->
@@ -40,7 +40,7 @@
<script>
// Packages
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
</script>
<script>
Object.keys(self.webPackagePaths).map(function (key, index) {
self.webPackagePaths[key] = `${baseUrl}/node_modules/${key}/${self.webPackagePaths[key]}`;
});
Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
+++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
@@ -282,6 +282,7 @@ export class BrowserSocketFactory implem
@@ -281,6 +281,7 @@ export class BrowserSocketFactory implem
connect({ host, port }: WebSocketRemoteConnection, path: string, query: string, debugLabel: string): Promise<ISocket> {
return new Promise<ISocket>((resolve, reject) => {
const webSocketSchema = (/^https:/.test(mainWindow.location.href) ? 'wss' : 'ws');
+ path = (mainWindow.location.pathname + "/" + path).replace(/\/\/+/g, "/")
const socket = this._webSocketFactory.create(`${webSocketSchema}://${(/:/.test(host) && !/\[/.test(host)) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
const disposables = new DisposableStore();
disposables.add(socket.onError(reject));
const errorListener = socket.onError(reject);
socket.onOpen(() => {
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
@@ -245,7 +245,9 @@ export class WebClientServer {
};
// Prefix routes with basePath for clients
- const basePath = getFirstHeader('x-forwarded-prefix') || this._basePath;
+ const rootBase = relativeRoot(getOriginalUrl(req))
+ const vscodeBase = relativePath(getOriginalUrl(req))
+ const basePath = vscodeBase || getFirstHeader('x-forwarded-prefix') || this._basePath;
const queryConnectionToken = parsedUrl.query[connectionTokenQueryName];
if (typeof queryConnectionToken === 'string') {
@@ -284,10 +286,14 @@ export class WebClientServer {
};
@@ -269,16 +269,15 @@ export class WebClientServer {
return void res.end();
}
- const getFirstHeader = (headerName: string) => {
- const val = req.headers[headerName];
- return Array.isArray(val) ? val[0] : val;
- };
-
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
+ // For now we are getting the remote authority from the client to avoid
+ // needing specific configuration for reverse proxies to work. Set this to
+ // something invalid to make sure we catch code that is using this value
+ // from the backend when it should not.
let remoteAuthority = (
const remoteAuthority = (
useTestResolver
? 'test+test'
- : (getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host)
@ -138,35 +133,52 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
);
if (!remoteAuthority) {
return serveError(req, res, 400, `Bad request.`);
@@ -334,6 +340,7 @@ export class WebClientServer {
@@ -305,8 +304,12 @@ export class WebClientServer {
scopes: [['user:email'], ['repo']]
} : undefined;
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
+ const base = relativeRoot(getOriginalUrl(req))
+ const vscodeBase = relativePath(getOriginalUrl(req))
+
const productConfiguration = {
codeServerVersion: this._productService.codeServerVersion,
+ rootEndpoint: rootBase,
+ rootEndpoint: base,
embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
...this._productService.extensionsGallery,
@@ -387,7 +394,9 @@ export class WebClientServer {
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
WORKBENCH_WEB_BASE_URL: staticRoute,
WORKBENCH_NLS_URL,
- WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`
+ WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`,
+ BASE: rootBase,
+ VS_BASE: basePath,
@@ -335,7 +338,7 @@ export class WebClientServer {
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration,
- callbackRoute: this._callbackRoute
+ callbackRoute: vscodeBase + this._callbackRoute
};
// DEV ---------------------------------------------------------------------------------------
@@ -424,7 +433,7 @@ export class WebClientServer {
const cookies = cookie.parse(req.headers.cookie || '');
@@ -352,9 +355,11 @@ export class WebClientServer {
const values: { [key: string]: string } = {
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
- WORKBENCH_WEB_BASE_URL: this._staticRoute,
+ WORKBENCH_WEB_BASE_URL: vscodeBase + this._staticRoute,
WORKBENCH_NLS_URL,
- WORKBENCH_NLS_FALLBACK_URL: `${this._staticRoute}/out/nls.messages.js`
+ WORKBENCH_NLS_FALLBACK_URL: `${vscodeBase}${this._staticRoute}/out/nls.messages.js`,
+ BASE: base,
+ VS_BASE: vscodeBase,
};
if (useTestResolver) {
@@ -381,7 +386,7 @@ export class WebClientServer {
'default-src \'self\';',
'img-src \'self\' https: data: blob:;',
'media-src \'self\';',
- `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : ``};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
- `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+ `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' ${useTestResolver ? '' : ``};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
'child-src \'self\';',
`frame-src 'self' https://*.vscode-cdn.net data:;`,
'worker-src \'self\' data: blob:;',
@@ -497,3 +506,70 @@ export class WebClientServer {
@@ -454,3 +459,70 @@ export class WebClientServer {
return void res.end(data);
}
}
@ -241,7 +253,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
@@ -65,6 +65,7 @@ export type ExtensionVirtualWorkspaceSup
@@ -56,6 +56,7 @@ export type ExtensionVirtualWorkspaceSup
export interface IProductConfiguration {
readonly codeServerVersion?: string
@ -253,7 +265,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -339,7 +339,8 @@ class LocalStorageURLCallbackProvider ex
@@ -304,7 +304,8 @@ class LocalStorageURLCallbackProvider ex
this.startListening();
}
@ -263,7 +275,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
}
private startListening(): void {
@@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
@@ -550,17 +551,6 @@ class WorkspaceProvider implements IWork
}
}
@ -281,7 +293,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
@@ -569,8 +559,8 @@ function readCookie(name: string): strin
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}
@ -296,7 +308,7 @@ Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/ext
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
+++ code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
@@ -120,7 +120,7 @@ export abstract class AbstractExtensionR
@@ -98,7 +98,7 @@ export abstract class AbstractExtensionR
: version,
path: 'extension'
}));

View file

@ -17,7 +17,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
@@ -107,10 +107,14 @@ class RemoteTerminalBackend extends Base
@@ -106,10 +106,14 @@ class RemoteTerminalBackend extends Base
}
const reqId = e.reqId;
const commandId = e.commandId;

View file

@ -2,16 +2,16 @@ Index: code-server/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands.ts
+++ code-server/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands.ts
@@ -8,6 +8,7 @@ import { isWeb } from '../../../base/com
import { isString } from '../../../base/common/types.js';
import { URI, UriComponents } from '../../../base/common/uri.js';
import { localize } from '../../../nls.js';
+import { IClipboardService } from '../../../platform/clipboard/common/clipboardService.js';
import { CommandsRegistry, ICommandService } from '../../../platform/commands/common/commands.js';
import { IExtensionGalleryService, IExtensionManagementService } from '../../../platform/extensionManagement/common/extensionManagement.js';
import { ExtensionManagementCLI } from '../../../platform/extensionManagement/common/extensionManagementCLI.js';
@@ -95,6 +96,11 @@ CommandsRegistry.registerCommand('_remot
@@ -8,6 +8,7 @@ import { isWeb } from 'vs/base/common/pl
import { isString } from 'vs/base/common/types';
import { URI, UriComponents } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
+import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementCLI } from 'vs/platform/extensionManagement/common/extensionManagementCLI';
@@ -89,6 +90,11 @@ CommandsRegistry.registerCommand('_remot
return lines.join('\n');
});
+CommandsRegistry.registerCommand('_remoteCLI.setClipboard', function (accessor: ServicesAccessor, content: string) {
@ -26,7 +26,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
@@ -44,7 +44,12 @@ export interface ExtensionManagementPipe
@@ -43,7 +43,12 @@ export interface ExtensionManagementPipe
force?: boolean;
}
@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
export interface ICommandsExecuter {
executeCommand<T>(id: string, ...args: any[]): Promise<T>;
@@ -106,6 +111,9 @@ export class CLIServerBase {
@@ -105,6 +110,9 @@ export class CLIServerBase {
case 'extensionManagement':
returnObj = await this.manageExtensions(data);
break;
@ -50,7 +50,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
default:
sendResponse(404, `Unknown message type: ${data.type}`);
break;
@@ -173,6 +181,10 @@ export class CLIServerBase {
@@ -172,6 +180,10 @@ export class CLIServerBase {
return await this._commands.executeCommand<string | undefined>('_remoteCLI.getSystemStatus');
}
@ -65,7 +65,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
@@ -98,7 +98,7 @@ class RemoteTerminalBackend extends Base
@@ -97,7 +97,7 @@ class RemoteTerminalBackend extends Base
}
});
@ -78,19 +78,19 @@ 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
@@ -137,6 +137,7 @@ export interface NativeParsedArgs {
'disable-chromium-sandbox'?: boolean;
@@ -119,6 +119,7 @@ export interface NativeParsedArgs {
sandbox?: boolean;
'enable-coi'?: boolean;
+ 'stdin-to-clipboard'?: boolean;
'unresponsive-sample-interval'?: string;
'unresponsive-sample-period'?: string;
'enable-rdp-display-tracking'?: boolean;
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
'no-proxy-server'?: boolean;
Index: code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/node/argv.ts
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
@@ -105,6 +105,7 @@ export const OPTIONS: OptionDescriptions
@@ -90,6 +90,7 @@ export const OPTIONS: OptionDescriptions
'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") },
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
@ -102,7 +102,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
@@ -77,6 +77,7 @@ const isSupportedForPipe = (optionId: ke
@@ -75,6 +75,7 @@ const isSupportedForPipe = (optionId: ke
case 'verbose':
case 'remote':
case 'locate-shell-integration-path':
@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
return true;
default:
return false;
@@ -295,6 +296,22 @@ export async function main(desc: Product
@@ -292,6 +293,23 @@ export async function main(desc: Product
}
}
} else {
@ -119,6 +119,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
+ console.error("stdin has a tty.");
+ return;
+ }
+ const fs = require("fs");
+ const stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0
+ const clipboardContent = stdinBuffer.toString();
+ sendToPipe({
@ -131,5 +132,5 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
+ }
+
if (parsedArgs.status) {
await sendToPipe({
sendToPipe({
type: 'status'

View file

@ -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
@@ -341,6 +341,10 @@ export class Extension implements IExten
@@ -299,6 +299,10 @@ export class Extension implements IExten
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
return false;
}

View file

@ -9,18 +9,18 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
@@ -12,7 +12,7 @@ import * as path from '../../base/common
import { IURITransformer } from '../../base/common/uriIpc.js';
import { getMachineId, getSqmMachineId, getDevDeviceId } from '../../base/node/id.js';
import { Promises } from '../../base/node/pfs.js';
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
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';
@@ -272,6 +272,9 @@ export async function setupServerService
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));
@@ -12,7 +12,7 @@ import * as path from 'vs/base/common/pa
import { IURITransformer } from 'vs/base/common/uriIpc';
import { getMachineId, getSqmMachineId, getdevDeviceId } from 'vs/base/node/id';
import { Promises } from 'vs/base/node/pfs';
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
import { ProtocolConstants } from 'vs/base/parts/ipc/common/ipc.net';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
@@ -239,6 +239,9 @@ export async function setupServerService
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
socketServer.registerChannel('extensions', channel);
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService), disposables);
+ socketServer.registerChannel('languagePacks', languagePackChannel);
@ -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
@@ -98,7 +98,7 @@ export abstract class AbstractNativeEnvi
@@ -101,7 +101,7 @@ export abstract class AbstractNativeEnvi
return URI.file(join(vscodePortable, 'argv.json'));
}
@ -51,9 +51,9 @@ Index: code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
+import { promises as fs } from 'fs';
+import * as path from 'path';
import { FileAccess } from '../../base/common/network.js';
import { join } from '../../base/common/path.js';
import type { INLSConfiguration } from '../../nls.js';
import { FileAccess } from 'vs/base/common/network';
import { join } from 'vs/base/common/path';
import type { INLSConfiguration } from 'vs/nls';
@@ -33,7 +35,94 @@ export async function getNLSConfiguratio
if (!result) {
result = resolveNLSConfiguration({ userLocale: language, osLocale: language, commit: product.commit, userDataPath, nlsMetadataPath });
@ -153,15 +153,31 @@ 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
@@ -25,6 +25,7 @@ import { URI } from '../../base/common/u
import { streamToBuffer } from '../../base/common/buffer.js';
import { IProductConfiguration } from '../../base/common/product.js';
import { isString, Mutable } from '../../base/common/types.js';
+import { getLocaleFromConfig, getBrowserNLSConfiguration } from './remoteLanguagePacks.js';
import { CharCode } from '../../base/common/charCode.js';
import { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
@@ -385,14 +386,22 @@ export class WebClientServer {
@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri'
import { streamToBuffer } from 'vs/base/common/buffer';
import { IProductConfiguration } from 'vs/base/common/product';
import { isString } from 'vs/base/common/types';
+import { getLocaleFromConfig, getBrowserNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
import { CharCode } from 'vs/base/common/charCode';
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
@@ -97,6 +98,7 @@ export class WebClientServer {
private readonly _webExtensionResourceUrlTemplate: URI | undefined;
private readonly _staticRoute: string;
+ private readonly _serverRoot: string;
private readonly _callbackRoute: string;
private readonly _webExtensionRoute: string;
@@ -111,6 +113,7 @@ export class WebClientServer {
) {
this._webExtensionResourceUrlTemplate = this._productService.extensionsGallery?.resourceUrlTemplate ? URI.parse(this._productService.extensionsGallery.resourceUrlTemplate) : undefined;
+ this._serverRoot = serverRootPath;
this._staticRoute = `${serverRootPath}/static`;
this._callbackRoute = `${serverRootPath}/callback`;
this._webExtensionRoute = `/web-extension-resource`;
@@ -349,14 +352,22 @@ export class WebClientServer {
};
const cookies = cookie.parse(req.headers.cookie || '');
@ -177,7 +193,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+ try {
+ const nlsFile = await getBrowserNLSConfiguration(locale, this._environmentService.userDataPath);
+ WORKBENCH_NLS_URL = nlsFile
+ ? `${vscodeBase}/vscode-remote-resource?path=${encodeURIComponent(nlsFile)}`
+ ? `${vscodeBase}${this._serverRoot}/vscode-remote-resource?path=${encodeURIComponent(nlsFile)}`
+ : '';
+ } catch (error) {
+ console.error("Failed to generate translations", error);
@ -190,7 +206,7 @@ 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
@@ -21,6 +21,7 @@ export const serverOptions: OptionDescri
@@ -19,6 +19,7 @@ export const serverOptions: OptionDescri
'disable-file-downloads': { type: 'boolean' },
'disable-file-uploads': { type: 'boolean' },
'disable-getting-started-override': { type: 'boolean' },
@ -198,7 +214,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -110,6 +111,7 @@ export interface ServerParsedArgs {
@@ -105,6 +106,7 @@ export interface ServerParsedArgs {
'disable-file-downloads'?: boolean;
'disable-file-uploads'?: boolean;
'disable-getting-started-override'?: boolean,
@ -206,21 +222,46 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
@@ -52,7 +52,7 @@ import 'vs/workbench/services/dialogs/br
import 'vs/workbench/services/host/browser/browserHostService';
import 'vs/workbench/services/lifecycle/browser/lifecycleService';
import 'vs/workbench/services/clipboard/browser/clipboardService';
-import 'vs/workbench/services/localization/browser/localeService';
+import 'vs/workbench/services/localization/electron-sandbox/localeService';
import 'vs/workbench/services/path/browser/pathService';
import 'vs/workbench/services/themes/browser/browserHostColorSchemeService';
import 'vs/workbench/services/encryption/browser/encryptionService';
@@ -118,8 +118,9 @@ registerSingleton(ILanguagePackService,
// Logs
import 'vs/workbench/contrib/logs/browser/logs.contribution';
-// Localization
-import 'vs/workbench/contrib/localization/browser/localization.contribution';
+// Localization. This does not actually import anything specific to Electron so
+// it should be safe.
+import 'vs/workbench/contrib/localization/electron-sandbox/localization.contribution';
// Performance
import 'vs/workbench/contrib/performance/browser/performance.web.contribution';
Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
+++ code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
@@ -5,18 +5,24 @@
import { CancellationTokenSource } from '../../../base/common/cancellation.js';
import { URI } from '../../../base/common/uri.js';
+import { ProxyChannel } from '../../../base/parts/ipc/common/ipc.js';
import { IExtensionGalleryService } from '../../extensionManagement/common/extensionManagement.js';
import { IExtensionResourceLoaderService } from '../../extensionResourceLoader/common/extensionResourceLoader.js';
-import { ILanguagePackItem, LanguagePackBaseService } from '../common/languagePacks.js';
+import { ILanguagePackItem, ILanguagePackService, LanguagePackBaseService } from '../common/languagePacks.js';
import { ILogService } from '../../log/common/log.js';
+import { IRemoteAgentService } from '../../../workbench/services/remote/common/remoteAgentService.js';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { URI } from 'vs/base/common/uri';
+import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLoader/common/extensionResourceLoader';
-import { ILanguagePackItem, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks';
+import { ILanguagePackItem, ILanguagePackService, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks';
import { ILogService } from 'vs/platform/log/common/log';
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
export class WebLanguagePacksService extends LanguagePackBaseService {
+ private readonly languagePackService: ILanguagePackService;
@ -244,10 +285,10 @@ Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePack
+ return this.languagePackService.getInstalledLanguages()
}
}
Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-browser/localeService.ts
Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/localization/electron-browser/localeService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/localization/electron-browser/localeService.ts
--- code-server.orig/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts
@@ -51,7 +51,8 @@ class NativeLocaleService implements ILo
@IProductService private readonly productService: IProductService
) { }
@ -272,7 +313,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
@@ -475,9 +475,6 @@ export class InstallAction extends Exten
@@ -411,9 +411,6 @@ export class InstallAction extends Exten
if (this.extension.isBuiltin) {
return;
}
@ -282,7 +323,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
if (this.extension.state !== ExtensionState.Uninstalled) {
return;
}
@@ -782,7 +779,7 @@ export abstract class InstallInOtherServ
@@ -695,7 +692,7 @@ export abstract class InstallInOtherServ
}
if (isLanguagePackExtension(this.extension.local.manifest)) {
@ -291,7 +332,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
// Prefers to run on UI
@@ -2073,17 +2070,6 @@ export class SetLanguageAction extends E
@@ -1951,17 +1948,6 @@ export class SetLanguageAction extends E
update(): void {
this.enabled = false;
this.class = SetLanguageAction.DisabledClass;
@ -309,7 +350,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
override async run(): Promise<any> {
@@ -2100,7 +2086,6 @@ export class ClearLanguageAction extends
@@ -1978,7 +1964,6 @@ export class ClearLanguageAction extends
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
constructor(
@ -317,7 +358,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
@ILocaleService private readonly localeService: ILocaleService,
) {
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
@@ -2110,17 +2095,6 @@ export class ClearLanguageAction extends
@@ -1988,17 +1973,6 @@ export class ClearLanguageAction extends
update(): void {
this.enabled = false;
this.class = ClearLanguageAction.DisabledClass;
@ -335,16 +376,15 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
}
override async run(): Promise<any> {
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
Index: code-server/lib/vscode/build/gulpfile.reh.js
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
@@ -55,7 +55,7 @@ import './services/dialogs/browser/fileD
import './services/host/browser/browserHostService.js';
import './services/lifecycle/browser/lifecycleService.js';
import './services/clipboard/browser/clipboardService.js';
-import './services/localization/browser/localeService.js';
+import './services/localization/electron-browser/localeService.js';
import './services/path/browser/pathService.js';
import './services/themes/browser/browserHostColorSchemeService.js';
import './services/encryption/browser/encryptionService.js';
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
+++ code-server/lib/vscode/build/gulpfile.reh.js
@@ -56,6 +56,7 @@ const serverResources = [
// NLS
'out-build/nls.messages.json',
+ 'out-build/nls.keys.json', // Required to generate translations.
// Process monitor
'out-build/vs/base/node/cpuUsage.sh',

View file

@ -90,7 +90,7 @@ 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
@@ -18,6 +18,8 @@ export const serverOptions: OptionDescri
@@ -16,6 +16,8 @@ export const serverOptions: OptionDescri
/* ----- code-server ----- */
'disable-update-check': { type: 'boolean' },
'auth': { type: 'string' },
@ -99,7 +99,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -104,6 +106,8 @@ export interface ServerParsedArgs {
@@ -99,6 +101,8 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
'auth'?: string;
@ -112,9 +112,9 @@ 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
@@ -369,6 +369,8 @@ export class WebClientServer {
serverBasePath: basePath,
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
@@ -333,6 +333,8 @@ export class WebClientServer {
serverBasePath: this._basePath,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
userDataPath: this._environmentService.userDataPath,
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
+ isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
@ -125,20 +125,21 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -6,10 +6,10 @@
import { Disposable } from '../../base/common/lifecycle.js';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext } from '../common/contextkeys.js';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
-import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
+import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js';
import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js';
import { getRemoteName } from '../../platform/remote/common/remoteHosts.js';
@@ -69,7 +69,7 @@ export class WorkbenchContextKeysHandler
@@ -7,11 +7,11 @@ import { Event } from 'vs/base/common/ev
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
@@ -70,7 +70,7 @@ export class WorkbenchContextKeysHandler
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@ -147,9 +148,9 @@ 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,
@@ -199,6 +199,10 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
@@ -197,6 +197,10 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
+ // code-server
+ IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
@ -163,15 +164,15 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
@@ -20,7 +20,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
import { AutoSaveAfterShortDelayContext } from '../../../services/filesConfiguration/common/filesConfigurationService.js';
import { WorkbenchListDoubleSelection } from '../../../../platform/list/browser/listService.js';
import { Schemas } from '../../../../base/common/network.js';
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
import { IsWebContext } from '../../../../platform/contextkey/common/contextkeys.js';
import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
@@ -571,13 +571,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { Schemas } from 'vs/base/common/network';
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from 'vs/workbench/common/contextkeys';
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from 'vs/workbench/common/contextkeys';
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ThemeIcon } from 'vs/base/common/themables';
@@ -561,13 +561,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL
},
@ -195,7 +196,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
)
}));
@@ -589,6 +592,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
@@ -579,6 +582,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
title: UPLOAD_LABEL,
},
when: ContextKeyExpr.and(
@ -207,30 +208,30 @@ 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
@@ -39,6 +39,9 @@ export const EmbedderIdentifierContext =
@@ -40,6 +40,9 @@ export const HasWebFileSystemAccess = ne
export const InAutomationContext = new RawContextKey<boolean>('inAutomation', false, localize('inAutomation', "Whether VS Code is running under automation/smoke test"));
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
+export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
+export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
+
//#endregion
//#region < --- Window --- >
Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
+++ code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
@@ -18,7 +18,7 @@ import { IModelService } from '../../../
import { ILanguageService } from '../../../../editor/common/languages/language.js';
import { getIconClasses } from '../../../../editor/common/services/getIconClasses.js';
import { Schemas } from '../../../../base/common/network.js';
-import { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';
+import { IBrowserWorkbenchEnvironmentService } from '../../environment/browser/environmentService.js';
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';
@@ -144,7 +144,7 @@ export class SimpleFileDialog extends Di
@@ -18,7 +18,7 @@ import { IModelService } from 'vs/editor
import { ILanguageService } from 'vs/editor/common/languages/language';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { Schemas } from 'vs/base/common/network';
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings';
@@ -143,7 +143,7 @@ export class SimpleFileDialog implements
@IFileDialogService private readonly fileDialogService: IFileDialogService,
@IModelService private readonly modelService: IModelService,
@ILanguageService private readonly languageService: ILanguageService,
@ -239,10 +240,10 @@ 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,
@@ -311,20 +311,22 @@ export class SimpleFileDialog extends Di
this.filePickBox.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path");
@@ -286,20 +286,22 @@ export class SimpleFileDialog implements
this.filePickBox.sortByLabel = false;
this.filePickBox.ignoreFocusOut = true;
this.filePickBox.ok = true;
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
- this.filePickBox.customButton = true;
- this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
@ -280,15 +281,15 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
@@ -65,6 +65,7 @@ import { timeout } from '../../../../../
import { IFilesConfigurationService } from '../../../../services/filesConfiguration/common/filesConfigurationService.js';
import { mainWindow } from '../../../../../base/browser/window.js';
import { IExplorerFileContribution, explorerFileContribRegistry } from '../explorerFileContrib.js';
+import { IBrowserWorkbenchEnvironmentService } from '../../../../services/environment/browser/environmentService.js';
import { WorkbenchCompressibleAsyncDataTree } from '../../../../../platform/list/browser/listService.js';
import { ISearchService, QueryType, getExcludes, ISearchConfiguration, ISearchComplete, IFileQuery } from '../../../../services/search/common/search.js';
import { CancellationToken } from '../../../../../base/common/cancellation.js';
@@ -1594,7 +1595,8 @@ export class FileDragAndDrop implements
@@ -65,6 +65,7 @@ import { timeout } from 'vs/base/common/
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { mainWindow } from 'vs/base/browser/window';
import { IExplorerFileContribution, explorerFileContribRegistry } from 'vs/workbench/contrib/files/browser/explorerFileContrib';
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
@@ -1001,7 +1002,8 @@ export class FileDragAndDrop implements
@IConfigurationService private configurationService: IConfigurationService,
@IInstantiationService private instantiationService: IInstantiationService,
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
@ -298,7 +299,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
) {
const updateDropEnablement = (e: IConfigurationChangeEvent | undefined) => {
if (!e || e.affectsConfiguration('explorer.enableDragAndDrop')) {
@@ -1819,15 +1821,17 @@ export class FileDragAndDrop implements
@@ -1226,15 +1228,17 @@ export class FileDragAndDrop implements
// External file DND (Import/Upload file)
if (data instanceof NativeDragAndDropData) {
@ -329,7 +330,7 @@ Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderS
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
+++ code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
@@ -99,6 +99,7 @@ export abstract class AbstractDiskFileSy
@@ -92,6 +92,7 @@ export abstract class AbstractDiskFileSy
private async readFile(uriTransformer: IURITransformer, _resource: UriComponents, opts?: IFileAtomicReadOptions): Promise<VSBuffer> {
const resource = this.transformIncoming(uriTransformer, _resource, true);
@ -337,7 +338,7 @@ Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderS
const buffer = await this.provider.readFile(resource, opts);
return VSBuffer.wrap(buffer);
@@ -117,6 +118,7 @@ export abstract class AbstractDiskFileSy
@@ -110,6 +111,7 @@ export abstract class AbstractDiskFileSy
}
});
@ -345,7 +346,7 @@ Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderS
const fileStream = this.provider.readFileStream(resource, opts, cts.token);
listenStream(fileStream, {
onData: chunk => emitter.fire(VSBuffer.wrap(chunk)),
@@ -137,7 +139,7 @@ export abstract class AbstractDiskFileSy
@@ -130,7 +132,7 @@ export abstract class AbstractDiskFileSy
private writeFile(uriTransformer: IURITransformer, _resource: UriComponents, content: VSBuffer, opts: IFileWriteOptions): Promise<void> {
const resource = this.transformIncoming(uriTransformer, _resource);

View file

@ -14,21 +14,21 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { $, Dimension, addDisposableListener, append, clearNode, reset } from '../../../../base/browser/dom.js';
+import { $, Dimension, addDisposableListener, append, clearNode, reset, prepend } from '../../../../base/browser/dom.js';
import { renderFormattedText } from '../../../../base/browser/formattedTextRenderer.js';
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
import { Button } from '../../../../base/browser/ui/button/button.js';
@@ -53,7 +53,7 @@ import { IRecentFolder, IRecentWorkspace
import { OpenRecentAction } from '../../../browser/actions/windowActions.js';
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from '../../../browser/actions/workspaceActions.js';
import { EditorPane } from '../../../browser/parts/editor/editorPane.js';
-import { WorkbenchStateContext } from '../../../common/contextkeys.js';
+import { IsEnabledCoderGettingStarted, WorkbenchStateContext } from '../../../common/contextkeys.js';
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
import './gettingStartedColors.js';
@@ -902,6 +902,72 @@ export class GettingStartedPage extends
-import { $, Dimension, addDisposableListener, append, clearNode, reset } from 'vs/base/browser/dom';
+import { $, Dimension, addDisposableListener, append, clearNode, reset, prepend } from 'vs/base/browser/dom';
import { renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Button } from 'vs/base/browser/ui/button/button';
@@ -54,7 +54,7 @@ import { IRecentFolder, IRecentWorkspace
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
-import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
+import { IsEnabledCoderGettingStarted, WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
import { IEditorOpenContext, IEditorSerializer } from 'vs/workbench/common/editor';
import { IWebviewElement, IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
import 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedColors';
@@ -804,6 +804,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', {},);
@@ -937,6 +1003,9 @@ export class GettingStartedPage extends
@@ -839,6 +905,9 @@ export class GettingStartedPage extends
recentList.setLimit(5);
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
}
@ -181,7 +181,7 @@ 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
@@ -20,6 +20,7 @@ export const serverOptions: OptionDescri
@@ -18,6 +18,7 @@ export const serverOptions: OptionDescri
'auth': { type: 'string' },
'disable-file-downloads': { type: 'boolean' },
'disable-file-uploads': { type: 'boolean' },
@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -108,6 +109,7 @@ export interface ServerParsedArgs {
@@ -103,6 +104,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
@@ -373,6 +373,7 @@ export class WebClientServer {
@@ -337,6 +337,7 @@ export class WebClientServer {
userDataPath: this._environmentService.userDataPath,
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
@ -213,16 +213,16 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -6,7 +6,7 @@
import { Disposable } from '../../base/common/lifecycle.js';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js';
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';
@@ -202,6 +202,7 @@ export class WorkbenchContextKeysHandler
@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/ev
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from 'vs/workbench/common/contextkeys';
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -200,6 +200,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
@@ -41,6 +41,7 @@ export const InAutomationContext = new R
@@ -42,6 +42,7 @@ export const EmbedderIdentifierContext =
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);

View file

@ -17,9 +17,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
@@ -1,7 +1,10 @@
import { Disposable } from "../../base/common/lifecycle.js";
+import { localize } from '../../nls.js';
+import { INotificationService, Severity } from '../../platform/notification/common/notification.js';
import { Disposable } from 'vs/base/common/lifecycle';
+import { localize } from 'vs/nls';
+import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
export class CodeServerClient extends Disposable {
constructor (

View file

@ -3,28 +3,26 @@ Prepare Code for integration with code-server
1. We already have the arguments so allow passing them in. There is also a
slight change in a few directories to preserve the directory structure we
have been using and to not override passed-in arguments.
2. Modify the entry point to allow importing the code, instead of just running
the server immediately.
3. Modify the terminal environment to filter out code-server environment variables.
4. Add the code-server version to the help dialog.
5. Add ready events for use in an iframe.
6. Add our icons and remove the existing ones.
7. Use our own manifest.
2. Modify the terminal environment to filter out code-server environment variables.
3. Add the code-server version to the help dialog.
4. Add ready events for use in an iframe.
5. Add our icons.
6. Use our own manifest.
Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/server.main.ts
+++ code-server/lib/vscode/src/vs/server/node/server.main.ts
@@ -12,7 +12,7 @@ import { createServer as doCreateServer,
import { parseArgs, ErrorReporter } from '../../platform/environment/node/argv.js';
import { join, dirname } from '../../base/common/path.js';
import { parseArgs, ErrorReporter } from 'vs/platform/environment/node/argv';
import { join, dirname } from 'vs/base/common/path';
import { performance } from 'perf_hooks';
-import { serverOptions } from './serverEnvironmentService.js';
+import { serverOptions, ServerParsedArgs } from './serverEnvironmentService.js';
import product from '../../platform/product/common/product.js';
import * as perf from '../../base/common/performance.js';
-import { serverOptions } from 'vs/server/node/serverEnvironmentService';
+import { serverOptions, ServerParsedArgs } from 'vs/server/node/serverEnvironmentService';
import product from 'vs/platform/product/common/product';
import * as perf from 'vs/base/common/performance';
@@ -34,38 +34,47 @@ const errorReporter: ErrorReporter = {
@@ -34,38 +34,43 @@ const errorReporter: ErrorReporter = {
}
};
@ -80,7 +78,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
*/
-export function spawnCli() {
- runCli(args, REMOTE_DATA_FOLDER, serverOptions);
+function spawnCli(args = parse()): Promise<void> {
+export function spawnCli(args = parse()): Promise<void> {
+ return runCli(args, createDirs(args), serverOptions);
}
@ -89,13 +87,9 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
*/
-export function createServer(address: string | net.AddressInfo | null): Promise<IServerAPI> {
- return doCreateServer(address, args, REMOTE_DATA_FOLDER);
+function createServer(address: string | net.AddressInfo | null, args = parse()): Promise<IServerAPI> {
+export function createServer(address: string | net.AddressInfo | null, args = parse()): Promise<IServerAPI> {
+ return doCreateServer(address, args, createDirs(args));
}
+
+// The aliases prevent the names getting mangled during minification which would
+// make it difficult to import.
+export { spawnCli as spawnCli, createServer as createServer };
Index: code-server/lib/vscode/src/vs/base/common/processes.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/processes.ts
@ -109,12 +103,30 @@ Index: code-server/lib/vscode/src/vs/base/common/processes.ts
];
const envKeys = Object.keys(env);
envKeys
Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
@@ -77,8 +77,11 @@ export class BrowserDialogHandler extend
async about(): Promise<void> {
const detailString = (useAgo: boolean): string => {
- return localize('aboutDetail',
- "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
+ return localize('aboutCodeServerDetail',
+ "code-server: {0}",
+ this.productService.codeServerVersion ? `v${this.productService.codeServerVersion}` : 'Unknown'
+ ) + '\n' + localize('aboutDetail',
+ "Code: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
this.productService.version || 'Unknown',
this.productService.commit || 'Unknown',
this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- /dev/null
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
@@ -0,0 +1,46 @@
+import { Disposable } from "../../base/common/lifecycle.js";
+import { Disposable } from 'vs/base/common/lifecycle';
+
+export class CodeServerClient extends Disposable {
+ constructor (
@ -164,15 +176,15 @@ 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
@@ -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';
+import { CodeServerClient } from '../../workbench/browser/client.js';
import { IProgressService } from '../../platform/progress/common/progress.js';
import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';
import { dirname, joinPath } from '../../base/common/resources.js';
@@ -130,6 +131,9 @@ export class BrowserMain extends Disposa
@@ -64,6 +64,7 @@ import { IOpenerService } from 'vs/platf
import { mixin, safeStringify } from 'vs/base/common/objects';
import { IndexedDB } from 'vs/base/browser/indexedDB';
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
+import { CodeServerClient } from 'vs/workbench/browser/client';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel';
@@ -131,6 +132,9 @@ export class BrowserMain extends Disposa
// Startup
const instantiationService = workbench.startup();
@ -186,7 +198,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
@@ -64,6 +64,8 @@ export type ExtensionVirtualWorkspaceSup
@@ -55,6 +55,8 @@ export type ExtensionVirtualWorkspaceSup
};
export interface IProductConfiguration {
@ -209,18 +221,19 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@@ -26,8 +27,9 @@
@@ -26,9 +27,9 @@
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
<!-- Workbench Icon/Manifest/CSS -->
- <link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
- <link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
-
+ <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<style id="vscode-css-modules" type="text/css" media="screen"></style>
</head>
<body aria-label="">
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@ -244,81 +257,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
+ <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
</head>
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
@@ -333,6 +333,7 @@ export class WebClientServer {
@@ -306,6 +306,7 @@ export class WebClientServer {
} : undefined;
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
const productConfiguration = {
+ codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
...this._productService.extensionsGallery,
Index: code-server/lib/vscode/src/server-main.ts
Index: code-server/lib/vscode/src/server-main.js
===================================================================
--- 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/
perf.mark('code/server/start');
(globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now();
+// This is not indented to make the diff less noisy. We need to move this out
+// of the top-level so it will not run immediately and we can control the start.
+async function start() {
// 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) {
}
--- code-server.orig/lib/vscode/src/server-main.js
+++ code-server/lib/vscode/src/server-main.js
@@ -336,4 +336,9 @@ function prompt(question) {
});
}
+}
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
});
});
}
+
-start();
+async function loadCodeWithNls() {
+ const nlsConfiguration = await resolveNLSConfiguration({
+ userLocale: 'en',
+ osLocale: 'en',
+ commit: product.commit,
+ userDataPath: '',
+ nlsMetadataPath: import.meta.dirname,
+ });
+ const nlsConfiguration = await resolveNLSConfiguration({ userLocale: 'en', osLocale: 'en', commit: product.commit, userDataPath: '', nlsMetadataPath: __dirname });
+ return loadCode(nlsConfiguration);
+}
+
+// This alias prevents the name getting mangled during minification which would
+// make it difficult to import.
+export { loadCodeWithNls as loadCodeWithNls };
+
+if (!process.env.CODE_SERVER_PARENT_PID) {
+ start();
+}
Index: code-server/lib/vscode/src/vs/platform/dialogs/browser/dialog.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/dialogs/browser/dialog.ts
+++ code-server/lib/vscode/src/vs/platform/dialogs/browser/dialog.ts
@@ -45,8 +45,11 @@ export function createWorkbenchDialogOpt
export function createBrowserAboutDialogDetails(productService: IProductService): { title: string; details: string; detailsToCopy: string } {
const detailString = (useAgo: boolean): string => {
- return localize('aboutDetail',
- "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
+ return localize('aboutCodeServerDetail',
+ "code-server: {0}",
+ productService.codeServerVersion ? `v${productService.codeServerVersion}` : 'Unknown'
+ ) + '\n' + localize('aboutDetail',
+ "Code: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
productService.version || 'Unknown',
productService.commit || 'Unknown',
productService.date ? `${productService.date}${useAgo ? ' (' + fromNow(new Date(productService.date), true) + ')' : ''}` : 'Unknown',
+module.exports.loadCodeWithNls = loadCodeWithNls;

View file

@ -18,10 +18,10 @@ 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
@@ -364,6 +364,7 @@ export class WebClientServer {
@@ -328,6 +328,7 @@ export class WebClientServer {
remoteAuthority,
serverBasePath: basePath,
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
serverBasePath: this._basePath,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ userDataPath: this._environmentService.userDataPath,
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -298,6 +298,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, unknown>;
readonly configurationDefaults?: Record<string, any>;
+ /**
+ * Path to the user data directory.
@ -66,7 +66,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
@@ -147,8 +147,10 @@ export class WorkspaceService extends Di
@@ -145,8 +145,10 @@ export class WorkspaceService extends Di
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
@ -79,7 +79,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
});
}));
@@ -556,6 +558,12 @@ export class WorkspaceService extends Di
@@ -552,6 +554,12 @@ export class WorkspaceService extends Di
previousFolders = this.workspace.folders;
this.workspace.update(workspace);
} else {

View file

@ -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
@@ -67,6 +67,7 @@ export interface IProductConfiguration {
@@ -58,6 +58,7 @@ export interface IProductConfiguration {
readonly codeServerVersion?: string
readonly rootEndpoint?: string
readonly updateEndpoint?: string
@ -20,7 +20,7 @@ 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
@@ -17,6 +17,7 @@ import { join } from '../../base/common/
@@ -15,6 +15,7 @@ import { URI } from 'vs/base/common/uri'
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
/* ----- code-server ----- */
'disable-update-check': { type: 'boolean' },
@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -102,6 +103,7 @@ export const serverOptions: OptionDescri
@@ -97,6 +98,7 @@ export const serverOptions: OptionDescri
export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
@ -40,27 +40,27 @@ 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
@@ -341,6 +341,7 @@ export class WebClientServer {
@@ -311,6 +311,7 @@ export class WebClientServer {
codeServerVersion: this._productService.codeServerVersion,
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,
rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
};
} satisfies Partial<IProductConfiguration>;
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
@@ -1,11 +1,15 @@
import { Disposable } from "../../base/common/lifecycle.js";
import { localize } from '../../nls.js';
+import { MenuId, MenuRegistry } from '../../platform/actions/common/actions.js';
+import { CommandsRegistry } from '../../platform/commands/common/commands.js';
import { ILogService } from '../../platform/log/common/log.js';
import { INotificationService, Severity } from '../../platform/notification/common/notification.js';
import { IProductService } from '../../platform/product/common/productService.js';
import { IStorageService, StorageScope, StorageTarget } from '../../platform/storage/common/storage.js';
import { Disposable } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
+import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
+import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { IProductService } from 'vs/platform/product/common/productService';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
export class CodeServerClient extends Disposable {
+ static LOGOUT_COMMAND_ID = 'code-server.logout';

View file

@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
@@ -49,6 +49,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
@@ -47,6 +47,16 @@ else if (globalThis._VSCODE_PRODUCT_JSON
version: pkg.version
});
}
@ -28,7 +28,6 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
+ extensionsGallery: env.EXTENSIONS_GALLERY ? JSON.parse(env.EXTENSIONS_GALLERY) : (product.extensionsGallery || {
+ serviceUrl: "https://open-vsx.org/vscode/gallery",
+ itemUrl: "https://open-vsx.org/vscode/item",
+ extensionUrlTemplate: "https://open-vsx.org/vscode/gallery/{publisher}/{name}/latest",
+ resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
+ controlUrl: "",
+ recommendationsUrl: "",
@ -41,43 +40,44 @@ 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
@@ -326,7 +326,6 @@ export class WebClientServer {
@@ -113,7 +113,7 @@ export class WebClientServer {
const staticRoute = posix.join(basePath, this._productPath, STATIC_PATH);
const callbackRoute = posix.join(basePath, this._productPath, CALLBACK_PATH);
- const webExtensionRoute = posix.join(basePath, this._productPath, WEB_EXTENSION_PATH);
this._staticRoute = `${serverRootPath}/static`;
this._callbackRoute = `${serverRootPath}/callback`;
- this._webExtensionRoute = `${serverRootPath}/web-extension-resource`;
+ this._webExtensionRoute = `/web-extension-resource`;
}
const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority });
@@ -342,14 +341,7 @@ export class WebClientServer {
/**
@@ -311,14 +311,7 @@ export class WebClientServer {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
rootEndpoint: base,
embedderIdentifier: 'server-distro',
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
- ...this._productService.extensionsGallery,
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
- scheme: 'http',
- authority: remoteAuthority,
- path: `${webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
- path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
- }).toString(true)
- } : undefined
+ extensionsGallery: this._productService.extensionsGallery,
};
} satisfies Partial<IProductConfiguration>;
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
+++ code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
@@ -15,7 +15,6 @@ import { getServiceMachineId } from '../
import { IStorageService } from '../../storage/common/storage.js';
import { TelemetryLevel } from '../../telemetry/common/telemetry.js';
import { getTelemetryLevel, supportsTelemetry } from '../../telemetry/common/telemetryUtils.js';
-import { RemoteAuthorities } from '../../../base/common/network.js';
import { TargetPlatform } from '../../extensions/common/extensions.js';
import { ExtensionGalleryResourceType, getExtensionGalleryManifestResourceUri, IExtensionGalleryManifest, IExtensionGalleryManifestService } from '../../extensionManagement/common/extensionGalleryManifest.js';
import { ILogService } from '../../log/common/log.js';
@@ -163,9 +162,9 @@ export abstract class AbstractExtensionR
@@ -15,7 +15,6 @@ import { getServiceMachineId } from 'vs/
import { IStorageService } from 'vs/platform/storage/common/storage';
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
-import { RemoteAuthorities } from 'vs/base/common/network';
import { TargetPlatform } from 'vs/platform/extensions/common/extensions';
const WEB_EXTENSION_RESOURCE_END_POINT_SEGMENT = '/web-extension-resource/';
@@ -140,9 +139,9 @@ export abstract class AbstractExtensionR
}
protected _isWebExtensionResourceEndPoint(uri: URI): boolean {
@ -90,3 +90,18 @@ Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/ext
}
}
Index: code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts
+++ code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts
@@ -114,7 +114,10 @@ export class ExtensionsDownloader extend
return false;
}
+ return false
+ // @ts-expect-error
const value = this.configurationService.getValue('extensions.verifySignature');
+ // @ts-expect-error
return isBoolean(value) ? value : true;
}

View file

@ -10,7 +10,7 @@ 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(
@@ -312,10 +312,7 @@ function extensionDescriptionArrayToMap(
}
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {

View file

@ -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
@@ -68,6 +68,7 @@ export interface IProductConfiguration {
@@ -59,6 +59,7 @@ export interface IProductConfiguration {
readonly rootEndpoint?: string
readonly updateEndpoint?: string
readonly logoutEndpoint?: string
@ -71,19 +71,19 @@ 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
@@ -342,6 +342,7 @@ export class WebClientServer {
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,
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
@@ -312,6 +312,7 @@ export class WebClientServer {
rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
};
} satisfies Partial<IProductConfiguration>;
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
@@ -292,7 +292,7 @@ export async function createTerminalEnvi
@@ -291,7 +291,7 @@ export async function createTerminalEnvi
// Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables
@ -96,15 +96,15 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -20,6 +20,7 @@ import { ISecretStorageProvider } from '
import { isFolderToOpen, isWorkspaceToOpen } from '../../../platform/window/common/window.js';
import type { IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from '../../../workbench/browser/web.api.js';
import { AuthenticationSessionInfo } from '../../../workbench/services/authentication/browser/authenticationService.js';
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from '../../../platform/tunnel/common/tunnel.js';
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
import { create } from '../../../workbench/workbench.web.main.internal.js';
@@ -19,6 +19,7 @@ import { ISecretStorageProvider } from '
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/window/common/window';
import type { IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from 'vs/workbench/browser/web.api';
import { AuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService';
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
import { create } from 'vs/workbench/workbench.web.main';
@@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
@@ -571,6 +572,39 @@ class WorkspaceProvider implements IWork
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
workspaceProvider: WorkspaceProvider.create(config),
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
@ -148,14 +148,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
@@ -83,8 +83,8 @@ export class ForwardedPortsView extends
private async enableForwardedPortsFeatures() {
@@ -77,7 +77,7 @@ export class ForwardedPortsView extends
private async enableForwardedPortsView() {
this.contextKeyListener.clear();
- const featuresEnabled: boolean = !!forwardedPortsFeaturesEnabled.getValue(this.contextKeyService);
- const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
+ const featuresEnabled: boolean = true;
+ const viewEnabled: boolean = true;
if (featuresEnabled || viewEnabled) {
// Also enable the view if it isn't already.
if (viewEnabled) {
const viewContainer = await this.getViewContainer();

View file

@ -20,5 +20,3 @@ getting-started.diff
keepalive.diff
clipboard.diff
display-language.diff
trusted-domains.diff
signature-verification.diff

View file

@ -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
@@ -69,6 +69,10 @@ export interface IProductConfiguration {
@@ -60,6 +60,10 @@ export interface IProductConfiguration {
readonly updateEndpoint?: string
readonly logoutEndpoint?: string
readonly proxyEndpointTemplate?: string
@ -54,14 +54,14 @@ 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
@@ -343,6 +343,10 @@ export class WebClientServer {
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
@@ -313,6 +313,10 @@ export class WebClientServer {
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
+ serviceWorker: {
+ scope: vscodeBase + '/',
+ path: rootBase + '/_static/out/browser/serviceWorker.js',
+ path: base + '/_static/out/browser/serviceWorker.js',
+ },
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
};
} satisfies Partial<IProductConfiguration>;

View file

@ -1,34 +0,0 @@
Disable signature verification.
Extension signature verification is now mandatory for all platforms and needs to be disabled.
Index: code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts
+++ code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionManagementService.ts
@@ -34,6 +34,7 @@ import {
ExtensionSignatureVerificationCode,
computeSize,
IAllowedExtensionsService,
+ // @ts-expect-error no-unused-variable
VerifyExtensionSignatureConfigKey,
shouldRequireRepositorySignatureFor,
} from '../common/extensionManagement.js';
@@ -87,6 +88,7 @@ export class ExtensionManagementService
@IDownloadService private downloadService: IDownloadService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IFileService private readonly fileService: IFileService,
+ // @ts-expect-error no-unused-variable
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExtensionGalleryManifestService protected readonly extensionGalleryManifestService: IExtensionGalleryManifestService,
@IProductService productService: IProductService,
@@ -339,8 +341,7 @@ export class ExtensionManagementService
private async downloadExtension(extension: IGalleryExtension, operation: InstallOperation, verifySignature: boolean, clientTargetPlatform?: TargetPlatform): Promise<{ readonly location: URI; readonly verificationStatus: ExtensionSignatureVerificationCode | undefined }> {
if (verifySignature) {
- const value = this.configurationService.getValue(VerifyExtensionSignatureConfigKey);
- verifySignature = isBoolean(value) ? value : true;
+ verifySignature = false;
}
const { location, verificationStatus } = await this.extensionsDownloader.download(extension, operation, verifySignature, clientTargetPlatform);
const shouldRequireSignature = shouldRequireRepositorySignatureFor(extension.private, await this.extensionGalleryManifestService.getExtensionGalleryManifest());

View file

@ -10,31 +10,31 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
+++ code-server/lib/vscode/build/gulpfile.reh.js
@@ -257,8 +257,7 @@ function packageTask(type, platform, arc
@@ -243,8 +243,7 @@ function packageTask(type, platform, arc
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
- .pipe(util.setExecutableBit(['**/*.sh']))
- .pipe(filter(['**', '!**/*.{js,css}.map']));
- .pipe(filter(['**', '!**/*.js.map']));
+ .pipe(util.setExecutableBit(['**/*.sh']));
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
const isUIExtension = (manifest) => {
@@ -297,9 +296,9 @@ function packageTask(type, platform, arc
@@ -283,9 +282,9 @@ function packageTask(type, platform, arc
.map(name => `.build/extensions/${name}/**`);
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
- const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true });
- const sources = es.merge(src, extensions, extensionsCommonDependencies)
+ const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true })
.pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true }));
.pipe(filter(['**', '!**/*.js.map'], { dot: true }));
+ const sources = es.merge(src, extensions, extensionsCommonDependencies);
let version = packageJson.version;
const quality = product.quality;
@@ -452,7 +451,7 @@ function tweakProductForServerWeb(produc
@@ -459,7 +458,7 @@ function tweakProductForServerWeb(produc
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
bundleTask,
optimizeTask,
util.rimraf(`out-vscode-${type}-min`),
- optimize.minifyTask(`out-vscode-${type}`, `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
+ optimize.minifyTask(`out-vscode-${type}`, ``)

View file

@ -15,24 +15,25 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
@@ -3,6 +3,7 @@
@@ -2,7 +2,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-
+import * as _http from 'http';
import * as performance from '../../../base/common/performance.js';
import type * as vscode from 'vscode';
import { createApiFactoryAndRegisterActors } from '../common/extHost.api.impl.js';
@@ -18,6 +19,7 @@ import { ExtensionRuntime } from '../com
import { CLIServer } from './extHostCLIServer.js';
import { realpathSync } from '../../../base/node/pfs.js';
import { ExtHostConsoleForwarder } from './extHostConsoleForwarder.js';
+import { IExtHostWorkspace } from '../common/extHostWorkspace.js';
import { ExtHostDiskFileSystemProvider } from './extHostDiskFileSystemProvider.js';
import nodeModule from 'node:module';
import { assertType } from '../../../base/common/types.js';
@@ -226,6 +228,52 @@ export class ExtHostExtensionService ext
import * as performance from 'vs/base/common/performance';
import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl';
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
@@ -17,6 +17,7 @@ import { ExtensionRuntime } from 'vs/wor
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
import { realpathSync } from 'vs/base/node/extpath';
import { ExtHostConsoleForwarder } from 'vs/workbench/api/node/extHostConsoleForwarder';
+import { IExtHostWorkspace } from '../common/extHostWorkspace';
import { ExtHostDiskFileSystemProvider } from 'vs/workbench/api/node/extHostDiskFileSystemProvider';
// ESM-uncomment-begin
// import { createRequire } from 'node:module';
@@ -87,6 +88,52 @@ export class ExtHostExtensionService ext
await interceptor.install();
performance.mark('code/extHost/didInitAPI');
+ (async () => {
@ -83,7 +84,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
+
// Do this when extension service exists, but extensions are not being activated yet.
const configProvider = await this._extHostConfiguration.getConfigProvider();
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._logService, this._mainThreadTelemetryProxy, this._initData, this._store);
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._logService, this._mainThreadTelemetryProxy, this._initData);
Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
@ -96,7 +97,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
import minimist from 'minimist';
import * as nativeWatchdog from 'native-watchdog';
import * as net from 'net';
@@ -451,7 +452,28 @@ async function startExtensionHostProcess
@@ -421,7 +422,28 @@ async function startExtensionHostProcess
);
// rewrite onTerminate-function to be a proper shutdown

View file

@ -17,19 +17,19 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
import { hostname, release } from 'os';
+import { promises as fs } from 'fs';
import { Emitter, Event } from '../../base/common/event.js';
import { DisposableStore, toDisposable } from '../../base/common/lifecycle.js';
import { Schemas } from '../../base/common/network.js';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
@@ -65,6 +66,7 @@ import { IExtensionsScannerService } fro
import { ExtensionsScannerService } from './extensionsScannerService.js';
import { IExtensionsProfileScannerService } from '../../platform/extensionManagement/common/extensionsProfileScannerService.js';
import { IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.js';
+import { TelemetryClient } from './telemetryClient.js';
import { NullPolicyService } from '../../platform/policy/common/policy.js';
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
import { LoggerService } from '../../platform/log/node/loggerService.js';
@@ -166,11 +168,23 @@ export async function setupServerService
const requestService = new RequestService('remote', configurationService, environmentService, logService);
import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
+import { TelemetryClient } from 'vs/server/node/telemetryClient';
import { NullPolicyService } from 'vs/platform/policy/common/policy';
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
import { LoggerService } from 'vs/platform/log/node/loggerService';
@@ -147,11 +149,23 @@ export async function setupServerService
const requestService = new RequestService(configurationService, environmentService, logService, loggerService);
services.set(IRequestService, requestService);
+ let isContainer = undefined;
@ -134,20 +134,20 @@ 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
@@ -347,6 +347,8 @@ export class WebClientServer {
@@ -317,6 +317,8 @@ export class WebClientServer {
scope: vscodeBase + '/',
path: rootBase + '/_static/out/browser/serviceWorker.js',
path: base + '/_static/out/browser/serviceWorker.js',
},
+ enableTelemetry: this._productService.enableTelemetry,
+ telemetryEndpoint: this._productService.telemetryEndpoint,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
};
} satisfies Partial<IProductConfiguration>;
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
@@ -73,6 +73,7 @@ export interface IProductConfiguration {
@@ -64,6 +64,7 @@ export interface IProductConfiguration {
readonly path: string;
readonly scope: string;
}
@ -159,7 +159,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
@@ -58,7 +58,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
@@ -55,7 +55,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
controlUrl: "",
recommendationsUrl: "",

View file

@ -1,49 +0,0 @@
Allow configuring trusted domains via product.json or flag.
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
@@ -22,6 +22,7 @@ export const serverOptions: OptionDescri
'disable-file-uploads': { type: 'boolean' },
'disable-getting-started-override': { type: 'boolean' },
'locale': { type: 'string' },
+ 'link-protection-trusted-domains': { type: 'string[]' },
/* ----- server setup ----- */
@@ -112,6 +113,7 @@ export interface ServerParsedArgs {
'disable-file-uploads'?: boolean;
'disable-getting-started-override'?: boolean,
'locale'?: string
+ 'link-protection-trusted-domains'?: 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
@@ -338,6 +338,14 @@ export class WebClientServer {
scopes: [['user:email'], ['repo']]
} : undefined;
+ const linkProtectionTrustedDomains: string[] = [];
+ if (this._environmentService.args['link-protection-trusted-domains']) {
+ linkProtectionTrustedDomains.push(...this._environmentService.args['link-protection-trusted-domains']);
+ }
+ if (this._productService.linkProtectionTrustedDomains) {
+ linkProtectionTrustedDomains.push(...this._productService.linkProtectionTrustedDomains);
+ }
+
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
@@ -352,6 +360,7 @@ export class WebClientServer {
telemetryEndpoint: this._productService.telemetryEndpoint,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
+ linkProtectionTrustedDomains,
};
const proposedApi = this._environmentService.args['enable-proposed-api'];

View file

@ -14,14 +14,14 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
--- code-server.orig/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
@@ -18,6 +18,7 @@ import { AbstractStorageService, isProfi
import { isUserDataProfile, IUserDataProfile } from '../../../../platform/userDataProfile/common/userDataProfile.js';
import { IAnyWorkspaceIdentifier } from '../../../../platform/workspace/common/workspace.js';
import { IUserDataProfileService } from '../../userDataProfile/common/userDataProfile.js';
+import { hash } from '../../../../base/common/hash.js';
import { isUserDataProfile, IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
import { IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
+import { hash } from 'vs/base/common/hash';
export class BrowserStorageService extends AbstractStorageService {
@@ -300,7 +301,11 @@ export class IndexedDBStorageDatabase ex
@@ -298,7 +299,11 @@ export class IndexedDBStorageDatabase ex
}
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {

View file

@ -13,12 +13,12 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/client.ts
@@ -1,10 +1,16 @@
import { Disposable } from "../../base/common/lifecycle.js";
import { localize } from '../../nls.js';
+import { ILogService } from '../../platform/log/common/log.js';
import { INotificationService, Severity } from '../../platform/notification/common/notification.js';
+import { IProductService } from '../../platform/product/common/productService.js';
+import { IStorageService, StorageScope, StorageTarget } from '../../platform/storage/common/storage.js';
import { Disposable } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
+import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
+import { IProductService } from 'vs/platform/product/common/productService';
+import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
export class CodeServerClient extends Disposable {
constructor (
@ -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
@@ -66,6 +66,7 @@ export type ExtensionVirtualWorkspaceSup
@@ -57,6 +57,7 @@ export type ExtensionVirtualWorkspaceSup
export interface IProductConfiguration {
readonly codeServerVersion?: string
readonly rootEndpoint?: string
@ -105,20 +105,20 @@ 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
@@ -340,6 +340,7 @@ export class WebClientServer {
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
@@ -310,6 +310,7 @@ export class WebClientServer {
const productConfiguration = {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: rootBase,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
rootEndpoint: base,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
};
} satisfies Partial<IProductConfiguration>;
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
@@ -15,6 +15,8 @@ import { joinPath } from '../../base/com
import { join } from '../../base/common/path.js';
@@ -13,6 +13,8 @@ import { memoize } from 'vs/base/common/
import { URI } from 'vs/base/common/uri';
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
+ /* ----- code-server ----- */
@ -126,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -98,6 +100,8 @@ export const serverOptions: OptionDescri
@@ -93,6 +95,8 @@ export const serverOptions: OptionDescri
};
export interface ServerParsedArgs {

View file

@ -41,7 +41,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
@@ -220,7 +220,7 @@ export class BrowserWorkbenchEnvironment
@@ -225,7 +225,7 @@ export class BrowserWorkbenchEnvironment
@memoize
get webviewExternalEndpoint(): string {
@ -54,14 +54,24 @@ 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
@@ -360,6 +360,7 @@ export class WebClientServer {
@@ -324,6 +324,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
serverBasePath: basePath,
+ webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
serverBasePath: this._basePath,
+ webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
@@ -373,7 +374,8 @@ export class WebClientServer {
return void res.end('Not found');
}
- const webWorkerExtensionHostIframeScriptSHA = 'sha256-V28GQnL3aYxbwgpV3yW1oJ+VKKe/PBSzWntNyH8zVXA=';
+ const webWorkerExtensionHostIframeScriptSHA = 'sha256-TMJESLUenkUgTCHw3qQlCngteoHhhRnn81kYP41UnCE=';
+
const cspDirectives = [
'default-src \'self\';',
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
@ -70,21 +80,29 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-ZcIhtIuU4M9PbKfs7w/CLqHimFJRK8L7mYTXOfiUv0I=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-dVbEBqfV68sWYG05nAX+55pv4dls0VnI6ZDMMV/0GYQ=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
- content="default-src 'none'; script-src 'sha256-dvxt5dlghGbz8hrqqochfoKEaHIMZ+yJVRvjJnGopzs=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-gzcLnrLeKQp7L5f+d7tdtNmK8h1NxVu1TdCfnv9uU+o=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
@@ -256,7 +256,7 @@
}
@@ -348,6 +348,12 @@
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`);
- navigator.serviceWorker.register(swPath, { type: 'module' })
+ navigator.serviceWorker.register(swPath)
.then(async registration => {
/**
* @param {MessageEvent} event
@@ -370,6 +370,12 @@
const hostname = location.hostname;
+ // It is safe to run if we are on the same host.
+ const parent = new URL(parentOrigin)
+ if (parent.hostname === hostname) {
+ return start(parentOrigin)
+ }
+
if (!crypto.subtle) {
// cannot validate, not running in a secure context
throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`);
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
@@ -343,6 +343,12 @@
const hostname = location.hostname;
@ -105,12 +123,12 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
child-src 'self' data: blob:;
- script-src 'self' 'unsafe-eval' 'sha256-cl8ijlOzEe+0GRCQNJQu2k6nUQ0fAYNYIuuKEm72JDs=' https: http://localhost:* blob:;
+ script-src 'self' 'unsafe-eval' 'sha256-yhZXuB8LS6t73dvNg6rtLX8y4PHLnqRm5+6DdOGkOcw=' https: http://localhost:* blob:;
- script-src 'self' 'unsafe-eval' 'sha256-V28GQnL3aYxbwgpV3yW1oJ+VKKe/PBSzWntNyH8zVXA=' https: http://localhost:* blob:;
+ script-src 'self' 'unsafe-eval' 'sha256-TMJESLUenkUgTCHw3qQlCngteoHhhRnn81kYP41UnCE=' https: http://localhost:* blob:;
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>
@@ -25,6 +25,13 @@
@@ -23,6 +23,13 @@
// validation not requested
return start();
}

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:625d2049c38ae27df0613fa533020e889fa98affd603050f46d3748be7b90d0b
size 38675

View file

@ -1,4 +1,7 @@
<svg width="100%" height="100%" viewBox="0 0 147 147" xmlns="http://www.w3.org/2000/svg">
<style>@media (prefers-color-scheme: dark) {* { fill: white; }}</style>
<path d="m42.4214,39.655c-24.4057,0 -42.1554,13.1721 -42.1554,33.845c0,20.5814 18.4892,33.845 42.1554,33.845c23.6662,0 38.1803,-11.6171 38.7349,-28.7225l-21.0777,-0.4574c-0.9244,9.3303 -9.1059,15.1845 -17.6572,15.1845c-11.7406,0 -20.4306,-7.5922 -20.4306,-19.8496c0,-12.2574 8.69,-19.9868 20.4306,-20.2155c8.5513,-0.183 16.9177,5.9457 17.4723,15.276l21.0777,-0.6403c-0.4622,-16.8311 -14.1442,-28.2652 -38.55,-28.2652zm48.8446,2l55.468,0l0,64.0311l-55.468,0l0,-64.0311z" clip-rule="evenodd" fill-rule="evenodd"/>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 2250 2250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><style>
@media (prefers-color-scheme: dark) {
* {
fill: white;
}
}
</style><rect id="favicon" x="0" y="0" width="2250" height="2250" style="fill:none;"/><g id="favicon1" serif:id="favicon"><path d="M1991.66,1034.72c-38.493,0 -64.144,-22.57 -64.144,-68.897l-0,-266.084c-0,-169.867 -69.982,-263.709 -250.762,-263.709l-83.976,0l-0,179.368l25.661,0c71.144,0 104.967,39.201 104.967,109.285l0,235.201c0,102.156 30.324,143.733 96.806,165.114c-66.482,20.196 -96.806,62.958 -96.806,165.114l0,174.621c0,48.7 0,96.216 -12.829,144.917c-12.829,45.141 -33.823,87.903 -62.98,124.726c-16.329,21.386 -34.991,39.202 -55.981,55.835l-0,23.755l83.971,-0c180.781,-0 250.763,-93.843 250.763,-263.709l-0,-266.084c-0,-47.516 24.485,-68.897 64.144,-68.897l47.822,-0l-0,-179.37l-46.656,-0l0,-1.186Z" style="fill-rule:nonzero;"/><path d="M1420.16,706.904l-258.923,0c-5.833,0 -10.495,-4.752 -10.495,-10.691l-0,-20.192c-0,-5.941 4.662,-10.692 10.495,-10.692l260.089,0c5.83,0 10.495,4.751 10.495,10.692l0,20.192c0,5.939 -5.833,10.691 -11.661,10.691Z" style="fill-rule:nonzero;"/><path d="M1464.48,963.474l-188.942,0c-5.833,0 -10.501,-4.754 -10.501,-10.693l0,-20.192c0,-5.938 4.668,-10.691 10.501,-10.691l188.942,-0c5.833,-0 10.495,4.753 10.495,10.691l-0,20.192c-0,4.754 -4.662,10.693 -10.495,10.693Z" style="fill-rule:nonzero;"/><path d="M1539.12,835.188l-377.885,0c-5.833,0 -10.495,-4.75 -10.495,-10.689l-0,-20.196c-0,-5.939 4.662,-10.69 10.495,-10.69l376.719,0c5.833,0 10.499,4.751 10.499,10.69l-0,20.196c-0,4.75 -3.5,10.689 -9.333,10.689Z" style="fill-rule:nonzero;"/><path d="M861.493,765.074c25.658,0 51.319,2.376 75.811,8.316l0,-48.705c0,-68.897 34.989,-109.285 104.971,-109.285l25.658,0l-0,-179.368l-83.977,0c-180.781,0 -250.758,93.842 -250.758,263.709l0,87.901c40.819,-14.252 83.977,-22.568 128.295,-22.568Z" style="fill-rule:nonzero;"/><path d="M1618.44,1411.25c-18.662,-150.861 -132.962,-276.776 -279.919,-305.285c-40.818,-8.314 -81.642,-9.504 -121.295,-2.376c-1.166,-0 -1.166,-1.189 -2.332,-1.189c-64.148,-136.605 -201.772,-226.884 -351.063,-226.884c-149.289,-0 -285.747,87.905 -351.062,224.51c-1.166,-0 -1.166,1.188 -2.332,1.188c-41.987,-4.753 -83.975,-2.379 -125.963,8.314c-144.623,35.634 -254.257,159.175 -274.085,308.847c-2.332,15.441 -3.499,30.883 -3.499,45.141c0,45.136 30.325,86.713 74.645,92.652c54.817,8.317 102.636,-34.448 101.469,-89.089c0,-8.317 0,-17.821 1.167,-26.134c9.331,-76.025 66.48,-140.168 141.123,-157.99c23.328,-5.939 46.654,-7.124 68.814,-3.559c71.146,9.502 141.124,-27.324 171.449,-91.467c22.162,-47.516 57.151,-89.094 103.804,-111.664c51.314,-24.946 109.633,-28.506 163.286,-9.499c55.979,20.192 97.966,62.954 123.627,116.409c26.824,52.27 39.653,89.093 96.805,96.221c23.325,3.559 88.639,2.374 113.132,1.185c47.82,0 95.64,16.631 129.463,51.079c22.156,23.757 38.485,53.455 45.486,86.715c10.495,53.455 -2.334,106.908 -33.825,147.296c-22.162,28.509 -52.485,49.89 -86.308,59.394c-16.329,4.754 -32.657,5.939 -48.986,5.939l-257.757,0c-51.314,0 -92.138,-41.573 -92.138,-93.842l0,-348.049c0,-14.251 -11.661,-26.13 -25.658,-26.13l-36.156,0c-71.148,1.185 -128.295,81.964 -128.295,167.488l-0,312.415c-0,92.652 73.476,167.488 164.451,167.488c0,0 404.714,-1.19 410.544,-1.19c93.304,-9.503 179.614,-58.204 237.927,-133.04c58.319,-72.46 85.142,-167.492 73.481,-264.894Z" style="fill-rule:nonzero;"/></g></svg>

Before

Width:  |  Height:  |  Size: 685 B

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -1,3 +1 @@
<svg width="100%" height="100%" viewBox="0 0 147 147" xmlns="http://www.w3.org/2000/svg">
<path d="m42.4214,39.655c-24.4057,0 -42.1554,13.1721 -42.1554,33.845c0,20.5814 18.4892,33.845 42.1554,33.845c23.6662,0 38.1803,-11.6171 38.7349,-28.7225l-21.0777,-0.4574c-0.9244,9.3303 -9.1059,15.1845 -17.6572,15.1845c-11.7406,0 -20.4306,-7.5922 -20.4306,-19.8496c0,-12.2574 8.69,-19.9868 20.4306,-20.2155c8.5513,-0.183 16.9177,5.9457 17.4723,15.276l21.0777,-0.6403c-0.4622,-16.8311 -14.1442,-28.2652 -38.55,-28.2652zm48.8446,2l55.468,0l0,64.0311l-55.468,0l0,-64.0311z" clip-rule="evenodd" fill-rule="evenodd"/>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 2250 2250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="favicon" x="0" y="0" width="2250" height="2250" style="fill:none;"/><g id="favicon1" serif:id="favicon"><path d="M1991.66,1034.72c-38.493,0 -64.144,-22.57 -64.144,-68.897l-0,-266.084c-0,-169.867 -69.982,-263.709 -250.762,-263.709l-83.976,0l-0,179.368l25.661,0c71.144,0 104.967,39.201 104.967,109.285l0,235.201c0,102.156 30.324,143.733 96.806,165.114c-66.482,20.196 -96.806,62.958 -96.806,165.114l0,174.621c0,48.7 0,96.216 -12.829,144.917c-12.829,45.141 -33.823,87.903 -62.98,124.726c-16.329,21.386 -34.991,39.202 -55.981,55.835l-0,23.755l83.971,-0c180.781,-0 250.763,-93.843 250.763,-263.709l-0,-266.084c-0,-47.516 24.485,-68.897 64.144,-68.897l47.822,-0l-0,-179.37l-46.656,-0l0,-1.186Z" style="fill-rule:nonzero;"/><path d="M1420.16,706.904l-258.923,0c-5.833,0 -10.495,-4.752 -10.495,-10.691l-0,-20.192c-0,-5.941 4.662,-10.692 10.495,-10.692l260.089,0c5.83,0 10.495,4.751 10.495,10.692l0,20.192c0,5.939 -5.833,10.691 -11.661,10.691Z" style="fill-rule:nonzero;"/><path d="M1464.48,963.474l-188.942,0c-5.833,0 -10.501,-4.754 -10.501,-10.693l0,-20.192c0,-5.938 4.668,-10.691 10.501,-10.691l188.942,-0c5.833,-0 10.495,4.753 10.495,10.691l-0,20.192c-0,4.754 -4.662,10.693 -10.495,10.693Z" style="fill-rule:nonzero;"/><path d="M1539.12,835.188l-377.885,0c-5.833,0 -10.495,-4.75 -10.495,-10.689l-0,-20.196c-0,-5.939 4.662,-10.69 10.495,-10.69l376.719,0c5.833,0 10.499,4.751 10.499,10.69l-0,20.196c-0,4.75 -3.5,10.689 -9.333,10.689Z" style="fill-rule:nonzero;"/><path d="M861.493,765.074c25.658,0 51.319,2.376 75.811,8.316l0,-48.705c0,-68.897 34.989,-109.285 104.971,-109.285l25.658,0l-0,-179.368l-83.977,0c-180.781,0 -250.758,93.842 -250.758,263.709l0,87.901c40.819,-14.252 83.977,-22.568 128.295,-22.568Z" style="fill-rule:nonzero;"/><path d="M1618.44,1411.25c-18.662,-150.861 -132.962,-276.776 -279.919,-305.285c-40.818,-8.314 -81.642,-9.504 -121.295,-2.376c-1.166,-0 -1.166,-1.189 -2.332,-1.189c-64.148,-136.605 -201.772,-226.884 -351.063,-226.884c-149.289,-0 -285.747,87.905 -351.062,224.51c-1.166,-0 -1.166,1.188 -2.332,1.188c-41.987,-4.753 -83.975,-2.379 -125.963,8.314c-144.623,35.634 -254.257,159.175 -274.085,308.847c-2.332,15.441 -3.499,30.883 -3.499,45.141c0,45.136 30.325,86.713 74.645,92.652c54.817,8.317 102.636,-34.448 101.469,-89.089c0,-8.317 0,-17.821 1.167,-26.134c9.331,-76.025 66.48,-140.168 141.123,-157.99c23.328,-5.939 46.654,-7.124 68.814,-3.559c71.146,9.502 141.124,-27.324 171.449,-91.467c22.162,-47.516 57.151,-89.094 103.804,-111.664c51.314,-24.946 109.633,-28.506 163.286,-9.499c55.979,20.192 97.966,62.954 123.627,116.409c26.824,52.27 39.653,89.093 96.805,96.221c23.325,3.559 88.639,2.374 113.132,1.185c47.82,0 95.64,16.631 129.463,51.079c22.156,23.757 38.485,53.455 45.486,86.715c10.495,53.455 -2.334,106.908 -33.825,147.296c-22.162,28.509 -52.485,49.89 -86.308,59.394c-16.329,4.754 -32.657,5.939 -48.986,5.939l-257.757,0c-51.314,0 -92.138,-41.573 -92.138,-93.842l0,-348.049c0,-14.251 -11.661,-26.13 -25.658,-26.13l-36.156,0c-71.148,1.185 -128.295,81.964 -128.295,167.488l-0,312.415c-0,92.652 73.476,167.488 164.451,167.488c0,0 404.714,-1.19 410.544,-1.19c93.304,-9.503 179.614,-58.204 237.927,-133.04c58.319,-72.46 85.142,-167.492 73.481,-264.894Z" style="fill-rule:nonzero;"/></g></svg>

Before

Width:  |  Height:  |  Size: 611 B

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -11,7 +11,6 @@
.error-display > .body {
color: #444;
color: light-dark(#444, #ccc);
font-size: 1.2rem;
}

View file

@ -10,7 +10,7 @@
http-equiv="Content-Security-Policy"
content="style-src 'self'; manifest-src 'self'; img-src 'self' data:; font-src 'self' data:;"
/>
<meta name="color-scheme" content="light dark" />
<title>{{ERROR_TITLE}} - code-server</title>
<link rel="icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon-dark-support.svg" />
<link rel="alternate icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon.ico" />

View file

@ -1,7 +1,3 @@
:root {
color-scheme: light dark;
}
html,
body,
#root {
@ -11,12 +7,9 @@ body,
body {
background: rgb(244, 247, 252);
background: light-dark(rgb(244, 247, 252), #111827);
color: #111;
color: light-dark(#111, #ddd);
margin: 0;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol";
overflow: hidden;
}
@ -30,15 +23,12 @@ button {
.-button {
background-color: rgb(87, 114, 245);
background-color: light-dark(rgb(87, 114, 245), rgb(26, 86, 219));
border-radius: 5px;
border: none;
box-sizing: border-box;
color: white;
color: light-dark(white, white);
cursor: pointer;
padding: 18px 20px;
font-weight: 500;
text-decoration: none;
}
@ -55,10 +45,9 @@ button {
.card-box {
background-color: rgb(250, 253, 258);
background-color: light-dark(rgb(250, 253, 258), #1f2937);
border-radius: 5px;
box-shadow:
light-dark(rgba(60, 66, 87, 0.117647), rgba(10, 10, 10, 0.617647)) 0px 7px 14px 0px,
rgba(60, 66, 87, 0.117647) 0px 7px 14px 0px,
rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
max-width: 650px;
width: 100%;
@ -66,9 +55,7 @@ button {
.card-box > .header {
border-bottom: 1px solid #ddd;
border-bottom: 1px solid light-dark(#ddd, #111827);
color: #444;
color: light-dark(#444, #fff);
padding: 30px;
}
@ -79,7 +66,6 @@ button {
.card-box > .header > .sub {
color: #555;
color: light-dark(#555, #9ca3af);
margin-top: 10px;
}

View file

@ -30,23 +30,14 @@ body {
.login-form > .field > .password {
background-color: rgb(244, 247, 252);
background-color: light-dark(rgb(244, 247, 252), #374151);
border-radius: 5px;
border: 1px solid #ddd;
border: 1px solid light-dark(#ddd, #4b5563);
box-sizing: border-box;
color: black;
flex: 1;
padding: 16px;
}
.login-form > .field > .password::placeholder {
color: rgb(148 163 184);
}
.login-form > .field > .password:focus {
outline: 2px solid rgb(63, 131, 248);
}
.login-form > .user {
display: none;
}

View file

@ -10,7 +10,6 @@
http-equiv="Content-Security-Policy"
content="style-src 'self'; script-src 'self' 'unsafe-inline'; manifest-src 'self'; img-src 'self' data:; font-src 'self' data:;"
/>
<meta name="color-scheme" content="light dark" />
<title>{{I18N_LOGIN_TITLE}}</title>
<link rel="icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon-dark-support.svg" />
<link rel="alternate icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon.ico" />

View file

@ -1,3 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
self.addEventListener("install", () => {
console.debug("[Service Worker] installed")
})

View file

@ -30,7 +30,7 @@ export enum LogLevel {
export class OptionalString extends Optional<string> {}
/**
* (VS) Code flags provided by the user.
* Code flags provided by the user.
*/
export interface UserProvidedCodeArgs {
"disable-telemetry"?: boolean
@ -53,9 +53,6 @@ export interface UserProvidedCodeArgs {
"disable-getting-started-override"?: boolean
"disable-proxy"?: boolean
"session-socket"?: string
"link-protection-trusted-domains"?: string[]
// locale is used by both VS Code and code-server.
locale?: string
}
/**
@ -75,6 +72,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
enable?: string[]
help?: boolean
host?: string
locale?: string
port?: number
json?: boolean
log?: LogLevel
@ -85,16 +83,12 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
"trusted-origins"?: string[]
version?: boolean
"proxy-domain"?: string[]
"skip-auth-preflight"?: boolean
"reuse-window"?: boolean
"new-window"?: boolean
"ignore-last-opened"?: boolean
verbose?: boolean
"app-name"?: string
"welcome-text"?: string
"abs-proxy-base-path"?: string
i18n?: string
"idle-timeout-seconds"?: number
/* Positional arguments. */
_?: string[]
}
@ -123,18 +117,18 @@ interface Option<T> {
type OptionType<T> = T extends boolean
? "boolean"
: T extends OptionalString
? typeof OptionalString
: T extends LogLevel
? typeof LogLevel
: T extends AuthType
? typeof AuthType
: T extends number
? "number"
: T extends string
? "string"
: T extends string[]
? "string[]"
: "unknown"
? typeof OptionalString
: T extends LogLevel
? typeof LogLevel
: T extends AuthType
? typeof AuthType
: T extends number
? "number"
: T extends string
? "string"
: T extends string[]
? "string[]"
: "unknown"
export type Options<T> = {
[P in keyof T]: Option<OptionType<T[P]>>
@ -198,10 +192,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
enable: { type: "string[]" },
help: { type: "boolean", short: "h", description: "Show this output." },
json: { type: "boolean" },
"link-protection-trusted-domains": {
type: "string[]",
description: "Links matching a trusted domain can be opened without link protection.",
},
locale: {
// The preferred way to set the locale is via the UI.
type: "string",
@ -261,10 +251,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
description: "GitHub authentication token (can only be passed in via $GITHUB_TOKEN or the config file).",
},
"proxy-domain": { type: "string[]", description: "Domain used for proxying ports." },
"skip-auth-preflight": {
type: "boolean",
description: "Allows preflight requests through proxy without authentication.",
},
"ignore-last-opened": {
type: "boolean",
short: "e",
@ -286,27 +272,12 @@ export const options: Options<Required<UserProvidedArgs>> = {
"app-name": {
type: "string",
short: "an",
description:
"Will replace the {{app}} placeholder in any strings, which by default includes the title bar and welcome message",
description: "The name to use in branding. Will be shown in titlebar and welcome message",
},
"welcome-text": {
type: "string",
short: "w",
description: "Text to show on login page",
deprecated: true,
},
"abs-proxy-base-path": {
type: "string",
description: "The base path to prefix to all absproxy requests",
},
i18n: {
type: "string",
path: true,
description: "Path to JSON file with custom translations. Merges with default strings and supports all i18n keys.",
},
"idle-timeout-seconds": {
type: "number",
description: "Timeout in seconds to wait before shutting down when idle.",
},
}
@ -401,10 +372,6 @@ export const parse = (
throw new Error("--github-auth can only be set in the config file or passed in via $GITHUB_TOKEN")
}
if (key === "idle-timeout-seconds" && Number(value) <= 60) {
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
}
const option = options[key]
if (option.type === "boolean") {
;(args[key] as boolean) = true
@ -620,16 +587,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args["github-auth"] = process.env.GITHUB_TOKEN
}
if (process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) {
if (isNaN(Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS))) {
logger.info("CODE_SERVER_IDLE_TIMEOUT_SECONDS must be a number")
}
if (Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) <= 60) {
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
}
args["idle-timeout-seconds"] = Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS)
}
// Ensure they're not readable by child processes.
delete process.env.PASSWORD
delete process.env.HASHED_PASSWORD
@ -740,16 +697,12 @@ export function parseConfigFile(configFile: string, configPath: string): ConfigA
// We convert the config file into a set of flags.
// This is a temporary measure until we add a proper CLI library.
const configFileArgv = Object.entries(config)
.map(([optName, opt]) => {
if (opt === true) {
return `--${optName}`
} else if (Array.isArray(opt)) {
return opt.map((o) => `--${optName}=${o}`)
}
return `--${optName}=${opt}`
})
.flat()
const configFileArgv = Object.entries(config).map(([optName, opt]) => {
if (opt === true) {
return `--${optName}`
}
return `--${optName}=${opt}`
})
const args = parse(configFileArgv, {
configFile: configPath,
})

View file

@ -1,6 +1,5 @@
import { logger } from "@coder/logger"
import { promises as fs } from "fs"
import { Emitter } from "../common/emitter"
/**
* Provides a heartbeat using a local file to indicate activity.
@ -9,9 +8,6 @@ export class Heart {
private heartbeatTimer?: NodeJS.Timeout
private heartbeatInterval = 60000
public lastHeartbeat = 0
private readonly _onChange = new Emitter<"alive" | "expired" | "unknown">()
readonly onChange = this._onChange.event
private state: "alive" | "expired" | "unknown" = "expired"
public constructor(
private readonly heartbeatPath: string,
@ -21,13 +17,6 @@ export class Heart {
this.alive = this.alive.bind(this)
}
private setState(state: typeof this.state) {
if (this.state !== state) {
this.state = state
this._onChange.emit(this.state)
}
}
public alive(): boolean {
const now = Date.now()
return now - this.lastHeartbeat < this.heartbeatInterval
@ -39,7 +28,6 @@ export class Heart {
*/
public async beat(): Promise<void> {
if (this.alive()) {
this.setState("alive")
return
}
@ -48,22 +36,7 @@ export class Heart {
if (typeof this.heartbeatTimer !== "undefined") {
clearTimeout(this.heartbeatTimer)
}
this.heartbeatTimer = setTimeout(async () => {
try {
if (await this.isActive()) {
this.beat()
} else {
this.setState("expired")
}
} catch (error: unknown) {
logger.warn((error as Error).message)
this.setState("unknown")
}
}, this.heartbeatInterval)
this.setState("alive")
this.heartbeatTimer = setTimeout(() => heartbeatTimer(this.isActive, this.beat), this.heartbeatInterval)
try {
return await fs.writeFile(this.heartbeatPath, "")
} catch (error: any) {
@ -80,3 +53,20 @@ export class Heart {
}
}
}
/**
* Helper function for the heartbeatTimer.
*
* If heartbeat is active, call beat. Otherwise do nothing.
*
* Extracted to make it easier to test.
*/
export async function heartbeatTimer(isActive: Heart["isActive"], beat: Heart["beat"]) {
try {
if (await isActive()) {
beat()
}
} catch (error: unknown) {
logger.warn((error as Error).message)
}
}

View file

@ -1,8 +1,9 @@
import { field, logger } from "@coder/logger"
import * as express from "express"
import * as expressCore from "express-serve-static-core"
import * as http from "http"
import * as net from "net"
import qs from "qs"
import * as qs from "qs"
import { Disposable } from "../common/emitter"
import { CookieKeys, HttpCode, HttpError } from "../common/http"
import { normalize } from "../common/util"
@ -184,7 +185,12 @@ export const constructRedirectPath = (req: express.Request, query: qs.ParsedQs,
* preserved. `to` should be a simple path without any query parameters
* `override` will merge with the existing query (use `undefined` to unset).
*/
export const redirect = (req: express.Request, res: express.Response, to: string, override: qs.ParsedQs = {}): void => {
export const redirect = (
req: express.Request,
res: express.Response,
to: string,
override: expressCore.Query = {},
): void => {
const query = Object.assign({}, req.query, override)
Object.keys(override).forEach((key) => {
if (typeof override[key] === "undefined") {

View file

@ -1,4 +1,3 @@
import { promises as fs } from "fs"
import i18next, { init } from "i18next"
import * as en from "./locales/en.json"
import * as ja from "./locales/ja.json"
@ -6,54 +5,29 @@ import * as th from "./locales/th.json"
import * as ur from "./locales/ur.json"
import * as zhCn from "./locales/zh-cn.json"
const defaultResources = {
en: {
translation: en,
},
"zh-cn": {
translation: zhCn,
},
th: {
translation: th,
},
ja: {
translation: ja,
},
ur: {
translation: ur,
},
}
export async function loadCustomStrings(filePath: string): Promise<void> {
try {
// Read custom strings from file path only
const fileContent = await fs.readFile(filePath, "utf8")
const customStringsData = JSON.parse(fileContent)
// User-provided strings override all languages.
Object.keys(defaultResources).forEach((locale) => {
i18next.addResourceBundle(locale, "translation", customStringsData)
})
} catch (error) {
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
throw new Error(`Custom strings file not found: ${filePath}\nPlease ensure the file exists and is readable.`)
} else if (error instanceof SyntaxError) {
throw new Error(`Invalid JSON in custom strings file: ${filePath}\n${error.message}`)
} else {
throw new Error(
`Failed to load custom strings from ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
)
}
}
}
init({
lng: "en",
fallbackLng: "en", // language to use if translations in user language are not available.
returnNull: false,
lowerCaseLng: true,
debug: process.env.NODE_ENV === "development",
resources: defaultResources,
resources: {
en: {
translation: en,
},
"zh-cn": {
translation: zhCn,
},
th: {
translation: th,
},
ja: {
translation: ja,
},
ur: {
translation: ur,
},
},
})
export default i18next

View file

@ -1,17 +1,14 @@
import { field, logger } from "@coder/logger"
import http from "http"
import * as os from "os"
import * as path from "path"
import { Disposable } from "../common/emitter"
import { plural } from "../common/util"
import { createApp, ensureAddress } from "./app"
import { AuthType, DefaultedArgs, Feature, toCodeArgs, UserProvidedArgs } from "./cli"
import { commit, version, vsRootPath } from "./constants"
import { loadCustomStrings } from "./i18n"
import { register } from "./routes"
import { VSCodeModule } from "./routes/vscode"
import { isDirectory, open } from "./util"
import { wrapper } from "./wrapper"
/**
* Return true if the user passed an extension-related VS Code flag.
@ -52,14 +49,7 @@ export interface OpenCommandPipeArgs {
export const runCodeCli = async (args: DefaultedArgs): Promise<void> => {
logger.debug("Running Code CLI")
try {
// See vscode.loadVSCode for more on this jank.
process.env.CODE_SERVER_PARENT_PID = process.pid.toString()
let modPath = path.join(vsRootPath, "out/server-main.js")
if (os.platform() === "win32") {
// On Windows, absolute paths of ESM modules must be a valid file URI.
modPath = "file:///" + modPath.replace(/\\/g, "/")
}
const mod = (await eval(`import("${modPath}")`)) as VSCodeModule
const mod = require(path.join(vsRootPath, "out/server-main")) as VSCodeModule
const serverModule = await mod.loadCodeWithNls()
await serverModule.spawnCli(await toCodeArgs(args))
// Rather than have the caller handle errors and exit, spawnCli will exit
@ -124,12 +114,6 @@ export const runCodeServer = async (
): Promise<{ dispose: Disposable["dispose"]; server: http.Server }> => {
logger.info(`code-server ${version} ${commit}`)
// Load custom strings if provided
if (args.i18n) {
await loadCustomStrings(args.i18n)
logger.info("Loaded custom strings")
}
logger.info(`Using user-data-dir ${args["user-data-dir"]}`)
logger.debug(`Using extensions-dir ${args["extensions-dir"]}`)
@ -142,7 +126,7 @@ export const runCodeServer = async (
const app = await createApp(args)
const protocol = args.cert ? "https" : "http"
const serverAddress = ensureAddress(app.server, protocol)
const { disposeRoutes, heart } = await register(app, args)
const disposeRoutes = await register(app, args)
logger.info(`Using config file ${args.config}`)
logger.info(`${protocol.toUpperCase()} server listening on ${serverAddress.toString()}`)
@ -152,8 +136,6 @@ export const runCodeServer = async (
logger.info(" - Using password from $PASSWORD")
} else if (args.usingEnvHashedPassword) {
logger.info(" - Using password from $HASHED_PASSWORD")
} else if (args["hashed-password"]) {
logger.info(` - Using hashed-password from ${args.config}`)
} else {
logger.info(` - Using password from ${args.config}`)
}
@ -167,36 +149,12 @@ export const runCodeServer = async (
logger.info(" - Not serving HTTPS")
}
if (args["idle-timeout-seconds"]) {
logger.info(` - Idle timeout set to ${args["idle-timeout-seconds"]} seconds`)
let idleShutdownTimer: NodeJS.Timeout | undefined
const startIdleShutdownTimer = () => {
idleShutdownTimer = setTimeout(() => {
logger.warn(`Idle timeout of ${args["idle-timeout-seconds"]} seconds exceeded`)
wrapper.exit(0)
}, args["idle-timeout-seconds"]! * 1000)
}
startIdleShutdownTimer()
heart.onChange((state) => {
clearTimeout(idleShutdownTimer)
if (state === "expired") {
startIdleShutdownTimer()
}
})
}
if (args["disable-proxy"]) {
logger.info(" - Proxy disabled")
} else if (args["proxy-domain"].length > 0) {
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
}
if (args["skip-auth-preflight"]) {
logger.info(" - Skipping authentication for preflight requests")
}
if (process.env.VSCODE_PROXY_URI) {
logger.info(`Using proxy URI in PORTS tab: ${process.env.VSCODE_PROXY_URI}`)
}

302
src/node/plugin.ts Normal file
View file

@ -0,0 +1,302 @@
import { field, Level, Logger } from "@coder/logger"
import * as express from "express"
import * as fs from "fs"
import * as path from "path"
import * as semver from "semver"
import * as pluginapi from "../../typings/pluginapi"
import { HttpCode, HttpError } from "../common/http"
import { version } from "./constants"
import { authenticated, ensureAuthenticated, replaceTemplates } from "./http"
import { proxy } from "./proxy"
import * as util from "./util"
import { Router as WsRouter, WebsocketRouter, wss } from "./wsRouter"
const fsp = fs.promises
// Represents a required module which could be anything.
type Module = any
/**
* Inject code-server when `require`d. This is required because the API provides
* more than just types so these need to be provided at run-time.
*/
const originalLoad = require("module")._load
require("module")._load = function (request: string, parent: object, isMain: boolean): Module {
return request === "code-server" ? codeServer : originalLoad.apply(this, [request, parent, isMain])
}
/**
* The module you get when importing "code-server".
*/
export const codeServer = {
HttpCode,
HttpError,
Level,
authenticated,
ensureAuthenticated,
express,
field,
proxy,
replaceTemplates,
WsRouter,
wss,
}
interface Plugin extends pluginapi.Plugin {
/**
* These fields are populated from the plugin's package.json
* and now guaranteed to exist.
*/
name: string
version: string
/**
* path to the node module on the disk.
*/
modulePath: string
}
interface Application extends pluginapi.Application {
/*
* Clone of the above without functions.
*/
plugin: Omit<Plugin, "init" | "deinit" | "router" | "applications">
}
/**
* PluginAPI implements the plugin API described in typings/pluginapi.d.ts
* Please see that file for details.
*/
export class PluginAPI {
private readonly plugins = new Map<string, Plugin>()
private readonly logger: Logger
public constructor(
logger: Logger,
/**
* These correspond to $CS_PLUGIN_PATH and $CS_PLUGIN respectively.
*/
private readonly csPlugin = "",
private readonly csPluginPath = `${path.join(util.paths.data, "plugins")}:/usr/share/code-server/plugins`,
private readonly workingDirectory: string | undefined = undefined,
) {
this.logger = logger.named("pluginapi")
}
/**
* applications grabs the full list of applications from
* all loaded plugins.
*/
public async applications(): Promise<Application[]> {
const apps = new Array<Application>()
for (const [, p] of this.plugins) {
if (!p.applications) {
continue
}
const pluginApps = await p.applications()
// Add plugin key to each app.
apps.push(
...pluginApps.map((app) => {
app = { ...app, path: path.join(p.routerPath, app.path || "") }
app = { ...app, iconPath: path.join(app.path || "", app.iconPath) }
return {
...app,
plugin: {
name: p.name,
version: p.version,
modulePath: p.modulePath,
displayName: p.displayName,
description: p.description,
routerPath: p.routerPath,
homepageURL: p.homepageURL,
},
}
}),
)
}
return apps
}
/**
* mount mounts all plugin routers onto r and websocket routers onto wr.
*/
public mount(r: express.Router, wr: express.Router): void {
for (const [, p] of this.plugins) {
if (p.router) {
r.use(`${p.routerPath}`, p.router())
}
if (p.wsRouter) {
wr.use(`${p.routerPath}`, (p.wsRouter() as WebsocketRouter).router)
}
}
}
/**
* loadPlugins loads all plugins based on this.csPlugin,
* this.csPluginPath and the built in plugins.
*/
public async loadPlugins(loadBuiltin = true): Promise<void> {
for (const dir of this.csPlugin.split(":")) {
if (!dir) {
continue
}
await this.loadPlugin(dir)
}
for (const dir of this.csPluginPath.split(":")) {
if (!dir) {
continue
}
await this._loadPlugins(dir)
}
if (loadBuiltin) {
await this._loadPlugins(path.join(__dirname, "../../plugins"))
}
}
/**
* _loadPlugins is the counterpart to loadPlugins.
*
* It differs in that it loads all plugins in a single
* directory whereas loadPlugins uses all available directories
* as documented.
*/
private async _loadPlugins(dir: string): Promise<void> {
try {
const entries = await fsp.readdir(dir, { withFileTypes: true })
for (const ent of entries) {
if (!ent.isDirectory()) {
continue
}
await this.loadPlugin(path.join(dir, ent.name))
}
} catch (error: any) {
if (error.code !== "ENOENT") {
this.logger.warn(`failed to load plugins from ${q(dir)}: ${error.message}`)
}
}
}
private async loadPlugin(dir: string): Promise<void> {
try {
const str = await fsp.readFile(path.join(dir, "package.json"), {
encoding: "utf8",
})
const packageJSON: PackageJSON = JSON.parse(str)
for (const [, p] of this.plugins) {
if (p.name === packageJSON.name) {
this.logger.warn(
`ignoring duplicate plugin ${q(p.name)} at ${q(dir)}, using previously loaded ${q(p.modulePath)}`,
)
return
}
}
const p = this._loadPlugin(dir, packageJSON)
this.plugins.set(p.name, p)
} catch (error: any) {
if (error.code !== "ENOENT") {
this.logger.warn(`failed to load plugin: ${error.stack}`)
}
}
}
/**
* _loadPlugin is the counterpart to loadPlugin and actually
* loads the plugin now that we know there is no duplicate
* and that the package.json has been read.
*/
private _loadPlugin(dir: string, packageJSON: PackageJSON): Plugin {
dir = path.resolve(dir)
const logger = this.logger.named(packageJSON.name)
logger.debug("loading plugin", field("plugin_dir", dir), field("package_json", packageJSON))
if (!packageJSON.name) {
throw new Error("plugin package.json missing name")
}
if (!packageJSON.version) {
throw new Error("plugin package.json missing version")
}
if (!packageJSON.engines || !packageJSON.engines["code-server"]) {
throw new Error(`plugin package.json missing code-server range like:
"engines": {
"code-server": "^3.7.0"
}
`)
}
if (!semver.satisfies(version, packageJSON.engines["code-server"])) {
this.logger.warn(
`plugin range ${q(packageJSON.engines["code-server"])} incompatible` + ` with code-server version ${version}`,
)
}
const pluginModule = require(dir)
if (!pluginModule.plugin) {
throw new Error("plugin module does not export a plugin")
}
const p = {
name: packageJSON.name,
version: packageJSON.version,
modulePath: dir,
...pluginModule.plugin,
} as Plugin
if (!p.displayName) {
throw new Error("plugin missing displayName")
}
if (!p.description) {
throw new Error("plugin missing description")
}
if (!p.routerPath) {
throw new Error("plugin missing router path")
}
if (!p.routerPath.startsWith("/")) {
throw new Error(`plugin router path ${q(p.routerPath)}: invalid`)
}
if (!p.homepageURL) {
throw new Error("plugin missing homepage")
}
p.init({
logger: logger,
workingDirectory: this.workingDirectory,
})
logger.debug("loaded")
return p
}
public async dispose(): Promise<void> {
await Promise.all(
Array.from(this.plugins.values()).map(async (p) => {
if (!p.deinit) {
return
}
try {
await p.deinit()
} catch (error: any) {
this.logger.error("plugin failed to deinit", field("name", p.name), field("error", error.message))
}
}),
)
}
}
interface PackageJSON {
name: string
version: string
engines: {
"code-server": string
}
}
function q(s: string | undefined): string {
if (s === undefined) {
s = "undefined"
}
return JSON.stringify(s)
}

17
src/node/routes/apps.ts Normal file
View file

@ -0,0 +1,17 @@
import * as express from "express"
import { PluginAPI } from "../plugin"
/**
* Implements the /api/applications endpoint
*
* See typings/pluginapi.d.ts for details.
*/
export function router(papi: PluginAPI): express.Router {
const router = express.Router()
router.get("/", async (req, res) => {
res.json(await papi.applications())
})
return router
}

View file

@ -61,11 +61,6 @@ router.all(/.*/, async (req, res, next) => {
ensureProxyEnabled(req)
if (req.method === "OPTIONS" && req.args["skip-auth-preflight"]) {
// Allow preflight requests with `skip-auth-preflight` flag
return next()
}
// Must be authenticated to use the proxy.
const isAuthenticated = await authenticated(req)
if (!isAuthenticated) {

Some files were not shown because too many files have changed in this diff Show more