Compare commits
106 Commits
v4.3.0
...
release/v4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
703e2cb62d | ||
|
|
2fb532a303 | ||
|
|
95cccacc9e | ||
|
|
7224b68b68 | ||
|
|
2bfe15b3e9 | ||
|
|
bef78e6a41 | ||
|
|
6037468e0f | ||
|
|
ba6b8da76b | ||
|
|
43b87edc72 | ||
|
|
b091b00406 | ||
|
|
17aaa8b347 | ||
|
|
2ec1e2de34 | ||
|
|
c69f2c69f6 | ||
|
|
91589fd106 | ||
|
|
3335d0a456 | ||
|
|
6d8f30d579 | ||
|
|
11b2ef9846 | ||
|
|
a51c94190f | ||
|
|
5c18e3556b | ||
|
|
6b9bb89f43 | ||
|
|
7bb35af04f | ||
|
|
f178f0400b | ||
|
|
efb5baec83 | ||
|
|
45e222b3c1 | ||
|
|
04ff8c355b | ||
|
|
ca8ed8e35b | ||
|
|
9087e0c091 | ||
|
|
0022473744 | ||
|
|
b2ed6b8461 | ||
|
|
da9e72cb69 | ||
|
|
3054f09838 | ||
|
|
de042173b2 | ||
|
|
f772d7bd13 | ||
|
|
23a84e156e | ||
|
|
cb09650d7c | ||
|
|
0e9ec02bef | ||
|
|
e79f6f3ad2 | ||
|
|
40b650b7c7 | ||
|
|
0659e565d0 | ||
|
|
f4fc2ebecf | ||
|
|
de317a09fe | ||
|
|
23a18786de | ||
|
|
033cdf2357 | ||
|
|
592973c1bb | ||
|
|
530bb66d7c | ||
|
|
19f486b672 | ||
|
|
907dd835e8 | ||
|
|
646f2436b0 | ||
|
|
714257b3c5 | ||
|
|
97af08b9e5 | ||
|
|
e189435a6a | ||
|
|
f79b38d25a | ||
|
|
9ad0d9e6ad | ||
|
|
55cfba8168 | ||
|
|
4f0d5566c3 | ||
|
|
79e96a99d3 | ||
|
|
c99f4cef25 | ||
|
|
1296848afc | ||
|
|
c51ff3bce1 | ||
|
|
a879844c2d | ||
|
|
f2693d366c | ||
|
|
5ce99f8d1c | ||
|
|
eb314ff727 | ||
|
|
61138b4a61 | ||
|
|
113ad85b37 | ||
|
|
a2bfcfcc78 | ||
|
|
a96162d075 | ||
|
|
744b301c7a | ||
|
|
ba990668a5 | ||
|
|
2c1cf0259e | ||
|
|
d75883bcc6 | ||
|
|
792e954937 | ||
|
|
5d47282ea5 | ||
|
|
d3f58f9b7d | ||
|
|
1e304b1e7d | ||
|
|
5276e41606 | ||
|
|
dedd770a78 | ||
|
|
a02f47714e | ||
|
|
b13849ded0 | ||
|
|
7a8d487729 | ||
|
|
1788537cce | ||
|
|
0155a12500 | ||
|
|
53b5d41271 | ||
|
|
55006ccb5a | ||
|
|
cd78f32dc0 | ||
|
|
3207bfd4ad | ||
|
|
7c1a45a8d8 | ||
|
|
60dd8ab374 | ||
|
|
6cf607eab9 | ||
|
|
f735c87ac7 | ||
|
|
5a5798e45f | ||
|
|
66a364358a | ||
|
|
ef0d76bc16 | ||
|
|
88e971c609 | ||
|
|
7027ec7d60 | ||
|
|
4e93db5b95 | ||
|
|
fc75db6edc | ||
|
|
e3c8bd692c | ||
|
|
a0b36147ea | ||
|
|
683412cb01 | ||
|
|
18ff99693b | ||
|
|
ed7bd2e65b | ||
|
|
c35bf1311e | ||
|
|
7780a13cce | ||
|
|
dea6a40ea8 | ||
|
|
09fc64a4f0 |
2
.github/CODEOWNERS
vendored
@@ -1,3 +1,5 @@
|
||||
* @coder/code-server-reviewers
|
||||
|
||||
ci/helm-chart/ @Matthew-Beckett @alexgorbatchev
|
||||
|
||||
docs/install.md @GNUxeava
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -66,11 +66,13 @@ body:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Does this issue happen in VS Code?
|
||||
description: Please try reproducing this issue in VS Code
|
||||
label: Does this issue happen in VS Code or GitHub Codespaces?
|
||||
description: Please try reproducing this issue in VS Code or GitHub Codespaces
|
||||
options:
|
||||
- label: I cannot reproduce this in VS Code.
|
||||
required: true
|
||||
- label: I cannot reproduce this in GitHub Codespaces.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you accessing code-server over HTTPS?
|
||||
|
||||
175
.github/workflows/ci.yaml
vendored
@@ -33,13 +33,13 @@ jobs:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Install helm
|
||||
uses: azure/setup-helm@v1.1
|
||||
uses: azure/setup-helm@v3.3
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
@@ -74,10 +74,10 @@ jobs:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
@@ -116,10 +116,10 @@ jobs:
|
||||
- name: Patch Code
|
||||
run: quilt push -a
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
@@ -143,14 +143,20 @@ jobs:
|
||||
id: vscode-rev
|
||||
run: echo "::set-output name=rev::$(git rev-parse HEAD:./lib/vscode)"
|
||||
|
||||
# We need to rebuild when we have a new version of Code or when any of
|
||||
# the patches changed. Use VSCODE_CACHE_VERSION to force a rebuild.
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq -r .version package.json)"
|
||||
|
||||
# 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
|
||||
# force a rebuild.
|
||||
- name: Fetch prebuilt Code package from cache
|
||||
id: cache-vscode
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: lib/vscode-reh-web-*
|
||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff') }}
|
||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ steps.version.outputs.version }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
||||
|
||||
- name: Build vscode
|
||||
if: steps.cache-vscode.outputs.cache-hit != 'true'
|
||||
@@ -164,7 +170,9 @@ jobs:
|
||||
if: success()
|
||||
|
||||
- name: Upload coverage report to Codecov
|
||||
run: yarn coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
if: success()
|
||||
|
||||
# The release package does not contain any native modules
|
||||
@@ -190,9 +198,9 @@ jobs:
|
||||
# This environment "npm" requires someone from
|
||||
# coder/code-server-reviewers to approve the PR before this job runs.
|
||||
environment: npm
|
||||
# Only run if PR comes from base repo
|
||||
# Only run if PR comes from base repo or event is not a PR
|
||||
# Reason: forks cannot access secrets and this will always fail
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
@@ -253,20 +261,21 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Install development tools
|
||||
run: |
|
||||
yum install -y epel-release centos-release-scl
|
||||
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync
|
||||
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync python3
|
||||
|
||||
- name: Install nfpm and envsubst
|
||||
run: |
|
||||
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1
|
||||
curl -L https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst
|
||||
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
|
||||
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
|
||||
@@ -287,8 +296,11 @@ jobs:
|
||||
- name: Build standalone release
|
||||
run: source scl_source enable devtoolset-9 && yarn release:standalone
|
||||
|
||||
- name: Sanity test standalone release
|
||||
run: yarn test:standalone-release
|
||||
- name: Install test dependencies
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn install
|
||||
|
||||
- name: Run integration tests on standalone release
|
||||
run: yarn test:integration
|
||||
|
||||
- name: Build packages with nfpm
|
||||
run: yarn package
|
||||
@@ -337,7 +349,7 @@ jobs:
|
||||
CXX: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
LINK: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
NPM_CONFIG_ARCH: ${{ matrix.arch }}
|
||||
NODE_VERSION: v14.17.4
|
||||
NODE_VERSION: v16.13.0
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
@@ -345,14 +357,15 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1
|
||||
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
|
||||
|
||||
- name: Install cross-compiler
|
||||
@@ -397,14 +410,15 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1
|
||||
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
|
||||
|
||||
- name: Download npm package
|
||||
@@ -418,8 +432,11 @@ jobs:
|
||||
- name: Build standalone release
|
||||
run: yarn release:standalone
|
||||
|
||||
- name: Sanity test standalone release
|
||||
run: yarn test:standalone-release
|
||||
- name: Install test dependencies
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn install
|
||||
|
||||
- name: Run integration tests on standalone release
|
||||
run: yarn test:integration
|
||||
|
||||
- name: Build packages with nfpm
|
||||
run: yarn package
|
||||
@@ -444,12 +461,11 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
|
||||
- name: Install Node.js v14
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "14"
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
@@ -474,7 +490,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
run: yarn --frozen-lockfile
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
|
||||
|
||||
- name: Install Playwright OS dependencies
|
||||
run: |
|
||||
@@ -482,7 +498,7 @@ jobs:
|
||||
./test/node_modules/.bin/playwright install
|
||||
|
||||
- name: Run end-to-end tests
|
||||
run: yarn test:e2e
|
||||
run: yarn test:e2e --global-timeout 840000
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
@@ -494,6 +510,93 @@ jobs:
|
||||
- name: Remove release packages and test artifacts
|
||||
run: rm -rf ./release-packages ./test/test-results
|
||||
|
||||
test-e2e-proxy:
|
||||
name: End-to-end tests behind proxy
|
||||
needs: package-linux-amd64
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
# Since we build code-server we might as well run tests from the release
|
||||
# since VS Code will load faster due to the bundling.
|
||||
CODE_SERVER_TEST_ENTRY: "./release-packages/code-server-linux-amd64"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
|
||||
- name: Download release packages
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: release-packages
|
||||
path: ./release-packages
|
||||
|
||||
- name: Untar code-server release
|
||||
run: |
|
||||
cd release-packages
|
||||
tar -xzf code-server*-linux-amd64.tar.gz
|
||||
mv code-server*-linux-amd64 code-server-linux-amd64
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-yarn.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@v2
|
||||
id: caddy-cache
|
||||
with:
|
||||
path: |
|
||||
~/.cache/caddy
|
||||
key: cache-caddy-2.5.2
|
||||
|
||||
- name: Install Caddy
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: steps.caddy-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
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
|
||||
|
||||
- name: Start Caddy
|
||||
run: sudo ~/.cache/caddy/caddy start --config ./ci/Caddyfile
|
||||
|
||||
- name: Run end-to-end tests
|
||||
run: yarn test:e2e:proxy
|
||||
|
||||
- name: Stop Caddy
|
||||
if: always()
|
||||
run: sudo ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-test-videos-proxy
|
||||
path: ./test/test-results
|
||||
|
||||
- name: Remove release packages and test artifacts
|
||||
run: rm -rf ./release-packages ./test/test-results
|
||||
|
||||
trivy-scan-repo:
|
||||
permissions:
|
||||
contents: read # for actions/checkout to fetch code
|
||||
@@ -506,7 +609,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
uses: aquasecurity/trivy-action@40c4ca9e7421287d0c5576712fdff370978f9c3c
|
||||
uses: aquasecurity/trivy-action@12814ff8bcb32c97f4d963e6e7903674b1692fa0
|
||||
with:
|
||||
scan-type: "fs"
|
||||
scan-ref: "."
|
||||
@@ -517,6 +620,6 @@ jobs:
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: "trivy-repo-results.sarif"
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
@@ -35,13 +35,13 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
config-file: ./.github/codeql-config.yml
|
||||
languages: javascript
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
31
.github/workflows/docker.yaml
vendored
@@ -24,32 +24,37 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq -r .version package.json)"
|
||||
|
||||
- name: Download artifact
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
- name: Download release artifacts
|
||||
uses: robinraju/release-downloader@v1.4
|
||||
with:
|
||||
branch: v${{ steps.version.outputs.version }}
|
||||
workflow: ci.yaml
|
||||
workflow_conclusion: completed
|
||||
name: "release-packages"
|
||||
path: release-packages
|
||||
repository: "coder/code-server"
|
||||
tag: v${{ steps.version.outputs.version }}
|
||||
fileName: "*.deb"
|
||||
out-file-path: "release-packages"
|
||||
|
||||
- name: Run ./ci/steps/docker-buildx-push.sh
|
||||
run: ./ci/steps/docker-buildx-push.sh
|
||||
- name: Publish to Docker
|
||||
run: yarn publish:docker
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
2
.github/workflows/docs-preview.yaml
vendored
@@ -4,6 +4,8 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
permissions:
|
||||
actions: none
|
||||
|
||||
6
.github/workflows/installer.yml
vendored
@@ -34,12 +34,12 @@ jobs:
|
||||
run: ./install.sh
|
||||
|
||||
- name: Test code-server
|
||||
run: yarn test:standalone-release code-server
|
||||
run: CODE_SERVER_PATH="code-server" yarn test:integration
|
||||
|
||||
alpine:
|
||||
name: Test installer on Alpine
|
||||
runs-on: ubuntu-latest
|
||||
container: "alpine:3.14"
|
||||
container: "alpine:3.16"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
@@ -66,4 +66,4 @@ jobs:
|
||||
run: ./install.sh
|
||||
|
||||
- name: Test code-server
|
||||
run: yarn test:standalone-release code-server
|
||||
run: CODE_SERVER_PATH="code-server" yarn test:integration
|
||||
|
||||
6
.github/workflows/npm-brew.yaml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
branch: v${{ steps.version.outputs.version }}
|
||||
branch: release/v${{ steps.version.outputs.version }}
|
||||
workflow: ci.yaml
|
||||
workflow_conclusion: completed
|
||||
name: "npm-package"
|
||||
@@ -60,8 +60,8 @@ jobs:
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config user.name cdrci
|
||||
git config user.email opensource@coder.com
|
||||
git config --global user.name cdrci
|
||||
git config --global user.email opensource@coder.com
|
||||
|
||||
- name: Bump code-server homebrew version
|
||||
env:
|
||||
|
||||
2
.github/workflows/scripts.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
name: Run script unit tests
|
||||
runs-on: ubuntu-latest
|
||||
# This runs on Alpine to make sure we're testing with actual sh.
|
||||
container: "alpine:3.14"
|
||||
container: "alpine:3.16"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
4
.github/workflows/trivy-docker.yaml
vendored
@@ -51,7 +51,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run Trivy vulnerability scanner in image mode
|
||||
uses: aquasecurity/trivy-action@40c4ca9e7421287d0c5576712fdff370978f9c3c
|
||||
uses: aquasecurity/trivy-action@12814ff8bcb32c97f4d963e6e7903674b1692fa0
|
||||
with:
|
||||
image-ref: "docker.io/codercom/code-server:latest"
|
||||
ignore-unfixed: true
|
||||
@@ -60,6 +60,6 @@ jobs:
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v1
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: "trivy-image-results.sarif"
|
||||
|
||||
@@ -1 +1 @@
|
||||
14
|
||||
16
|
||||
|
||||
1
.prettierignore
Normal file
@@ -0,0 +1 @@
|
||||
lib/vscode
|
||||
@@ -4,14 +4,3 @@ trailingComma: all
|
||||
arrowParens: always
|
||||
singleQuote: false
|
||||
useTabs: false
|
||||
|
||||
overrides:
|
||||
# Attempt to keep VScode's existing code style intact.
|
||||
- files: "lib/vscode/**/*.ts"
|
||||
options:
|
||||
# No limit defined upstream.
|
||||
printWidth: 10000
|
||||
semi: true
|
||||
singleQuote: true
|
||||
useTabs: true
|
||||
arrowParens: avoid
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
{
|
||||
"file": "src/node/heart.ts",
|
||||
"line": 7,
|
||||
"description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/master/docs/FAQ.md#heartbeat-file)"
|
||||
"description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file)"
|
||||
},
|
||||
{
|
||||
"file": "src/node/socket.ts",
|
||||
@@ -80,12 +80,12 @@
|
||||
{
|
||||
"file": "src/node/routes/domainProxy.ts",
|
||||
"line": 18,
|
||||
"description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
||||
"description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
||||
},
|
||||
{
|
||||
"file": "src/node/routes/pathProxy.ts",
|
||||
"line": 19,
|
||||
"description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
||||
"description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
||||
},
|
||||
{
|
||||
"file": "src/node/proxy.ts",
|
||||
@@ -95,7 +95,7 @@
|
||||
{
|
||||
"file": "src/node/routes/health.ts",
|
||||
"line": 5,
|
||||
"description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/master/docs/FAQ.md#healthz-endpoint)"
|
||||
"description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint)"
|
||||
},
|
||||
{
|
||||
"file": "src/node/routes/login.ts",
|
||||
@@ -145,7 +145,7 @@
|
||||
{
|
||||
"directory": "lib/vscode",
|
||||
"line": 1,
|
||||
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
|
||||
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{
|
||||
"file": "package.json",
|
||||
"line": 31,
|
||||
"description": "## Commands\n\nTo start developing, make sure you have Node 14+ 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"
|
||||
"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 `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/master/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/coder/code-server/blob/master/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)"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
156
CHANGELOG.md
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [9.99.999] - 9090-09-09
|
||||
|
||||
VS Code v99.99.999
|
||||
Code v99.99.999
|
||||
|
||||
### Changed
|
||||
### Added
|
||||
@@ -20,6 +20,160 @@ VS Code v99.99.999
|
||||
|
||||
-->
|
||||
|
||||
## [4.6.0](https://github.com/coder/code-server/releases/tag/v4.6.0) - 2022-08-17
|
||||
|
||||
Code v1.70.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated Code to 1.70.1.
|
||||
|
||||
### Added
|
||||
|
||||
- Added a heartbeat to sockets. This should prevent them from getting closed by
|
||||
reverse proxy timeouts when idle like NGINX's default 60-second timeout.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed logout option appearing even when authentication is disabled.
|
||||
|
||||
## [4.5.2](https://github.com/coder/code-server/releases/tag/v4.5.2) - 2022-08-15
|
||||
|
||||
Code v1.68.1
|
||||
|
||||
### Security
|
||||
|
||||
- Fixed the proxy route not performing authentication. For example if you were
|
||||
to run a development HTTP server using `python -m http.server 8000` then it
|
||||
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.
|
||||
|
||||
### Changed
|
||||
|
||||
- Invoking `code-server` in the integrated terminal will now use the script that
|
||||
comes with upstream Code. This means flags like `--wait` will be
|
||||
automatically supported now. However the upstream script only has the ability
|
||||
to interact with the running code-server and cannot spawn new instances. If
|
||||
you need to spawn a new code-server from the integrated terminal please
|
||||
specify the full path to code-server's usual script (for example
|
||||
`/usr/bin/code-server`).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Invoking `code-server` in the integrated terminal will now work instead of
|
||||
erroring about not finding Node.
|
||||
|
||||
## [4.5.1](https://github.com/coder/code-server/releases/tag/v4.5.1) - 2022-07-18
|
||||
|
||||
Code v1.68.1
|
||||
|
||||
### Changed
|
||||
|
||||
- We now use `release/v<0.0.0>` for the release branch name so it doesn't
|
||||
conflict with the tag name
|
||||
- Added `.prettierignore` to ignore formatting files in `lib/vscode`
|
||||
|
||||
### Added
|
||||
|
||||
- Allow more comprehensive affinity config in Helm chart
|
||||
- Added custom message in Homebrew PR to make sure code-server maintainers are
|
||||
tagged
|
||||
- Allow setting `priorityClassName` via Helm chart
|
||||
- Added troubleshooting docs to `CONTRIBUTING.md`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Removed default memory limit which was set via `NODE_OPTIONS`
|
||||
- Changed output in pipe to make it easier to debug code-server when doing live
|
||||
edits
|
||||
- Fixed display-language patch to use correct path which broke in 4.5.0
|
||||
- Fixed multiple code-server windows opening when using the code-server CLI in
|
||||
the Integrated Terminal
|
||||
- Fixed Integrated Terminal not working when web base was not the root path
|
||||
|
||||
### Security
|
||||
|
||||
- Updated `glob-parent` version in dependencies
|
||||
|
||||
## [4.5.0](https://github.com/coder/code-server/releases/tag/v4.5.0) - 2022-06-29
|
||||
|
||||
Code v1.68.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated codecov to use codecov uploader
|
||||
- Moved integration tests to Jest
|
||||
- Fixed docker release to only download .deb
|
||||
- Upgraded to Code 1.68.1
|
||||
- Install `nfpm` from GitHub
|
||||
- Upgraded to TypeScript 4.6
|
||||
|
||||
### Added
|
||||
|
||||
- Added tests for `open`, `isWsl`, `handlePasswordValidation`
|
||||
- Provided alternate image registry to dockerhub
|
||||
- Allowed users to have scripts run on container with `ENTRYPOINTD` environment
|
||||
variable
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed open CLI command to work on macOS
|
||||
|
||||
## [4.4.0](https://github.com/coder/code-server/releases/tag/v4.4.0) - 2022-05-06
|
||||
|
||||
Code v1.66.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Refactored methods in `Heart` class and made `Heart.beat()` async to make
|
||||
testing easier.
|
||||
- Upgraded to Code 1.66.2.
|
||||
|
||||
### Added
|
||||
|
||||
- Added back telemetry patch which was removed in the Code reachitecture.
|
||||
- Added support to use `true` for `CS_DISABLE_FILE_DOWNLOADS` environment
|
||||
variable. This means you can disable file downloads by setting
|
||||
`CS_DISABLE_FILE_DOWNLOADS` to `true` or `1`.
|
||||
- Added tests for `Heart` class.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed installation issue in AUR after LICENSE rename.
|
||||
- Fixed issue with listening on IPv6 addresses.
|
||||
- Fixed issue with Docker publish action not being able to find artifacts. Now
|
||||
it downloads the release assets from the release.
|
||||
|
||||
## [4.3.0](https://github.com/coder/code-server/releases/tag/v4.3.0) - 2022-04-14
|
||||
|
||||
Code v1.65.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Excluded .deb files from release Docker image which drops the compressed and
|
||||
uncompressed size by 58% and 34%.
|
||||
- Upgraded to Code 1.65.2.
|
||||
|
||||
### Added
|
||||
|
||||
- Added a new CLI flag called `--disable-file-downloads` which allows you to
|
||||
disable the "Download..." option that shows in the UI when right-clicking on a
|
||||
file. This can also set by running `CS_DISABLE_FILE_DOWNLOADS=1`.
|
||||
- Aligned the dependencies for binary and npm release artifacts.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the code-server version from not displaying in the Help > About dialog.
|
||||
- Fixed issues with the TypeScript and JavaScript Language Features Extension
|
||||
failing to activate.
|
||||
- Fixed missing files in ipynb extension.
|
||||
- Fixed the homebrew release workflow.
|
||||
- Fixed the Docker release workflow from not always publishing version tags.
|
||||
|
||||
## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22
|
||||
|
||||
Code v1.64.2
|
||||
|
||||
15
ci/Caddyfile
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
admin localhost:4444
|
||||
}
|
||||
:8000 {
|
||||
@portLocalhost path_regexp port ^/([0-9]+)\/ide
|
||||
handle @portLocalhost {
|
||||
uri strip_prefix {re.port.1}/ide
|
||||
reverse_proxy localhost:{re.port.1}
|
||||
}
|
||||
|
||||
handle {
|
||||
respond "Bad hostname" 400
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,9 +45,6 @@ You can disable minification by setting `MINIFY=`.
|
||||
- Builds vscode into `./lib/vscode/out-vscode`.
|
||||
- [./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/build-standalone-release.sh](./build/build-standalone-release.sh) (`yarn release:standalone`)
|
||||
- Requires a node module already built into `./release` with the above script.
|
||||
- Will build a standalone release with node and node_modules bundled into `./release-standalone`.
|
||||
- [./ci/build/clean.sh](./build/clean.sh) (`yarn clean`)
|
||||
- Removes all build artifacts.
|
||||
- Useful to do a clean build.
|
||||
@@ -97,6 +94,8 @@ Helps avoid clobbering the CI configuration.
|
||||
- Runs `yarn lint`.
|
||||
- [./steps/test-unit.sh](./steps/test-unit.sh)
|
||||
- Runs `yarn test:unit`.
|
||||
- [./steps/test-integration.sh](./steps/test-integration.sh)
|
||||
- Runs `yarn test:integration`.
|
||||
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
|
||||
- Runs `yarn test:e2e`.
|
||||
- [./steps/release.sh](./steps/release.sh)
|
||||
|
||||
@@ -98,43 +98,6 @@ bundle_vscode() {
|
||||
|
||||
rsync "${rsync_opts[@]}" ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"
|
||||
|
||||
# Add the commit, date, our name, links, and enable telemetry. This just makes
|
||||
# telemetry available; telemetry can still be disabled by flag or setting.
|
||||
jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
|
||||
cat << EOF
|
||||
{
|
||||
"enableTelemetry": true,
|
||||
"commit": "$(cd "$VSCODE_SRC_PATH" && git rev-parse HEAD)",
|
||||
"quality": "stable",
|
||||
"date": $(jq -n 'now | todate'),
|
||||
"codeServerVersion": "$VERSION",
|
||||
"nameShort": "code-server",
|
||||
"nameLong": "code-server",
|
||||
"applicationName": "code-server",
|
||||
"dataFolderName": ".code-server",
|
||||
"win32MutexName": "codeserver",
|
||||
"licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
|
||||
"win32DirName": "code-server",
|
||||
"win32NameVersion": "code-server",
|
||||
"win32AppUserModelId": "coder.code-server",
|
||||
"win32ShellNameShort": "c&ode-server",
|
||||
"darwinBundleIdentifier": "com.coder.code.server",
|
||||
"linuxIconName": "com.coder.code.server",
|
||||
"reportIssueUrl": "https://github.com/coder/code-server/issues/new",
|
||||
"documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
|
||||
"keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
|
||||
"keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
|
||||
"keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
|
||||
"introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
|
||||
"tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
|
||||
"newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
|
||||
"linkProtectionTrustedDomains": [
|
||||
"https://open-vsx.org"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
) > "$VSCODE_OUT_PATH/product.json"
|
||||
|
||||
# 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}' \
|
||||
@@ -146,11 +109,7 @@ EOF
|
||||
# Include global extension dependencies as well.
|
||||
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions/yarn.lock"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/postinstall.js" "$VSCODE_OUT_PATH/extensions/postinstall.js"
|
||||
|
||||
pushd "$VSCODE_OUT_PATH"
|
||||
symlink_asar
|
||||
popd
|
||||
rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -27,8 +27,9 @@ main() {
|
||||
ln -s "./bin/code-server" "$RELEASE_PATH/code-server"
|
||||
ln -s "./lib/node" "$RELEASE_PATH/node"
|
||||
|
||||
cd "$RELEASE_PATH"
|
||||
pushd "$RELEASE_PATH"
|
||||
yarn --production --frozen-lockfile
|
||||
popd
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -6,13 +6,109 @@ set -euo pipefail
|
||||
# MINIFY controls whether a minified version of vscode is built.
|
||||
MINIFY=${MINIFY-true}
|
||||
|
||||
delete-bin-script() {
|
||||
rm -f "lib/vscode-reh-web-linux-x64/bin/$1"
|
||||
}
|
||||
|
||||
copy-bin-script() {
|
||||
local script="$1"
|
||||
local dest="lib/vscode-reh-web-linux-x64/bin/$script"
|
||||
cp "lib/vscode/resources/server/bin/$script" "$dest"
|
||||
sed -i.bak "s/@@VERSION@@/$(vscode_version)/g" "$dest"
|
||||
sed -i.bak "s/@@COMMIT@@/$VSCODE_DISTRO_COMMIT/g" "$dest"
|
||||
sed -i.bak "s/@@APPNAME@@/code-server/g" "$dest"
|
||||
|
||||
# Fix Node path on Darwin and Linux.
|
||||
# We do not want expansion here; this text should make it to the file as-is.
|
||||
# shellcheck disable=SC2016
|
||||
sed -i.bak 's/^ROOT=\(.*\)$/VSROOT=\1\nROOT="$(dirname "$(dirname "$VSROOT")")"/g' "$dest"
|
||||
sed -i.bak 's/ROOT\/out/VSROOT\/out/g' "$dest"
|
||||
|
||||
# Fix Node path on Windows.
|
||||
sed -i.bak 's/^set ROOT_DIR=\(.*\)$/set ROOT_DIR=%~dp0..\\..\\..\\..\r\nset VSROOT_DIR=\1/g' "$dest"
|
||||
sed -i.bak 's/%ROOT_DIR%\\out/%VSROOT_DIR%\\out/g' "$dest"
|
||||
|
||||
chmod +x "$dest"
|
||||
rm "$dest.bak"
|
||||
}
|
||||
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
cd lib/vscode
|
||||
source ./ci/lib.sh
|
||||
|
||||
# Any platform works since we have our own packaging step (for now).
|
||||
pushd lib/vscode
|
||||
|
||||
# Set the commit Code will embed into the product.json. We need to do this
|
||||
# since Code tries to get the commit from the `.git` directory which will fail
|
||||
# as it is a submodule.
|
||||
export VSCODE_DISTRO_COMMIT
|
||||
VSCODE_DISTRO_COMMIT=$(git rev-parse HEAD)
|
||||
|
||||
# Add the date, our name, links, and enable telemetry (this just makes
|
||||
# telemetry available; telemetry can still be disabled by flag or setting).
|
||||
# This needs to be done before building as Code will read this file and embed
|
||||
# it into the client-side code.
|
||||
git checkout product.json # Reset in case the script exited early.
|
||||
cp product.json product.original.json # Since jq has no inline edit.
|
||||
jq --slurp '.[0] * .[1]' product.original.json <(
|
||||
cat << EOF
|
||||
{
|
||||
"enableTelemetry": true,
|
||||
"quality": "stable",
|
||||
"codeServerVersion": "$VERSION",
|
||||
"nameShort": "code-server",
|
||||
"nameLong": "code-server",
|
||||
"applicationName": "code-server",
|
||||
"dataFolderName": ".code-server",
|
||||
"win32MutexName": "codeserver",
|
||||
"licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
|
||||
"win32DirName": "code-server",
|
||||
"win32NameVersion": "code-server",
|
||||
"win32AppUserModelId": "coder.code-server",
|
||||
"win32ShellNameShort": "c&ode-server",
|
||||
"darwinBundleIdentifier": "com.coder.code.server",
|
||||
"linuxIconName": "com.coder.code.server",
|
||||
"reportIssueUrl": "https://github.com/coder/code-server/issues/new",
|
||||
"documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
|
||||
"keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
|
||||
"keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
|
||||
"keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
|
||||
"introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
|
||||
"tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
|
||||
"newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
|
||||
"linkProtectionTrustedDomains": [
|
||||
"https://open-vsx.org"
|
||||
]
|
||||
}
|
||||
EOF
|
||||
) > product.json
|
||||
|
||||
# Any platform here works since we will do our own packaging. We have to do
|
||||
# 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.
|
||||
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
|
||||
# product.json which will have `stable-$commit`).
|
||||
git checkout product.json
|
||||
|
||||
popd
|
||||
|
||||
# These provide a `code-server` command in the integrated terminal to open
|
||||
# files in the current instance.
|
||||
delete-bin-script remote-cli/code-server
|
||||
copy-bin-script remote-cli/code-darwin.sh
|
||||
copy-bin-script remote-cli/code-linux.sh
|
||||
copy-bin-script remote-cli/code.cmd
|
||||
|
||||
# These provide a way for terminal applications to open browser windows.
|
||||
delete-bin-script helpers/browser.sh
|
||||
copy-bin-script helpers/browser-darwin.sh
|
||||
copy-bin-script helpers/browser-linux.sh
|
||||
copy-bin-script helpers/browser.cmd
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -1,23 +1,69 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
# Copied from arch() in ci/lib.sh.
|
||||
detect_arch() {
|
||||
case "$(uname -m)" in
|
||||
aarch64)
|
||||
echo arm64
|
||||
;;
|
||||
x86_64 | amd64)
|
||||
echo amd64
|
||||
;;
|
||||
*)
|
||||
# This will cause the download to fail, but is intentional
|
||||
uname -m
|
||||
;;
|
||||
# Copied from ../lib.sh.
|
||||
arch() {
|
||||
cpu="$(uname -m)"
|
||||
case "$cpu" in
|
||||
aarch64) cpu=arm64 ;;
|
||||
x86_64) cpu=amd64 ;;
|
||||
esac
|
||||
echo "$cpu"
|
||||
}
|
||||
|
||||
# Copied from ../lib.sh except we do not rename Darwin since the cloud agent
|
||||
# uses "darwin" in the release names and we do not need to detect Alpine.
|
||||
os() {
|
||||
osname=$(uname | tr '[:upper:]' '[:lower:]')
|
||||
case $osname in
|
||||
cygwin* | mingw*) osname="windows" ;;
|
||||
esac
|
||||
echo "$osname"
|
||||
}
|
||||
|
||||
# Create a symlink at $2 pointing to $1 on any platform. Anything that
|
||||
# currently exists at $2 will be deleted.
|
||||
symlink() {
|
||||
source="$1"
|
||||
dest="$2"
|
||||
rm -rf "$dest"
|
||||
case $OS in
|
||||
windows) mklink /J "$dest" "$source" ;;
|
||||
*) ln -s "$source" "$dest" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
ARCH="${NPM_CONFIG_ARCH:-$(detect_arch)}"
|
||||
# VS Code bundles some modules into an asar which is an archive format that
|
||||
# works like tar. It then seems to get unpacked into node_modules.asar.
|
||||
#
|
||||
# I don't know why they do this but all the dependencies they bundle already
|
||||
# exist in node_modules so just symlink it. We have to do this since not only
|
||||
# Code itself but also extensions will look specifically in this directory for
|
||||
# files (like the ripgrep binary or the oniguruma wasm).
|
||||
symlink_asar() {
|
||||
symlink node_modules node_modules.asar
|
||||
}
|
||||
|
||||
# Make a symlink at bin/$1/$3 pointing to the platform-specific version of the
|
||||
# script in $2. The extension of the link will be .cmd for Windows otherwise it
|
||||
# will be whatever is in $4 (or no extension if $4 is not set).
|
||||
symlink_bin_script() {
|
||||
oldpwd="$(pwd)"
|
||||
cd "bin/$1"
|
||||
source="$2"
|
||||
dest="$3"
|
||||
ext="${4-}"
|
||||
case $OS in
|
||||
windows) symlink "$source.cmd" "$dest.cmd" ;;
|
||||
darwin | macos) symlink "$source-darwin.sh" "$dest$ext" ;;
|
||||
*) symlink "$source-linux.sh" "$dest$ext" ;;
|
||||
esac
|
||||
cd "$oldpwd"
|
||||
}
|
||||
|
||||
ARCH="${NPM_CONFIG_ARCH:-$(arch)}"
|
||||
OS="$(os)"
|
||||
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
@@ -33,8 +79,8 @@ main() {
|
||||
echo "USE AT YOUR OWN RISK!"
|
||||
fi
|
||||
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-14}" ]; then
|
||||
echo "ERROR: code-server currently requires node v14."
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-16}" ]; then
|
||||
echo "ERROR: code-server currently requires node v16."
|
||||
if [ -n "$FORCE_NODE_VERSION" ]; then
|
||||
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
||||
fi
|
||||
@@ -56,8 +102,6 @@ main() {
|
||||
;;
|
||||
esac
|
||||
|
||||
OS="$(uname | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
mkdir -p ./lib
|
||||
|
||||
if curl -fsSL "https://github.com/coder/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent; then
|
||||
@@ -68,7 +112,7 @@ main() {
|
||||
|
||||
if ! vscode_yarn; then
|
||||
echo "You may not have the required dependencies to build the native modules."
|
||||
echo "Please see https://github.com/coder/code-server/blob/master/docs/npm.md"
|
||||
echo "Please see https://github.com/coder/code-server/blob/main/docs/npm.md"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -79,22 +123,14 @@ main() {
|
||||
fi
|
||||
}
|
||||
|
||||
# This is a copy of symlink_asar in ../lib.sh. Look there for details.
|
||||
symlink_asar() {
|
||||
rm -rf node_modules.asar
|
||||
if [ "${WINDIR-}" ]; then
|
||||
mklink /J node_modules.asar node_modules
|
||||
else
|
||||
ln -s node_modules node_modules.asar
|
||||
fi
|
||||
}
|
||||
|
||||
vscode_yarn() {
|
||||
echo 'Installing Code dependencies...'
|
||||
cd lib/vscode
|
||||
yarn --production --frozen-lockfile
|
||||
yarn --production --frozen-lockfile --no-default-rc
|
||||
|
||||
symlink_asar
|
||||
symlink_bin_script remote-cli code code-server
|
||||
symlink_bin_script helpers browser browser .sh
|
||||
|
||||
cd extensions
|
||||
yarn --production --frozen-lockfile
|
||||
|
||||
@@ -81,7 +81,7 @@ main() {
|
||||
read -r -p "What version of code-server do you want to update to?"$'\n' CODE_SERVER_VERSION_TO_UPDATE
|
||||
|
||||
echo -e "Great! We'll prep a PR for updating to $CODE_SERVER_VERSION_TO_UPDATE\n"
|
||||
$CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE"
|
||||
$CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' -g '!lib/vscode/**' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE"
|
||||
|
||||
$CMD git commit --no-verify -am "chore(release): bump version to $CODE_SERVER_VERSION_TO_UPDATE"
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Make sure a code-server release works. You can pass in the path otherwise it
|
||||
# will use release-standalone in the current directory.
|
||||
#
|
||||
# This is to make sure we don't have Node version errors or any other
|
||||
# compilation-related errors.
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
local EXTENSIONS_DIR
|
||||
EXTENSIONS_DIR="$(mktemp -d)"
|
||||
|
||||
local path=${1:-./release-standalone/bin/code-server}
|
||||
|
||||
echo "Testing standalone release in $path."
|
||||
|
||||
# NOTE: using a basic theme extension because it doesn't update often and is more reliable for testing
|
||||
"$path" --extensions-dir "$EXTENSIONS_DIR" --install-extension wesbos.theme-cobalt2
|
||||
local installed_extensions
|
||||
installed_extensions="$("$path" --extensions-dir "$EXTENSIONS_DIR" --list-extensions 2>&1)"
|
||||
# We use grep as wesbos.theme-cobalt2 may have dependency extensions that change.
|
||||
if ! echo "$installed_extensions" | grep -q "wesbos.theme-cobalt2"; then
|
||||
echo "Unexpected output from listing extensions:"
|
||||
echo "$installed_extensions"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Standalone release works correctly."
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -7,6 +7,9 @@ install-deps() {
|
||||
if [[ ${CI-} ]]; then
|
||||
args+=(--frozen-lockfile)
|
||||
fi
|
||||
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).
|
||||
@@ -26,7 +29,11 @@ main() {
|
||||
|
||||
install-deps test
|
||||
install-deps test/e2e/extensions/test-extension
|
||||
install-deps lib/vscode
|
||||
# We don't need these when running the integration tests
|
||||
# so you can pass SKIP_SUBMODULE_DEPS
|
||||
if [[ ! ${SKIP_SUBMODULE_DEPS-} ]]; then
|
||||
install-deps lib/vscode
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
39
ci/dev/test-integration.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
help() {
|
||||
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' yarn test:integration"
|
||||
}
|
||||
|
||||
# Make sure a code-server release works. You can pass in the path otherwise it
|
||||
# will look for release-standalone in the current directory.
|
||||
#
|
||||
# This is to make sure we don't have Node version errors or any other
|
||||
# compilation-related errors.
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
local path="$RELEASE_PATH-standalone/bin/code-server"
|
||||
if [[ ! ${CODE_SERVER_PATH-} ]]; then
|
||||
echo "Set CODE_SERVER_PATH to test another build of code-server"
|
||||
else
|
||||
path="$CODE_SERVER_PATH"
|
||||
fi
|
||||
|
||||
echo "Running tests with code-server binary: '$path'"
|
||||
|
||||
if [[ ! -f $path ]]; then
|
||||
echo >&2 "No code-server build detected"
|
||||
echo >&2 "Looked in $path"
|
||||
help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CODE_SERVER_PATH="$path" CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -30,7 +30,7 @@ main() {
|
||||
# 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.
|
||||
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@"
|
||||
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts" --testPathIgnorePatterns "./test/unit/node/test-plugin"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -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: 2.3.0
|
||||
version: 3.2.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.2.0
|
||||
appVersion: 4.6.0
|
||||
|
||||
@@ -25,6 +25,9 @@ spec:
|
||||
{{- if .Values.hostnameOverride }}
|
||||
hostname: {{ .Values.hostnameOverride }}
|
||||
{{- end }}
|
||||
{{- if .Values.priorityClassName }}
|
||||
priorityClassName: {{ .Values.priorityClassName }}
|
||||
{{- end }}
|
||||
{{- if .Values.securityContext.enabled }}
|
||||
securityContext:
|
||||
fsGroup: {{ .Values.securityContext.fsGroup }}
|
||||
@@ -59,6 +62,17 @@ spec:
|
||||
securityContext:
|
||||
runAsUser: {{ .Values.securityContext.runAsUser }}
|
||||
{{- end }}
|
||||
{{- if .Values.lifecycle.enabled }}
|
||||
lifecycle:
|
||||
{{- if .Values.lifecycle.postStart }}
|
||||
postStart:
|
||||
{{ toYaml .Values.lifecycle.postStart | nindent 14 }}
|
||||
{{- end }}
|
||||
{{- if .Values.lifecycle.preStop }}
|
||||
preStop:
|
||||
{{ toYaml .Values.lifecycle.preStop | nindent 14 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if .Values.extraVars }}
|
||||
{{ toYaml .Values.extraVars | indent 10 }}
|
||||
@@ -116,7 +130,7 @@ spec:
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- tpl . $ | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
|
||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: codercom/code-server
|
||||
tag: '4.2.0'
|
||||
tag: '4.6.0'
|
||||
pullPolicy: Always
|
||||
|
||||
# Specifies one or more secrets to be used when pulling images from a
|
||||
@@ -33,6 +33,8 @@ podAnnotations: {}
|
||||
podSecurityContext: {}
|
||||
# fsGroup: 2000
|
||||
|
||||
priorityClassName: ""
|
||||
|
||||
service:
|
||||
type: ClusterIP
|
||||
port: 8080
|
||||
@@ -125,6 +127,15 @@ persistence:
|
||||
# existingClaim: ""
|
||||
# hostPath: /data
|
||||
|
||||
lifecycle:
|
||||
enabled: false
|
||||
# postStart:
|
||||
# exec:
|
||||
# command:
|
||||
# - /bin/bash
|
||||
# - -c
|
||||
# - curl -s -L SOME_SCRIPT | bash
|
||||
|
||||
## Enable an Specify container in extraContainers.
|
||||
## This is meant to allow adding code-server dependencies, like docker-dind.
|
||||
extraContainers: |
|
||||
@@ -145,6 +156,25 @@ extraContainers: |
|
||||
# - name: DOCKER_DRIVER
|
||||
# value: "overlay2"
|
||||
|
||||
extraInitContainers: |
|
||||
# - name: customization
|
||||
# image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
|
||||
# imagePullPolicy: IfNotPresent
|
||||
# env:
|
||||
# - name: SERVICE_URL
|
||||
# value: https://open-vsx.org/vscode/gallery
|
||||
# - name: ITEM_URL
|
||||
# value: https://open-vsx.org/vscode/item
|
||||
# command:
|
||||
# - sh
|
||||
# - -c
|
||||
# - |
|
||||
# code-server --install-extension ms-python.python
|
||||
# code-server --install-extension golang.Go
|
||||
# volumeMounts:
|
||||
# - name: data
|
||||
# mountPath: /home/coder
|
||||
|
||||
## Additional code-server secret mounts
|
||||
extraSecretMounts: []
|
||||
# - name: secret-files
|
||||
|
||||
61
ci/lib.sh
@@ -18,35 +18,30 @@ vscode_version() {
|
||||
}
|
||||
|
||||
os() {
|
||||
local os
|
||||
os=$(uname | tr '[:upper:]' '[:lower:]')
|
||||
if [[ $os == "linux" ]]; then
|
||||
# Alpine's ldd doesn't have a version flag but if you use an invalid flag
|
||||
# (like --version) it outputs the version to stderr and exits with 1.
|
||||
local ldd_output
|
||||
ldd_output=$(ldd --version 2>&1 || true)
|
||||
if echo "$ldd_output" | grep -iq musl; then
|
||||
os="alpine"
|
||||
fi
|
||||
elif [[ $os == "darwin" ]]; then
|
||||
os="macos"
|
||||
fi
|
||||
echo "$os"
|
||||
osname=$(uname | tr '[:upper:]' '[:lower:]')
|
||||
case $osname in
|
||||
linux)
|
||||
# Alpine's ldd doesn't have a version flag but if you use an invalid flag
|
||||
# (like --version) it outputs the version to stderr and exits with 1.
|
||||
# TODO: Better to check /etc/os-release; see ../install.sh.
|
||||
ldd_output=$(ldd --version 2>&1 || true)
|
||||
if echo "$ldd_output" | grep -iq musl; then
|
||||
osname="alpine"
|
||||
fi
|
||||
;;
|
||||
darwin) osname="macos" ;;
|
||||
cygwin* | mingw*) osname="windows" ;;
|
||||
esac
|
||||
echo "$osname"
|
||||
}
|
||||
|
||||
arch() {
|
||||
cpu="$(uname -m)"
|
||||
case "$cpu" in
|
||||
aarch64)
|
||||
echo arm64
|
||||
;;
|
||||
x86_64 | amd64)
|
||||
echo amd64
|
||||
;;
|
||||
*)
|
||||
echo "$cpu"
|
||||
;;
|
||||
aarch64) cpu=arm64 ;;
|
||||
x86_64) cpu=amd64 ;;
|
||||
esac
|
||||
echo "$cpu"
|
||||
}
|
||||
|
||||
# Grabs the most recent ci.yaml github workflow run that was triggered from the
|
||||
@@ -57,7 +52,7 @@ arch() {
|
||||
# https://developer.github.com/v3/actions/workflow-runs/#list-workflow-runs
|
||||
get_artifacts_url() {
|
||||
local artifacts_url
|
||||
local version_branch="v$VERSION"
|
||||
local version_branch="release/v$VERSION"
|
||||
local workflow_runs_url="repos/:owner/:repo/actions/workflows/ci.yaml/runs?event=pull_request&branch=$version_branch"
|
||||
artifacts_url=$(gh api "$workflow_runs_url" | jq -r ".workflow_runs[] | select(.head_branch == \"$version_branch\") | .artifacts_url" | head -n 1)
|
||||
if [[ -z "$artifacts_url" ]]; then
|
||||
@@ -104,21 +99,3 @@ export OS
|
||||
# RELEASE_PATH is the destination directory for the release from the root.
|
||||
# Defaults to release
|
||||
RELEASE_PATH="${RELEASE_PATH-release}"
|
||||
|
||||
# VS Code bundles some modules into an asar which is an archive format that
|
||||
# works like tar. It then seems to get unpacked into node_modules.asar.
|
||||
#
|
||||
# I don't know why they do this but all the dependencies they bundle already
|
||||
# exist in node_modules so just symlink it. We have to do this since not only VS
|
||||
# Code itself but also extensions will look specifically in this directory for
|
||||
# files (like the ripgrep binary or the oniguruma wasm).
|
||||
symlink_asar() {
|
||||
rm -rf node_modules.asar
|
||||
if [ "${WINDIR-}" ]; then
|
||||
# mklink takes the link name first.
|
||||
mklink /J node_modules.asar node_modules
|
||||
else
|
||||
# ln takes the link name second.
|
||||
ln -s node_modules node_modules.asar
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ RUN ARCH="$(dpkg --print-architecture)" && \
|
||||
COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
|
||||
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages dpkg -i /tmp/packages/code-server*$(dpkg --print-architecture).deb
|
||||
|
||||
# Allow users to have scripts run on container startup to prepare workspace.
|
||||
# https://github.com/coder/code-server/issues/5177
|
||||
ENV ENTRYPOINTD=${HOME}/entrypoint.d
|
||||
|
||||
EXPOSE 8080
|
||||
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
|
||||
# the uid will remain the same. note: only relevant if -u isn't passed to
|
||||
|
||||
@@ -15,6 +15,8 @@ target "code-server" {
|
||||
tags = [
|
||||
"docker.io/codercom/code-server:latest",
|
||||
notequal("latest",VERSION) ? "docker.io/codercom/code-server:${VERSION}" : "",
|
||||
"ghcr.io/coder/code-server:latest",
|
||||
notequal("latest",VERSION) ? "ghcr.io/coder/code-server:${VERSION}" : "",
|
||||
]
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
@@ -18,4 +18,10 @@ if [ "${DOCKER_USER-}" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Allow users to have scripts run on container startup to prepare workspace.
|
||||
# https://github.com/coder/code-server/issues/5177
|
||||
if [ -d "${ENTRYPOINTD}" ]; then
|
||||
find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
|
||||
fi
|
||||
|
||||
exec dumb-init /usr/bin/code-server "$@"
|
||||
|
||||
@@ -23,7 +23,7 @@ main() {
|
||||
# Find the docs for bump-formula-pr here
|
||||
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
|
||||
local output
|
||||
if ! output=$(brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit 2>&1); then
|
||||
if ! output=$(brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit --message="PR opened by @${GITHUB_ACTOR}" 2>&1); then
|
||||
if [[ $output == *"Duplicate PRs should not be opened"* ]]; then
|
||||
echo "$VERSION is already submitted"
|
||||
exit 0
|
||||
|
||||
@@ -81,10 +81,6 @@ main() {
|
||||
# https://github.com/actions/upload-artifact/issues/38
|
||||
tar -xzf release-npm-package/package.tar.gz
|
||||
|
||||
# Ignore symlink when publishing npm package
|
||||
# See: https://github.com/coder/code-server/pull/3935
|
||||
echo "node_modules.asar" > release/.npmignore
|
||||
|
||||
# We use this to set the name of the package in the
|
||||
# package.json
|
||||
PACKAGE_NAME="code-server"
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
- [Version updates to Code](#version-updates-to-code)
|
||||
- [Patching Code](#patching-code)
|
||||
- [Build](#build)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [I see "Forbidden access" when I load code-server in the browser](#i-see-forbidden-access-when-i-load-code-server-in-the-browser)
|
||||
- ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
|
||||
- [Help](#help)
|
||||
- [Test](#test)
|
||||
- [Unit tests](#unit-tests)
|
||||
@@ -31,7 +34,7 @@ for [VS
|
||||
Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||
Here is what is needed:
|
||||
|
||||
- `node` v14.x
|
||||
- `node` v16.x
|
||||
- `git` v2.x or greater
|
||||
- [`git-lfs`](https://git-lfs.github.com)
|
||||
- [`yarn`](https://classic.yarnpkg.com/en/)
|
||||
@@ -96,6 +99,8 @@ re-apply the patches.
|
||||
### Version updates to Code
|
||||
|
||||
1. Update the `lib/vscode` submodule to the desired upstream version branch.
|
||||
1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
|
||||
2. `git add lib && git commit -m "chore: update Code"`
|
||||
2. Apply the patches (`quilt push -a`) or restore your stashed changes. At this
|
||||
stage you may need to resolve conflicts. For example use `quilt push -f`,
|
||||
manually apply the rejected portions, then `quilt refresh`.
|
||||
@@ -130,11 +135,13 @@ yarn build:vscode
|
||||
yarn release
|
||||
```
|
||||
|
||||
_NOTE: this does not keep `node_modules`. If you want them to be kept, use `KEEP_MODULES=1 yarn release` (if you're testing in Coder, you'll want to do this)_
|
||||
|
||||
Run your build:
|
||||
|
||||
```shell
|
||||
cd release
|
||||
yarn --production
|
||||
yarn --production # Skip if you used KEEP_MODULES=1
|
||||
# Runs the built JavaScript with Node.
|
||||
node .
|
||||
```
|
||||
@@ -143,7 +150,7 @@ Build the release packages (make sure that you run `yarn release` first):
|
||||
|
||||
```shell
|
||||
yarn release:standalone
|
||||
yarn test:standalone-release
|
||||
yarn test:integration
|
||||
yarn package
|
||||
```
|
||||
|
||||
@@ -152,6 +159,18 @@ yarn package
|
||||
> If you need your builds to support older distros, run the build commands
|
||||
> inside a Docker container with all the build requirements installed.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### I see "Forbidden access" when I load code-server in the browser
|
||||
|
||||
This means your patches didn't apply correctly. We have a patch to remove the auth from vanilla Code because we use our own.
|
||||
|
||||
Try popping off the patches with `quilt pop -a` and reapplying with `quilt push -a`.
|
||||
|
||||
### "Can only have one anonymous define call per script"
|
||||
|
||||
Code might be trying to use a dev or prod HTML in the wrong context. You can try re-running code-server and setting `VSCODE_DEV=1`.
|
||||
|
||||
### Help
|
||||
|
||||
If you get stuck or need help, you can always start a new GitHub Discussion [here](https://github.com/coder/code-server/discussions). One of the maintainers will respond and help you out.
|
||||
@@ -184,9 +203,8 @@ 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 a script called
|
||||
[test-standalone-release.sh](../ci/build/test-standalone-release.sh), which
|
||||
ensures that code-server's CLI is working.
|
||||
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.
|
||||
|
||||
Our integration tests look at components that rely on one another. For example,
|
||||
testing the CLI requires us to build and package code-server.
|
||||
|
||||
@@ -164,16 +164,18 @@ If you're the current release manager, follow these steps:
|
||||
|
||||
### Publishing a release
|
||||
|
||||
1. Create a new branch called `v0.0.0` (replace 0s with actual version aka v4.2.0)
|
||||
1. Create a new branch called `release/v0.0.0` (replace 0s with actual version aka v4.5.0)
|
||||
1. If you don't do this, the `npm-brew` GitHub workflow will fail. It looks for the release artifacts under the branch pattern.
|
||||
1. Run `yarn release:prep` and type in the new version (e.g., `3.8.1`)
|
||||
1. GitHub Actions will generate the `npm-package`, `release-packages` and
|
||||
`release-images` artifacts. You do not have to wait for this step to complete
|
||||
before proceeding.
|
||||
1. Run `yarn release:github-draft` to create a GitHub draft release from the
|
||||
template with the updated version.
|
||||
template with the updated version. Make sure to update the `CHANGELOG.md`.
|
||||
1. Bump chart version in `Chart.yaml`.
|
||||
1. Summarize the major changes in the release notes and link to the relevant
|
||||
issues.
|
||||
1. Change the @ to target the version branch. Example: `v3.9.0 @ Target: v3.9.0`
|
||||
1. Change the @ to target the version branch. Example: `v3.9.0 @ Target: release/v3.9.0`
|
||||
1. Wait for the `npm-package`, `release-packages` and `release-images` artifacts
|
||||
to build.
|
||||
1. Run `yarn release:github-assets` to download the `release-packages` artifact.
|
||||
|
||||
@@ -14,19 +14,16 @@ access it in the browser.
|
||||
- Preserve battery life when you're on the go; all intensive tasks run on your
|
||||
server
|
||||
|
||||
| 🔔 code-server is a free browser-based IDE while [Coder](https://coder.com/) is our enterprise developer workspace platform. For more information, visit [Coder.com](https://coder.com/docs/comparison)
|
||||
| ---
|
||||
|
||||
## Requirements
|
||||
|
||||
See [requirements](requirements.md) for minimum specs, as well as instructions
|
||||
on how to set up a Google VM on which you can install code-server.
|
||||
|
||||
**TL;DR:** Linux machine with WebSockets enabled, 1 GB RAM, and 2 CPUs
|
||||
**TL;DR:** Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs
|
||||
|
||||
## Getting started
|
||||
|
||||
There are three 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
|
||||
@@ -34,7 +31,8 @@ There are three ways to get started:
|
||||
possible.
|
||||
2. Manually [installing
|
||||
code-server](https://coder.com/docs/code-server/latest/install)
|
||||
3. Using our one-click buttons and guides to [deploy code-server to a cloud
|
||||
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) ⚡
|
||||
|
||||
If you use the install script, you can preview what occurs during the install
|
||||
@@ -53,6 +51,9 @@ curl -fsSL https://code-server.dev/install.sh | sh
|
||||
When done, the install script prints out instructions for running and starting
|
||||
code-server.
|
||||
|
||||
> **Note**
|
||||
> To manage code-server for a team on your infrastructure, see: [coder/coder](https://cdr.co/coder-github)
|
||||
|
||||
We also have an in-depth [setup and
|
||||
configuration](https://coder.com/docs/code-server/latest/guide) guide.
|
||||
|
||||
|
||||
@@ -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 14:
|
||||
7. Install and use Node.js 16:
|
||||
|
||||
```shell
|
||||
nvm install 14
|
||||
nvm use 14
|
||||
nvm install 16
|
||||
nvm use 16
|
||||
```
|
||||
|
||||
8. Install code-server globally on device with: `npm i -g code-server`
|
||||
|
||||
1
docs/assets/images/icons/collab.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="20" height="20" viewBox="0 0 20 20"> <path d="M12.2 13.4357L9.5 11.4357C10.4 10.7357 11 9.7357 11 8.5357V7.7357C11 5.8357 9.6 4.1357 7.7 4.0357C5.7 3.9357 4 5.5357 4 7.5357V8.5357C4 9.7357 4.6 10.7357 5.5 11.4357L2.8 13.5357C2.3 13.9357 2 14.5357 2 15.1357V17.0357C2 17.6357 2.4 18.0357 3 18.0357H12C12.6 18.0357 13 17.6357 13 17.0357V15.0357C13 14.4357 12.7 13.8357 12.2 13.4357Z"/> <path d="M17.1 8.43436L15.3 7.23436C15.7 6.83436 16 6.23436 16 5.53436V4.63436C16 3.43436 15.1 2.23436 13.9 2.03436C12.7 1.83436 11.7 2.53436 11.2 3.43436C12.3 4.43436 13 5.83436 13 7.43436V8.43436C13 9.33436 12.8 10.2344 12.4 10.9344C12.4 10.9344 13.6 11.8344 13.6 11.9344H17C17.6 11.9344 18 11.5344 18 10.9344V10.1344C18 9.43436 17.7 8.83436 17.1 8.43436Z"/></svg>
|
||||
|
After Width: | Height: | Size: 854 B |
1
docs/assets/images/icons/contributing.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="20" height="20" fill="none" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M5 2.5V12.5" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M15 7.5C16.3807 7.5 17.5 6.38071 17.5 5C17.5 3.61929 16.3807 2.5 15 2.5C13.6193 2.5 12.5 3.61929 12.5 5C12.5 6.38071 13.6193 7.5 15 7.5Z" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M5 17.5C6.38071 17.5 7.5 16.3807 7.5 15C7.5 13.6193 6.38071 12.5 5 12.5C3.61929 12.5 2.5 13.6193 2.5 15C2.5 16.3807 3.61929 17.5 5 17.5Z" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M15 7.5C15 9.48912 14.2098 11.3968 12.8033 12.8033C11.3968 14.2098 9.48912 15 7.5 15" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
|
After Width: | Height: | Size: 909 B |
1
docs/assets/images/icons/faq.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><path d="M10.0001 18.3333C14.6025 18.3333 18.3334 14.6024 18.3334 10C18.3334 5.39762 14.6025 1.66666 10.0001 1.66666C5.39771 1.66666 1.66675 5.39762 1.66675 10C1.66675 14.6024 5.39771 18.3333 10.0001 18.3333Z" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M7.57495 7.5C7.77087 6.94306 8.15758 6.47342 8.66658 6.17428C9.17558 5.87513 9.77403 5.76578 10.3559 5.86559C10.9378 5.96541 11.4656 6.26794 11.8458 6.71961C12.2261 7.17128 12.4342 7.74294 12.4333 8.33333C12.4333 10 9.93328 10.8333 9.93328 10.8333" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M10 14.1667H10.0083" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
|
After Width: | Height: | Size: 941 B |
1
docs/assets/images/icons/home.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 16 16" width="16px" xml:space="preserve"><path d="M15.45,7L14,5.551V2c0-0.55-0.45-1-1-1h-1c-0.55,0-1,0.45-1,1v0.553L9,0.555C8.727,0.297,8.477,0,8,0S7.273,0.297,7,0.555 L0.55,7C0.238,7.325,0,7.562,0,8c0,0.563,0.432,1,1,1h1v6c0,0.55,0.45,1,1,1h3v-5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v5h3 c0.55,0,1-0.45,1-1V9h1c0.568,0,1-0.437,1-1C16,7.562,15.762,7.325,15.45,7z"></path></svg>
|
||||
|
After Width: | Height: | Size: 489 B |
1
docs/assets/images/icons/requirements.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><path d="M6 2V11H2V15C2 16.7 3.3 18 5 18H15C16.7 18 18 16.7 18 15V2H6ZM16 15C16 15.6 15.6 16 15 16H8V4H16V15Z" /><path d="M14 7H10V9H14V7Z" /><path d="M14 11H10V13H14V11Z" /></svg>
|
||||
|
After Width: | Height: | Size: 321 B |
1
docs/assets/images/icons/upgrade.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><path d="M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.5.028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z"/><path d="M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0.12 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z"/><path d="M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944.5.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z"/><path d="M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
3
docs/assets/images/icons/usage.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.8 3.6H0V16.2C0 17.19 0.81 18 1.8 18H14.4V16.2H1.8V3.6ZM16.2 0H5.4C4.41 0 3.6 0.81 3.6 1.8V12.6C3.6 13.59 4.41 14.4 5.4 14.4H16.2C17.19 14.4 18 13.59 18 12.6V1.8C18 0.81 17.19 0 16.2 0ZM16.2 9L13.95 7.65L11.7 9V1.8H16.2V9Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 352 B |
1
docs/assets/images/icons/wrench.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z"></path></svg>
|
||||
|
After Width: | Height: | Size: 271 B |
@@ -60,6 +60,6 @@ As `code-server` is based on VS Code, you can follow the steps described on Duck
|
||||
code-server --enable-proposed-api genuitecllc.codetogether
|
||||
```
|
||||
|
||||
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.2.0/FAQ#how-does-the-config-file-work).
|
||||
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.6.0/FAQ#how-does-the-config-file-work).
|
||||
|
||||
3. Refresh code-server and navigate to the CodeTogether icon in the sidebar to host or join a coding session.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
- [Stripping `/proxy/<port>` from the request path](#stripping-proxyport-from-the-request-path)
|
||||
- [Proxying to create a React app](#proxying-to-create-a-react-app)
|
||||
- [Proxying to a Vue app](#proxying-to-a-vue-app)
|
||||
- [Proxying to an Angular app](#proxying-to-an-angular-app)
|
||||
- [SSH into code-server on VS Code](#ssh-into-code-server-on-vs-code)
|
||||
- [Option 1: cloudflared tunnel](#option-1-cloudflared-tunnel)
|
||||
- [Option 2: ngrok tunnel](#option-2-ngrok-tunnel)
|
||||
@@ -126,8 +127,8 @@ access code-server on an iPad or do not want to use SSH port forwarding.
|
||||
|
||||
```console
|
||||
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/gpg/gpg.155B6D79CA56EA34.key' | sudo apt-key add -
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/setup/config.deb.txt?distro=debian&version=any-version' | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list
|
||||
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
|
||||
```
|
||||
@@ -382,6 +383,15 @@ module.exports = {
|
||||
|
||||
Read more about `publicPath` in the [Vue.js docs](https://cli.vuejs.org/config/#publicpath)
|
||||
|
||||
### 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:
|
||||
|
||||
1. use `<base href="./.">` in `src/index.html`
|
||||
2. add `--serve-path /absproxy/4200` to `ng serve` in your `package.json`
|
||||
|
||||
For additional context, see [this GitHub Discussion](https://github.com/coder/code-server/discussions/5439#discussioncomment-3371983).
|
||||
|
||||
## SSH into code-server on VS Code
|
||||
|
||||
[](https://ohmyz.sh/) [](https://img.shields.io/badge/Terminal-2E2E2E?style=for-the-badge&logo=Windows+Terminal&logoColor=ffffff) [](vscode:extension/ms-vscode-remote.remote-ssh)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# code-server Helm Chart
|
||||
|
||||
[](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [](https://img.shields.io/badge/Type-application-informational?style=flat-square) [](https://img.shields.io/badge/AppVersion-4.2.0-informational?style=flat-square)
|
||||
[](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [](https://img.shields.io/badge/Type-application-informational?style=flat-square) [](https://img.shields.io/badge/AppVersion-4.6.0-informational?style=flat-square)
|
||||
|
||||
[code-server](https://github.com/coder/code-server) code-server is VS Code running
|
||||
on a remote server, accessible through the browser.
|
||||
@@ -73,7 +73,7 @@ and their default values.
|
||||
| hostnameOverride | string | `""` |
|
||||
| image.pullPolicy | string | `"Always"` |
|
||||
| image.repository | string | `"codercom/code-server"` |
|
||||
| image.tag | string | `"4.2.0"` |
|
||||
| image.tag | string | `"4.6.0"` |
|
||||
| imagePullSecrets | list | `[]` |
|
||||
| ingress.enabled | bool | `false` |
|
||||
| nameOverride | string | `""` |
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
- [Debian, Ubuntu](#debian-ubuntu)
|
||||
- [Fedora, CentOS, RHEL, SUSE](#fedora-centos-rhel-suse)
|
||||
- [Arch Linux](#arch-linux)
|
||||
- [Artix Linux](#artix-linux)
|
||||
- [macOS](#macos)
|
||||
- [Docker](#docker)
|
||||
- [Helm](#helm)
|
||||
@@ -190,6 +191,72 @@ sudo systemctl enable --now code-server@$USER
|
||||
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
||||
```
|
||||
|
||||
## Artix Linux
|
||||
|
||||
```bash
|
||||
# Install code-server from the AUR
|
||||
git clone https://aur.archlinux.org/code-server.git
|
||||
cd code-server
|
||||
makepkg -si
|
||||
```
|
||||
|
||||
Save the file as `code-server` in `/etc/init.d/` and make it executable with `chmod +x code-server`. Put your username in line 3.
|
||||
|
||||
```bash
|
||||
#!/sbin/openrc-run
|
||||
name=$RC_SVCNAME
|
||||
description="$name - VS Code on a remote server"
|
||||
user="" # your username here
|
||||
homedir="/home/$user"
|
||||
command="$(which code-server)"
|
||||
# Just because you can do this does not mean you should. Use ~/.config/code-server/config.yaml instead
|
||||
#command_args="--extensions-dir $homedir/.local/share/$name/extensions --user-data-dir $homedir/.local/share/$name --disable-telemetry"
|
||||
command_user="$user:$user"
|
||||
pidfile="/run/$name/$name.pid"
|
||||
command_background="yes"
|
||||
extra_commands="report"
|
||||
|
||||
depend() {
|
||||
use logger dns
|
||||
need net
|
||||
}
|
||||
|
||||
start_pre() {
|
||||
checkpath --directory --owner $command_user --mode 0755 /run/$name /var/log/$name
|
||||
}
|
||||
|
||||
start() {
|
||||
default_start
|
||||
report
|
||||
}
|
||||
|
||||
stop() {
|
||||
default_stop
|
||||
}
|
||||
|
||||
status() {
|
||||
default_status
|
||||
report
|
||||
}
|
||||
|
||||
report() {
|
||||
# Report to the user
|
||||
einfo "Reading configuration from ~/.config/code-server/config.yaml"
|
||||
}
|
||||
```
|
||||
|
||||
Start on boot with default runlevel
|
||||
|
||||
```
|
||||
rc-update add code-server default
|
||||
```
|
||||
|
||||
Start the service immediately
|
||||
|
||||
```
|
||||
rc-service code-server start
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
```bash
|
||||
@@ -237,6 +304,8 @@ We currently [do not publish Windows releases](https://github.com/coder/code-ser
|
||||
We recommend installing code-server onto Raspberry Pi with [`yarn` or
|
||||
`npm`](#yarn-npm).
|
||||
|
||||
If you see an error related to `node-gyp` during installation, See [#5174](https://github.com/coder/code-server/issues/5174) for more information.
|
||||
|
||||
## Termux
|
||||
|
||||
Please see code-server's [Termux docs](./termux.md#installation) for more
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
{
|
||||
"versions": ["v4.2.0"],
|
||||
"versions": ["v4.6.0"],
|
||||
"routes": [
|
||||
{
|
||||
"title": "Home",
|
||||
"description": "Learn how to install and run code-server.",
|
||||
"path": "./README.md",
|
||||
"icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16px\" xml:space=\"preserve\"><path d=\"M15.45,7L14,5.551V2c0-0.55-0.45-1-1-1h-1c-0.55,0-1,0.45-1,1v0.553L9,0.555C8.727,0.297,8.477,0,8,0S7.273,0.297,7,0.555 L0.55,7C0.238,7.325,0,7.562,0,8c0,0.563,0.432,1,1,1h1v6c0,0.55,0.45,1,1,1h3v-5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v5h3 c0.55,0,1-0.45,1-1V9h1c0.568,0,1-0.437,1-1C16,7.562,15.762,7.325,15.45,7z\"></path></svg>"
|
||||
"icon_path": "assets/images/icons/home.svg"
|
||||
},
|
||||
{
|
||||
"title": "Requirements",
|
||||
"description": "Learn about what you need to run code-server.",
|
||||
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6 2V11H2V15C2 16.7 3.3 18 5 18H15C16.7 18 18 16.7 18 15V2H6ZM16 15C16 15.6 15.6 16 15 16H8V4H16V15Z\" /><path d=\"M14 7H10V9H14V7Z\" /><path d=\"M14 11H10V13H14V11Z\" /></svg>",
|
||||
"icon_path": "assets/images/icons/requirements.svg",
|
||||
"path": "./requirements.md"
|
||||
},
|
||||
{
|
||||
"title": "Install",
|
||||
"description": "How to install code-server.",
|
||||
"icon": "<svg class=\"MuiSvgIcon-root jss172\" focusable=\"false\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z\"></path></svg>",
|
||||
"icon_path": "assets/images/icons/wrench.svg",
|
||||
"path": "./install.md",
|
||||
"children": [
|
||||
{
|
||||
@@ -34,7 +34,7 @@
|
||||
{
|
||||
"title": "Usage",
|
||||
"description": "How to set up and use code-server.",
|
||||
"icon": "<svg viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 10l-2.5-1.5L15 12V4h5v8z\"></path></svg>",
|
||||
"icon_path": "assets/images/icons/usage.svg",
|
||||
"path": "./guide.md",
|
||||
"children": [
|
||||
{
|
||||
@@ -67,25 +67,25 @@
|
||||
{
|
||||
"title": "Collaboration",
|
||||
"description": "How to setup real time collaboration using code server.",
|
||||
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"> <path d=\"M12.2 13.4357L9.5 11.4357C10.4 10.7357 11 9.7357 11 8.5357V7.7357C11 5.8357 9.6 4.1357 7.7 4.0357C5.7 3.9357 4 5.5357 4 7.5357V8.5357C4 9.7357 4.6 10.7357 5.5 11.4357L2.8 13.5357C2.3 13.9357 2 14.5357 2 15.1357V17.0357C2 17.6357 2.4 18.0357 3 18.0357H12C12.6 18.0357 13 17.6357 13 17.0357V15.0357C13 14.4357 12.7 13.8357 12.2 13.4357Z\"/> <path d=\"M17.1 8.43436L15.3 7.23436C15.7 6.83436 16 6.23436 16 5.53436V4.63436C16 3.43436 15.1 2.23436 13.9 2.03436C12.7 1.83436 11.7 2.53436 11.2 3.43436C12.3 4.43436 13 5.83436 13 7.43436V8.43436C13 9.33436 12.8 10.2344 12.4 10.9344C12.4 10.9344 13.6 11.8344 13.6 11.9344H17C17.6 11.9344 18 11.5344 18 10.9344V10.1344C18 9.43436 17.7 8.83436 17.1 8.43436Z\"/></svg>",
|
||||
"icon_path": "assets/images/icons/collab.svg",
|
||||
"path": "./collaboration.md"
|
||||
},
|
||||
{
|
||||
"title": "Upgrade",
|
||||
"description": "How to upgrade code-server.",
|
||||
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.35028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z\"/><path d=\"M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0.12 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z\"/><path d=\"M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944 3.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z\"/><path d=\"M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z\"/></svg>",
|
||||
"icon_path": "assets/images/icons/upgrade.svg",
|
||||
"path": "./upgrade.md"
|
||||
},
|
||||
{
|
||||
"title": "FAQ",
|
||||
"description": "Frequently asked questions on installing and running code-server.",
|
||||
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10.0001 18.3333C14.6025 18.3333 18.3334 14.6024 18.3334 10C18.3334 5.39762 14.6025 1.66666 10.0001 1.66666C5.39771 1.66666 1.66675 5.39762 1.66675 10C1.66675 14.6024 5.39771 18.3333 10.0001 18.3333Z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M7.57495 7.5C7.77087 6.94306 8.15758 6.47342 8.66658 6.17428C9.17558 5.87513 9.77403 5.76578 10.3559 5.86559C10.9378 5.96541 11.4656 6.26794 11.8458 6.71961C12.2261 7.17128 12.4342 7.74294 12.4333 8.33333C12.4333 10 9.93328 10.8333 9.93328 10.8333\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M10 14.1667H10.0083\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>",
|
||||
"icon_path": "assets/images/icons/faq.svg",
|
||||
"path": "./FAQ.md"
|
||||
},
|
||||
{
|
||||
"title": "Contributing",
|
||||
"description": "How to contribute to code-server.",
|
||||
"icon": "<svg width=\"20\" height=\"20\" fill=\"none\" viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M5 2.5V12.5\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 7.5C16.3807 7.5 17.5 6.38071 17.5 5C17.5 3.61929 16.3807 2.5 15 2.5C13.6193 2.5 12.5 3.61929 12.5 5C12.5 6.38071 13.6193 7.5 15 7.5Z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5 17.5C6.38071 17.5 7.5 16.3807 7.5 15C7.5 13.6193 6.38071 12.5 5 12.5C3.61929 12.5 2.5 13.6193 2.5 15C2.5 16.3807 3.61929 17.5 5 17.5Z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 7.5C15 9.48912 14.2098 11.3968 12.8033 12.8033C11.3968 14.2098 9.48912 15 7.5 15\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>",
|
||||
"icon_path": "assets/images/icons/contributing.svg",
|
||||
"path": "./CONTRIBUTING.md",
|
||||
"children": [
|
||||
{
|
||||
|
||||
@@ -22,8 +22,8 @@ includes installing instructions based on your operating system.
|
||||
|
||||
## Node.js version
|
||||
|
||||
We use the same major version of Node.js shipped with VSCode's Electron,
|
||||
which is currently `14.x`. VS Code also [lists Node.js
|
||||
We use the same major version of Node.js shipped with Code's remote, which is
|
||||
currently `16.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
|
||||
@@ -72,7 +72,7 @@ Proceed to [installing](#installing)
|
||||
## FreeBSD
|
||||
|
||||
```sh
|
||||
pkg install -y git python npm-node14 yarn-node14 pkgconf
|
||||
pkg install -y git python npm-node16 yarn-node16 pkgconf
|
||||
pkg install -y libinotify
|
||||
```
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ for communication between the browser and the server.
|
||||
The following steps walk you through setting up a VM running Debian using Google
|
||||
Cloud (though you are welcome to use any machine or VM provider).
|
||||
|
||||
If you're [signing up with Google](https://console.cloud.google.com/getting-started) for the first time, you should get a 12-month trial with
|
||||
If you're [signing up with Google](https://console.cloud.google.com/getting-started) for the first time, you should get a 3-month trial with
|
||||
$300 of credits.
|
||||
|
||||
After you sign up and create a new Google Cloud Provider (GCP) project, create a
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# Termux
|
||||
|
||||
- [Install](#install)
|
||||
- [Yarn Installation](#yarn-installation)
|
||||
- [Upgrade](#upgrade)
|
||||
- [Known Issues](#known-issues)
|
||||
- [Git won't work in `/sdcard`](#git-wont-work-in-sdcard)
|
||||
@@ -65,6 +66,59 @@ curl -fsSL https://code-server.dev/install.sh | sh
|
||||
> Consider using a new user instead of root, read [here](https://www.howtogeek.com/124950/htg-explains-why-you-shouldnt-log-into-your-linux-system-as-root/) why using root is not recommended.\
|
||||
> Learn how to add a user [here](#create-a-new-user).
|
||||
|
||||
## Yarn Installation
|
||||
|
||||
1. Get [Termux](https://f-droid.org/en/packages/com.termux/) from **F-Droid**.
|
||||
|
||||
2. We will now change using the following command.
|
||||
|
||||
```sh
|
||||
termux-change-repo
|
||||
```
|
||||
|
||||
Now select `Main Repository` then change repo to `Mirrors by Grimler Hosted on grimler.se`.
|
||||
|
||||
3. After successfully updating of repository update and upgrade all the packages by the following command
|
||||
|
||||
```sh
|
||||
pkg update
|
||||
pkg upgrade -y
|
||||
```
|
||||
|
||||
4. Now let's install requirement dependancy.
|
||||
|
||||
```sh
|
||||
pkg install -y \
|
||||
build-essential \
|
||||
binutils \
|
||||
pkg-config \
|
||||
python3 \
|
||||
yarn \
|
||||
nodejs-lts
|
||||
npm config set python python3
|
||||
node -v
|
||||
```
|
||||
|
||||
you will get node version `v16.15.0`
|
||||
|
||||
5. Now install code-server
|
||||
|
||||
```sh
|
||||
yarn global add code-server
|
||||
```
|
||||
|
||||
6. Congratulation code-server is installed on your device using the following command.
|
||||
|
||||
```sh
|
||||
code-server --auth none
|
||||
```
|
||||
|
||||
7. If already installed then use the following command for upgradation.
|
||||
|
||||
```
|
||||
yarn upgrade code-server
|
||||
```
|
||||
|
||||
## Upgrade
|
||||
|
||||
1. Remove all previous installs `rm -rf ~/.local/lib/code-server-*`
|
||||
|
||||
30
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-server",
|
||||
"license": "MIT",
|
||||
"version": "4.2.0",
|
||||
"version": "4.6.0",
|
||||
"description": "Run VS Code on a remote server.",
|
||||
"homepage": "https://github.com/coder/code-server",
|
||||
"bugs": {
|
||||
@@ -18,20 +18,21 @@
|
||||
"release:github-assets": "./ci/build/release-github-assets.sh",
|
||||
"release:prep": "./ci/build/release-prep.sh",
|
||||
"test:e2e": "VSCODE_IPC_HOOK_CLI= ./ci/dev/test-e2e.sh",
|
||||
"test:standalone-release": "./ci/build/test-standalone-release.sh",
|
||||
"test:e2e:proxy": "USE_PROXY=1 ./ci/dev/test-e2e.sh",
|
||||
"test:unit": "./ci/dev/test-unit.sh --forceExit --detectOpenHandles",
|
||||
"test:integration": "./ci/dev/test-integration.sh",
|
||||
"test:scripts": "./ci/dev/test-scripts.sh",
|
||||
"package": "./ci/build/build-packages.sh",
|
||||
"postinstall": "./ci/dev/postinstall.sh",
|
||||
"publish:npm": "./ci/steps/publish-npm.sh",
|
||||
"publish:docker": "./ci/steps/docker-buildx-push.sh",
|
||||
"_audit": "./ci/dev/audit.sh",
|
||||
"fmt": "./ci/dev/fmt.sh",
|
||||
"lint": "./ci/dev/lint.sh",
|
||||
"test": "echo 'Run yarn test:unit or yarn test:e2e' && exit 1",
|
||||
"ci": "./ci/dev/ci.sh",
|
||||
"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",
|
||||
"coverage": "codecov"
|
||||
"icons": "./ci/dev/gen_icons.sh"
|
||||
},
|
||||
"main": "out/node/entry.js",
|
||||
"devDependencies": {
|
||||
@@ -41,18 +42,17 @@
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/http-proxy": "^1.17.4",
|
||||
"@types/js-yaml": "^4.0.0",
|
||||
"@types/node": "^14.17.1",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/pem": "^1.9.5",
|
||||
"@types/proxy-from-env": "^1.0.1",
|
||||
"@types/safe-compare": "^1.1.0",
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/split2": "^3.2.0",
|
||||
"@types/trusted-types": "^2.0.2",
|
||||
"@types/ws": "^8.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||
"@typescript-eslint/parser": "^5.0.0",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.23.0",
|
||||
"@typescript-eslint/parser": "^5.23.0",
|
||||
"audit-ci": "^6.0.0",
|
||||
"codecov": "^3.8.3",
|
||||
"doctoc": "^2.0.0",
|
||||
"eslint": "^7.7.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
@@ -61,13 +61,13 @@
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"json": "^11.0.0",
|
||||
"prettier": "^2.2.1",
|
||||
"prettier-plugin-sh": "^0.10.0",
|
||||
"prettier-plugin-sh": "^0.12.0",
|
||||
"shellcheck": "^1.0.0",
|
||||
"stylelint": "^13.0.0",
|
||||
"stylelint-config-recommended": "^5.0.0",
|
||||
"synp": "^1.9.10",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^4.4.0-dev.20210528"
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"ansi-regex": "^5.0.1",
|
||||
@@ -84,7 +84,9 @@
|
||||
"follow-redirects": "^1.14.8",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nanoid": "^3.1.31",
|
||||
"minimist": "npm:minimist-lite@2.2.1"
|
||||
"minimist": "npm:minimist-lite@2.2.1",
|
||||
"glob-parent": "^6.0.1",
|
||||
"@types/node": "^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "1.1.16",
|
||||
@@ -99,7 +101,7 @@
|
||||
"limiter": "^1.1.5",
|
||||
"pem": "^1.14.2",
|
||||
"proxy-agent": "^5.0.0",
|
||||
"qs": "6.10.3",
|
||||
"qs": "6.11.0",
|
||||
"rotating-file-stream": "^3.0.0",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"safe-compare": "^1.1.4",
|
||||
@@ -121,7 +123,7 @@
|
||||
"browser-ide"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": "16"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
|
||||
@@ -10,16 +10,14 @@ 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
|
||||
@@ -151,8 +151,10 @@ class RemoteAuthoritiesImpl {
|
||||
}
|
||||
@@ -162,7 +162,9 @@ class RemoteAuthoritiesImpl {
|
||||
return URI.from({
|
||||
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
||||
- authority: `${host}:${port}`,
|
||||
- path: `/vscode-remote-resource`,
|
||||
+ authority: platform.isWeb ? window.location.host : `${host}:${port}`,
|
||||
authority: `${host}:${port}`,
|
||||
- path: this._remoteResourcesPath,
|
||||
+ path: platform.isWeb
|
||||
+ ? URI.joinPath(URI.parse(window.location.href), `/vscode-remote-resource`).path
|
||||
+ : `/vscode-remote-resource`,
|
||||
+ ? (window.location.pathname + "/" + this._remoteResourcesPath).replace(/\/\/+/g, "/")
|
||||
+ : this._remoteResourcesPath,
|
||||
query
|
||||
});
|
||||
}
|
||||
@@ -38,40 +36,28 @@ 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">
|
||||
@@ -27,23 +27,26 @@
|
||||
@@ -27,9 +27,9 @@
|
||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
|
||||
- <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="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
|
||||
+ <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" />
|
||||
</head>
|
||||
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
- <script src="./static/out/vs/loader.js"></script>
|
||||
- <script src="./static/out/vs/webPackagePaths.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
|
||||
@@ -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();
|
||||
Object.keys(self.webPackagePaths).map(function (key, index) {
|
||||
- self.webPackagePaths[key] = `${window.location.origin}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
|
||||
+ self.webPackagePaths[key] = new URL(
|
||||
+ `{{VS_BASE}}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`,
|
||||
+ window.location,
|
||||
+ ).toString();
|
||||
self.webPackagePaths[key] = `${baseUrl}/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
|
||||
});
|
||||
require.config({
|
||||
- baseUrl: `${window.location.origin}/static/out`,
|
||||
+ baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
|
||||
recordStats: true,
|
||||
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL(value) {
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
@@ -87,68 +73,41 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.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">
|
||||
@@ -24,10 +24,10 @@
|
||||
@@ -24,9 +24,9 @@
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
|
||||
- <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 data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
|
||||
+ <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" />
|
||||
+ <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 data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.css">
|
||||
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
|
||||
|
||||
</head>
|
||||
|
||||
@@ -35,14 +35,17 @@
|
||||
</body>
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
- <script src="./static/out/vs/loader.js"></script>
|
||||
- <script src="./static/out/vs/webPackagePaths.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
|
||||
@@ -38,7 +38,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();
|
||||
Object.keys(self.webPackagePaths).map(function (key, index) {
|
||||
- self.webPackagePaths[key] = `${window.location.origin}/static/node_modules/${key}/${self.webPackagePaths[key]}`;
|
||||
+ self.webPackagePaths[key] = new URL(
|
||||
+ `{{VS_BASE}}/static/node_modules/${key}/${self.webPackagePaths[key]}`,
|
||||
+ window.location,
|
||||
+ ).toString();
|
||||
self.webPackagePaths[key] = `${baseUrl}/node_modules/${key}/${self.webPackagePaths[key]}`;
|
||||
});
|
||||
require.config({
|
||||
- baseUrl: `${window.location.origin}/static/out`,
|
||||
+ baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
|
||||
recordStats: true,
|
||||
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
|
||||
createScriptURL(value) {
|
||||
@@ -55,7 +58,7 @@
|
||||
<script>
|
||||
performance.mark('code/willLoadWorkbenchMain');
|
||||
</script>
|
||||
- <script src="./static/out/vs/workbench/workbench.web.main.nls.js"></script>
|
||||
- <script src="./static/out/vs/workbench/workbench.web.main.js"></script>
|
||||
- <script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.nls.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.js"></script>
|
||||
+ <script src="{{VS_BASE}}/static/out/vs/code/browser/workbench/workbench.js"></script>
|
||||
</html>
|
||||
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
|
||||
@@ -274,7 +274,7 @@ export class BrowserSocketFactory implem
|
||||
@@ -274,6 +274,7 @@ export class BrowserSocketFactory implem
|
||||
|
||||
connect(host: string, port: number, query: string, debugLabel: string, callback: IConnectCallback): void {
|
||||
connect(host: string, port: number, path: string, query: string, debugLabel: string, callback: IConnectCallback): void {
|
||||
const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
|
||||
- const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}/?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
+ const socket = this._webSocketFactory.create(`${webSocketSchema}://${window.location.host}${window.location.pathname}?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
|
||||
const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
const errorListener = socket.onError((err) => callback(err, undefined));
|
||||
socket.onOpen(() => {
|
||||
errorListener.dispose();
|
||||
@@ -282,6 +282,3 @@ export class BrowserSocketFactory implem
|
||||
@@ -282,6 +283,3 @@ export class BrowserSocketFactory implem
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -159,47 +118,64 @@ 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
|
||||
@@ -252,7 +252,10 @@ export class WebClientServer {
|
||||
@@ -267,12 +267,11 @@ export class WebClientServer {
|
||||
return res.end();
|
||||
}
|
||||
|
||||
- const remoteAuthority = req.headers.host;
|
||||
+ // It is not possible to reliably detect the remote authority on the server
|
||||
+ // in all cases. Set this to something invalid to make sure we catch code
|
||||
+ // that is using this when it should not.
|
||||
- const getFirstHeader = (headerName: string) => {
|
||||
- const val = req.headers[headerName];
|
||||
- return Array.isArray(val) ? val[0] : val;
|
||||
- };
|
||||
-
|
||||
- const remoteAuthority = getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host;
|
||||
+ // 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.
|
||||
+ const remoteAuthority = 'remote';
|
||||
|
||||
function escapeAttribute(value: string): string {
|
||||
return value.replace(/"/g, '"');
|
||||
@@ -272,6 +275,8 @@ export class WebClientServer {
|
||||
accessToken: this._environmentService.args['github-auth'],
|
||||
if (!remoteAuthority) {
|
||||
return serveError(req, res, 400, `Bad request.`);
|
||||
}
|
||||
@@ -298,6 +297,8 @@ export class WebClientServer {
|
||||
scopes: [['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
|
||||
+ const base = relativeRoot(getOriginalUrl(req))
|
||||
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
const data = (await util.promisify(fs.readFile)(filePath)).toString()
|
||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
|
||||
remoteAuthority,
|
||||
@@ -279,6 +284,7 @@ export class WebClientServer {
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
+ rootEndpoint: base,
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
@@ -291,7 +297,9 @@ export class WebClientServer {
|
||||
} : undefined
|
||||
}
|
||||
})))
|
||||
- .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '');
|
||||
+ .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
|
||||
+ .replace(/{{BASE}}/g, base)
|
||||
+ .replace(/{{VS_BASE}}/g, vscodeBase);
|
||||
|
||||
const cspDirectives = [
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
@@ -309,6 +310,7 @@ export class WebClientServer {
|
||||
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
+ rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -326,8 +328,10 @@ 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_NLS_BASE_URL: nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : '',
|
||||
+ WORKBENCH_WEB_BASE_URL: vscodeBase + this._staticRoute,
|
||||
+ WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''),
|
||||
+ BASE: base,
|
||||
+ VS_BASE: vscodeBase,
|
||||
};
|
||||
|
||||
|
||||
@@ -344,7 +348,7 @@ export class WebClientServer {
|
||||
'default-src \'self\';',
|
||||
@@ -370,3 +378,70 @@ export class WebClientServer {
|
||||
'img-src \'self\' https: data: blob:;',
|
||||
'media-src \'self\';',
|
||||
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' http://${remoteAuthority};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=';`, // 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:;',
|
||||
@@ -417,3 +421,70 @@ export class WebClientServer {
|
||||
return res.end(data);
|
||||
}
|
||||
}
|
||||
@@ -286,7 +262,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
|
||||
@@ -482,6 +482,7 @@ function doCreateUri(path: string, query
|
||||
@@ -485,6 +485,7 @@ function doCreateUri(path: string, query
|
||||
});
|
||||
}
|
||||
|
||||
@@ -294,12 +270,12 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
return URI.parse(window.location.href).with({ path, query });
|
||||
}
|
||||
|
||||
@@ -493,7 +494,7 @@ function doCreateUri(path: string, query
|
||||
@@ -496,7 +497,7 @@ function doCreateUri(path: string, query
|
||||
if (!configElement || !configElementAttribute) {
|
||||
throw new Error('Missing web configuration element');
|
||||
}
|
||||
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
|
||||
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
|
||||
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = JSON.parse(configElementAttribute);
|
||||
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
|
||||
|
||||
// Create workbench
|
||||
create(document.body, {
|
||||
@@ -312,10 +288,10 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/
|
||||
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 { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
|
||||
|
||||
@@ -72,7 +71,7 @@ export abstract class AbstractExtensionR
|
||||
@@ -75,7 +74,7 @@ export abstract class AbstractExtensionR
|
||||
public getExtensionGalleryResourceURL(galleryExtension: { publisher: string; name: string; version: string }, path?: string): URI | undefined {
|
||||
if (this._extensionGalleryResourceUrlTemplate) {
|
||||
const uri = URI.parse(format2(this._extensionGalleryResourceUrlTemplate, { publisher: galleryExtension.publisher, name: galleryExtension.name, version: galleryExtension.version, path: 'extension' }));
|
||||
|
||||
96
patches/cli-window-open.diff
Normal file
@@ -0,0 +1,96 @@
|
||||
Make opening files/folders from the terminal only open in the current instance
|
||||
|
||||
Previously they would open in every code-server tab/window.
|
||||
|
||||
To test:
|
||||
|
||||
1. Run code-server
|
||||
2. Open code-server
|
||||
3. Open terminal
|
||||
4. Open another code-server window
|
||||
5. Run code-server with a file or directory argument
|
||||
|
||||
The file or directory should only open from the instance attached to that
|
||||
terminal.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/remoteTerminalChannel.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/remoteTerminalChannel.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/remoteTerminalChannel.ts
|
||||
@@ -89,7 +89,7 @@ export class RemoteTerminalChannel exten
|
||||
uriTransformer: IURITransformer;
|
||||
}>();
|
||||
|
||||
- private readonly _onExecuteCommand = this._register(new Emitter<{ reqId: number; commandId: string; commandArgs: any[] }>());
|
||||
+ private readonly _onExecuteCommand = this._register(new Emitter<{ reqId: number; terminalId: number; commandId: string; commandArgs: any[] }>());
|
||||
readonly onExecuteCommand = this._onExecuteCommand.event;
|
||||
|
||||
constructor(
|
||||
@@ -241,20 +241,20 @@ export class RemoteTerminalChannel exten
|
||||
const ipcHandlePath = createRandomIPCHandle();
|
||||
env.VSCODE_IPC_HOOK_CLI = ipcHandlePath;
|
||||
const commandsExecuter: ICommandsExecuter = {
|
||||
- executeCommand: <T>(id: string, ...args: any[]): Promise<T> => this._executeCommand(id, args, uriTransformer)
|
||||
+ executeCommand: <T>(commandId: string, ...args: any[]): Promise<T> => this._executeCommand(terminalId, commandId, args, uriTransformer)
|
||||
};
|
||||
const cliServer = new CLIServerBase(commandsExecuter, this._logService, ipcHandlePath);
|
||||
|
||||
- const id = await this._ptyService.createProcess(shellLaunchConfig, initialCwd, args.cols, args.rows, args.unicodeVersion, env, baseEnv, args.options, args.shouldPersistTerminal, args.workspaceId, args.workspaceName);
|
||||
- this._ptyService.onProcessExit(e => e.id === id && cliServer.dispose());
|
||||
+ const terminalId = await this._ptyService.createProcess(shellLaunchConfig, initialCwd, args.cols, args.rows, args.unicodeVersion, env, baseEnv, args.options, args.shouldPersistTerminal, args.workspaceId, args.workspaceName);
|
||||
+ this._ptyService.onProcessExit(e => e.id === terminalId && cliServer.dispose());
|
||||
|
||||
return {
|
||||
- persistentTerminalId: id,
|
||||
+ persistentTerminalId: terminalId,
|
||||
resolvedShellLaunchConfig: shellLaunchConfig
|
||||
};
|
||||
}
|
||||
|
||||
- private _executeCommand<T>(commandId: string, commandArgs: any[], uriTransformer: IURITransformer): Promise<T> {
|
||||
+ private _executeCommand<T>(terminalId: number, commandId: string, commandArgs: any[], uriTransformer: IURITransformer): Promise<T> {
|
||||
let resolve!: (data: any) => void;
|
||||
let reject!: (err: any) => void;
|
||||
const result = new Promise<T>((_resolve, _reject) => {
|
||||
@@ -277,6 +277,7 @@ export class RemoteTerminalChannel exten
|
||||
});
|
||||
this._onExecuteCommand.fire({
|
||||
reqId,
|
||||
+ terminalId,
|
||||
commandId,
|
||||
commandArgs: serializedCommandArgs
|
||||
});
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
===================================================================
|
||||
--- 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
|
||||
@@ -94,10 +94,14 @@ class RemoteTerminalBackend extends Base
|
||||
this._remoteTerminalChannel.onExecuteCommand(async e => {
|
||||
const reqId = e.reqId;
|
||||
const commandId = e.commandId;
|
||||
+ const terminalId = e.terminalId;
|
||||
if (!allowedCommands.includes(commandId)) {
|
||||
this._remoteTerminalChannel.sendCommandResult(reqId, true, 'Invalid remote cli command: ' + commandId);
|
||||
return;
|
||||
}
|
||||
+ if (typeof terminalId !== "undefined" && !this._ptys.has(terminalId)) {
|
||||
+ return
|
||||
+ }
|
||||
const commandArgs = e.commandArgs.map(arg => revive(arg));
|
||||
try {
|
||||
const result = await this._commandService.executeCommand(e.commandId, ...commandArgs);
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts
|
||||
@@ -88,8 +88,8 @@ export class RemoteTerminalChannelClient
|
||||
get onProcessOrphanQuestion(): Event<{ id: number }> {
|
||||
return this._channel.listen<{ id: number }>('$onProcessOrphanQuestion');
|
||||
}
|
||||
- get onExecuteCommand(): Event<{ reqId: number; commandId: string; commandArgs: any[] }> {
|
||||
- return this._channel.listen<{ reqId: number; commandId: string; commandArgs: any[] }>('$onExecuteCommand');
|
||||
+ get onExecuteCommand(): Event<{ reqId: number; terminalId: number; commandId: string; commandArgs: any[] }> {
|
||||
+ return this._channel.listen<{ reqId: number; terminalId: number; commandId: string; commandArgs: any[] }>('$onExecuteCommand');
|
||||
}
|
||||
get onDidRequestDetach(): Event<{ requestId: number; workspaceId: string; instanceId: number }> {
|
||||
return this._channel.listen<{ requestId: number; workspaceId: string; instanceId: number }>('$onDidRequestDetach');
|
||||
@@ -4,16 +4,23 @@ This allows the backend to distinguish them. In our case we use them to count a
|
||||
single "open" of Code so we need to be able to distinguish between web sockets
|
||||
from two instances and two web sockets used in a single instance.
|
||||
|
||||
To test this,
|
||||
1. Run code-server
|
||||
2. Open Network tab in Browser DevTools and filter for websocket requests
|
||||
3. You should see the `type=<connection-type>` in the request url
|
||||
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
|
||||
@@ -231,7 +231,7 @@ async function connectToRemoteExtensionH
|
||||
@@ -233,7 +233,8 @@ async function connectToRemoteExtensionH
|
||||
|
||||
let socket: ISocket;
|
||||
try {
|
||||
- socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
|
||||
+ socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `type=${connectionTypeToString(connectionType)}&reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
|
||||
- socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, getRemoteServerRootPath(options), `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
|
||||
+
|
||||
+ socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, getRemoteServerRootPath(options), `type=${connectionTypeToString(connectionType)}&reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);
|
||||
} catch (error) {
|
||||
options.logService.error(`${logPrefix} socketFactory.connect() failed or timed out. Error:`);
|
||||
options.logService.error(error);
|
||||
|
||||
31
patches/disable-builtin-ext-update.diff
Normal file
@@ -0,0 +1,31 @@
|
||||
Prevent builtin extensions from being updated
|
||||
|
||||
Updating builtin extensions from the marketplace prevents us from patching them
|
||||
(for example out GitHub authentication patches).
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||
===================================================================
|
||||
--- 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
|
||||
@@ -237,6 +237,10 @@ export class Extension implements IExten
|
||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
||||
return false;
|
||||
}
|
||||
+ // Do not update builtin extensions.
|
||||
+ if (this.type !== ExtensionType.User) {
|
||||
+ return false;
|
||||
+ }
|
||||
if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
|
||||
return false;
|
||||
}
|
||||
@@ -1122,6 +1126,10 @@ export class ExtensionsWorkbenchService
|
||||
// Skip if check updates only for builtin extensions and current extension is not builtin.
|
||||
continue;
|
||||
}
|
||||
+ if (installed.type !== ExtensionType.User) {
|
||||
+ // Never update builtin extensions.
|
||||
+ continue;
|
||||
+ }
|
||||
if (installed.isBuiltin && (!installed.local?.identifier.uuid || (!isWeb && this.productService.quality === 'stable'))) {
|
||||
// Skip checking updates for a builtin extension if it does not has Marketplace identifier or the current product is VS Code Desktop stable.
|
||||
continue;
|
||||
@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -210,6 +210,11 @@ export interface IWorkbenchConstructionO
|
||||
@@ -267,6 +267,11 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly userDataPath?: string
|
||||
|
||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -30,6 +30,11 @@ export interface IBrowserWorkbenchEnviro
|
||||
@@ -31,6 +31,11 @@ export interface IBrowserWorkbenchEnviro
|
||||
* Options used to configure the workbench.
|
||||
*/
|
||||
readonly options?: IWorkbenchConstructionOptions;
|
||||
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
}
|
||||
|
||||
export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
|
||||
@@ -61,6 +66,13 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -62,6 +67,13 @@ export class BrowserWorkbenchEnvironment
|
||||
return this.options.userDataPath;
|
||||
}
|
||||
|
||||
@@ -52,24 +52,24 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
+ }
|
||||
+
|
||||
@memoize
|
||||
get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
|
||||
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
|
||||
|
||||
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,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
'locale': { type: 'string' },
|
||||
+ 'disable-file-downloads': { type: 'boolean' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -92,6 +93,7 @@ export interface ServerParsedArgs {
|
||||
@@ -95,6 +96,7 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
'locale'?: string
|
||||
+ 'disable-file-downloads'?: boolean;
|
||||
|
||||
/* ----- server setup ----- */
|
||||
@@ -78,14 +78,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
|
||||
@@ -290,6 +290,7 @@ export class WebClientServer {
|
||||
logLevel: this._logService.getLevel(),
|
||||
},
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
@@ -304,6 +304,7 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: {
|
||||
enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@@ -7,12 +7,11 @@ import { Event } from 'vs/base/common/ev
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
|
||||
@@ -104,24 +104,24 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
@@ -24,6 +23,7 @@ import { IEditorResolverService } from '
|
||||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||
@@ -25,6 +24,7 @@ import { IPaneCompositePartService } fro
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
|
||||
+import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
|
||||
export class WorkbenchContextKeysHandler extends Disposable {
|
||||
private inputFocusedContext: IContextKey<boolean>;
|
||||
@@ -75,7 +75,7 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -76,7 +76,7 @@ export class WorkbenchContextKeysHandler
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
- @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
+ @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@@ -194,6 +194,9 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -199,6 +199,9 @@ export class WorkbenchContextKeysHandler
|
||||
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
|
||||
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
|
||||
|
||||
@@ -135,7 +135,7 @@ 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
|
||||
@@ -21,7 +21,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
|
||||
@@ -22,7 +22,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
|
||||
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
@@ -144,7 +144,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
|
||||
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
@@ -475,13 +475,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||
@@ -477,13 +477,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||
id: DOWNLOAD_COMMAND_ID,
|
||||
title: DOWNLOAD_LABEL
|
||||
},
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
Add display language support
|
||||
|
||||
This likely needs tweaking if we want to upstream.
|
||||
We can remove this once upstream supports all language packs.
|
||||
|
||||
1. Proxies language packs to the service on the backend.
|
||||
2. NLS configuration is embedded into the HTML for the browser to pick up. This
|
||||
code to generate this configuration is copied from the native portion.
|
||||
3. Remove configuredLocale since we have our own thing.
|
||||
4. Move the argv.json file to the server instead of in-browser storage. This is
|
||||
where the current locale is stored and currently the server needs to be able
|
||||
to read it.
|
||||
5. Add the locale flag.
|
||||
6. Remove the redundant locale verification. It does the same as the existing
|
||||
one but is worse because it does not handle non-existent or empty files.
|
||||
7. Replace some caching and Node requires because code-server does not restart
|
||||
when changing the language unlike native Code.
|
||||
|
||||
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
|
||||
@@ -188,6 +188,9 @@ export async function setupServerService
|
||||
@@ -212,6 +212,9 @@ export async function setupServerService
|
||||
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
|
||||
socketServer.registerChannel('extensions', channel);
|
||||
|
||||
+ const localizationsChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILocalizationsService));
|
||||
+ socketServer.registerChannel('localizations', localizationsChannel);
|
||||
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService));
|
||||
+ socketServer.registerChannel('languagePacks', languagePackChannel);
|
||||
+
|
||||
const encryptionChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(IEncryptionMainService));
|
||||
socketServer.registerChannel('encryption', encryptionChannel);
|
||||
@@ -20,11 +33,31 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/platform.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
@@ -84,6 +84,17 @@ if (typeof navigator === 'object' && !is
|
||||
@@ -2,8 +2,6 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
-import * as nls from 'vs/nls';
|
||||
-
|
||||
const LANGUAGE_DEFAULT = 'en';
|
||||
|
||||
let _isWindows = false;
|
||||
@@ -81,17 +79,19 @@ if (typeof navigator === 'object' && !is
|
||||
_isLinux = _userAgent.indexOf('Linux') >= 0;
|
||||
_isWeb = true;
|
||||
_locale = navigator.language;
|
||||
|
||||
- const configuredLocale = nls.getConfiguredDefaultLocale(
|
||||
- // This call _must_ be done in the file that calls `nls.getConfiguredDefaultLocale`
|
||||
- // to ensure that the NLS AMD Loader plugin has been loaded and configured.
|
||||
- // This is because the loader plugin decides what the default locale is based on
|
||||
- // how it's able to resolve the strings.
|
||||
- nls.localize({ key: 'ensureLoaderPluginIsLoaded', comment: ['{Locked}'] }, '_')
|
||||
- );
|
||||
-
|
||||
- _locale = configuredLocale || LANGUAGE_DEFAULT;
|
||||
+ _locale = LANGUAGE_DEFAULT;
|
||||
|
||||
_language = _locale;
|
||||
+
|
||||
+ const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration');
|
||||
+ const rawNlsConfig = el && el.getAttribute('data-settings');
|
||||
+ if (rawNlsConfig) {
|
||||
@@ -51,23 +84,31 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
+
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<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" />
|
||||
@@ -38,6 +41,27 @@
|
||||
<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
|
||||
<script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
|
||||
<script>
|
||||
+ let nlsConfig
|
||||
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
@@ -46,15 +49,26 @@
|
||||
// Set up nls if the user is not using the default language (English)
|
||||
const nlsConfig = {};
|
||||
const locale = window.localStorage.getItem('vscode.nls.locale') || navigator.language;
|
||||
- if (!locale.startsWith('en')) {
|
||||
- nlsConfig['vs/nls'] = {
|
||||
- availableLanguages: {
|
||||
- '*': locale
|
||||
- },
|
||||
- translationServiceUrl: '{{WORKBENCH_NLS_BASE_URL}}'
|
||||
- };
|
||||
- }
|
||||
-
|
||||
+ try {
|
||||
+ nlsConfig = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
|
||||
+ if (nlsConfig._resolvedLanguagePackCoreLocation) {
|
||||
+ nlsConfig['vs/nls'] = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
|
||||
+ if (nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation) {
|
||||
+ const bundles = Object.create(null)
|
||||
+ nlsConfig.loadBundle = (bundle, _language, cb) => {
|
||||
+ nlsConfig['vs/nls'].loadBundle = (bundle, _language, cb) => {
|
||||
+ const result = bundles[bundle]
|
||||
+ if (result) {
|
||||
+ return cb(undefined, result)
|
||||
+ }
|
||||
+ const path = nlsConfig._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
|
||||
+ fetch(`{{VS_BASE}}/vscode-remote-resource?path=${encodeURIComponent(path)}`)
|
||||
+ const path = nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
|
||||
+ fetch(`{{WORKBENCH_WEB_BASE_URL}}/../vscode-remote-resource?path=${encodeURIComponent(path)}`)
|
||||
+ .then((response) => response.json())
|
||||
+ .then((json) => {
|
||||
+ bundles[bundle] = json
|
||||
@@ -77,19 +118,9 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (error) { /* Probably fine. */ }
|
||||
Object.keys(self.webPackagePaths).map(function (key, index) {
|
||||
self.webPackagePaths[key] = new URL(
|
||||
`{{VS_BASE}}/static/node_modules/${key}/${self.webPackagePaths[key]}`,
|
||||
@@ -52,7 +76,8 @@
|
||||
return value;
|
||||
}
|
||||
}),
|
||||
- paths: self.webPackagePaths
|
||||
+ paths: self.webPackagePaths,
|
||||
+ 'vs/nls': nlsConfig,
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
require.config({
|
||||
baseUrl: `${baseUrl}/out`,
|
||||
recordStats: true,
|
||||
Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
@@ -173,93 +204,129 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
import { IProductConfiguration } from 'vs/base/common/product';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
+import { getLocaleFromConfig, getNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
@@ -299,6 +300,8 @@ export class WebClientServer {
|
||||
|
||||
const textMimeType = {
|
||||
'.html': 'text/html',
|
||||
@@ -277,6 +278,8 @@ export class WebClientServer {
|
||||
} : undefined;
|
||||
const base = relativeRoot(getOriginalUrl(req))
|
||||
const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
+ const locale = this._environmentService.args.locale || await getLocaleFromConfig(this._environmentService.argvResource.fsPath);
|
||||
+ const nlsConfiguration = await getNLSConfiguration(locale, this._environmentService.userDataPath)
|
||||
const data = (await util.promisify(fs.readFile)(filePath)).toString()
|
||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
|
||||
remoteAuthority,
|
||||
@@ -303,7 +306,8 @@ export class WebClientServer {
|
||||
})))
|
||||
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
|
||||
.replace(/{{BASE}}/g, base)
|
||||
- .replace(/{{VS_BASE}}/g, vscodeBase);
|
||||
+ .replace(/{{VS_BASE}}/g, vscodeBase)
|
||||
+ .replace(/{{NLS_CONFIGURATION}}/g, () => escapeAttribute(JSON.stringify(nlsConfiguration)));
|
||||
|
||||
const cspDirectives = [
|
||||
'default-src \'self\';',
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
@@ -339,6 +342,7 @@ export class WebClientServer {
|
||||
WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''),
|
||||
BASE: base,
|
||||
VS_BASE: vscodeBase,
|
||||
+ NLS_CONFIGURATION: asJSON(nlsConfiguration),
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
|
||||
/* ----- code-server ----- */
|
||||
@@ -15,6 +15,7 @@ export const serverOptions: OptionDescri
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
+ 'locale': { type: 'string' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -90,6 +91,7 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
@@ -97,6 +98,7 @@ export interface ServerParsedArgs {
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
'disable-file-downloads'?: boolean;
|
||||
+ 'locale'?: string
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
|
||||
@@ -0,0 +1,28 @@
|
||||
+/*---------------------------------------------------------------------------------------------
|
||||
+ * Copyright (c) Coder Technologies. All rights reserved.
|
||||
+ * Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
+ *--------------------------------------------------------------------------------------------*/
|
||||
+
|
||||
+import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
+import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
+import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
+
|
||||
+/**
|
||||
+ * Add localizations service for the browser.
|
||||
+ * @author coder
|
||||
+ */
|
||||
+
|
||||
+// @ts-ignore: interface is implemented via proxy
|
||||
+export class LocalizationsService implements ILocalizationsService {
|
||||
+
|
||||
+ declare readonly _serviceBrand: undefined;
|
||||
+
|
||||
+ constructor(
|
||||
+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
+ ) {
|
||||
+ return ProxyChannel.toService<ILocalizationsService>(remoteAgentService.getConnection()!.getChannel('localizations'));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+registerSingleton(ILocalizationsService, LocalizationsService, true);
|
||||
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
|
||||
@@ -111,6 +111,10 @@ registerSingleton(IDiagnosticsService, N
|
||||
@@ -122,8 +122,9 @@ import 'vs/workbench/contrib/logs/browse
|
||||
// Explorer
|
||||
import 'vs/workbench/contrib/files/browser/files.web.contribution';
|
||||
|
||||
//#region --- workbench contributions
|
||||
-// 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';
|
||||
|
||||
+// Localizations
|
||||
+import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
|
||||
+import 'vs/workbench/services/localizations/browser/localizationsService';
|
||||
// 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
|
||||
@@ -4,10 +4,23 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ILanguagePackItem, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
+import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
+import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
+import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
|
||||
export class WebLanguagePacksService extends LanguagePackBaseService {
|
||||
- // Web doesn't have a concept of language packs, so we just return an empty array
|
||||
+ private readonly languagePackService: ILanguagePackService;
|
||||
+
|
||||
// Output
|
||||
import 'vs/workbench/contrib/output/common/outputChannelModelService';
|
||||
+ constructor(
|
||||
+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
+ @IExtensionGalleryService extensionGalleryService: IExtensionGalleryService
|
||||
+ ) {
|
||||
+ super(extensionGalleryService)
|
||||
+ this.languagePackService = ProxyChannel.toService<ILanguagePackService>(remoteAgentService.getConnection()!.getChannel('languagePacks'));
|
||||
+ }
|
||||
+
|
||||
getInstalledLanguages(): Promise<ILanguagePackItem[]> {
|
||||
- return Promise.resolve([]);
|
||||
+ return this.languagePackService.getInstalledLanguages()
|
||||
}
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts
|
||||
@@ -41,7 +41,8 @@ export class NativeLocaleService impleme
|
||||
@IProductService private readonly productService: IProductService
|
||||
) { }
|
||||
|
||||
- private async validateLocaleFile(): Promise<boolean> {
|
||||
+ // Make public just so we do not have to patch all the unused code out.
|
||||
+ public async validateLocaleFile(): Promise<boolean> {
|
||||
try {
|
||||
const content = await this.textFileService.read(this.environmentService.argvResource, { encoding: 'utf8' });
|
||||
|
||||
@@ -68,9 +69,6 @@ export class NativeLocaleService impleme
|
||||
}
|
||||
|
||||
private async writeLocaleValue(locale: string | undefined): Promise<boolean> {
|
||||
- if (!(await this.validateLocaleFile())) {
|
||||
- return false;
|
||||
- }
|
||||
await this.jsonEditingService.write(this.environmentService.argvResource, [{ path: ['locale'], value: locale }], true);
|
||||
return true;
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/base/node/languagePacks.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/node/languagePacks.js
|
||||
+++ code-server/lib/vscode/src/vs/base/node/languagePacks.js
|
||||
@@ -73,7 +73,10 @@
|
||||
function getLanguagePackConfigurations(userDataPath) {
|
||||
const configFile = path.join(userDataPath, 'languagepacks.json');
|
||||
try {
|
||||
- return nodeRequire(configFile);
|
||||
+ // This must not use Node's require otherwise it will be cached forever.
|
||||
+ // Code can get away with this since the process actually restarts but
|
||||
+ // that is not currently the case with code-server.
|
||||
+ return JSON.parse(fs.readFileSync(configFile, "utf8"));
|
||||
} catch (err) {
|
||||
// Do nothing. If we can't read the file we have no
|
||||
// language pack config.
|
||||
|
||||
@@ -1,118 +1,106 @@
|
||||
Use our own GitHub auth relay server
|
||||
Add the ability to provide a GitHub token
|
||||
|
||||
Microsoft's does not work with self-hosted instances so we run our own.
|
||||
To test install the GitHub PR extension and start code-server with GITHUB_TOKEN
|
||||
or set github-auth in the config file. The extension should be authenticated.
|
||||
|
||||
Also add an extra set of scopes so that tokens provided via --github-auth will
|
||||
work for the PR extension.
|
||||
|
||||
Index: code-server/lib/vscode/extensions/github-authentication/src/githubServer.ts
|
||||
Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/extensions/github-authentication/src/githubServer.ts
|
||||
+++ code-server/lib/vscode/extensions/github-authentication/src/githubServer.ts
|
||||
@@ -17,7 +17,7 @@ const localize = nls.loadMessageBundle()
|
||||
const CLIENT_ID = '01ab8ac9400c4e429b23';
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
@@ -5,9 +5,18 @@
|
||||
|
||||
const NETWORK_ERROR = 'network error';
|
||||
-const AUTH_RELAY_SERVER = 'vscode-auth.github.com';
|
||||
+const AUTH_RELAY_SERVER = 'auth.code-server.dev';
|
||||
// const AUTH_RELAY_STAGING_SERVER = 'client-auth-staging-14a768b.herokuapp.com';
|
||||
|
||||
class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.UriHandler {
|
||||
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
|
||||
@@ -274,7 +274,7 @@ export class WebClientServer {
|
||||
id: generateUuid(),
|
||||
providerId: 'github',
|
||||
accessToken: this._environmentService.args['github-auth'],
|
||||
- scopes: [['user:email'], ['repo']]
|
||||
+ scopes: [['read:user', 'user:email', 'repo'], ['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
const base = relativeRoot(getOriginalUrl(req))
|
||||
const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
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
|
||||
@@ -17,6 +17,7 @@ import { isFolderToOpen, isWorkspaceToOp
|
||||
import { create, ICredentialsProvider, IURLCallbackProvider, IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from 'vs/workbench/workbench.web.main';
|
||||
import { posix } from 'vs/base/common/path';
|
||||
import { ltrim } from 'vs/base/common/strings';
|
||||
import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
-import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
+import { IServerEnvironmentService } from 'vs/server/node/serverEnvironmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { BaseCredentialsMainService, KeytarModule } from 'vs/platform/credentials/common/credentialsMainService';
|
||||
+import { generateUuid } from 'vs/base/common/uuid';
|
||||
+import { equals as arrayEquals } from 'vs/base/common/arrays';
|
||||
|
||||
interface ICredential {
|
||||
service: string;
|
||||
@@ -24,6 +25,13 @@ interface ICredential {
|
||||
password: string;
|
||||
}
|
||||
|
||||
+
|
||||
+interface IToken {
|
||||
+ accessToken: string
|
||||
+ account?: { label: string }
|
||||
+ id: string
|
||||
+ scopes: string[]
|
||||
+}
|
||||
+
|
||||
class LocalStorageCredentialsProvider implements ICredentialsProvider {
|
||||
|
||||
private static readonly CREDENTIALS_STORAGE_KEY = 'credentials.provider';
|
||||
@@ -51,6 +59,58 @@ class LocalStorageCredentialsProvider im
|
||||
scopes,
|
||||
accessToken: authSessionInfo!.accessToken
|
||||
}))));
|
||||
+
|
||||
+ // Add tokens for extensions to use. This works for extensions like the
|
||||
+ // pull requests one or GitLens.
|
||||
+ const extensionId = `vscode.${authSessionInfo.providerId}-authentication`;
|
||||
+ const service = `${product.urlProtocol}${extensionId}`;
|
||||
+ const account = `${authSessionInfo.providerId}.auth`;
|
||||
+ // Oddly the scopes need to match exactly so we cannot just have one token
|
||||
+ // with all the scopes, instead we have to duplicate the token for each
|
||||
+ // expected set of scopes.
|
||||
+ const tokens: IToken[] = authSessionInfo.scopes.map((scopes) => ({
|
||||
+ id: authSessionInfo!.id,
|
||||
+ scopes: scopes.sort(), // Sort for comparing later.
|
||||
+ accessToken: authSessionInfo!.accessToken,
|
||||
+ }));
|
||||
+ this.getPassword(service, account).then((raw) => {
|
||||
+ let existing: {
|
||||
+ content: IToken[]
|
||||
+ } | undefined;
|
||||
+
|
||||
+ if (raw) {
|
||||
+ try {
|
||||
+ const json = JSON.parse(raw);
|
||||
+ json.content = JSON.parse(json.content);
|
||||
+ existing = json;
|
||||
+ } catch (error) {
|
||||
+ console.log(error);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Keep tokens for account and scope combinations we do not have in case
|
||||
+ // there is an extension that uses scopes we have not accounted for (in
|
||||
+ // these cases the user will need to manually authenticate the extension
|
||||
+ // through the UI) or the user has tokens for other accounts.
|
||||
+ if (existing?.content) {
|
||||
+ existing.content = existing.content.filter((existingToken) => {
|
||||
+ const scopes = existingToken.scopes.sort();
|
||||
+ return !(tokens.find((token) => {
|
||||
+ return arrayEquals(scopes, token.scopes)
|
||||
+ && token.account?.label === existingToken.account?.label;
|
||||
+ }))
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return this.setPassword(service, account, JSON.stringify({
|
||||
+ extensionId,
|
||||
+ ...(existing || {}),
|
||||
+ content: JSON.stringify([
|
||||
+ ...tokens,
|
||||
+ ...(existing?.content || []),
|
||||
+ ])
|
||||
+ }));
|
||||
export class CredentialsWebMainService extends BaseCredentialsMainService {
|
||||
// Since we fallback to the in-memory credentials provider, we do not need to surface any Keytar load errors
|
||||
@@ -16,10 +25,15 @@ export class CredentialsWebMainService e
|
||||
|
||||
constructor(
|
||||
@ILogService logService: ILogService,
|
||||
- @INativeEnvironmentService private readonly environmentMainService: INativeEnvironmentService,
|
||||
+ @IServerEnvironmentService private readonly environmentMainService: IServerEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
) {
|
||||
super(logService);
|
||||
+ if (this.environmentMainService.args["github-auth"]) {
|
||||
+ this.storeGitHubToken(this.environmentMainService.args["github-auth"]).catch((error) => {
|
||||
+ this.logService.error('Failed to store provided GitHub token', error)
|
||||
+ })
|
||||
}
|
||||
+ }
|
||||
}
|
||||
|
||||
// If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the
|
||||
@@ -48,4 +62,59 @@ export class CredentialsWebMainService e
|
||||
}
|
||||
return this._keytarCache;
|
||||
}
|
||||
+
|
||||
+ private async storeGitHubToken(githubToken: string): Promise<void> {
|
||||
+ const extensionId = 'vscode.github-authentication';
|
||||
+ const service = `${await this.getSecretStoragePrefix()}${extensionId}`;
|
||||
+ const account = 'github.auth';
|
||||
+ const scopes = [['read:user', 'user:email', 'repo']]
|
||||
+
|
||||
+ // Oddly the scopes need to match exactly so we cannot just have one token
|
||||
+ // with all the scopes, instead we have to duplicate the token for each
|
||||
+ // expected set of scopes.
|
||||
+ const tokens: IToken[] = scopes.map((scopes) => ({
|
||||
+ id: generateUuid(),
|
||||
+ scopes: scopes.sort(), // Sort for comparing later.
|
||||
+ accessToken: githubToken,
|
||||
+ }));
|
||||
+
|
||||
+ const raw = await this.getPassword(service, account)
|
||||
+
|
||||
+ let existing: {
|
||||
+ content: IToken[]
|
||||
+ } | undefined;
|
||||
+
|
||||
+ if (raw) {
|
||||
+ try {
|
||||
+ const json = JSON.parse(raw);
|
||||
+ json.content = JSON.parse(json.content);
|
||||
+ existing = json;
|
||||
+ } catch (error) {
|
||||
+ this.logService.error('Failed to parse existing GitHub credentials', error)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Keep tokens for account and scope combinations we do not have in case
|
||||
+ // there is an extension that uses scopes we have not accounted for (in
|
||||
+ // these cases the user will need to manually authenticate the extension
|
||||
+ // through the UI) or the user has tokens for other accounts.
|
||||
+ if (existing?.content) {
|
||||
+ existing.content = existing.content.filter((existingToken) => {
|
||||
+ const scopes = existingToken.scopes.sort();
|
||||
+ return !(tokens.find((token) => {
|
||||
+ return arrayEquals(scopes, token.scopes)
|
||||
+ && token.account?.label === existingToken.account?.label;
|
||||
+ }))
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return this.setPassword(service, account, JSON.stringify({
|
||||
+ extensionId,
|
||||
+ ...(existing || {}),
|
||||
+ content: JSON.stringify([
|
||||
+ ...tokens,
|
||||
+ ...(existing?.content || []),
|
||||
+ ])
|
||||
+ }));
|
||||
+ }
|
||||
}
|
||||
|
||||
37
patches/heartbeat.diff
Normal file
@@ -0,0 +1,37 @@
|
||||
Add a heartbeat to web socket connections
|
||||
|
||||
This prevents them from being killed when they are idle. To test run behind
|
||||
NGINX, make sure the sockets are idle (check dev tools), then wait 60+ seconds.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/parts/ipc/common/ipc.net.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/parts/ipc/common/ipc.net.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/parts/ipc/common/ipc.net.ts
|
||||
@@ -7,6 +7,7 @@ import { VSBuffer } from 'vs/base/common
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IIPCLogger, IMessagePassingProtocol, IPCClient } from 'vs/base/parts/ipc/common/ipc';
|
||||
+import { isWeb } from 'vs/base/common/platform';
|
||||
|
||||
export const enum SocketDiagnosticsEventType {
|
||||
Created = 'created',
|
||||
@@ -828,6 +829,19 @@ export class PersistentProtocol implemen
|
||||
this._socketDisposables.push(this._socketWriter);
|
||||
this._socketReader = new ProtocolReader(this._socket);
|
||||
this._socketDisposables.push(this._socketReader);
|
||||
+ // Send empty messages to keep the socket alive. We only need this on the
|
||||
+ // web where sockets can be killed by reverse proxies for inactivity.
|
||||
+ if (isWeb) {
|
||||
+ const timer = setInterval(() => {
|
||||
+ const msg = new ProtocolMessage(ProtocolMessageType.None, 0, 0, getEmptyBuffer());
|
||||
+ this._socketWriter.write(msg);
|
||||
+ }, 45000); // NGINX has a 60 second default timeout so try 45 seconds.
|
||||
+ this._socketDisposables.push({
|
||||
+ dispose: () => {
|
||||
+ clearInterval(timer);
|
||||
+ },
|
||||
+ });
|
||||
+ }
|
||||
this._socketDisposables.push(this._socketReader.onMessage(msg => this._receiveMessage(msg)));
|
||||
this._socketDisposables.push(this._socket.onClose((e) => this._onSocketClose.fire(e)));
|
||||
if (initialChunk) {
|
||||
@@ -5,7 +5,12 @@ may think code-server is broken. Ideally there would be a notification at the
|
||||
point where these things are used instead of this though.
|
||||
|
||||
To test access over something like an HTTP domain or an IP address (not
|
||||
localhost).
|
||||
localhost). For example:
|
||||
|
||||
1. run code-server
|
||||
2. use ngrok to expose code-server
|
||||
3. access via HTTP
|
||||
4. look for notification in bottom right
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
|
||||
@@ -7,6 +7,7 @@ Prepare Code for integration with code-server
|
||||
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
|
||||
===================================================================
|
||||
@@ -21,7 +22,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import * as perf from 'vs/base/common/performance';
|
||||
|
||||
@@ -33,37 +33,42 @@ const errorReporter: ErrorReporter = {
|
||||
@@ -34,38 +34,43 @@ const errorReporter: ErrorReporter = {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,6 +35,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
-const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
|
||||
-const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
|
||||
-const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
|
||||
-const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
|
||||
-const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
|
||||
-args['user-data-dir'] = USER_DATA_PATH;
|
||||
-const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
|
||||
@@ -41,7 +43,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
-args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
|
||||
-args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
|
||||
-
|
||||
-[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => {
|
||||
-[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => {
|
||||
- try {
|
||||
- if (!fs.existsSync(f)) {
|
||||
- fs.mkdirSync(f, { mode: 0o700 });
|
||||
@@ -53,6 +55,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
+ const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data');
|
||||
+ const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
|
||||
+ const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
|
||||
+ const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
|
||||
+ const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
|
||||
+ args['user-data-dir'] = USER_DATA_PATH;
|
||||
+ const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
|
||||
@@ -60,14 +63,14 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
+ args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
|
||||
+ args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
|
||||
+
|
||||
+ [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => {
|
||||
+ [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => {
|
||||
+ try {
|
||||
+ if (!fs.existsSync(f)) {
|
||||
+ fs.mkdirSync(f, { mode: 0o700 });
|
||||
+ }
|
||||
+ } catch (err) { console.error(err); }
|
||||
+ });
|
||||
+ return REMOTE_DATA_FOLDER
|
||||
+ return REMOTE_DATA_FOLDER;
|
||||
+}
|
||||
|
||||
/**
|
||||
@@ -104,7 +107,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
|
||||
===================================================================
|
||||
--- 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
|
||||
@@ -143,12 +143,15 @@ export class BrowserDialogHandler implem
|
||||
@@ -143,8 +143,11 @@ export class BrowserDialogHandler implem
|
||||
|
||||
async about(): Promise<void> {
|
||||
const detailString = (useAgo: boolean): string => {
|
||||
@@ -118,11 +121,6 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
|
||||
this.productService.version || 'Unknown',
|
||||
this.productService.commit || 'Unknown',
|
||||
this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
|
||||
- navigator.userAgent
|
||||
+ navigator.userAgent,
|
||||
);
|
||||
};
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
@@ -183,10 +181,10 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
|
||||
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
|
||||
+import { CodeServerClient } from 'vs/workbench/browser/client';
|
||||
|
||||
export class BrowserMain extends Disposable {
|
||||
|
||||
@@ -103,6 +104,9 @@ export class BrowserMain extends Disposa
|
||||
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';
|
||||
@@ -116,6 +117,9 @@ export class BrowserMain extends Disposa
|
||||
// Startup
|
||||
const instantiationService = workbench.startup();
|
||||
|
||||
@@ -217,22 +215,24 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Code">
|
||||
- <link rel="apple-touch-icon" href="/code-192.png" />
|
||||
- <link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
|
||||
|
||||
<!-- 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,7 +27,8 @@
|
||||
@@ -26,8 +27,9 @@
|
||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
- <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" />
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
</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
|
||||
@@ -241,31 +241,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-title" content="Code">
|
||||
- <link rel="apple-touch-icon" href="/code-192.png" />
|
||||
- <link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
|
||||
+ <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
|
||||
|
||||
<!-- 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">
|
||||
@@ -23,7 +24,8 @@
|
||||
@@ -23,8 +24,9 @@
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
- <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" />
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
|
||||
+ <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 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
|
||||
@@ -279,6 +279,7 @@ export class WebClientServer {
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
+ codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -308,6 +308,7 @@ export class WebClientServer {
|
||||
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
|
||||
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
+ codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
Remove last opened functionality
|
||||
|
||||
This conflicts with our own handling of the last opened workspace. If we wanted
|
||||
to switch to this we would need to pass through the disable-last-opened flag and
|
||||
respect it here then remove our own redirction code that handles this.
|
||||
|
||||
Our version might be better anyway since it puts the workspace in the URL.
|
||||
|
||||
@@ -20,19 +20,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
|
||||
@@ -289,6 +289,7 @@ export class WebClientServer {
|
||||
enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
|
||||
logLevel: this._logService.getLevel(),
|
||||
},
|
||||
+ userDataPath: this._environmentService.userDataPath,
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
@@ -303,6 +303,7 @@ export class WebClientServer {
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
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,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -205,6 +205,11 @@ export interface IWorkbenchConstructionO
|
||||
@@ -262,6 +262,11 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly configurationDefaults?: Record<string, any>;
|
||||
|
||||
@@ -48,11 +48,11 @@ 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
|
||||
@@ -52,7 +52,14 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -53,7 +53,14 @@ export class BrowserWorkbenchEnvironment
|
||||
get logFile(): URI { return joinPath(this.logsHome, 'window.log'); }
|
||||
|
||||
@memoize
|
||||
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.userData }); }
|
||||
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.vscodeUserData }); }
|
||||
+ get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }
|
||||
+
|
||||
+ get userDataPath(): string {
|
||||
@@ -63,4 +63,4 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
+ }
|
||||
|
||||
@memoize
|
||||
get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
|
||||
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
|
||||
|
||||
@@ -7,15 +7,15 @@ 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
|
||||
@@ -285,7 +285,10 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
- developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
+ developmentOptions: {
|
||||
+ enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
|
||||
+ logLevel: this._logService.getLevel(),
|
||||
+ },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
@@ -304,7 +304,10 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
- developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
|
||||
+ 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,
|
||||
enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
|
||||
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
|
||||
|
||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -88,6 +89,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -93,6 +94,7 @@ export const serverOptions: OptionDescri
|
||||
export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
@@ -40,14 +40,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
|
||||
@@ -287,6 +287,7 @@ export class WebClientServer {
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
+ logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: {
|
||||
@@ -313,6 +313,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
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,
|
||||
},
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
|
||||
@@ -3,6 +3,13 @@ Add Open VSX default and an env var for marketplace, fix old marketplace
|
||||
Our old marketplace only supports `serviceUrl` but this causes the marketplace
|
||||
to be disabled entirely so this moves the template var check to fix that.
|
||||
|
||||
This also removes serverRootPath from the web extension route because that will
|
||||
include the commit. When you update code-server (including this update) the web
|
||||
extension will continue using the old path since it is stored in the browser but
|
||||
the path will 404 because the commit no longer matches. This change is only to
|
||||
support current installations though because this patch also removes the
|
||||
in-between and has web extensions install directly from the marketplace.
|
||||
|
||||
This can be tested by setting EXTENSIONS_GALLERY set to:
|
||||
|
||||
'{"serviceUrl": "https://extensions.coder.com/api"}'
|
||||
@@ -32,22 +39,49 @@ 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
|
||||
@@ -287,14 +287,14 @@ export class WebClientServer {
|
||||
rootEndpoint: base,
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
- extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
+ extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
- 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
|
||||
+ 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
scheme: 'http',
|
||||
authority: remoteAuthority,
|
||||
path: `web-extension-resource/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
||||
- }).toString(true)
|
||||
- } : undefined
|
||||
+ }).toString(true) : undefined
|
||||
+ },
|
||||
}
|
||||
})))
|
||||
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
|
||||
@@ -111,7 +111,7 @@ export class WebClientServer {
|
||||
const serverRootPath = getRemoteServerRootPath(_productService);
|
||||
this._staticRoute = `${serverRootPath}/static`;
|
||||
this._callbackRoute = `${serverRootPath}/callback`;
|
||||
- this._webExtensionRoute = `${serverRootPath}/web-extension-resource`;
|
||||
+ this._webExtensionRoute = `/web-extension-resource`;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,14 +312,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
- extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
- ...this._productService.extensionsGallery,
|
||||
- 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
|
||||
- scheme: 'http',
|
||||
- authority: remoteAuthority,
|
||||
- path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
||||
- }).toString(true)
|
||||
- } : undefined
|
||||
+ extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
callbackRoute: this._callbackRoute
|
||||
};
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
@@ -16,7 +16,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 { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
|
||||
|
||||
@@ -60,7 +59,7 @@ export abstract class AbstractExtensionR
|
||||
private readonly _environmentService: IEnvironmentService,
|
||||
private readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
- this._webExtensionResourceEndPoint = `${getRemoteServerRootPath(_productService)}/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
|
||||
+ this._webExtensionResourceEndPoint = `/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
|
||||
if (_productService.extensionsGallery) {
|
||||
this._extensionGalleryResourceUrlTemplate = _productService.extensionsGallery.resourceUrlTemplate;
|
||||
this._extensionGalleryAuthority = this._extensionGalleryResourceUrlTemplate ? this._getExtensionGalleryAuthority(URI.parse(this._extensionGalleryResourceUrlTemplate)) : undefined;
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
Patch the Node version to use the current version of Node
|
||||
|
||||
Previously it would use the yarnrc which results in builds that cannot run with
|
||||
the version of Node they were built with because the native modules are
|
||||
targeting the wrong version.
|
||||
|
||||
One way test this is to build in a fresh Docker container, run the build, then
|
||||
try opening the built-in terminal.
|
||||
|
||||
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
|
||||
@@ -124,9 +124,7 @@ const serverWithWebEntryPoints = [
|
||||
];
|
||||
|
||||
function getNodeVersion() {
|
||||
- const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8');
|
||||
- const target = /^target "(.*)"$/m.exec(yarnrc)[1];
|
||||
- return target;
|
||||
+ return process.versions.node;
|
||||
}
|
||||
|
||||
const nodeVersion = getNodeVersion();
|
||||
Index: code-server/lib/vscode/build/lib/node.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/node.js
|
||||
+++ code-server/lib/vscode/build/lib/node.js
|
||||
@@ -7,9 +7,7 @@ Object.defineProperty(exports, "__esModu
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
-const yarnrcPath = path.join(root, 'remote', '.yarnrc');
|
||||
-const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
|
||||
-const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1];
|
||||
+const version = process.versions.node;
|
||||
const platform = process.platform;
|
||||
const arch = platform === 'darwin' ? 'x64' : process.arch;
|
||||
const node = platform === 'win32' ? 'node.exe' : 'node';
|
||||
Index: code-server/lib/vscode/build/lib/node.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/node.ts
|
||||
+++ code-server/lib/vscode/build/lib/node.ts
|
||||
@@ -7,9 +7,7 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
-const yarnrcPath = path.join(root, 'remote', '.yarnrc');
|
||||
-const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
|
||||
-const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)![1];
|
||||
+const version = process.versions.node;
|
||||
|
||||
const platform = process.platform;
|
||||
const arch = platform === 'darwin' ? 'x64' : process.arch;
|
||||
Index: code-server/lib/vscode/build/lib/util.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/util.js
|
||||
+++ code-server/lib/vscode/build/lib/util.js
|
||||
@@ -298,9 +298,7 @@ function streamToPromise(stream) {
|
||||
}
|
||||
exports.streamToPromise = streamToPromise;
|
||||
function getElectronVersion() {
|
||||
- const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
|
||||
- const target = /^target "(.*)"$/m.exec(yarnrc)[1];
|
||||
- return target;
|
||||
+ return process.versions.node;
|
||||
}
|
||||
exports.getElectronVersion = getElectronVersion;
|
||||
function acquireWebNodePaths() {
|
||||
Index: code-server/lib/vscode/build/lib/util.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/util.ts
|
||||
+++ code-server/lib/vscode/build/lib/util.ts
|
||||
@@ -371,9 +371,7 @@ export function streamToPromise(stream:
|
||||
}
|
||||
|
||||
export function getElectronVersion(): string {
|
||||
- const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
|
||||
- const target = /^target "(.*)"$/m.exec(yarnrc)![1];
|
||||
- return target;
|
||||
+ return process.versions.node;
|
||||
}
|
||||
|
||||
export function acquireWebNodePaths() {
|
||||
@@ -455,4 +453,3 @@ export function buildWebNodePaths(outDir
|
||||
result.taskName = 'build-web-node-paths';
|
||||
return result;
|
||||
}
|
||||
-
|
||||
Index: code-server/lib/vscode/remote/.yarnrc
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/remote/.yarnrc
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-disturl "http://nodejs.org/dist"
|
||||
-target "14.16.0"
|
||||
-runtime "node"
|
||||
-build_from_source "true"
|
||||
Index: code-server/lib/vscode/.yarnrc
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/.yarnrc
|
||||
+++ /dev/null
|
||||
@@ -1,4 +0,0 @@
|
||||
-disturl "https://electronjs.org/headers"
|
||||
-target "13.5.2"
|
||||
-runtime "electron"
|
||||
-build_from_source "true"
|
||||
24
patches/parent-origin.diff
Normal file
@@ -0,0 +1,24 @@
|
||||
Remove parentOriginHash checko
|
||||
|
||||
This fixes webviews from not working properly due to a change upstream.
|
||||
Upstream added a check to ensure parent authority is encoded into the webview
|
||||
origin. Since our webview origin is the parent authority, we can bypass this
|
||||
check.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
|
||||
@@ -317,6 +317,12 @@ const hostMessaging = new class HostMess
|
||||
const id = searchParams.get('id');
|
||||
|
||||
const hostname = location.hostname;
|
||||
+
|
||||
+ // It is safe to run if we are on the same host.
|
||||
+ const parent = new URL(parentOrigin)
|
||||
+ if (parent.hostname == location.hostname) {
|
||||
+ return start(parentOrigin)
|
||||
+ }
|
||||
|
||||
if (!crypto.subtle) {
|
||||
// cannot validate, not running in a secure context
|
||||
@@ -1,26 +0,0 @@
|
||||
Replace rimraf with fs.rmSync in postinstall
|
||||
|
||||
The postinstall gets ran when you install with npm but rimraf is a development
|
||||
dependency so it will not exist.
|
||||
|
||||
Index: code-server/lib/vscode/extensions/postinstall.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/extensions/postinstall.js
|
||||
+++ code-server/lib/vscode/extensions/postinstall.js
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const rimraf = require('rimraf');
|
||||
|
||||
const root = path.join(__dirname, 'node_modules', 'typescript');
|
||||
|
||||
@@ -21,7 +20,7 @@ function processRoot() {
|
||||
if (!toKeep.has(name)) {
|
||||
const filePath = path.join(root, name);
|
||||
console.log(`Removed ${filePath}`);
|
||||
- rimraf.sync(filePath);
|
||||
+ fs.rmSync(filePath, { recursive: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstra
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
@@ -1163,7 +1163,7 @@ class ProposedApiController {
|
||||
@@ -1460,7 +1460,7 @@ class ProposedApiController {
|
||||
|
||||
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
|
||||
|
||||
@@ -22,7 +22,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
|
||||
@@ -134,10 +134,7 @@ export interface IExtensionHost {
|
||||
@@ -359,10 +359,7 @@ function extensionDescriptionArrayToMap(
|
||||
}
|
||||
|
||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
|
||||
@@ -26,41 +26,37 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
@@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/comm
|
||||
import { RemoteAuthorities } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
-import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
+import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { getRemoteServerRootPath, parseAuthorityWithOptionalPort } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
|
||||
|
||||
@@ -20,7 +20,7 @@ export class RemoteAuthorityResolverServ
|
||||
@@ -22,7 +22,7 @@ export class RemoteAuthorityResolverServ
|
||||
private readonly _connectionToken: string | undefined;
|
||||
private readonly _connectionTokens: Map<string, string>;
|
||||
|
||||
- constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
|
||||
+ constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
|
||||
- constructor(@IProductService productService: IProductService, connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
|
||||
+ constructor(@IProductService productService: IProductService, connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
|
||||
super();
|
||||
this._cache = new Map<string, ResolverResult>();
|
||||
this._connectionToken = connectionToken;
|
||||
@@ -59,12 +59,17 @@ export class RemoteAuthorityResolverServ
|
||||
@@ -62,9 +62,14 @@ export class RemoteAuthorityResolverServ
|
||||
|
||||
private _doResolveAuthority(authority: string): ResolverResult {
|
||||
const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
|
||||
+ let options: ResolvedOptions | undefined
|
||||
+ let options: ResolvedOptions | undefined;
|
||||
+ if (this.proxyEndpointTemplate) {
|
||||
+ const proxyUrl = new URL(this.proxyEndpointTemplate, window.location.href);
|
||||
+ options = { extensionHostEnv: { VSCODE_PROXY_URI: decodeURIComponent(proxyUrl.toString()) }}
|
||||
+ }
|
||||
if (authority.indexOf(':') >= 0) {
|
||||
const pieces = authority.split(':');
|
||||
- return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken } };
|
||||
+ return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken }, options };
|
||||
}
|
||||
const port = (/^https:/.test(window.location.href) ? 443 : 80);
|
||||
- return { authority: { authority, host: authority, port: port, connectionToken } };
|
||||
+ return { authority: { authority, host: authority, port: port, connectionToken }, options };
|
||||
const defaultPort = (/^https:/.test(window.location.href) ? 443 : 80);
|
||||
const { host, port } = parseAuthorityWithOptionalPort(authority, defaultPort);
|
||||
- return { authority: { authority, host: host, port: port, connectionToken } };
|
||||
+ return { authority: { authority, host: host, port: port, connectionToken }, options };
|
||||
}
|
||||
|
||||
_clearResolvedAuthority(authority: string): void {
|
||||
@@ -68,24 +64,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
|
||||
@@ -288,6 +288,7 @@ export class WebClientServer {
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
|
||||
+ proxyEndpointTemplate: base + '/proxy/{{port}}',
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: {
|
||||
@@ -314,6 +314,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: base + '/proxy/{{port}}',
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
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
|
||||
@@ -179,7 +179,7 @@ export class BrowserMain extends Disposa
|
||||
@@ -239,7 +239,7 @@ export class BrowserMain extends Disposa
|
||||
|
||||
// Remote
|
||||
const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);
|
||||
- const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider);
|
||||
+ const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
|
||||
- const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider);
|
||||
+ const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
|
||||
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
|
||||
|
||||
// Signing
|
||||
@@ -93,7 +89,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalE
|
||||
===================================================================
|
||||
--- 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
|
||||
@@ -390,7 +390,7 @@ export function createTerminalEnvironmen
|
||||
@@ -388,7 +388,7 @@ export async function createTerminalEnvi
|
||||
|
||||
// Sanitize the environment, removing any undesirable VS Code and Electron environment
|
||||
// variables
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
integration.diff
|
||||
node-version.diff
|
||||
base-path.diff
|
||||
proposed-api.diff
|
||||
marketplace.diff
|
||||
webview.diff
|
||||
disable-builtin-ext-update.diff
|
||||
insecure-notification.diff
|
||||
update-check.diff
|
||||
logout.diff
|
||||
store-socket.diff
|
||||
proxy-uri.diff
|
||||
display-language.diff
|
||||
github-auth.diff
|
||||
unique-db.diff
|
||||
post-install.diff
|
||||
log-level.diff
|
||||
local-storage.diff
|
||||
service-worker.diff
|
||||
connection-type.diff
|
||||
sourcemaps.diff
|
||||
disable-downloads.diff
|
||||
telemetry.diff
|
||||
display-language.diff
|
||||
cli-window-open.diff
|
||||
heartbeat.diff
|
||||
|
||||
@@ -21,17 +21,17 @@ 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
|
||||
@@ -298,6 +298,10 @@ export class WebClientServer {
|
||||
proxyEndpointTemplate: base + '/proxy/{{port}}',
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
+ serviceWorker: {
|
||||
+ scope: vscodeBase + '/',
|
||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
||||
+ },
|
||||
extensionsGallery: {
|
||||
...this._productService.extensionsGallery,
|
||||
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
|
||||
@@ -319,6 +319,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: base + '/proxy/{{port}}',
|
||||
+ serviceWorker: {
|
||||
+ scope: vscodeBase + '/',
|
||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
||||
+ },
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
|
||||
@@ -10,7 +10,7 @@ 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
|
||||
@@ -197,8 +197,7 @@ function packageTask(type, platform, arc
|
||||
@@ -194,8 +194,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'); }))
|
||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
|
||||
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
||||
const isUIExtension = (manifest) => {
|
||||
@@ -237,9 +236,9 @@ function packageTask(type, platform, arc
|
||||
@@ -234,9 +233,9 @@ function packageTask(type, platform, arc
|
||||
.map(name => `.build/extensions/${name}/**`);
|
||||
|
||||
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
|
||||
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
|
||||
let version = packageJson.version;
|
||||
const quality = product.quality;
|
||||
@@ -374,7 +373,7 @@ function tweakProductForServerWeb(produc
|
||||
@@ -371,7 +370,7 @@ function tweakProductForServerWeb(produc
|
||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
||||
optimizeTask,
|
||||
util.rimraf(`out-vscode-${type}-min`),
|
||||
|
||||
@@ -3,6 +3,12 @@ Store a static reference to the IPC socket
|
||||
This lets us use it to open files inside code-server from outside of
|
||||
code-server.
|
||||
|
||||
To test this:
|
||||
1. run code-server
|
||||
2. open file outside of code-server i.e. `code-server <path-to-file`
|
||||
|
||||
It should open in your existing code-server instance.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
@@ -18,7 +24,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
|
||||
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';
|
||||
@@ -69,6 +71,10 @@ export class ExtHostExtensionService ext
|
||||
@@ -72,6 +74,10 @@ export class ExtHostExtensionService ext
|
||||
if (this._initData.remote.isRemote && this._initData.remote.authority) {
|
||||
const cliServer = this._instaService.createInstance(CLIServer);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
|
||||
147
patches/telemetry.diff
Normal file
@@ -0,0 +1,147 @@
|
||||
Add support for telemetry endpoint
|
||||
|
||||
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
|
||||
@@ -71,6 +71,7 @@ import { IExtensionsScannerService } fro
|
||||
import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
|
||||
import { ExtensionsProfileScannerService, IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
|
||||
import { IUserDataProfilesService, UserDataProfilesService } 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';
|
||||
|
||||
@@ -133,10 +134,13 @@ export async function setupServerService
|
||||
const machineId = await getMachineId();
|
||||
const isInternal = isInternalTelemetry(productService, configurationService);
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
- if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
+ const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track";
|
||||
+ if (telemetryEndpoint) {
|
||||
+ oneDsAppender = new OneDataSystemAppender(false, eventPrefix, null, () => new TelemetryClient(telemetryEndpoint));
|
||||
+ } else if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
oneDsAppender = new OneDataSystemAppender(isInternal, eventPrefix, null, productService.aiConfig.ariaKey);
|
||||
- disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
}
|
||||
+ disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appenders: [oneDsAppender],
|
||||
Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
|
||||
@@ -0,0 +1,49 @@
|
||||
+import { AppInsightsCore, IExtendedTelemetryItem, ITelemetryItem } from '@microsoft/1ds-core-js';
|
||||
+import * as https from 'https';
|
||||
+import * as http from 'http';
|
||||
+import * as os from 'os';
|
||||
+
|
||||
+export class TelemetryClient extends AppInsightsCore {
|
||||
+ public constructor(private readonly endpoint: string) {
|
||||
+ super();
|
||||
+ }
|
||||
+
|
||||
+ public override track(item: IExtendedTelemetryItem | ITelemetryItem): void {
|
||||
+ const options = item.baseData || {}
|
||||
+ if (!options.properties) {
|
||||
+ options.properties = {};
|
||||
+ }
|
||||
+ if (!options.measurements) {
|
||||
+ options.measurements = {};
|
||||
+ }
|
||||
+
|
||||
+ try {
|
||||
+ const cpus = os.cpus();
|
||||
+ options.measurements.cores = cpus.length;
|
||||
+ options.properties['common.cpuModel'] = cpus[0].model;
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ options.measurements.memoryFree = os.freemem();
|
||||
+ options.measurements.memoryTotal = os.totalmem();
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ options.properties['common.shell'] = os.userInfo().shell;
|
||||
+ options.properties['common.release'] = os.release();
|
||||
+ options.properties['common.arch'] = os.arch();
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ const request = (/^http:/.test(this.endpoint) ? http : https).request(this.endpoint, {
|
||||
+ method: 'POST',
|
||||
+ headers: {
|
||||
+ 'Content-Type': 'application/json',
|
||||
+ },
|
||||
+ });
|
||||
+ request.on('error', () => { /* We don't care. */ });
|
||||
+ request.write(JSON.stringify(options));
|
||||
+ request.end();
|
||||
+ } catch (error) {}
|
||||
+ }
|
||||
+}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
|
||||
@@ -38,26 +38,30 @@ export class TelemetryService extends Di
|
||||
) {
|
||||
super();
|
||||
|
||||
- if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.ariaKey) {
|
||||
+ if (supportsTelemetry(productService, environmentService)) {
|
||||
// If remote server is present send telemetry through that, else use the client side appender
|
||||
const appenders = [];
|
||||
const isInternal = isInternalTelemetry(productService, configurationService);
|
||||
- const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new OneDataSystemWebAppender(isInternal, 'monacoworkbench', null, productService.aiConfig?.ariaKey);
|
||||
- appenders.push(telemetryProvider);
|
||||
- appenders.push(new TelemetryLogAppender(loggerService, environmentService));
|
||||
- const config: ITelemetryServiceConfig = {
|
||||
- appenders,
|
||||
- commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, isInternal, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties),
|
||||
- sendErrorTelemetry: this.sendErrorTelemetry,
|
||||
- };
|
||||
- this.impl = this._register(new BaseTelemetryService(config, configurationService, productService));
|
||||
+ const telemetryProvider: ITelemetryAppender | undefined = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : productService.aiConfig?.ariaKey ? new OneDataSystemWebAppender(isInternal, 'monacoworkbench', null, productService.aiConfig?.ariaKey) : undefined;
|
||||
+ if (telemetryProvider) {
|
||||
+ appenders.push(telemetryProvider);
|
||||
+ appenders.push(new TelemetryLogAppender(loggerService, environmentService));
|
||||
+ const config: ITelemetryServiceConfig = {
|
||||
+ appenders,
|
||||
+ commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, isInternal, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties),
|
||||
+ sendErrorTelemetry: this.sendErrorTelemetry,
|
||||
+ };
|
||||
+ this.impl = this._register(new BaseTelemetryService(config, configurationService, productService));
|
||||
|
||||
- if (getTelemetryLevel(configurationService) !== TelemetryLevel.NONE) {
|
||||
- // If we cannot fetch the endpoint it means it is down and we should not send any telemetry.
|
||||
- // This is most likely due to ad blockers
|
||||
- fetch(telemetryEndpointUrl, { method: 'POST' }).catch(err => {
|
||||
- this.impl = NullTelemetryService;
|
||||
- });
|
||||
+ if (remoteAgentService.getConnection() === null && getTelemetryLevel(configurationService) !== TelemetryLevel.NONE) {
|
||||
+ // If we cannot fetch the endpoint it means it is down and we should not send any telemetry.
|
||||
+ // This is most likely due to ad blockers
|
||||
+ fetch(telemetryEndpointUrl, { method: 'POST' }).catch(err => {
|
||||
+ this.impl = NullTelemetryService;
|
||||
+ });
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.impl = NullTelemetryService;
|
||||
}
|
||||
} else {
|
||||
this.impl = NullTelemetryService;
|
||||
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
|
||||
@@ -324,6 +324,7 @@ export class WebClientServer {
|
||||
scope: vscodeBase + '/',
|
||||
path: base + '/_static/out/browser/serviceWorker.js',
|
||||
},
|
||||
+ enableTelemetry: this._productService.enableTelemetry,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
@@ -14,35 +14,37 @@ code-server.
|
||||
|
||||
This has e2e tests.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
@@ -13,6 +13,7 @@ import { InMemoryStorageDatabase, isStor
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { AbstractStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
--- 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
|
||||
@@ -17,6 +17,7 @@ import { AbstractStorageService, isProfi
|
||||
import { 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 {
|
||||
|
||||
@@ -36,7 +37,11 @@ export class BrowserStorageService exten
|
||||
@@ -67,7 +68,11 @@ export class BrowserStorageService exten
|
||||
return `global-${this.profileStorageProfile.id}`;
|
||||
}
|
||||
case StorageScope.WORKSPACE:
|
||||
- return this.payload.id;
|
||||
+ // Add a unique ID based on the current path for per-workspace databases.
|
||||
+ // This prevents workspaces on different machines that share the same domain
|
||||
+ // and file path from colliding (since it does not appear IndexedDB can be
|
||||
+ // scoped to a path) as long as they are hosted on different paths.
|
||||
+ return this.payload.id + '-' + hash(location.pathname.toString().replace(/\/$/, "")).toString(16);
|
||||
}
|
||||
}
|
||||
|
||||
private getId(scope: StorageScope): string {
|
||||
- return scope === StorageScope.GLOBAL ? 'global' : this.payload.id;
|
||||
+ // Add a unique ID based on the current path for per-workspace databases.
|
||||
+ // This prevents workspaces on different machines that share the same domain
|
||||
+ // and file path from colliding (since it does not appear IndexedDB can be
|
||||
+ // scoped to a path) as long as they are hosted on different paths.
|
||||
+ return scope === StorageScope.GLOBAL ? 'global' : (this.payload.id + '-' + hash(location.pathname.toString().replace(/\/$/, "")).toString(16));
|
||||
}
|
||||
@@ -141,6 +146,25 @@ export class BrowserStorageService exten
|
||||
|
||||
protected async doInitialize(): Promise<void> {
|
||||
@@ -75,6 +80,21 @@ export class BrowserStorageService exten
|
||||
const firstWorkspaceOpen = this.workspaceStorage.getBoolean(IS_NEW_KEY);
|
||||
if (firstWorkspaceOpen === undefined) {
|
||||
this.workspaceStorage.set(IS_NEW_KEY, true);
|
||||
await this.workspaceStorage.init();
|
||||
|
||||
+ const firstWorkspaceOpen = this.workspaceStorage.getBoolean(IS_NEW_KEY);
|
||||
+ if (firstWorkspaceOpen === undefined) {
|
||||
+ // Migrate the old database.
|
||||
+ let db: IIndexedDBStorageDatabase | undefined
|
||||
+ try {
|
||||
@@ -58,6 +60,8 @@ Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||||
+ db.close()
|
||||
+ }
|
||||
+ }
|
||||
} else if (firstWorkspaceOpen) {
|
||||
this.workspaceStorage.set(IS_NEW_KEY, false);
|
||||
}
|
||||
+ }
|
||||
+
|
||||
this.updateIsNew(this.workspaceStorage);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@ Add a notification that lets you know when an update is out
|
||||
The easiest way to test this is probably to change the version in your
|
||||
package.json and delete the last notification storage item.
|
||||
|
||||
1. change version in root `package.json`
|
||||
2. Open DevTools > Application > Storage (top-level)
|
||||
3. Click "Clear site data"
|
||||
4. See update notification
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
@@ -52,7 +57,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ const lastNoti = this.storageService.getNumber('csLastUpdateNotification', StorageScope.GLOBAL);
|
||||
+ const lastNoti = this.storageService.getNumber('csLastUpdateNotification', StorageScope.APPLICATION);
|
||||
+ if (lastNoti) {
|
||||
+ // Only remind them again after 1 week.
|
||||
+ const timeout = 1000 * 60 * 60 * 24 * 7;
|
||||
@@ -62,7 +67,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ this.storageService.store('csLastUpdateNotification', Date.now(), StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
+ this.storageService.store('csLastUpdateNotification', Date.now(), StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
+
|
||||
+ this.notificationService.notify({
|
||||
+ severity: Severity.Info,
|
||||
@@ -100,14 +105,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
|
||||
@@ -286,6 +286,7 @@ export class WebClientServer {
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
rootEndpoint: base,
|
||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: {
|
||||
@@ -312,6 +312,7 @@ export class WebClientServer {
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -121,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -84,6 +86,8 @@ export const serverOptions: OptionDescri
|
||||
@@ -89,6 +91,8 @@ export const serverOptions: OptionDescri
|
||||
};
|
||||
|
||||
export interface ServerParsedArgs {
|
||||
|
||||
@@ -15,62 +15,103 @@ Since this code exists only for the authentication case we can just skip it when
|
||||
it is served from the current host as authentication is not a problem if the
|
||||
request is not cross-origin.
|
||||
|
||||
There is also an origin check we bypass (this seems to be related to how the
|
||||
webview host is separate by default but we serve on the same host).
|
||||
|
||||
To test, open a few types of webviews (images, markdown, extension details, etc).
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
===================================================================
|
||||
--- 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
|
||||
@@ -176,7 +176,7 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -177,7 +177,7 @@ export class BrowserWorkbenchEnvironment
|
||||
|
||||
@memoize
|
||||
get webviewExternalEndpoint(): string {
|
||||
- const endpoint = this.options.webviewEndpoint
|
||||
+ const endpoint = (this.options.webviewEndpoint && new URL(this.options.webviewEndpoint, window.location.toString()).toString())
|
||||
|| this.productService.webviewContentExternalBaseUrlTemplate
|
||||
|| 'https://{{uuid}}.vscode-webview.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
|
||||
|| 'https://{{uuid}}.vscode-cdn.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
|
||||
|
||||
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
|
||||
@@ -280,6 +280,7 @@ export class WebClientServer {
|
||||
const data = (await util.promisify(fs.readFile)(filePath)).toString()
|
||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
|
||||
remoteAuthority,
|
||||
+ webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/common/webview.ts
|
||||
@@ -302,6 +302,7 @@ export class WebClientServer {
|
||||
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
+ webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/webview.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/webview.ts
|
||||
@@ -24,7 +24,7 @@ export const webviewResourceBaseHost = '
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
|
||||
export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
- content="default-src 'none'; script-src 'sha256-JpX/ganPoxpavjxWCz9DUZgwVZ59o2lwSYTQrziPsdU=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
+ content="default-src 'none'; script-src 'sha256-BRi/ZOLWtsisl3jAheglVzKmoA1T6n2Mmf2NM4UnIXE=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
|
||||
-export const webviewGenericCspSource = `https://*.${webviewResourceBaseHost}`;
|
||||
+export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost}`;
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport"
|
||||
@@ -331,6 +331,12 @@
|
||||
|
||||
/**
|
||||
* Construct a uri that can load resources inside a webview
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/service-worker.js
|
||||
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(`Cannot validate in current context!`);
|
||||
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/service-worker.js
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/service-worker.js
|
||||
@@ -188,9 +188,11 @@ sw.addEventListener('fetch', (event) =>
|
||||
--- 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
|
||||
@@ -330,6 +330,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(`Cannot validate in current context!`);
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta http-equiv="Content-Security-Policy" content="
|
||||
default-src 'none';
|
||||
child-src 'self' data: blob:;
|
||||
- script-src 'self' 'unsafe-eval' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' https:;
|
||||
+ script-src 'self' 'unsafe-eval' 'sha256-TkIM/TmudlFEe0ZRp0ptvN54LClwk30Rql4ZPE0hm/I=' https:;
|
||||
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
||||
</head>
|
||||
<body>
|
||||
@@ -23,6 +23,13 @@
|
||||
// validation not requested
|
||||
return start();
|
||||
}
|
||||
}
|
||||
|
||||
- // If we're making a request against the remote authority, we want to go
|
||||
- // back through VS Code itself so that we are authenticated properly
|
||||
- if (requestUrl.host === remoteAuthority) {
|
||||
+ // If we're making a request against the remote authority, we want to go back
|
||||
+ // through VS Code itself so that we are authenticated properly. If the
|
||||
+ // service worker is hosted on the same origin we will have cookies and
|
||||
+ // authentication will not be an issue.
|
||||
+ if (requestUrl.origin !== sw.origin && requestUrl.host === remoteAuthority) {
|
||||
switch (event.request.method) {
|
||||
case 'GET':
|
||||
case 'HEAD':
|
||||
+
|
||||
+ // It is safe to run if we are on the same host.
|
||||
+ const parent = new URL(parentOrigin)
|
||||
+ if (parent.hostname === hostname) {
|
||||
+ return start()
|
||||
+ }
|
||||
+
|
||||
if (!crypto.subtle) {
|
||||
// cannot validate, not running in a secure context
|
||||
return sendError(new Error(`Cannot validate in current context!`));
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
/**
|
||||
* Split a string up to the delimiter. If the delimiter doesn't exist the first
|
||||
* item will have all the text and the second item will be an empty string.
|
||||
*/
|
||||
export const split = (str: string, delimiter: string): [string, string] => {
|
||||
const index = str.indexOf(delimiter)
|
||||
return index !== -1 ? [str.substring(0, index).trim(), str.substring(index + 1)] : [str, ""]
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an 's' to the provided string if count is greater than one;
|
||||
* otherwise the string is returned
|
||||
@@ -34,27 +25,6 @@ export const normalize = (url: string, keepTrailing = false): string => {
|
||||
return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "")
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove leading and trailing slashes.
|
||||
*/
|
||||
export const trimSlashes = (url: string): string => {
|
||||
return url.replace(/^\/+|\/+$/g, "")
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the value in an array if it's not already an array. If the value is
|
||||
* undefined return an empty array.
|
||||
*/
|
||||
export const arrayify = <T>(value?: T | T[]): T[] => {
|
||||
if (Array.isArray(value)) {
|
||||
return value
|
||||
}
|
||||
if (typeof value === "undefined") {
|
||||
return []
|
||||
}
|
||||
return [value]
|
||||
}
|
||||
|
||||
// TODO: Might make sense to add Error handling to the logger itself.
|
||||
export function logError(logger: { error: (msg: string) => void }, prefix: string, err: unknown): void {
|
||||
if (err instanceof Error) {
|
||||
|
||||
@@ -94,36 +94,14 @@ export const ensureAddress = (server: http.Server, protocol: string): URL | stri
|
||||
}
|
||||
|
||||
if (typeof addr !== "string") {
|
||||
return new URL(`${protocol}://${addr.address}:${addr.port}`)
|
||||
const host = addr.family === "IPv6" ? `[${addr.address}]` : addr.address
|
||||
return new URL(`${protocol}://${host}:${addr.port}`)
|
||||
}
|
||||
|
||||
// If this is a string then it is a pipe or Unix socket.
|
||||
return addr
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles error events from the server.
|
||||
*
|
||||
* If the outlying Promise didn't resolve
|
||||
* then we reject with the error.
|
||||
*
|
||||
* Otherwise, we log the error.
|
||||
*
|
||||
* We extracted into a function so that we could
|
||||
* test this logic more easily.
|
||||
*/
|
||||
export const handleServerError = (resolved: boolean, err: Error, reject: (err: Error) => void) => {
|
||||
// Promise didn't resolve earlier so this means it's an error
|
||||
// that occurs before the server can successfully listen.
|
||||
// Possibly triggered by listening on an invalid port or socket.
|
||||
if (!resolved) {
|
||||
reject(err)
|
||||
} else {
|
||||
// Promise resolved earlier so this is an unrelated error.
|
||||
util.logError(logger, "http server error", err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the error that occurs in the catch block
|
||||
* after we try fs.unlink(args.socket).
|
||||
|
||||
@@ -160,7 +160,8 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
},
|
||||
"disable-file-downloads": {
|
||||
type: "boolean",
|
||||
description: "Disable file downloads from Code.",
|
||||
description:
|
||||
"Disable file downloads from Code. This can also be set with CS_DISABLE_FILE_DOWNLOADS set to 'true' or '1'.",
|
||||
},
|
||||
// --enable can be used to enable experimental features. These features
|
||||
// provide no guarantees.
|
||||
@@ -542,7 +543,7 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args.password = process.env.PASSWORD
|
||||
}
|
||||
|
||||
if (process.env.CS_DISABLE_FILE_DOWNLOADS === "1") {
|
||||
if (process.env.CS_DISABLE_FILE_DOWNLOADS?.match(/^(1|true)$/)) {
|
||||
args["disable-file-downloads"] = true
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ import type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
|
||||
export const WORKBENCH_WEB_CONFIG_ID = "vscode-workbench-web-configuration"
|
||||
|
||||
export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles {
|
||||
let pkg = {}
|
||||
try {
|
||||
@@ -21,7 +19,6 @@ export const vsRootPath = path.join(rootPath, "lib/vscode")
|
||||
const PACKAGE_JSON = "package.json"
|
||||
const pkg = getPackageJson(`${rootPath}/${PACKAGE_JSON}`)
|
||||
const codePkg = getPackageJson(`${vsRootPath}/${PACKAGE_JSON}`) || { version: "0.0.0" }
|
||||
export const pkgName = pkg.name || "code-server"
|
||||
export const version = pkg.version || "development"
|
||||
export const commit = pkg.commit || "development"
|
||||
export const codeVersion = codePkg.version || "development"
|
||||
|
||||
@@ -9,7 +9,10 @@ export class Heart {
|
||||
private heartbeatInterval = 60000
|
||||
public lastHeartbeat = 0
|
||||
|
||||
public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise<boolean>) {}
|
||||
public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise<boolean>) {
|
||||
this.beat = this.beat.bind(this)
|
||||
this.alive = this.alive.bind(this)
|
||||
}
|
||||
|
||||
public alive(): boolean {
|
||||
const now = Date.now()
|
||||
@@ -20,30 +23,22 @@ export class Heart {
|
||||
* timeout and start or reset a timer that keeps running as long as there is
|
||||
* activity. Failures are logged as warnings.
|
||||
*/
|
||||
public beat(): void {
|
||||
public async beat(): Promise<void> {
|
||||
if (this.alive()) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.trace("heartbeat")
|
||||
fs.writeFile(this.heartbeatPath, "").catch((error) => {
|
||||
logger.warn(error.message)
|
||||
})
|
||||
this.lastHeartbeat = Date.now()
|
||||
if (typeof this.heartbeatTimer !== "undefined") {
|
||||
clearTimeout(this.heartbeatTimer)
|
||||
}
|
||||
this.heartbeatTimer = setTimeout(() => {
|
||||
this.isActive()
|
||||
.then((active) => {
|
||||
if (active) {
|
||||
this.beat()
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.warn(error.message)
|
||||
})
|
||||
}, this.heartbeatInterval)
|
||||
this.heartbeatTimer = setTimeout(() => heartbeatTimer(this.isActive, this.beat), this.heartbeatInterval)
|
||||
try {
|
||||
return await fs.writeFile(this.heartbeatPath, "")
|
||||
} catch (error: any) {
|
||||
logger.warn(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,3 +50,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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
||||
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
|
||||
// it look like code-server is always in use.
|
||||
if (!/^\/healthz\/?$/.test(req.url)) {
|
||||
// NOTE@jsjoeio - intentionally not awaiting the .beat() call here because
|
||||
// we don't want to slow down the request.
|
||||
heart.beat()
|
||||
}
|
||||
|
||||
@@ -92,8 +94,8 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
||||
app.router.use("/", domainProxy.router)
|
||||
app.wsRouter.use("/", domainProxy.wsRouter.router)
|
||||
|
||||
app.router.all("/proxy/(:port)(/*)?", (req, res) => {
|
||||
pathProxy.proxy(req, res)
|
||||
app.router.all("/proxy/(:port)(/*)?", async (req, res) => {
|
||||
await pathProxy.proxy(req, res)
|
||||
})
|
||||
app.wsRouter.get("/proxy/(:port)(/*)?", async (req) => {
|
||||
await pathProxy.wsProxy(req as pluginapi.WebsocketRequest)
|
||||
@@ -101,8 +103,8 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
||||
// These two routes pass through the path directly.
|
||||
// So the proxied app must be aware it is running
|
||||
// under /absproxy/<someport>/
|
||||
app.router.all("/absproxy/(:port)(/*)?", (req, res) => {
|
||||
pathProxy.proxy(req, res, {
|
||||
app.router.all("/absproxy/(:port)(/*)?", async (req, res) => {
|
||||
await pathProxy.proxy(req, res, {
|
||||
passthroughPath: true,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -14,14 +14,14 @@ const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
|
||||
return `http://0.0.0.0:${req.params.port}/${req.params[0] || ""}${query ? `?${query}` : ""}`
|
||||
}
|
||||
|
||||
export function proxy(
|
||||
export async function proxy(
|
||||
req: Request,
|
||||
res: Response,
|
||||
opts?: {
|
||||
passthroughPath?: boolean
|
||||
},
|
||||
): void {
|
||||
if (!authenticated(req)) {
|
||||
): Promise<void> {
|
||||
if (!(await authenticated(req))) {
|
||||
// If visiting the root (/:port only) redirect to the login page.
|
||||
if (!req.params[0] || req.params[0] === "/") {
|
||||
const to = self(req)
|
||||
|
||||
@@ -127,7 +127,10 @@ export class CodeServerRouteWrapper {
|
||||
|
||||
private $proxyWebsocket = async (req: WebsocketRequest) => {
|
||||
const wrappedSocket = await this._socketProxyProvider.createProxy(req.ws)
|
||||
this._codeServerMain.handleUpgrade(req, wrappedSocket)
|
||||
// This should actually accept a duplex stream but it seems Code has not
|
||||
// been updated to match the Node 16 types so cast for now. There does not
|
||||
// appear to be any code specific to sockets so this should be fine.
|
||||
this._codeServerMain.handleUpgrade(req, wrappedSocket as net.Socket)
|
||||
|
||||
req.ws.resume()
|
||||
}
|
||||
@@ -170,9 +173,9 @@ export class CodeServerRouteWrapper {
|
||||
|
||||
constructor() {
|
||||
this.router.get("/", this.ensureCodeServerLoaded, this.$root)
|
||||
this.router.get(/manifest.json$/, this.manifest)
|
||||
this.router.get("/manifest.json", this.manifest)
|
||||
this.router.all("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyRequest)
|
||||
this._wsRouterWrapper.ws("/", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
|
||||
this._wsRouterWrapper.ws("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { promises as fs } from "fs"
|
||||
import * as net from "net"
|
||||
import * as path from "path"
|
||||
import * as stream from "stream"
|
||||
import * as tls from "tls"
|
||||
import { Emitter } from "../common/emitter"
|
||||
import { generateUuid } from "../common/util"
|
||||
@@ -27,10 +28,13 @@ export class SocketProxyProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a socket proxy for TLS sockets. If it's not a TLS socket the
|
||||
* original socket is returned. This will spawn a proxy server on demand.
|
||||
* Create a socket proxy for TLS sockets. If it is not a TLS socket the
|
||||
* original socket or stream is returned. This will spawn a proxy server on
|
||||
* demand.
|
||||
*/
|
||||
public async createProxy(socket: net.Socket): Promise<net.Socket> {
|
||||
public async createProxy(socket: tls.TLSSocket | net.Socket): Promise<net.Socket>
|
||||
public async createProxy(socket: stream.Duplex): Promise<stream.Duplex>
|
||||
public async createProxy(socket: tls.TLSSocket | net.Socket | stream.Duplex): Promise<net.Socket | stream.Duplex> {
|
||||
if (!(socket instanceof tls.TLSSocket)) {
|
||||
return socket
|
||||
}
|
||||
@@ -77,7 +81,7 @@ export class SocketProxyProvider {
|
||||
this.proxyPipe = pipe
|
||||
return Promise.all([
|
||||
fs.mkdir(path.dirname(this.proxyPipe), { recursive: true }),
|
||||
fs.rmdir(this.proxyPipe, { recursive: true }),
|
||||
fs.rm(this.proxyPipe, { force: true, recursive: true }),
|
||||
])
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
100
src/node/util.ts
@@ -377,11 +377,62 @@ export const getMediaMime = (filePath?: string): string => {
|
||||
return (filePath && mimeTypes[path.extname(filePath)]) || "text/plain"
|
||||
}
|
||||
|
||||
export const isWsl = async (): Promise<boolean> => {
|
||||
return (
|
||||
(process.platform === "linux" && os.release().toLowerCase().indexOf("microsoft") !== -1) ||
|
||||
(await fs.readFile("/proc/version", "utf8")).toLowerCase().indexOf("microsoft") !== -1
|
||||
)
|
||||
/**
|
||||
* A helper function that checks if the platform is Windows Subsystem for Linux
|
||||
* (WSL)
|
||||
*
|
||||
* @see https://github.com/sindresorhus/is-wsl/blob/main/index.js
|
||||
* @returns {Boolean} boolean if it is WSL
|
||||
*/
|
||||
export const isWsl = async (
|
||||
platform: NodeJS.Platform,
|
||||
osRelease: string,
|
||||
procVersionFilePath: string,
|
||||
): Promise<boolean> => {
|
||||
if (platform !== "linux") {
|
||||
return false
|
||||
}
|
||||
|
||||
if (osRelease.toLowerCase().includes("microsoft")) {
|
||||
return true
|
||||
}
|
||||
|
||||
try {
|
||||
return (await fs.readFile(procVersionFilePath, "utf8")).toLowerCase().includes("microsoft")
|
||||
} catch (_) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
interface OpenOptions {
|
||||
args: string[]
|
||||
command: string
|
||||
urlSearch: string
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to construct options for `open` function.
|
||||
*
|
||||
* Extract to make it easier to test.
|
||||
*
|
||||
* @param platform - platform on machine
|
||||
* @param urlSearch - url.search
|
||||
* @returns an object with args, command, options and urlSearch
|
||||
*/
|
||||
export function constructOpenOptions(platform: NodeJS.Platform | "wsl", urlSearch: string): OpenOptions {
|
||||
const args: string[] = []
|
||||
let command = platform === "darwin" ? "open" : "xdg-open"
|
||||
if (platform === "win32" || platform === "wsl") {
|
||||
command = platform === "wsl" ? "cmd.exe" : "cmd"
|
||||
args.push("/c", "start", '""', "/b")
|
||||
urlSearch = urlSearch.replace(/&/g, "^&")
|
||||
}
|
||||
|
||||
return {
|
||||
args,
|
||||
command,
|
||||
urlSearch,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -396,16 +447,10 @@ export const open = async (address: URL | string): Promise<void> => {
|
||||
if (url.hostname === "0.0.0.0") {
|
||||
url.hostname = "localhost"
|
||||
}
|
||||
const args = [] as string[]
|
||||
const options = {} as cp.SpawnOptions
|
||||
const platform = (await isWsl()) ? "wsl" : process.platform
|
||||
let command = platform === "darwin" ? "open" : "xdg-open"
|
||||
if (platform === "win32" || platform === "wsl") {
|
||||
command = platform === "wsl" ? "cmd.exe" : "cmd"
|
||||
args.push("/c", "start", '""', "/b")
|
||||
url.search = url.search.replace(/&/g, "^&")
|
||||
}
|
||||
const proc = cp.spawn(command, [...args, url.toString()], options)
|
||||
const platform = (await isWsl(process.platform, os.release(), "/proc/version")) ? "wsl" : process.platform
|
||||
const { command, args, urlSearch } = constructOpenOptions(platform, url.search)
|
||||
url.search = urlSearch
|
||||
const proc = cp.spawn(command, [...args, url.toString()], {})
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
proc.on("error", reject)
|
||||
proc.on("close", (code) => {
|
||||
@@ -414,31 +459,6 @@ export const open = async (address: URL | string): Promise<void> => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* For iterating over an enum's values.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const enumToArray = (t: any): string[] => {
|
||||
const values = [] as string[]
|
||||
for (const k in t) {
|
||||
values.push(t[k])
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
/**
|
||||
* For displaying all allowed options in an enum.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const buildAllowedMessage = (t: any): string => {
|
||||
const values = enumToArray(t)
|
||||
return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(", ")}`
|
||||
}
|
||||
|
||||
export const isObject = <T extends object>(obj: T): obj is T => {
|
||||
return !Array.isArray(obj) && typeof obj === "object" && obj !== null
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise that resolves with whether the socket path is active.
|
||||
*/
|
||||
|
||||
@@ -203,8 +203,9 @@ class ChildProcess extends Process {
|
||||
|
||||
/**
|
||||
* Parent process wrapper that spawns the child process and performs a handshake
|
||||
* with it. Will relaunch the child if it receives a SIGUSR1 or is asked to by
|
||||
* the child. If the child otherwise exits the parent will also exit.
|
||||
* with it. Will relaunch the child if it receives a SIGUSR1 or SIGUSR2 or is
|
||||
* asked to by the child. If the child otherwise exits the parent will also
|
||||
* exit.
|
||||
*/
|
||||
export class ParentProcess extends Process {
|
||||
public logger = logger.named(`parent:${process.pid}`)
|
||||
@@ -227,6 +228,11 @@ export class ParentProcess extends Process {
|
||||
this.relaunch()
|
||||
})
|
||||
|
||||
process.on("SIGUSR2", async () => {
|
||||
this.logger.info("Received SIGUSR2; hotswapping")
|
||||
this.relaunch()
|
||||
})
|
||||
|
||||
const opts = {
|
||||
size: "10M",
|
||||
maxFiles: 10,
|
||||
@@ -286,14 +292,18 @@ export class ParentProcess extends Process {
|
||||
const child = this.spawn()
|
||||
this.child = child
|
||||
|
||||
// Log both to stdout and to the log directory.
|
||||
// Log child output to stdout/stderr and to the log directory.
|
||||
if (child.stdout) {
|
||||
child.stdout.pipe(this.logStdoutStream)
|
||||
child.stdout.pipe(process.stdout)
|
||||
child.stdout.on("data", (data) => {
|
||||
this.logStdoutStream.write(data)
|
||||
process.stdout.write(data)
|
||||
})
|
||||
}
|
||||
if (child.stderr) {
|
||||
child.stderr.pipe(this.logStderrStream)
|
||||
child.stderr.pipe(process.stderr)
|
||||
child.stderr.on("data", (data) => {
|
||||
this.logStderrStream.write(data)
|
||||
process.stderr.write(data)
|
||||
})
|
||||
}
|
||||
|
||||
this.logger.debug(`spawned inner process ${child.pid}`)
|
||||
@@ -312,7 +322,6 @@ export class ParentProcess extends Process {
|
||||
env: {
|
||||
...process.env,
|
||||
CODE_SERVER_PARENT_PID: process.pid.toString(),
|
||||
NODE_OPTIONS: `--max-old-space-size=2048 ${process.env.NODE_OPTIONS || ""}`,
|
||||
},
|
||||
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
||||
})
|
||||
|
||||
@@ -8,13 +8,14 @@ export const handleUpgrade = (app: express.Express, server: http.Server): void =
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
socket.pause()
|
||||
|
||||
req.ws = socket
|
||||
req.head = head
|
||||
req._ws_handled = false
|
||||
const wreq = req as InternalWebsocketRequest
|
||||
wreq.ws = socket
|
||||
wreq.head = head
|
||||
wreq._ws_handled = false
|
||||
|
||||
// Send the request off to be handled by Express.
|
||||
;(app as any).handle(req, new http.ServerResponse(req), () => {
|
||||
if (!req._ws_handled) {
|
||||
;(app as any).handle(wreq, new http.ServerResponse(wreq), () => {
|
||||
if (!wreq._ws_handled) {
|
||||
socket.end("HTTP/1.1 404 Not Found\r\n\r\n")
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { field, logger } from "@coder/logger"
|
||||
import { test as base } from "@playwright/test"
|
||||
import { CodeServer, CodeServerPage } from "./models/CodeServer"
|
||||
|
||||
@@ -11,14 +10,13 @@ import { CodeServer, CodeServerPage } from "./models/CodeServer"
|
||||
*/
|
||||
export const describe = (
|
||||
name: string,
|
||||
includeCredentials: boolean,
|
||||
codeServerArgs: string[],
|
||||
codeServerEnv: NodeJS.ProcessEnv,
|
||||
fn: (codeServer: CodeServer) => void,
|
||||
) => {
|
||||
test.describe(name, () => {
|
||||
// This will spawn on demand so nothing is necessary on before.
|
||||
const codeServer = new CodeServer(name, codeServerArgs, codeServerEnv)
|
||||
const codeServer = new CodeServer(name, codeServerArgs, codeServerEnv, undefined)
|
||||
|
||||
// Kill code-server after the suite has ended. This may happen even without
|
||||
// doing it explicitly but it seems prudent to be sure.
|
||||
@@ -26,22 +24,10 @@ export const describe = (
|
||||
await codeServer.close()
|
||||
})
|
||||
|
||||
const storageState = JSON.parse(process.env.STORAGE || "{}")
|
||||
|
||||
// Sanity check to ensure the cookie is set.
|
||||
const cookies = storageState?.cookies
|
||||
if (includeCredentials && (!cookies || cookies.length !== 1 || !!cookies[0].key)) {
|
||||
logger.error("no cookies", field("storage", JSON.stringify(cookies)))
|
||||
throw new Error("no credentials to include")
|
||||
}
|
||||
|
||||
test.use({
|
||||
// Makes `codeServer` and `authenticated` available to the extend call
|
||||
// below.
|
||||
codeServer,
|
||||
authenticated: includeCredentials,
|
||||
// This provides a cookie that authenticates with code-server.
|
||||
storageState: includeCredentials ? storageState : {},
|
||||
// NOTE@jsjoeio some tests use --cert which uses a self-signed certificate
|
||||
// without this option, those tests will fail.
|
||||
ignoreHTTPSErrors: true,
|
||||
@@ -52,7 +38,6 @@ export const describe = (
|
||||
}
|
||||
|
||||
interface TestFixtures {
|
||||
authenticated: boolean
|
||||
codeServer: CodeServer
|
||||
codeServerPage: CodeServerPage
|
||||
}
|
||||
@@ -62,15 +47,14 @@ interface TestFixtures {
|
||||
* ready.
|
||||
*/
|
||||
export const test = base.extend<TestFixtures>({
|
||||
authenticated: false,
|
||||
codeServer: undefined, // No default; should be provided through `test.use`.
|
||||
codeServerPage: async ({ authenticated, codeServer, page }, use) => {
|
||||
codeServerPage: async ({ codeServer, page }, use) => {
|
||||
// It's possible code-server might prevent navigation because of unsaved
|
||||
// changes (seems to happen based on timing even if no changes have been
|
||||
// made too). In these cases just accept.
|
||||
page.on("dialog", (d) => d.accept())
|
||||
|
||||
const codeServerPage = new CodeServerPage(codeServer, page, authenticated)
|
||||
const codeServerPage = new CodeServerPage(codeServer, page)
|
||||
await codeServerPage.navigate()
|
||||
await use(codeServerPage)
|
||||
},
|
||||
|
||||
@@ -3,10 +3,11 @@ import { promises as fs } from "fs"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import * as util from "util"
|
||||
import { getMaybeProxiedCodeServer } from "../utils/helpers"
|
||||
import { describe, test, expect } from "./baseFixture"
|
||||
import { CodeServer } from "./models/CodeServer"
|
||||
|
||||
describe("code-server", true, [], {}, () => {
|
||||
describe("code-server", [], {}, () => {
|
||||
// TODO@asher: Generalize this? Could be nice if we were to ever need
|
||||
// multiple migration tests in other suites.
|
||||
const instances = new Map<string, CodeServer>()
|
||||
@@ -48,7 +49,8 @@ describe("code-server", true, [], {}, () => {
|
||||
const url = codeServerPage.page.url()
|
||||
// We use match because there may be a / at the end
|
||||
// so we don't want it to fail if we expect http://localhost:8080 to match http://localhost:8080/
|
||||
expect(url).toMatch(await codeServerPage.address())
|
||||
const address = await getMaybeProxiedCodeServer(codeServerPage)
|
||||
expect(url).toMatch(address)
|
||||
})
|
||||
|
||||
test("should always see the code-server editor", async ({ codeServerPage }) => {
|
||||
@@ -70,7 +72,9 @@ describe("code-server", true, [], {}, () => {
|
||||
test("should migrate state to avoid collisions", async ({ codeServerPage }) => {
|
||||
// This can take a very long time in development because of how long pages
|
||||
// take to load and we are doing a lot of that here.
|
||||
test.slow()
|
||||
if (process.env.VSCODE_DEV === "1") {
|
||||
test.slow()
|
||||
}
|
||||
|
||||
const dir = await codeServerPage.workspaceDir
|
||||
const files = [path.join(dir, "foo"), path.join(dir, "bar")]
|
||||
@@ -90,6 +94,7 @@ describe("code-server", true, [], {}, () => {
|
||||
// domain and can write to the same database.
|
||||
const cs = await spawn("4.0.2", dir)
|
||||
const address = new URL(await cs.address())
|
||||
|
||||
await codeServerPage.navigate("/proxy/" + address.port + "/")
|
||||
await codeServerPage.openFile(files[1])
|
||||
expect(await codeServerPage.tabIsVisible(files[0])).toBe(false)
|
||||
|
||||