mirror of
https://github.com/coder/code-server.git
synced 2026-10-30 18:22:02 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
279b5702aa | ||
|
|
27baccf843 | ||
|
|
8aab1b0d72 | ||
|
|
777c493a9b | ||
|
|
f07405cba3 | ||
|
|
c5fee2d2f9 | ||
|
|
83670e50c6 | ||
|
|
41cf6f7eaf | ||
|
|
78aad47ce6 | ||
|
|
8b41915d25 | ||
|
|
6d7b6f8a17 | ||
|
|
be95e9f163 | ||
|
|
317a591ed7 | ||
|
|
5244097e99 | ||
|
|
8a1f2e3d55 | ||
|
|
8b20b3e128 | ||
|
|
b43e8a3dd1 | ||
|
|
48b45385f7 | ||
|
|
74571ff255 | ||
|
|
04ab55c4f2 | ||
|
|
8be4df7ab0 | ||
|
|
067f1e35dd | ||
|
|
ccc19adc2e | ||
|
|
f871c1663b | ||
|
|
fa7caee4dd | ||
|
|
2bb012c17a | ||
|
|
96e468eaa6 | ||
|
|
53c2f3253b | ||
|
|
8a7bf87a4d | ||
|
|
cd0f21dc72 | ||
|
|
59c988c744 | ||
|
|
ef5eba4348 | ||
|
|
20a260f748 | ||
|
|
729815064f | ||
|
|
771a637516 | ||
|
|
b11dabdaca | ||
|
|
7f25500e74 | ||
|
|
ebc25530a2 | ||
|
|
c218591a83 | ||
|
|
e57e399b41 | ||
|
|
61ad19ca2a | ||
|
|
b262510fd8 | ||
|
|
bcfff05ae9 | ||
|
|
dc044303c7 | ||
|
|
8ab0bec5f3 | ||
|
|
8604302ded | ||
|
|
9219c40229 | ||
|
|
ca7a314339 | ||
|
|
0bb6a31fb0 | ||
|
|
0e439cb9dc | ||
|
|
75d7e662b4 | ||
|
|
716a4eedbe | ||
|
|
577da3111f | ||
|
|
8f2983bab5 | ||
|
|
6f23ab892b | ||
|
|
76f7789303 | ||
|
|
9d72dceac6 | ||
|
|
53692fd9fd | ||
|
|
f1dde9b093 | ||
|
|
8c8476eb76 | ||
|
|
322f065cf0 | ||
|
|
8d5f383f30 | ||
|
|
c9b1fa2e16 | ||
|
|
00672a5522 | ||
|
|
62284ed549 | ||
|
|
11699e6cd7 | ||
|
|
2b2f8b3d5c | ||
|
|
de89acbcdc | ||
|
|
e08e907889 | ||
|
|
92f44d9c7b | ||
|
|
88c2b7432e | ||
|
|
4cb856c475 | ||
|
|
2d5dbf0b77 | ||
|
|
7833136337 | ||
|
|
1735f6d3fb | ||
|
|
0a7b4b1e16 | ||
|
|
fa4426393e | ||
|
|
04ce2301a7 | ||
|
|
2edeb1c991 | ||
|
|
02badb2056 | ||
|
|
fb43d02d10 | ||
|
|
b9653442b3 | ||
|
|
30852bb006 | ||
|
|
f69d40ce6f | ||
|
|
876304f95f | ||
|
|
c22dc74d53 | ||
|
|
d2f7a12252 | ||
|
|
596dbf3416 | ||
|
|
51f90a376b | ||
|
|
29785ddfba | ||
|
|
313bf0359b | ||
|
|
41cbd28c44 | ||
|
|
208c81a072 | ||
|
|
f836314954 | ||
|
|
1a370bb606 | ||
|
|
7ff34158a1 | ||
|
|
2a1c2637cd | ||
|
|
4f73664880 | ||
|
|
eb4ba56acb | ||
|
|
924bfac9fd | ||
|
|
4cf9c11e3f | ||
|
|
a3fc2899bd | ||
|
|
b95360f302 | ||
|
|
9edf867909 | ||
|
|
f3aca85d02 | ||
|
|
14bdb36f92 | ||
|
|
197ef3e8da | ||
|
|
5cf68f6241 | ||
|
|
1dabd152be | ||
|
|
3ed5f97448 | ||
|
|
b99ce9a992 | ||
|
|
c2337fec2d | ||
|
|
1e2b734be8 | ||
|
|
31e6279646 | ||
|
|
227d08660b | ||
|
|
22b0a3eeab | ||
|
|
77baee7fe0 | ||
|
|
3e76a04b1b | ||
|
|
421e7eb084 | ||
|
|
cb22f74650 | ||
|
|
d103d5057a | ||
|
|
aed61bf6ab | ||
|
|
1e160477be | ||
|
|
1e6ed874e3 | ||
|
|
dd48f7753b | ||
|
|
2c06497ca9 | ||
|
|
9ccf763b02 | ||
|
|
40b39293fa | ||
|
|
02e28cd254 | ||
|
|
fade53fcaf | ||
|
|
804ba5bfce | ||
|
|
9545b26036 | ||
|
|
2ef530ce11 | ||
|
|
8009d3c360 | ||
|
|
4ae1fc202e | ||
|
|
a59c3ab990 | ||
|
|
a7f457046f | ||
|
|
25e847dc94 | ||
|
|
e1c839fb1d | ||
|
|
7dfd68589a | ||
|
|
72086edbdb | ||
|
|
7617ab2b92 | ||
|
|
d31d0347cf | ||
|
|
5dca609c2a | ||
|
|
87ac56bf8c | ||
|
|
a056406eff | ||
|
|
24811a6269 | ||
|
|
53ed1e30d2 | ||
|
|
7393d50b09 | ||
|
|
f7663cc34c | ||
|
|
71ba0191f2 | ||
|
|
19be49ebe4 | ||
|
|
9fe7eb79d5 | ||
|
|
1ccd4f04d2 | ||
|
|
364cf99338 | ||
|
|
92a7dce46f | ||
|
|
d0d53d924e | ||
|
|
77d880d0c3 | ||
|
|
559d73a636 | ||
|
|
6fd40c04c7 | ||
|
|
63c071959f | ||
|
|
7be257b252 | ||
|
|
923cb753b8 | ||
|
|
6cad75773e | ||
|
|
cb2548f989 | ||
|
|
f87e243225 | ||
|
|
d98fcd3598 | ||
|
|
93d3ee8ab1 | ||
|
|
030bdcf771 | ||
|
|
4a50b99b67 | ||
|
|
382aa3ba87 | ||
|
|
2243efb2e6 | ||
|
|
477c0b11b8 | ||
|
|
2396092ae9 | ||
|
|
4f9c23893a | ||
|
|
62e5c450f7 | ||
|
|
265713561c | ||
|
|
c9faf343ba | ||
|
|
99bfbd5931 | ||
|
|
238769e535 | ||
|
|
bf61384523 | ||
|
|
2114937ec6 | ||
|
|
cd1586214e | ||
|
|
51bc3c0f09 | ||
|
|
3c3f87a3d2 | ||
|
|
174b7757a5 | ||
|
|
359b40d422 | ||
|
|
ef7ea3e515 | ||
|
|
190b09cc76 | ||
|
|
53d981a724 | ||
|
|
89ca02c1f7 | ||
|
|
2fafe8771d | ||
|
|
41c9ed499b | ||
|
|
1605d68709 | ||
|
|
93ce398e28 | ||
|
|
62a552d896 | ||
|
|
bd41dca064 | ||
|
|
3dbddaaadf | ||
|
|
58491f317f | ||
|
|
9527b7879f | ||
|
|
0059d37db5 | ||
|
|
58aedd0ebc | ||
|
|
7056332f0b | ||
|
|
672b4edfbc | ||
|
|
442db744d5 | ||
|
|
871f1d9048 | ||
|
|
f6bd6aa1a4 | ||
|
|
2787a5ca5d | ||
|
|
dbd25c945c | ||
|
|
02f4d6ea0b | ||
|
|
80a642f511 | ||
|
|
ddeb0a3de0 | ||
|
|
22ec1ea65b | ||
|
|
e0b100ee31 | ||
|
|
5f7c23bd8e | ||
|
|
367dcda592 | ||
|
|
6ecac88f4d | ||
|
|
cc8ac4f40f | ||
|
|
a12c89658c | ||
|
|
4b4903e809 | ||
|
|
be537ce77a | ||
|
|
cc8f0b7348 | ||
|
|
7cc2270228 | ||
|
|
34ac5f47de | ||
|
|
523c0cbaa7 | ||
|
|
05f481d2f0 | ||
|
|
c66372452f | ||
|
|
aee8825558 | ||
|
|
f612511974 | ||
|
|
287f8ecd56 | ||
|
|
1c6fb2dc20 | ||
|
|
f04dc2cabd | ||
|
|
4af6408e39 | ||
|
|
1fa5d5084b | ||
|
|
d74b002969 | ||
|
|
394c6fc3f9 | ||
|
|
0b15b91dc1 | ||
|
|
5fe286e8d5 | ||
|
|
82fe3a72a2 |
@@ -6,9 +6,9 @@ updates:
|
|||||||
interval: "monthly"
|
interval: "monthly"
|
||||||
time: "06:00"
|
time: "06:00"
|
||||||
timezone: "America/Chicago"
|
timezone: "America/Chicago"
|
||||||
|
cooldown:
|
||||||
|
default-days: 7
|
||||||
labels: []
|
labels: []
|
||||||
commit-message:
|
|
||||||
prefix: "chore"
|
|
||||||
|
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
directory: "/"
|
directory: "/"
|
||||||
@@ -16,8 +16,8 @@ updates:
|
|||||||
interval: "monthly"
|
interval: "monthly"
|
||||||
time: "06:00"
|
time: "06:00"
|
||||||
timezone: "America/Chicago"
|
timezone: "America/Chicago"
|
||||||
commit-message:
|
cooldown:
|
||||||
prefix: "chore"
|
default-days: 7
|
||||||
labels: []
|
labels: []
|
||||||
ignore:
|
ignore:
|
||||||
# Ignore patch updates for all dependencies
|
# Ignore patch updates for all dependencies
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
###############################################################################
|
|
||||||
# This file configures "Semantic Pull Requests", which is documented here:
|
|
||||||
# https://github.com/zeke/semantic-pull-requests
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
# Scopes are optionally supplied after a 'type'. For example, in
|
|
||||||
#
|
|
||||||
# feat(docs): autostart ui
|
|
||||||
#
|
|
||||||
# '(docs)' is the scope. Scopes are used to signify where the change occurred.
|
|
||||||
scopes:
|
|
||||||
# docs: changes to the code-server documentation.
|
|
||||||
- docs
|
|
||||||
|
|
||||||
# vendor: changes to vendored dependencies.
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
# deps: changes to code-server's dependencies.
|
|
||||||
- deps
|
|
||||||
|
|
||||||
# cs: changes to code specific to code-server.
|
|
||||||
- cs
|
|
||||||
|
|
||||||
# cli: changes to the command-line interface.
|
|
||||||
- cli
|
|
||||||
|
|
||||||
# We only check that the PR title is semantic. The PR title is automatically
|
|
||||||
# applied to the "Squash & Merge" flow as the suggested commit message, so this
|
|
||||||
# should suffice unless someone drastically alters the message in that flow.
|
|
||||||
titleOnly: true
|
|
||||||
|
|
||||||
# Types are the 'tag' types in a commit or PR title. For example, in
|
|
||||||
#
|
|
||||||
# chore: fix thing
|
|
||||||
#
|
|
||||||
# 'chore' is the type.
|
|
||||||
types:
|
|
||||||
# A build of any kind.
|
|
||||||
- build
|
|
||||||
|
|
||||||
# A user-facing change that corrects a defect in code-server.
|
|
||||||
- fix
|
|
||||||
|
|
||||||
# Any code task that is ignored for changelog purposes. Examples include
|
|
||||||
# devbin scripts and internal-only configurations.
|
|
||||||
- chore
|
|
||||||
|
|
||||||
# Any work performed on CI.
|
|
||||||
- ci
|
|
||||||
|
|
||||||
# Work that directly implements or supports the implementation of a feature.
|
|
||||||
- feat
|
|
||||||
|
|
||||||
# A refactor changes code structure without any behavioral change.
|
|
||||||
- refactor
|
|
||||||
|
|
||||||
# A git revert for any style of commit.
|
|
||||||
- revert
|
|
||||||
|
|
||||||
# Adding tests of any kind. Should be separate from feature or fix
|
|
||||||
# implementations. For example, if a commit adds a fix + test, it's a fix
|
|
||||||
# commit. If a commit is simply bumping coverage, it's a test commit.
|
|
||||||
- test
|
|
||||||
|
|
||||||
# A new release.
|
|
||||||
- release
|
|
||||||
@@ -21,12 +21,13 @@ jobs:
|
|||||||
outputs:
|
outputs:
|
||||||
ci: ${{ steps.filter.outputs.ci }}
|
ci: ${{ steps.filter.outputs.ci }}
|
||||||
code: ${{ steps.filter.outputs.code }}
|
code: ${{ steps.filter.outputs.code }}
|
||||||
deps: ${{ steps.filter.outputs.deps }}
|
npm: ${{ steps.filter.outputs.npm }}
|
||||||
|
vscode: ${{ steps.filter.outputs.vscode }}
|
||||||
docs: ${{ steps.filter.outputs.docs }}
|
docs: ${{ steps.filter.outputs.docs }}
|
||||||
helm: ${{ steps.filter.outputs.helm }}
|
helm: ${{ steps.filter.outputs.helm }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3
|
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
||||||
id: filter
|
id: filter
|
||||||
with:
|
with:
|
||||||
filters: |
|
filters: |
|
||||||
@@ -42,11 +43,12 @@ jobs:
|
|||||||
code:
|
code:
|
||||||
- "src/**"
|
- "src/**"
|
||||||
- "test/**"
|
- "test/**"
|
||||||
deps:
|
npm:
|
||||||
- "lib/**"
|
|
||||||
- "patches/**"
|
|
||||||
- "package-lock.json"
|
- "package-lock.json"
|
||||||
- "test/package-lock.json"
|
- "test/package-lock.json"
|
||||||
|
vscode:
|
||||||
|
- "lib/**"
|
||||||
|
- "patches/**"
|
||||||
- id: debug
|
- id: debug
|
||||||
run: |
|
run: |
|
||||||
echo "${{ toJSON(steps.filter )}}"
|
echo "${{ toJSON(steps.filter )}}"
|
||||||
@@ -55,8 +57,8 @@ jobs:
|
|||||||
name: Run prettier check
|
name: Run prettier check
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -72,8 +74,8 @@ jobs:
|
|||||||
needs: changes
|
needs: changes
|
||||||
if: needs.changes.outputs.docs == 'true'
|
if: needs.changes.outputs.docs == 'true'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -89,21 +91,20 @@ jobs:
|
|||||||
needs: changes
|
needs: changes
|
||||||
if: needs.changes.outputs.helm == 'true'
|
if: needs.changes.outputs.helm == 'true'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
|
- uses: bmuschko/setup-kubeconform@e5d264ec1eafe2314e750c429a9da7639dd5a003 # v1.1.0
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
kubeconform-version: "0.8.0"
|
||||||
- run: helm plugin install https://github.com/instrumenta/helm-kubeval
|
- run: kubeconform ci/helm-chart
|
||||||
- run: helm kubeval ci/helm-chart
|
|
||||||
|
|
||||||
lint-ts:
|
lint-ts:
|
||||||
name: Lint TypeScript files
|
name: Lint TypeScript files
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: changes
|
needs: changes
|
||||||
if: needs.changes.outputs.code == 'true'
|
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.ci == 'true' || needs.changes.outputs.npm == 'true'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -120,7 +121,7 @@ jobs:
|
|||||||
if: needs.changes.outputs.ci == 'true'
|
if: needs.changes.outputs.ci == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- name: Check workflow files
|
- name: Check workflow files
|
||||||
run: |
|
run: |
|
||||||
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
|
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
|
||||||
@@ -131,10 +132,10 @@ jobs:
|
|||||||
name: Run unit tests
|
name: Run unit tests
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: changes
|
needs: changes
|
||||||
if: needs.changes.outputs.code == 'true'
|
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -143,7 +144,7 @@ jobs:
|
|||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
- run: npm run test:unit
|
- run: npm run test:unit
|
||||||
- uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5
|
- uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||||
if: success()
|
if: success()
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
@@ -155,6 +156,7 @@ jobs:
|
|||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
DISABLE_V8_COMPILE_CACHE: 1
|
DISABLE_V8_COMPILE_CACHE: 1
|
||||||
VERSION: 0.0.0
|
VERSION: 0.0.0
|
||||||
|
VSCODE_ARCH: x64
|
||||||
VSCODE_TARGET: linux-x64
|
VSCODE_TARGET: linux-x64
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||||
@@ -162,49 +164,60 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||||
- uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
|
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
|
||||||
with:
|
with:
|
||||||
packages: quilt
|
packages: quilt
|
||||||
version: 1.0
|
version: 1.0
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- run: quilt push -a
|
- run: quilt push -a
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
package-lock.json
|
package-lock.json
|
||||||
test/package-lock.json
|
test/package-lock.json
|
||||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
|
||||||
- run: npm run build
|
|
||||||
# Get Code's git hash. When this changes it means the content is
|
# Get Code's git hash. When this changes it means the content is
|
||||||
# different and we need to rebuild.
|
# different and we need to rebuild.
|
||||||
- name: Get latest lib/vscode rev
|
- name: Get latest lib/vscode rev
|
||||||
id: vscode-rev
|
id: vscode-rev
|
||||||
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
|
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# We need to rebuild when we have a new version of Code, when any of the
|
# 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
|
# patches changed, or when the code-server version changes (since it gets
|
||||||
# embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild.
|
# embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild.
|
||||||
- name: Fetch prebuilt linux-x64 Code package from cache
|
- name: Fetch prebuilt linux-x64 Code package from cache
|
||||||
id: cache-vscode
|
id: cache-vscode
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||||
with:
|
with:
|
||||||
path: lib/vscode-reh-web-linux-x64
|
path: lib/vscode-reh-web-linux-x64
|
||||||
key: vscode-linux-x64-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
key: vscode-linux-x64-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
||||||
- name: Build vscode
|
- name: Build vscode
|
||||||
if: steps.cache-vscode.outputs.cache-hit != 'true'
|
if: steps.cache-vscode.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
pushd lib/vscode
|
cd lib/vscode/build
|
||||||
npm ci
|
npm ci
|
||||||
popd
|
cd ..
|
||||||
|
source ./build/azure-pipelines/linux/setup-env.sh
|
||||||
|
# Run preinstall script before root dependencies are installed
|
||||||
|
# so that v8 headers are patched correctly for native modules.
|
||||||
|
node build/npm/preinstall.ts
|
||||||
|
npm ci
|
||||||
|
cd ../..
|
||||||
npm run build:vscode
|
npm run build:vscode
|
||||||
|
|
||||||
|
# Build the code-server wrapper.
|
||||||
|
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||||
|
- run: npm run build
|
||||||
|
|
||||||
# Push up an artifact containing the linux-x64 release.
|
# Push up an artifact containing the linux-x64 release.
|
||||||
- run: KEEP_MODULES=1 npm run release
|
- run: KEEP_MODULES=1 npm run release
|
||||||
- run: tar -czf package.tar.gz release
|
- run: tar -czf package.tar.gz release
|
||||||
- uses: actions/upload-artifact@v7
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||||
with:
|
with:
|
||||||
name: linux-x64-package
|
name: linux-x64-package
|
||||||
path: ./package.tar.gz
|
path: ./package.tar.gz
|
||||||
@@ -212,12 +225,14 @@ jobs:
|
|||||||
test-e2e:
|
test-e2e:
|
||||||
name: Run e2e tests
|
name: Run e2e tests
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
env:
|
||||||
|
LOG_LEVEL: debug
|
||||||
needs: [changes, build]
|
needs: [changes, build]
|
||||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true'
|
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -230,13 +245,13 @@ jobs:
|
|||||||
./test/node_modules/.bin/playwright install-deps
|
./test/node_modules/.bin/playwright install-deps
|
||||||
./test/node_modules/.bin/playwright install
|
./test/node_modules/.bin/playwright install
|
||||||
|
|
||||||
- uses: actions/download-artifact@v8
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||||
with:
|
with:
|
||||||
name: linux-x64-package
|
name: linux-x64-package
|
||||||
- run: tar -xzf package.tar.gz
|
- run: tar -xzf package.tar.gz
|
||||||
|
|
||||||
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
|
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
|
||||||
- uses: actions/upload-artifact@v7
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: failed-test-videos
|
name: failed-test-videos
|
||||||
@@ -247,12 +262,13 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
LOG_LEVEL: debug
|
||||||
needs: [changes, build]
|
needs: [changes, build]
|
||||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true' || needs.changes.outputs.ci == 'true'
|
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Cache Caddy
|
- name: Cache Caddy
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||||
id: caddy-cache
|
id: caddy-cache
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -265,8 +281,8 @@ jobs:
|
|||||||
mkdir -p ~/.cache/caddy
|
mkdir -p ~/.cache/caddy
|
||||||
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
|
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -279,7 +295,7 @@ jobs:
|
|||||||
./test/node_modules/.bin/playwright install-deps
|
./test/node_modules/.bin/playwright install-deps
|
||||||
./test/node_modules/.bin/playwright install
|
./test/node_modules/.bin/playwright install
|
||||||
|
|
||||||
- uses: actions/download-artifact@v8
|
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||||
with:
|
with:
|
||||||
name: linux-x64-package
|
name: linux-x64-package
|
||||||
- run: tar -xzf package.tar.gz
|
- run: tar -xzf package.tar.gz
|
||||||
@@ -288,7 +304,7 @@ jobs:
|
|||||||
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
|
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
|
||||||
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
|
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
|
||||||
if: always()
|
if: always()
|
||||||
- uses: actions/upload-artifact@v7
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: failed-test-videos-proxy
|
name: failed-test-videos-proxy
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
- name: Install code-server
|
- name: Install code-server
|
||||||
run: ./install.sh
|
run: ./install.sh
|
||||||
@@ -44,7 +44,7 @@ jobs:
|
|||||||
container: "alpine:3.17"
|
container: "alpine:3.17"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
- name: Install curl
|
- name: Install curl
|
||||||
run: apk add curl
|
run: apk add curl
|
||||||
@@ -67,7 +67,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
- name: Install code-server
|
- name: Install code-server
|
||||||
run: ./install.sh
|
run: ./install.sh
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
|
|
||||||
- uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
|
- uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
|
||||||
with:
|
with:
|
||||||
repository: "coder/code-server"
|
repository: "coder/code-server"
|
||||||
tag: ${{ env.TAG }}
|
tag: ${{ env.TAG }}
|
||||||
@@ -64,25 +64,26 @@ jobs:
|
|||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Checkout code-server-aur repo
|
- name: Checkout code-server-aur repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
with:
|
with:
|
||||||
repository: "cdrci/code-server-aur"
|
repository: "cdrci/code-server-aur"
|
||||||
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||||
ref: "master"
|
ref: "master"
|
||||||
|
|
||||||
- name: Merge in master
|
|
||||||
run: |
|
|
||||||
git remote add upstream https://github.com/coder/code-server-aur.git
|
|
||||||
git fetch upstream
|
|
||||||
git merge upstream/master
|
|
||||||
|
|
||||||
- name: Configure git
|
- name: Configure git
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name cdrci
|
git config --global user.name cdrci
|
||||||
git config --global user.email opensource@coder.com
|
git config --global user.email opensource@coder.com
|
||||||
|
|
||||||
|
- name: Fetch and reset master
|
||||||
|
run: |
|
||||||
|
git remote add upstream https://github.com/coder/code-server-aur.git
|
||||||
|
git fetch upstream
|
||||||
|
git reset --hard upstream/master
|
||||||
|
git push --force
|
||||||
|
|
||||||
- name: Validate package
|
- name: Validate package
|
||||||
uses: heyhusen/archlinux-package-action@c9f94059ccbebe8710d31d582f33ef4e84fe575c # v3.0.0
|
uses: heyhusen/archlinux-package-action@3f7aaada28c782497bfe02d6d6ea365b25fdea12 # v3.0.1
|
||||||
with:
|
with:
|
||||||
pkgver: ${{ env.VERSION }}
|
pkgver: ${{ env.VERSION }}
|
||||||
updpkgsums: true
|
updpkgsums: true
|
||||||
@@ -92,9 +93,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git checkout -b update-version-${{ env.VERSION }}
|
git checkout -b update-version-${{ env.VERSION }}
|
||||||
git add .
|
git add .
|
||||||
git commit -m "chore: updating version to ${{ env.VERSION }}"
|
git commit -m "Update to ${{ env.VERSION }}"
|
||||||
git push -u origin $(git branch --show)
|
git push -u origin $(git branch --show)
|
||||||
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
gh pr create --repo coder/code-server-aur --title "Update to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -107,27 +108,27 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
|
- uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4.3.0
|
||||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
|
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
||||||
|
|
||||||
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
|
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
|
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
|
- uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
|
||||||
with:
|
with:
|
||||||
repository: "coder/code-server"
|
repository: "coder/code-server"
|
||||||
tag: v${{ env.VERSION }}
|
tag: v${{ env.VERSION }}
|
||||||
fileName: "*.deb"
|
fileName: "*.deb"
|
||||||
out-file-path: "release-packages"
|
out-file-path: "release-packages"
|
||||||
- uses: robinraju/release-downloader@daf26c55d821e836577a15f77d86ddc078948b05 # v1.12
|
- uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
|
||||||
with:
|
with:
|
||||||
repository: "coder/code-server"
|
repository: "coder/code-server"
|
||||||
tag: v${{ env.VERSION }}
|
tag: v${{ env.VERSION }}
|
||||||
@@ -135,3 +136,32 @@ jobs:
|
|||||||
out-file-path: "release-packages"
|
out-file-path: "release-packages"
|
||||||
|
|
||||||
- run: npm run publish:docker
|
- run: npm run publish:docker
|
||||||
|
|
||||||
|
repo:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||||
|
TAG: ${{ inputs.version || github.ref_name }}
|
||||||
|
needs: docker
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set version to tag without leading v
|
||||||
|
run: |
|
||||||
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
|
- run: ./ci/build/update-repo.sh
|
||||||
|
|
||||||
|
- name: Open PR
|
||||||
|
run: |
|
||||||
|
git config --global user.name cdrci
|
||||||
|
git config --global user.email opensource@coder.com
|
||||||
|
git checkout -b "helm/$VERSION"
|
||||||
|
git add .
|
||||||
|
git commit -m "Update Helm chart and changelog with $VERSION"
|
||||||
|
git push -u origin "$(git branch --show)"
|
||||||
|
gh pr create \
|
||||||
|
--repo coder/code-server \
|
||||||
|
--body-file .cache/checklist \
|
||||||
|
--title "Update Helm chart and changelog with $VERSION"
|
||||||
|
|||||||
+205
-17
@@ -6,6 +6,11 @@ on:
|
|||||||
version:
|
version:
|
||||||
type: string
|
type: string
|
||||||
required: true
|
required: true
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- closed
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write # For creating releases.
|
contents: write # For creating releases.
|
||||||
@@ -21,6 +26,9 @@ jobs:
|
|||||||
package-linux:
|
package-linux:
|
||||||
name: ${{ format('linux-{0}', matrix.vscode_arch) }}
|
name: ${{ format('linux-{0}', matrix.vscode_arch) }}
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
if: >-
|
||||||
|
(github.event_name == 'workflow_dispatch') ||
|
||||||
|
(github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@@ -31,26 +39,27 @@ jobs:
|
|||||||
- npm_arch: arm64
|
- npm_arch: arm64
|
||||||
vscode_arch: arm64
|
vscode_arch: arm64
|
||||||
package_arch: arm64
|
package_arch: arm64
|
||||||
- npm_arch: arm
|
|
||||||
vscode_arch: armhf
|
|
||||||
package_arch: armv7l
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
TAG: ${{ inputs.version || github.ref_name }}
|
TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
|
||||||
# Set release package name.
|
# Set release package name.
|
||||||
ARCH: ${{ matrix.package_arch }}
|
ARCH: ${{ matrix.package_arch }}
|
||||||
# Cross-compile target.
|
# Cross-compile target.
|
||||||
VSCODE_ARCH: ${{ matrix.vscode_arch }}
|
VSCODE_ARCH: ${{ matrix.vscode_arch }}
|
||||||
npm_config_arch: ${{ matrix.npm_arch }}
|
npm_config_arch: ${{ matrix.npm_arch }}
|
||||||
|
# Ensure native modules are built from source to avoid prebuilds and use
|
||||||
|
# the correct version of glibc.
|
||||||
|
npm_config_build_from_source: true
|
||||||
# Gulp target name.
|
# Gulp target name.
|
||||||
|
# TODO: Pull from VSCODE_ARCH instead.
|
||||||
VSCODE_TARGET: ${{ format('linux-{0}', matrix.vscode_arch) }}
|
VSCODE_TARGET: ${{ format('linux-{0}', matrix.vscode_arch) }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||||
- uses: awalsh128/cache-apt-pkgs-action@2c09a5e66da6c8016428a2172bd76e5e4f14bb17 # latest
|
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
|
||||||
with:
|
with:
|
||||||
packages: quilt
|
packages: quilt
|
||||||
version: 1.0
|
version: 1.0
|
||||||
@@ -60,15 +69,21 @@ jobs:
|
|||||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
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
|
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Set version to tag without leading v
|
- name: Strip update/ and v from tag and set major version
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
version=${TAG#update/}
|
||||||
|
version=${version#v}
|
||||||
|
version=4${version:1}
|
||||||
|
echo "VERSION=$version" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
# When an update/ branch is merged, a release is automatically created
|
||||||
|
# which requires secrets.
|
||||||
|
allow-unsafe-pr-checkout: true
|
||||||
- run: quilt push -a
|
- run: quilt push -a
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -95,25 +110,36 @@ jobs:
|
|||||||
if: ${{ matrix.vscode_arch == 'x64' }}
|
if: ${{ matrix.vscode_arch == 'x64' }}
|
||||||
- run: tar -czf package.tar.gz release
|
- run: tar -czf package.tar.gz release
|
||||||
if: ${{ matrix.vscode_arch == 'x64' }}
|
if: ${{ matrix.vscode_arch == 'x64' }}
|
||||||
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
- run: |
|
||||||
|
sed "/^## Unreleased/,/^## / ! d" CHANGELOG.md | head -n -2 | tail -n +3 > .cache/release-notes
|
||||||
|
if: ${{ matrix.vscode_arch == 'x64' }}
|
||||||
|
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
||||||
if: ${{ matrix.vscode_arch == 'x64' }}
|
if: ${{ matrix.vscode_arch == 'x64' }}
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
discussion_category_name: "📣 Announcements"
|
discussion_category_name: "📣 Announcements"
|
||||||
files: package.tar.gz
|
files: package.tar.gz
|
||||||
|
tag_name: v${{ env.VERSION }}
|
||||||
|
name: v${{ env.VERSION }}
|
||||||
|
body_path: .cache/release-notes
|
||||||
|
|
||||||
# Platform-specific release.
|
# Platform-specific release.
|
||||||
- run: KEEP_MODULES=1 npm run release
|
- run: KEEP_MODULES=1 npm run release
|
||||||
- run: npm run package
|
- run: npm run package
|
||||||
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
discussion_category_name: "📣 Announcements"
|
discussion_category_name: "📣 Announcements"
|
||||||
files: ./release-packages/*
|
files: ./release-packages/*
|
||||||
|
tag_name: v${{ env.VERSION }}
|
||||||
|
name: v${{ env.VERSION }}
|
||||||
|
|
||||||
package-macos:
|
package-macos:
|
||||||
name: ${{ matrix.vscode_target }}
|
name: ${{ matrix.vscode_target }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
if: >-
|
||||||
|
(github.event_name == 'workflow_dispatch') ||
|
||||||
|
(github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
@@ -124,7 +150,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
VSCODE_TARGET: ${{ matrix.vscode_target }}
|
VSCODE_TARGET: ${{ matrix.vscode_target }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAG: ${{ inputs.version || github.ref_name }}
|
TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
|
||||||
|
# Ensure native modules are built from source to avoid prebuilds.
|
||||||
|
npm_config_build_from_source: true
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# The version of node-gyp we use depends on distutils but it was removed
|
# The version of node-gyp we use depends on distutils but it was removed
|
||||||
@@ -138,15 +166,21 @@ jobs:
|
|||||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
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
|
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
- name: Set version to tag without leading v
|
- name: Strip update/ and v from tag and set major version
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
version=${TAG#update/}
|
||||||
|
version=${version#v}
|
||||||
|
version=4${version:1}
|
||||||
|
echo "VERSION=$version" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
# When an update/ branch is merged, a release is automatically created
|
||||||
|
# which requires secrets.
|
||||||
|
allow-unsafe-pr-checkout: true
|
||||||
- run: quilt push -a
|
- run: quilt push -a
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
cache: npm
|
cache: npm
|
||||||
@@ -161,8 +195,162 @@ jobs:
|
|||||||
- run: npm run test:native
|
- run: npm run test:native
|
||||||
|
|
||||||
- run: npm run package
|
- run: npm run package
|
||||||
- uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
|
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
discussion_category_name: "📣 Announcements"
|
discussion_category_name: "📣 Announcements"
|
||||||
files: ./release-packages/*
|
files: ./release-packages/*
|
||||||
|
tag_name: v${{ env.VERSION }}
|
||||||
|
name: v${{ env.VERSION }}
|
||||||
|
|
||||||
|
package-windows:
|
||||||
|
name: win32-x64
|
||||||
|
runs-on: windows-2022
|
||||||
|
if: >-
|
||||||
|
(github.event_name == 'workflow_dispatch') ||
|
||||||
|
(github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
env:
|
||||||
|
VSCODE_TARGET: win32-x64
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
|
||||||
|
# Ensure native modules are built from source to avoid prebuilds.
|
||||||
|
npm_config_build_from_source: true
|
||||||
|
OS: windows
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Git rewrites line endings on windows by default, which turns every
|
||||||
|
# shell script the build is made of into one bash cannot read, and
|
||||||
|
# every name in patches/series into one with a stray return.
|
||||||
|
- name: Keep line endings as they are in the repository
|
||||||
|
run: git config --global core.autocrlf false
|
||||||
|
|
||||||
|
- name: Strip update/ and v from tag and set major version
|
||||||
|
run: |
|
||||||
|
version=${TAG#update/}
|
||||||
|
version=${version#v}
|
||||||
|
version=4${version:1}
|
||||||
|
echo "VERSION=$version" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
# When an update/ branch is merged, a release is automatically created
|
||||||
|
# which requires secrets.
|
||||||
|
allow-unsafe-pr-checkout: true
|
||||||
|
|
||||||
|
# quilt has no windows build. The patches are ordinary -p1 diffs
|
||||||
|
# against the repository root, so git applies them in series order.
|
||||||
|
- name: Apply patches
|
||||||
|
run: |
|
||||||
|
while read -r patch; do
|
||||||
|
case "$patch" in '' | '#'*) continue ;; esac
|
||||||
|
echo "applying $patch"
|
||||||
|
git apply --whitespace=nowarn "patches/$patch"
|
||||||
|
done < patches/series
|
||||||
|
|
||||||
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
|
with:
|
||||||
|
node-version-file: .node-version
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: |
|
||||||
|
package-lock.json
|
||||||
|
test/package-lock.json
|
||||||
|
|
||||||
|
# npm hands every script it runs to cmd, which cannot run the shell
|
||||||
|
# scripts this repository is built out of. Point it at the same bash
|
||||||
|
# the steps here use rather than at a path, which moves between
|
||||||
|
# images.
|
||||||
|
- name: Let npm run shell scripts
|
||||||
|
run: echo "npm_config_script_shell=$(cygpath -w "$(command -v bash)")" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# The build merges json by handing jq a process substitution, which
|
||||||
|
# bash presents as a file under /dev/fd. The jq on this image is a
|
||||||
|
# windows program and cannot open those, so it reads the second input
|
||||||
|
# as nothing and the merge fails. Both the product and the package
|
||||||
|
# merge go through here.
|
||||||
|
- name: Let jq read what bash hands it
|
||||||
|
run: |
|
||||||
|
mkdir -p "$RUNNER_TEMP/shim"
|
||||||
|
cat > "$RUNNER_TEMP/shim/jq" <<'SHIM'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
args=()
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
/dev/fd/* | /proc/*/fd/*)
|
||||||
|
copy=$(mktemp)
|
||||||
|
cat "$arg" > "$copy"
|
||||||
|
args+=("$copy")
|
||||||
|
;;
|
||||||
|
*) args+=("$arg") ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
exec jq.exe "${args[@]}"
|
||||||
|
SHIM
|
||||||
|
chmod +x "$RUNNER_TEMP/shim/jq"
|
||||||
|
echo "$RUNNER_TEMP/shim" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# Stamping version details into the native binaries clears any
|
||||||
|
# signature they arrived with and asks signtool whether there is one.
|
||||||
|
# That only reads and removes, so it wants no certificate and signs
|
||||||
|
# nothing. It just has to be findable, and the sdk carrying it is not
|
||||||
|
# on the path.
|
||||||
|
- name: Put signtool on the path
|
||||||
|
run: |
|
||||||
|
sdk=$(ls -d "/c/Program Files (x86)/Windows Kits/10/bin"/*/x64 | sort -V | tail -1)
|
||||||
|
test -x "$sdk/signtool.exe"
|
||||||
|
cygpath -w "$sdk" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
# build-release.sh copies the tree with rsync, which neither windows
|
||||||
|
# nor the git bash on this image has. MSYS2 is already here, just not
|
||||||
|
# on the path.
|
||||||
|
- name: Install rsync
|
||||||
|
shell: cmd
|
||||||
|
run: C:\msys64\usr\bin\pacman -Sy --noconfirm --needed rsync
|
||||||
|
|
||||||
|
# Only rsync crosses over. Putting msys2's /usr/bin in front instead
|
||||||
|
# breaks the release step: npm on the path is a shell script whose
|
||||||
|
# shebang reads /usr/bin/env bash, so with msys2 first it is msys2's
|
||||||
|
# bash that runs it, and crossing into a second msys runtime does not
|
||||||
|
# carry the environment. npm then sees no script-shell and falls back
|
||||||
|
# to cmd, which cannot run ./ci/build/build-release.sh, and
|
||||||
|
# KEEP_MODULES is dropped on the way. A forwarder avoids the whole
|
||||||
|
# class: rsync is a native exe that loads its runtime from beside
|
||||||
|
# itself, and nothing else on the path moves.
|
||||||
|
- name: Reach rsync without moving the path
|
||||||
|
run: |
|
||||||
|
cat > "$RUNNER_TEMP/shim/rsync" <<'SHIM'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
exec /c/msys64/usr/bin/rsync.exe "$@"
|
||||||
|
SHIM
|
||||||
|
chmod +x "$RUNNER_TEMP/shim/rsync"
|
||||||
|
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm run build:vscode
|
||||||
|
- run: KEEP_MODULES=1 npm run release
|
||||||
|
|
||||||
|
# Of the two tars on this image it is git bash's GNU one that can
|
||||||
|
# rename the tree's top directory as it archives; the windows bsdtar
|
||||||
|
# is built without substitution support. Asserted rather than
|
||||||
|
# assumed, since the two are interchangeable everywhere except here.
|
||||||
|
- name: Package
|
||||||
|
run: |
|
||||||
|
case "$(tar --version | head -1)" in
|
||||||
|
*GNU*) ;;
|
||||||
|
*) echo "expected GNU tar for --transform, got $(tar --version | head -1)" >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
npm run package
|
||||||
|
|
||||||
|
- uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
|
||||||
|
with:
|
||||||
|
draft: true
|
||||||
|
discussion_category_name: "📣 Announcements"
|
||||||
|
files: ./release-packages/*
|
||||||
|
tag_name: v${{ env.VERSION }}
|
||||||
|
name: v${{ env.VERSION }}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
container: "alpine:3.17"
|
container: "alpine:3.17"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
- name: Install test utilities
|
- name: Install test utilities
|
||||||
run: apk add bats checkbashisms
|
run: apk add bats checkbashisms
|
||||||
@@ -58,7 +58,7 @@ jobs:
|
|||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
- name: Install lint utilities
|
- name: Install lint utilities
|
||||||
run: sudo apt install shellcheck
|
run: sudo apt install shellcheck
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ jobs:
|
|||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||||
with:
|
with:
|
||||||
node-version-file: .node-version
|
node-version-file: .node-version
|
||||||
|
|
||||||
@@ -46,12 +46,12 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner in repo mode
|
- name: Run Trivy vulnerability scanner in repo mode
|
||||||
uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478
|
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
|
||||||
with:
|
with:
|
||||||
scan-type: "fs"
|
scan-type: "fs"
|
||||||
scan-ref: "."
|
scan-ref: "."
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
severity: "HIGH,CRITICAL"
|
severity: "HIGH,CRITICAL"
|
||||||
|
|
||||||
- name: Upload Trivy scan results to GitHub Security tab
|
- name: Upload Trivy scan results to GitHub Security tab
|
||||||
uses: github/codeql-action/upload-sarif@v4
|
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
||||||
with:
|
with:
|
||||||
sarif_file: "trivy-repo-results.sarif"
|
sarif_file: "trivy-repo-results.sarif"
|
||||||
|
|
||||||
@@ -76,17 +76,17 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v4
|
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||||
with:
|
with:
|
||||||
config-file: ./.github/codeql-config.yml
|
config-file: ./.github/codeql-config.yml
|
||||||
languages: javascript
|
languages: javascript
|
||||||
|
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v4
|
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v4
|
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ on:
|
|||||||
- .github/workflows/trivy-docker.yaml
|
- .github/workflows/trivy-docker.yaml
|
||||||
|
|
||||||
schedule:
|
schedule:
|
||||||
# Run at 10:15 am UTC (3:15am PT/5:15am CT)
|
|
||||||
# Run at 0 minutes 0 hours of every day.
|
|
||||||
- cron: "15 10 * * *"
|
- cron: "15 10 * * *"
|
||||||
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -48,10 +46,10 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner in image mode
|
- name: Run Trivy vulnerability scanner in image mode
|
||||||
uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478
|
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
|
||||||
with:
|
with:
|
||||||
image-ref: "docker.io/codercom/code-server:latest"
|
image-ref: "docker.io/codercom/code-server:latest"
|
||||||
ignore-unfixed: true
|
ignore-unfixed: true
|
||||||
@@ -60,6 +58,6 @@ jobs:
|
|||||||
severity: "HIGH,CRITICAL"
|
severity: "HIGH,CRITICAL"
|
||||||
|
|
||||||
- name: Upload Trivy scan results to GitHub Security tab
|
- name: Upload Trivy scan results to GitHub Security tab
|
||||||
uses: github/codeql-action/upload-sarif@v4
|
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
||||||
with:
|
with:
|
||||||
sarif_file: "trivy-image-results.sarif"
|
sarif_file: "trivy-image-results.sarif"
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: Update code-server
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
schedule:
|
||||||
|
- cron: "0 16,21 * * *"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TAG: ${{ inputs.version }}
|
||||||
|
GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Fetch latest tag
|
||||||
|
if: env.TAG == ''
|
||||||
|
run: |
|
||||||
|
tag=$(curl -fsSLI -o /dev/null -w "%{url_effective}" https://github.com/microsoft/vscode/releases/latest)
|
||||||
|
tag="${tag#https://github.com/microsoft/vscode/releases/tag/}"
|
||||||
|
echo "TAG=$tag" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Remove leading v from tag
|
||||||
|
run: |
|
||||||
|
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Check current version
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
commit="$(git -C lib/vscode rev-parse HEAD)"
|
||||||
|
if [[ $(git -C lib/vscode ls-remote --tags | grep "$commit") == */"$VERSION" ]] ; then
|
||||||
|
echo "$VERSION update has already been merged into $(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
echo done=true >> $GITHUB_OUTPUT
|
||||||
|
elif git ls-remote --exit-code --heads origin "update/$VERSION" ; then
|
||||||
|
echo "There is already a PR for updating to $VERSION"
|
||||||
|
echo done=true >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "$VERSION update has not started yet"
|
||||||
|
echo done=false >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
|
||||||
|
if: steps.check.outputs.done == 'false'
|
||||||
|
with:
|
||||||
|
packages: quilt
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
- run: ./ci/build/update-vscode.sh
|
||||||
|
if: steps.check.outputs.done == 'false'
|
||||||
|
|
||||||
|
- name: Open PR
|
||||||
|
if: steps.check.outputs.done == 'false'
|
||||||
|
run: |
|
||||||
|
git config --global user.name cdrci
|
||||||
|
git config --global user.email opensource@coder.com
|
||||||
|
git checkout -b "update/$VERSION"
|
||||||
|
git add .
|
||||||
|
git commit -m "Update Code to $VERSION"
|
||||||
|
git push -u origin "$(git branch --show)"
|
||||||
|
gh pr create \
|
||||||
|
--repo coder/code-server \
|
||||||
|
--title "Update Code to $VERSION" \
|
||||||
|
--body-file .cache/checklist \
|
||||||
|
--draft
|
||||||
@@ -11,6 +11,7 @@ node_modules
|
|||||||
.home
|
.home
|
||||||
coverage
|
coverage
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
|
*.bak
|
||||||
|
|
||||||
# Code packages itself here.
|
# Code packages itself here.
|
||||||
/lib/vscode-reh-web-*
|
/lib/vscode-reh-web-*
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
22.22.1
|
24.22.1
|
||||||
|
|||||||
+317
@@ -22,6 +22,323 @@ Code v99.99.999
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Update bundled Node.js to 24.22.1 to fix a remote code execution bug in the
|
||||||
|
Brotli decoder (CVE-2026-111497).
|
||||||
|
- Reject compressed request bodies (`Content-Encoding: br`, `gzip`, or
|
||||||
|
`deflate`) instead of decompressing them.
|
||||||
|
|
||||||
|
## [4.141.0](https://github.com/coder/code-server/releases/tag/v4.141.0) - 2026-10-08
|
||||||
|
|
||||||
|
Code v1.141.0
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- A new `--enable-remote-storage` flag can be used to make code-server persist
|
||||||
|
workbench storage on the remote server instead of browser storage. Use this if
|
||||||
|
you want to share storage between multiple devices.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The Typescript extension was trying to load as a browser extension even though
|
||||||
|
we build the remote server version, causing it to fail to activate.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.141.0
|
||||||
|
|
||||||
|
## [4.140.0](https://github.com/coder/code-server/releases/tag/v4.140.0) - 2026-10-02
|
||||||
|
|
||||||
|
Code v1.140.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.140.0
|
||||||
|
|
||||||
|
## [4.139.1](https://github.com/coder/code-server/releases/tag/v4.139.1) - 2026-09-26
|
||||||
|
|
||||||
|
Code v1.139.1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.139.1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `--idle-timeout-seconds` was only validated when passed as
|
||||||
|
`--idle-timeout-seconds=<value>`; values of 60 or less passed as
|
||||||
|
`--idle-timeout-seconds <value>` were silently accepted.
|
||||||
|
|
||||||
|
## [4.138.0](https://github.com/coder/code-server/releases/tag/v4.138.0) - 2026-09-19
|
||||||
|
|
||||||
|
Code v1.138.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.138.0
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Preserve the original path, query parameters, and fragment when rewriting
|
||||||
|
localhost URLs through the port proxy. If `VSCODE_PROXY_URI` has any query
|
||||||
|
parameters or fragments, those will be lost.
|
||||||
|
|
||||||
|
## [4.137.0](https://github.com/coder/code-server/releases/tag/v4.137.0) - 2026-09-11
|
||||||
|
|
||||||
|
Code v1.137.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.137.0
|
||||||
|
|
||||||
|
## [4.136.2](https://github.com/coder/code-server/releases/tag/v4.136.2) - 2026-09-08
|
||||||
|
|
||||||
|
Code v1.136.1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.136.1
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 4.136.2 replaces a removed 4.136.1 release that had the data path incorrectly
|
||||||
|
being set to `~/.vscode-server-oss/data`.
|
||||||
|
|
||||||
|
## [4.135.0](https://github.com/coder/code-server/releases/tag/v4.135.0) - 2026-08-27
|
||||||
|
|
||||||
|
Code v1.135.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.135.0
|
||||||
|
|
||||||
|
## [4.134.0](https://github.com/coder/code-server/releases/tag/v4.134.0) - 2026-08-24
|
||||||
|
|
||||||
|
Code v1.134.0
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- New `--socket-fd` flag that can be used to listen on a file descriptor. In
|
||||||
|
particular, this allows using code-server with systemd's socket activation.
|
||||||
|
- New `--vscode-option` repeatable flag that can be used to pass through options
|
||||||
|
to VS Code. It requires `flag=value` or simply `flag` for booleans. For
|
||||||
|
example: `--vscode-option enable-sandbox --vscode-option agents=true`. The
|
||||||
|
`VSCODE_OPTIONS` environment variable may also be used. For example:
|
||||||
|
`VSCODE_OPTIONS="enable-sandbox agents=true"`. Note that code-server simply
|
||||||
|
splits this variable on spaces and is not aware of quoting.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.134.0
|
||||||
|
- Remove `--unsafe-perm` from installation scripts. This flag results in an
|
||||||
|
error when used with npm since v12 and has been a no-op since v7. If you are
|
||||||
|
installing with a version of npm older than v7 as root, installation may not
|
||||||
|
work correctly.
|
||||||
|
|
||||||
|
## [4.133.0](https://github.com/coder/code-server/releases/tag/v4.133.0) - 2026-08-17
|
||||||
|
|
||||||
|
Code v1.133.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.133.0
|
||||||
|
|
||||||
|
## [4.132.0](https://github.com/coder/code-server/releases/tag/v4.132.0) - 2026-08-10
|
||||||
|
|
||||||
|
Code v1.132.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.132.0
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- When proxying, cookies were being decoded and re-encoded, which could cause
|
||||||
|
issues for applications that encode differently. Cookies are now passed
|
||||||
|
through unchanged (aside from stripping out code-server's session token).
|
||||||
|
|
||||||
|
## [4.131.0](https://github.com/coder/code-server/releases/tag/v4.131.0) - 2026-07-30
|
||||||
|
|
||||||
|
Code v1.131.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.131.0
|
||||||
|
|
||||||
|
## [4.130.0](https://github.com/coder/code-server/releases/tag/v4.130.0) - 2026-07-24
|
||||||
|
|
||||||
|
Code v1.130.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.130.0
|
||||||
|
|
||||||
|
## [4.129.0](https://github.com/coder/code-server/releases/tag/v4.129.0) - 2026-07-17
|
||||||
|
|
||||||
|
Code v1.129.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.129.0
|
||||||
|
|
||||||
|
## [4.128.0](https://github.com/coder/code-server/releases/tag/v4.128.0) - 2026-07-11
|
||||||
|
|
||||||
|
Code v1.128.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.128.0
|
||||||
|
|
||||||
|
## [4.127.0](https://github.com/coder/code-server/releases/tag/v4.127.0) - 2026-07-02
|
||||||
|
|
||||||
|
Code v1.127.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.127.0
|
||||||
|
|
||||||
|
## [4.126.0](https://github.com/coder/code-server/releases/tag/v4.126.0) - 2026-06-24
|
||||||
|
|
||||||
|
Code v1.126.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.126.0
|
||||||
|
|
||||||
|
## [4.125.0](https://github.com/coder/code-server/releases/tag/v4.125.0) - 2026-06-18
|
||||||
|
|
||||||
|
Code v1.125.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.125.0
|
||||||
|
|
||||||
|
## [4.124.2](https://github.com/coder/code-server/releases/tag/v4.124.2) - 2026-06-16
|
||||||
|
|
||||||
|
Code v1.124.2
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Strip code-server's session token from the cookie before proxying to a local
|
||||||
|
port. Previously, when you used built-in password authentication, the cookie
|
||||||
|
would be sent to the local proxied port, which meant if the service was
|
||||||
|
malicious and not already running as your code-server user it could use the
|
||||||
|
cookie to log into code-server and execute commands as your code-server user.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.124.2
|
||||||
|
|
||||||
|
## [4.123.0](https://github.com/coder/code-server/releases/tag/v4.123.0) - 2026-06-03
|
||||||
|
|
||||||
|
Code v1.123.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.123.0
|
||||||
|
- Microsoft dropped support for armhf remotes so there will no longer be any
|
||||||
|
builds for armhf.
|
||||||
|
|
||||||
|
## [4.122.1](https://github.com/coder/code-server/releases/tag/v4.122.1) - 2026-06-02
|
||||||
|
|
||||||
|
Code v1.122.1
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.122.1
|
||||||
|
|
||||||
|
## [4.122.0](https://github.com/coder/code-server/releases/tag/v4.122.0) - 2026-05-29
|
||||||
|
|
||||||
|
Code v1.122.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.122.0
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `--app-name` will now affect window titles within the editor (it is now used
|
||||||
|
as the value for `${appName}` in the title template) as well as some other
|
||||||
|
places like the help > about dialog.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- App name can now be set with the `CODE_SERVER_APP_NAME` environment variable.
|
||||||
|
|
||||||
|
## [4.121.0](https://github.com/coder/code-server/releases/tag/v4.121.0) - 2026-05-20
|
||||||
|
|
||||||
|
Code v1.121.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.121.0
|
||||||
|
|
||||||
|
## [4.118.0](https://github.com/coder/code-server/releases/tag/v4.118.0) - 2026-05-06
|
||||||
|
|
||||||
|
Code v1.118.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.118.0
|
||||||
|
|
||||||
|
## [4.117.0](https://github.com/coder/code-server/releases/tag/v4.117.0) - 2026-04-22
|
||||||
|
|
||||||
|
Code v1.117.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.117.0
|
||||||
|
|
||||||
|
## [4.116.0](https://github.com/coder/code-server/releases/tag/v4.116.0) - 2026-04-16
|
||||||
|
|
||||||
|
Code v1.116.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.116.0
|
||||||
|
|
||||||
|
## [4.115.0](https://github.com/coder/code-server/releases/tag/v4.115.0) - 2026-04-08
|
||||||
|
|
||||||
|
Code v1.115.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.115.0
|
||||||
|
|
||||||
|
## [4.114.1](https://github.com/coder/code-server/releases/tag/v4.114.1) - 2026-04-06
|
||||||
|
|
||||||
|
Code v1.114.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Ensure native modules are built from source so they use the correct version of
|
||||||
|
glibc. This should bring down the requirement from 2.34 back down to 2.28.
|
||||||
|
|
||||||
|
## [4.114.0](https://github.com/coder/code-server/releases/tag/v4.114.0) - 2026-04-04
|
||||||
|
|
||||||
|
Code v1.114.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.114.0.
|
||||||
|
|
||||||
|
## [4.113.1](https://github.com/coder/code-server/releases/tag/v4.113.1) - 2026-04-03
|
||||||
|
|
||||||
|
Code v1.113.0
|
||||||
|
|
||||||
|
This is a re-release of v4.113.0 but with the correct Node binaries for arm64
|
||||||
|
and armv7l. Previously they were packaging the amd64 Node binary due to a
|
||||||
|
mistake while refactoring CI to use more of the upstream build scripts.
|
||||||
|
|
||||||
|
## [4.113.0](https://github.com/coder/code-server/releases/tag/v4.113.0) - 2026-04-02
|
||||||
|
|
||||||
|
Code v1.113.0
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Update to Code 1.113.0
|
||||||
|
|
||||||
## [4.112.0](https://github.com/coder/code-server/releases/tag/v4.112.0) - 2026-03-19
|
## [4.112.0](https://github.com/coder/code-server/releases/tag/v4.112.0) - 2026-03-19
|
||||||
|
|
||||||
Code v1.112.0
|
Code v1.112.0
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ main() {
|
|||||||
|
|
||||||
release_archive() {
|
release_archive() {
|
||||||
local release_name="code-server-$VERSION-$OS-$ARCH"
|
local release_name="code-server-$VERSION-$OS-$ARCH"
|
||||||
if [[ $OS == "linux" ]]; then
|
if [[ $OS == "linux" || $OS == "windows" ]]; then
|
||||||
tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
|
tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
|
||||||
else
|
else
|
||||||
tar -czf "release-packages/$release_name.tar.gz" -s "/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
|
tar -czf "release-packages/$release_name.tar.gz" -s "/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
|
||||||
|
|||||||
+29
-12
@@ -36,18 +36,16 @@ main() {
|
|||||||
rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
|
rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
|
||||||
|
|
||||||
if [ "$KEEP_MODULES" = 1 ]; then
|
if [ "$KEEP_MODULES" = 1 ]; then
|
||||||
# Copy Node. Package managers may shim their own "node" wrapper into the
|
|
||||||
# PATH, so run node and ask it for its true path.
|
|
||||||
local node_path
|
|
||||||
node_path="$(node -p process.execPath)"
|
|
||||||
rsync "$node_path" "$RELEASE_PATH/lib/node"
|
|
||||||
chmod 755 "$RELEASE_PATH/lib/node"
|
|
||||||
|
|
||||||
# Copy the code-server launcher.
|
# Copy the code-server launcher.
|
||||||
mkdir -p "$RELEASE_PATH/bin"
|
mkdir -p "$RELEASE_PATH/bin"
|
||||||
rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
|
rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
|
||||||
chmod 755 "$RELEASE_PATH/bin/code-server"
|
chmod 755 "$RELEASE_PATH/bin/code-server"
|
||||||
|
|
||||||
|
# Windows cannot run the shell launcher, so it gets one of its own.
|
||||||
|
if [ "$OS" = windows ]; then
|
||||||
|
rsync ./ci/build/code-server.cmd "$RELEASE_PATH/bin/code-server.cmd"
|
||||||
|
fi
|
||||||
|
|
||||||
# Delete the extra bin scripts.
|
# Delete the extra bin scripts.
|
||||||
rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code-darwin.sh"
|
rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code-darwin.sh"
|
||||||
rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code-linux.sh"
|
rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code-linux.sh"
|
||||||
@@ -86,7 +84,15 @@ EOF
|
|||||||
mv npm-shrinkwrap.json "$RELEASE_PATH"
|
mv npm-shrinkwrap.json "$RELEASE_PATH"
|
||||||
|
|
||||||
if [ "$KEEP_MODULES" = 1 ]; then
|
if [ "$KEEP_MODULES" = 1 ]; then
|
||||||
rsync node_modules/ "$RELEASE_PATH/node_modules"
|
local rsync_opts=(-a)
|
||||||
|
if [[ ${DEBUG-} = 1 ]]; then
|
||||||
|
rsync_opts+=(-vh)
|
||||||
|
fi
|
||||||
|
# If we build from source, exclude the prebuilds.
|
||||||
|
if [[ ${npm_config_build_from_source-} = true ]]; then
|
||||||
|
rsync_opts+=(--exclude /argon2/prebuilds)
|
||||||
|
fi
|
||||||
|
rsync "${rsync_opts[@]}" node_modules/ "$RELEASE_PATH/node_modules"
|
||||||
# Remove dev dependencies.
|
# Remove dev dependencies.
|
||||||
pushd "$RELEASE_PATH"
|
pushd "$RELEASE_PATH"
|
||||||
npm prune --production
|
npm prune --production
|
||||||
@@ -99,7 +105,7 @@ EOF
|
|||||||
bundle_vscode() {
|
bundle_vscode() {
|
||||||
mkdir -p "$VSCODE_OUT_PATH"
|
mkdir -p "$VSCODE_OUT_PATH"
|
||||||
|
|
||||||
local rsync_opts=()
|
local rsync_opts=(-a)
|
||||||
if [[ ${DEBUG-} = 1 ]]; then
|
if [[ ${DEBUG-} = 1 ]]; then
|
||||||
rsync_opts+=(-vh)
|
rsync_opts+=(-vh)
|
||||||
fi
|
fi
|
||||||
@@ -108,9 +114,9 @@ bundle_vscode() {
|
|||||||
# npm package so exclude any .gitignore files.
|
# npm package so exclude any .gitignore files.
|
||||||
rsync_opts+=(--exclude .gitignore)
|
rsync_opts+=(--exclude .gitignore)
|
||||||
|
|
||||||
# Exclude Node as we will add it ourselves for the standalone and will not
|
# Exclude Node since we want to place it in a directory above.
|
||||||
# need it for the npm package.
|
|
||||||
rsync_opts+=(--exclude /node)
|
rsync_opts+=(--exclude /node)
|
||||||
|
rsync_opts+=(--exclude /node.exe)
|
||||||
|
|
||||||
# Exclude Node modules. Note that these will already only include production
|
# Exclude Node modules. Note that these will already only include production
|
||||||
# dependencies, so if we do keep them there is no need to do any
|
# dependencies, so if we do keep them there is no need to do any
|
||||||
@@ -121,9 +127,20 @@ bundle_vscode() {
|
|||||||
|
|
||||||
rsync "${rsync_opts[@]}" "./lib/vscode-reh-web-$VSCODE_TARGET/" "$VSCODE_OUT_PATH"
|
rsync "${rsync_opts[@]}" "./lib/vscode-reh-web-$VSCODE_TARGET/" "$VSCODE_OUT_PATH"
|
||||||
|
|
||||||
|
# Copy the Node binary.
|
||||||
|
if [[ $KEEP_MODULES = 1 ]]; then
|
||||||
|
if [ "$OS" = windows ]; then
|
||||||
|
cp "./lib/vscode-reh-web-$VSCODE_TARGET/node.exe" "$RELEASE_PATH/lib"
|
||||||
|
else
|
||||||
|
cp "./lib/vscode-reh-web-$VSCODE_TARGET/node" "$RELEASE_PATH/lib"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Merge the package.json for the web/remote server so we can include
|
# Merge the package.json for the web/remote server so we can include
|
||||||
# dependencies, since we want to ship this via NPM.
|
# dependencies, since we want to ship this via NPM.
|
||||||
jq --slurp '.[0] * .[1]' \
|
# Also override the name to prevent vulnerability scanners from
|
||||||
|
# misidentifying this package as VS Code (see #7071).
|
||||||
|
jq --slurp '.[0] * .[1] | .name = "code-oss"' \
|
||||||
"$VSCODE_SRC_PATH/remote/package.json" \
|
"$VSCODE_SRC_PATH/remote/package.json" \
|
||||||
"$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
|
"$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
|
||||||
mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"
|
mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ fix-bin-script() {
|
|||||||
# Fix Node path on Windows.
|
# Fix Node path on Windows.
|
||||||
sed -i.bak 's/^set ROOT_DIR=\(.*\)$/set ROOT_DIR=%~dp0..\\..\\..\\..\r\nset VSROOT_DIR=\1/g' "$script"
|
sed -i.bak 's/^set ROOT_DIR=\(.*\)$/set ROOT_DIR=%~dp0..\\..\\..\\..\r\nset VSROOT_DIR=\1/g' "$script"
|
||||||
sed -i.bak 's/%ROOT_DIR%\\out/%VSROOT_DIR%\\out/g' "$script"
|
sed -i.bak 's/%ROOT_DIR%\\out/%VSROOT_DIR%\\out/g' "$script"
|
||||||
|
sed -i.bak 's/%ROOT_DIR%\\node.exe/%ROOT_DIR%\\lib\\node.exe/g' "$script"
|
||||||
|
|
||||||
chmod +x "$script"
|
chmod +x "$script"
|
||||||
rm "$script.bak"
|
rm "$script.bak"
|
||||||
@@ -57,10 +58,17 @@ main() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add the date, our name, links, enable telemetry (this just makes telemetry
|
# Modify the product.json:
|
||||||
# available; telemetry can still be disabled by flag or setting), and
|
# - Add the date
|
||||||
# configure trusted extensions (since some, like github.copilot-chat, never
|
# - Set the code-server name.
|
||||||
# ask to be trusted and this is the only way to get auth working).
|
# - Add our links
|
||||||
|
# - Enable telemetry (this just makes telemetry available; telemetry can still
|
||||||
|
# be disabled by flag or setting)
|
||||||
|
# - Configure trusted extensions (since some, like github.copilot-chat, never
|
||||||
|
# ask to be trusted and this is the only way to get auth working).
|
||||||
|
# - Make Typescript server plugins run in the workspace. We build the remote
|
||||||
|
# server version, so there is no browser distribution, and this key is not
|
||||||
|
# added automatically.
|
||||||
#
|
#
|
||||||
# This needs to be done before building as Code will read this file and embed
|
# This needs to be done before building as Code will read this file and embed
|
||||||
# it into the client-side code.
|
# it into the client-side code.
|
||||||
@@ -102,11 +110,17 @@ main() {
|
|||||||
],
|
],
|
||||||
"aiConfig": {
|
"aiConfig": {
|
||||||
"ariaKey": "code-server"
|
"ariaKey": "code-server"
|
||||||
|
},
|
||||||
|
"extensionPointExtensionKind": {
|
||||||
|
"typescriptServerPlugins": ["workspace"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
) > product.json
|
) > product.json
|
||||||
|
|
||||||
|
|
||||||
|
VSCODE_QUALITY=stable npm run gulp compile-copilot-extension-full-build
|
||||||
|
|
||||||
npm run gulp core-ci
|
npm run gulp core-ci
|
||||||
npm run gulp "vscode-reh-web-$VSCODE_TARGET${MINIFY:+-min}-ci"
|
npm run gulp "vscode-reh-web-$VSCODE_TARGET${MINIFY:+-min}-ci"
|
||||||
|
|
||||||
@@ -129,7 +143,7 @@ EOF
|
|||||||
# Set vars and fix paths.
|
# Set vars and fix paths.
|
||||||
case $OS in
|
case $OS in
|
||||||
windows)
|
windows)
|
||||||
fix-bin-script remote-cli/code.cmd
|
fix-bin-script remote-cli/code-server.cmd
|
||||||
fix-bin-script helpers/browser.cmd
|
fix-bin-script helpers/browser.cmd
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
rem This script is intended to be bundled into the standalone releases.
|
||||||
|
rem Runs code-server with the bundled node binary.
|
||||||
|
|
||||||
|
setlocal
|
||||||
|
set "ROOT=%~dp0.."
|
||||||
|
"%ROOT%\lib\node.exe" "%ROOT%" %*
|
||||||
@@ -18,7 +18,7 @@ symlink() {
|
|||||||
dest="$2"
|
dest="$2"
|
||||||
rm -rf "$dest"
|
rm -rf "$dest"
|
||||||
case $OS in
|
case $OS in
|
||||||
windows) mklink /J "$dest" "$source" ;;
|
windows) cmd //c mklink //J "$dest" "$source" ;;
|
||||||
*) ln -s "$source" "$dest" ;;
|
*) ln -s "$source" "$dest" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -65,9 +65,9 @@ main() {
|
|||||||
echo "USE AT YOUR OWN RISK!"
|
echo "USE AT YOUR OWN RISK!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then
|
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-24}" ]; then
|
||||||
echo "ERROR: code-server currently requires node v22."
|
echo "ERROR: code-server currently requires node v24."
|
||||||
if [ -n "$FORCE_NODE_VERSION" ]; then
|
if [ -n "${FORCE_NODE_VERSION:-}" ]; then
|
||||||
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
||||||
fi
|
fi
|
||||||
echo "We have detected that you are on node v$major_node_version"
|
echo "We have detected that you are on node v$major_node_version"
|
||||||
@@ -76,20 +76,6 @@ main() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Under npm, if we are running as root, we need --unsafe-perm otherwise
|
|
||||||
# post-install scripts will not have sufficient permissions to do their thing.
|
|
||||||
if is_root; then
|
|
||||||
case "${npm_config_user_agent-}" in npm*)
|
|
||||||
if [ "${npm_config_unsafe_perm-}" != "true" ]; then
|
|
||||||
echo "Please pass --unsafe-perm to npm to install code-server"
|
|
||||||
echo "Otherwise post-install scripts will not have permissions to run"
|
|
||||||
echo "See https://docs.npmjs.com/misc/config#unsafe-perm"
|
|
||||||
echo "See https://stackoverflow.com/questions/49084929/npm-sudo-global-installation-unsafe-perm"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! vscode_install; then
|
if ! vscode_install; then
|
||||||
echo "You may not have the required dependencies to build the native modules."
|
echo "You may not have the required dependencies to build the native modules."
|
||||||
@@ -110,7 +96,7 @@ install_with_yarn_or_npm() {
|
|||||||
# end-user we want to keep using whatever package manager is in use.
|
# end-user we want to keep using whatever package manager is in use.
|
||||||
case "${npm_config_user_agent-}" in
|
case "${npm_config_user_agent-}" in
|
||||||
npm*)
|
npm*)
|
||||||
if ! npm install --unsafe-perm --omit=dev; then
|
if ! npm install --omit=dev; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|||||||
Executable
+96
@@ -0,0 +1,96 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
# Given versions $1 and $2 figure out the first component that is different
|
||||||
|
# (major, minor, patch).
|
||||||
|
function find_version_diff() {
|
||||||
|
# shellcheck disable=SC2206
|
||||||
|
local a=( ${1//./ } )
|
||||||
|
# shellcheck disable=SC2206
|
||||||
|
local b=( ${2//./ } )
|
||||||
|
|
||||||
|
if [[ ${a[0]} != "${b[0]}" ]] ; then
|
||||||
|
echo major
|
||||||
|
elif [[ ${a[1]} != "${b[1]}" ]] ; then
|
||||||
|
echo minor
|
||||||
|
else
|
||||||
|
echo patch
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Bump $1 by the bump type (major, minor, patch) in $2.
|
||||||
|
function bump_version() {
|
||||||
|
# shellcheck disable=SC2206
|
||||||
|
local a=( ${1//./ } )
|
||||||
|
case $2 in
|
||||||
|
major)
|
||||||
|
((a[0]++))
|
||||||
|
a[1]=0
|
||||||
|
a[2]=0
|
||||||
|
;;
|
||||||
|
minor)
|
||||||
|
((a[1]++))
|
||||||
|
a[2]=0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
((a[2]++))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "${a[0]}.${a[1]}.${a[2]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_helm() {
|
||||||
|
local chart_version
|
||||||
|
chart_version=$(yq .version ci/helm-chart/Chart.yaml)
|
||||||
|
local app_version
|
||||||
|
app_version=$(yq .appVersion ci/helm-chart/Chart.yaml)
|
||||||
|
local image_version
|
||||||
|
image_version=$(yq .image.tag ci/helm-chart/values.yaml)
|
||||||
|
|
||||||
|
local bump_type
|
||||||
|
bump_type=$(find_version_diff "$app_version" "$version")
|
||||||
|
local chart_version_bump
|
||||||
|
chart_version_bump=$(bump_version "$chart_version" "$bump_type")
|
||||||
|
|
||||||
|
# Use sed to replace because yq will reformat.
|
||||||
|
echo "Bumping version from $chart_version to $chart_version_bump..."
|
||||||
|
sed -i.bak "s/^version: $chart_version\$/version: $chart_version_bump/" ci/helm-chart/Chart.yaml
|
||||||
|
|
||||||
|
echo "Bumping app version from $app_version to $version..."
|
||||||
|
sed -i.bak "s/^appVersion: .\+\$/appVersion: $version/" ci/helm-chart/Chart.yaml
|
||||||
|
|
||||||
|
echo "Bumping image version from $image_version to $version..."
|
||||||
|
sed -i.bak "s/^ tag: .\+\$/ tag: '$version'/" ci/helm-chart/values.yaml
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_changelog() {
|
||||||
|
local date
|
||||||
|
date=$(printf '%(%Y-%m-%d)T\n' -1)
|
||||||
|
local link="https://github.com/coder/code-server/releases/tag/v$version"
|
||||||
|
sed -i.bak "s|## Unreleased|## Unreleased\n\n## [$version]($link) - $date|" CHANGELOG.md
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
|
||||||
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
local version=${VERSION:-$(git describe --tags)}
|
||||||
|
version="${version#v}"
|
||||||
|
|
||||||
|
declare -a steps
|
||||||
|
|
||||||
|
steps+=(
|
||||||
|
"Update Helm chart" "update_helm"
|
||||||
|
"Update changelog" "update_changelog"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Even if a step failed, still output the last checkmark.
|
||||||
|
run-steps "${steps[@]}" || true
|
||||||
|
|
||||||
|
# This step is always manual.
|
||||||
|
echo "- [ ] https://github.com/coder/code-server-aur/pulls" >> .cache/checklist
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
Executable
+162
@@ -0,0 +1,162 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
function unapply_patches() {
|
||||||
|
local -i exit_code=0
|
||||||
|
quiet quilt pop -af 2>&1 || exit_code=$?
|
||||||
|
case $exit_code in
|
||||||
|
# Sucessfully unapplied.
|
||||||
|
0) ;;
|
||||||
|
# No more patches to unapply.
|
||||||
|
2) ;;
|
||||||
|
# Some error.
|
||||||
|
*) return $exit_code ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function apply_patches() {
|
||||||
|
local -i exit_code=0
|
||||||
|
quiet quilt push -a 2>&1 || exit_code=$?
|
||||||
|
case $exit_code in
|
||||||
|
# Sucessfully applied.
|
||||||
|
0) ;;
|
||||||
|
# No more patches to apply.
|
||||||
|
2) ;;
|
||||||
|
# Some error.
|
||||||
|
*) return $exit_code ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_vscode() {
|
||||||
|
pushd lib/vscode
|
||||||
|
if ! git checkout 2>&1 "$target_vscode_version" ; then
|
||||||
|
echo "$target_vscode_version does not exist locally, fetching..."
|
||||||
|
git fetch --all --prune --tags
|
||||||
|
echo "Checking out $target_vscode_version again..."
|
||||||
|
git checkout "$target_vscode_version"
|
||||||
|
fi
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_patches() {
|
||||||
|
local -i exit_code=0
|
||||||
|
while quiet quilt push 2>&1 ; ! (( exit_code=$? )) ; do
|
||||||
|
quilt refresh 2>&1
|
||||||
|
done
|
||||||
|
case $exit_code in
|
||||||
|
# No more patches to apply.
|
||||||
|
2) ;;
|
||||||
|
# Some error.
|
||||||
|
*) return $exit_code ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_node() {
|
||||||
|
local node_version
|
||||||
|
node_version=$(cat .node-version)
|
||||||
|
local target_node_version
|
||||||
|
target_node_version=$(grep target lib/vscode/remote/.npmrc | awk -F= '{print $2}' | tr -d '"')
|
||||||
|
if [[ $node_version == "$target_node_version" ]] ; then
|
||||||
|
echo "Already set to $target_node_version"
|
||||||
|
else
|
||||||
|
echo "Updating from $node_version to $target_node_version..."
|
||||||
|
echo "$target_node_version" > .node-version
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function get-webview-script-hash() {
|
||||||
|
local html
|
||||||
|
html=$(<"$1")
|
||||||
|
local start_tag='<script async type="module">'
|
||||||
|
if [[ $file == */webWorkerExtensionHostIframe.html ]] ; then
|
||||||
|
start_tag='<script>'
|
||||||
|
fi
|
||||||
|
local end_tag="</script>"
|
||||||
|
html=${html##*"$start_tag"}
|
||||||
|
html=${html%%"$end_tag"*}
|
||||||
|
echo -n "$html" | openssl sha256 -binary | openssl base64
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete_csp() {
|
||||||
|
quilt delete csp-hashes.diff || true
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_csp() {
|
||||||
|
apply_patches
|
||||||
|
|
||||||
|
local files=(
|
||||||
|
./lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||||
|
./lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||||
|
)
|
||||||
|
|
||||||
|
quilt new csp-hashes.diff
|
||||||
|
|
||||||
|
local file
|
||||||
|
for file in "${files[@]}" ; do
|
||||||
|
quilt add "$file"
|
||||||
|
|
||||||
|
local hash
|
||||||
|
hash=$(get-webview-script-hash "$file")
|
||||||
|
echo "Calculated hash as $hash"
|
||||||
|
# Use octothorpe as a delimiter since the hash may contain a slash.
|
||||||
|
sed -i.bak "s#'sha256-[^']\+'#'sha256-$hash'#" "$file"
|
||||||
|
done
|
||||||
|
|
||||||
|
quilt refresh
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_changelog() {
|
||||||
|
local file=CHANGELOG.md
|
||||||
|
if grep --quiet "Code $target_vscode_version" "$file" ; then
|
||||||
|
echo "Changelog for $target_vscode_version already exists"
|
||||||
|
else
|
||||||
|
# TODO: This is not exactly robust. In particular, it needs to handle if
|
||||||
|
# there is already a "changed" section.
|
||||||
|
sed -i.bak "s/## Unreleased/## Unreleased\n\nCode v$target_vscode_version\n\n### Changed\n\n- Update to Code $target_vscode_version/" "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
|
||||||
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
declare -a steps
|
||||||
|
|
||||||
|
# Hashes are always regenerated to avoid having to resolve conflicts..
|
||||||
|
steps+=("Revert CSP hashes" "delete_csp")
|
||||||
|
|
||||||
|
# If version is not set, assume we are already at the target version and the
|
||||||
|
# user is just trying to resolve conflics.
|
||||||
|
local target_vscode_version
|
||||||
|
if [[ ${VERSION-} ]] ; then
|
||||||
|
# Removing patches only needs to be done locally; in CI we start from a
|
||||||
|
# fresh clone each time.
|
||||||
|
if [[ ! ${CI-} ]] ; then
|
||||||
|
steps+=("Unapplying patches" "unapply_patches")
|
||||||
|
fi
|
||||||
|
target_vscode_version="${VERSION#v}"
|
||||||
|
steps+=(
|
||||||
|
"Update Code to $target_vscode_version" "update_vscode"
|
||||||
|
"Refresh Code patches" "refresh_patches"
|
||||||
|
)
|
||||||
|
else
|
||||||
|
target_vscode_version="$(git -C lib/vscode describe --tags --exact-match)"
|
||||||
|
echo "Detected Code version $target_vscode_version"
|
||||||
|
fi
|
||||||
|
|
||||||
|
steps+=(
|
||||||
|
"Update Node version" "update_node"
|
||||||
|
"Regenerate CSP hashes" "update_csp"
|
||||||
|
"Add changelog note" "add_changelog"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Even if a step failed, still output the last checkmark.
|
||||||
|
run-steps "${steps[@]}" || true
|
||||||
|
|
||||||
|
# This step is always manual.
|
||||||
|
echo "- [ ] Verify changelog" >> .cache/checklist
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
||||||
@@ -15,9 +15,9 @@ type: application
|
|||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# 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.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 3.33.0
|
version: 3.56.0
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# 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
|
# 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.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
appVersion: 4.109.5
|
appVersion: 4.141.0
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ metadata:
|
|||||||
annotations: {{- toYaml .Values.annotations | nindent 4 }}
|
annotations: {{- toYaml .Values.annotations | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
replicas: {{ .Values.replicaCount | default 1 }}
|
{{- if ne .Values.replicaCount nil }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
{{- end }}
|
||||||
strategy:
|
strategy:
|
||||||
type: Recreate
|
type: Recreate
|
||||||
selector:
|
selector:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
repository: codercom/code-server
|
repository: codercom/code-server
|
||||||
tag: '4.109.5'
|
tag: '4.141.0'
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|
||||||
# Specifies one or more secrets to be used when pulling images from a
|
# Specifies one or more secrets to be used when pulling images from a
|
||||||
@@ -34,6 +34,10 @@ serviceAccount:
|
|||||||
# Specifies annotations for deployment
|
# Specifies annotations for deployment
|
||||||
annotations: {}
|
annotations: {}
|
||||||
|
|
||||||
|
# code-server.labels -- The Deployment labels. See:
|
||||||
|
# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||||
|
labels: {}
|
||||||
|
|
||||||
podAnnotations: {}
|
podAnnotations: {}
|
||||||
|
|
||||||
podSecurityContext: {}
|
podSecurityContext: {}
|
||||||
|
|||||||
@@ -49,7 +49,10 @@ if [[ ! ${ARCH-} ]]; then
|
|||||||
export ARCH
|
export ARCH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! ${OS-} ]]; then
|
# Windows predefines OS as Windows_NT for every process, so on a windows shell
|
||||||
|
# the check below would always find a value and never call os(). That is not a
|
||||||
|
# name this build knows, so it does not count as one the caller chose.
|
||||||
|
if [[ ! ${OS-} || ${OS-} == "Windows_NT" ]]; then
|
||||||
OS=$(os)
|
OS=$(os)
|
||||||
export OS
|
export OS
|
||||||
fi
|
fi
|
||||||
@@ -78,6 +81,45 @@ nodeArch() {
|
|||||||
echo "$cpu"
|
echo "$cpu"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run-steps() {
|
||||||
|
local -i failed=0
|
||||||
|
mkdir -p .cache
|
||||||
|
rm -f .cache/checklist
|
||||||
|
while (( $# )) ; do
|
||||||
|
local name=$1 ; shift
|
||||||
|
local fn=$1 ; shift
|
||||||
|
echo "$name..."
|
||||||
|
# Only run if an earlier step has not failed.
|
||||||
|
# For all failed steps, write out an empty checkbox.
|
||||||
|
if [[ $failed == 0 ]] ; then
|
||||||
|
if $fn | indent ; then
|
||||||
|
echo "- [X] $name" >> .cache/checklist
|
||||||
|
else
|
||||||
|
((failed++))
|
||||||
|
echo "- [ ] $name" >> .cache/checklist
|
||||||
|
echo "Failed" | indent
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "- [ ] $name" >> .cache/checklist
|
||||||
|
echo "Skipped" | indent
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ $failed != 0 ]] ; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
quiet() {
|
||||||
|
"$@" >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
indent() {
|
||||||
|
local count=2
|
||||||
|
local space
|
||||||
|
space=$(printf "%${count}s")
|
||||||
|
sed "s/^/$space| /g"
|
||||||
|
}
|
||||||
|
|
||||||
# See gulpfile.reh.ts for available targets.
|
# See gulpfile.reh.ts for available targets.
|
||||||
if [[ ! ${VSCODE_TARGET-} ]]; then
|
if [[ ! ${VSCODE_TARGET-} ]]; then
|
||||||
VSCODE_TARGET="$(nodeOS)-$(nodeArch)"
|
VSCODE_TARGET="$(nodeOS)-$(nodeArch)"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ group "default" {
|
|||||||
"code-server-debian-12",
|
"code-server-debian-12",
|
||||||
"code-server-ubuntu-focal",
|
"code-server-ubuntu-focal",
|
||||||
"code-server-ubuntu-noble",
|
"code-server-ubuntu-noble",
|
||||||
|
"code-server-ubuntu-resolute",
|
||||||
"code-server-fedora-39",
|
"code-server-fedora-39",
|
||||||
"code-server-opensuse-tumbleweed",
|
"code-server-opensuse-tumbleweed",
|
||||||
]
|
]
|
||||||
@@ -73,7 +74,6 @@ target "code-server-debian-12" {
|
|||||||
target "code-server-ubuntu-focal" {
|
target "code-server-ubuntu-focal" {
|
||||||
dockerfile = "ci/release-image/Dockerfile"
|
dockerfile = "ci/release-image/Dockerfile"
|
||||||
tags = concat(
|
tags = concat(
|
||||||
gen_tags_for_docker_and_ghcr("ubuntu"),
|
|
||||||
gen_tags_for_docker_and_ghcr("focal"),
|
gen_tags_for_docker_and_ghcr("focal"),
|
||||||
)
|
)
|
||||||
args = {
|
args = {
|
||||||
@@ -86,6 +86,7 @@ target "code-server-ubuntu-noble" {
|
|||||||
dockerfile = "ci/release-image/Dockerfile"
|
dockerfile = "ci/release-image/Dockerfile"
|
||||||
tags = concat(
|
tags = concat(
|
||||||
gen_tags_for_docker_and_ghcr("noble"),
|
gen_tags_for_docker_and_ghcr("noble"),
|
||||||
|
gen_tags_for_docker_and_ghcr("ubuntu"),
|
||||||
)
|
)
|
||||||
args = {
|
args = {
|
||||||
BASE = "ubuntu:noble"
|
BASE = "ubuntu:noble"
|
||||||
@@ -93,6 +94,17 @@ target "code-server-ubuntu-noble" {
|
|||||||
platforms = ["linux/amd64", "linux/arm64"]
|
platforms = ["linux/amd64", "linux/arm64"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target "code-server-ubuntu-resolute" {
|
||||||
|
dockerfile = "ci/release-image/Dockerfile"
|
||||||
|
tags = concat(
|
||||||
|
gen_tags_for_docker_and_ghcr("resolute"),
|
||||||
|
)
|
||||||
|
args = {
|
||||||
|
BASE = "ubuntu:resolute"
|
||||||
|
}
|
||||||
|
platforms = ["linux/amd64", "linux/arm64"]
|
||||||
|
}
|
||||||
|
|
||||||
target "code-server-fedora-39" {
|
target "code-server-fedora-39" {
|
||||||
dockerfile = "ci/release-image/Dockerfile.fedora"
|
dockerfile = "ci/release-image/Dockerfile.fedora"
|
||||||
tags = concat(
|
tags = concat(
|
||||||
|
|||||||
+15
-12
@@ -31,7 +31,7 @@ The prerequisites for contributing to code-server are almost the same as those
|
|||||||
for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||||
Here is what is needed:
|
Here is what is needed:
|
||||||
|
|
||||||
- `node` v22.x
|
- `node` v24.x
|
||||||
- `git` v2.x or greater
|
- `git` v2.x or greater
|
||||||
- [`git-lfs`](https://git-lfs.github.com)
|
- [`git-lfs`](https://git-lfs.github.com)
|
||||||
- [`npm`](https://www.npmjs.com/)
|
- [`npm`](https://www.npmjs.com/)
|
||||||
@@ -93,17 +93,20 @@ commits first if you are doing this).
|
|||||||
|
|
||||||
### Version updates to Code
|
### Version updates to Code
|
||||||
|
|
||||||
1. Remove any patches with `quilt pop -a`.
|
PRs will be automatically created with updates to VS Code. If a patch cannot be
|
||||||
2. Update the `lib/vscode` submodule to the desired upstream version branch.
|
automatically resolved, it will be necessary to clone the branch, resolve the
|
||||||
1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
|
conflicts manually, and finish the update. To do this:
|
||||||
2. `git add lib && git commit -m "chore: update to Code <version>"`
|
|
||||||
3. Apply the patches one at a time (`quilt push`). If the application succeeds
|
1. Apply as many patches as possible `quilt push -a`.
|
||||||
but the lines changed, update the patch with `quilt refresh`. If there are
|
2. Once you hit a conflict, force apply with `quilt push -f`, manually add back
|
||||||
conflicts, then force apply with `quilt push -f`, manually add back the
|
the rejected code, then run `quilt refresh`.
|
||||||
rejected code, then run `quilt refresh`.
|
3. Once all patches have been resolved, run `./ci/build/update.sh` to finish the
|
||||||
4. From the code-server **project root**, run `npm install`.
|
update process.
|
||||||
5. Check the Node.js version that's used by Electron (which is shipped with VS
|
4. Commit all changes, push them up to the branch, and update the checklist in
|
||||||
Code. If necessary, update our version of Node.js to match.
|
the PR description.
|
||||||
|
|
||||||
|
Once the PR is ready, manually verify that the unreleased changelog section
|
||||||
|
contains all the changes going into this version before merging.
|
||||||
|
|
||||||
### Patching Code
|
### Patching Code
|
||||||
|
|
||||||
|
|||||||
+73
@@ -17,6 +17,7 @@
|
|||||||
- [Where is VS Code configuration stored?](#where-is-vs-code-configuration-stored)
|
- [Where is VS Code configuration stored?](#where-is-vs-code-configuration-stored)
|
||||||
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
|
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
|
||||||
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
|
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
|
||||||
|
- [Can I open a file at a specific line from a URL?](#can-i-open-a-file-at-a-specific-line-from-a-url)
|
||||||
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
|
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
|
||||||
- [How do I direct server-side requests through a proxy?](#how-do-i-direct-server-side-requests-through-a-proxy)
|
- [How do I direct server-side requests through a proxy?](#how-do-i-direct-server-side-requests-through-a-proxy)
|
||||||
- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
|
- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
|
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
|
||||||
- [How do I disable file download?](#how-do-i-disable-file-download)
|
- [How do I disable file download?](#how-do-i-disable-file-download)
|
||||||
- [Why do web views not work?](#why-do-web-views-not-work)
|
- [Why do web views not work?](#why-do-web-views-not-work)
|
||||||
|
- [Can I run code-server with systemd socket activation?](#can-i-run-code-server-with-systemd-socket-activation)
|
||||||
|
|
||||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
@@ -230,6 +232,39 @@ code-server tries the following in this order:
|
|||||||
3. The workspace or directory passed via the command line
|
3. The workspace or directory passed via the command line
|
||||||
4. The last opened workspace or directory
|
4. The last opened workspace or directory
|
||||||
|
|
||||||
|
## Can I open a file at a specific line from a URL?
|
||||||
|
|
||||||
|
Yes. In addition to `workspace` and `folder`, code-server supports VS Code's
|
||||||
|
`payload` query parameter, which can open a specific file — optionally at a
|
||||||
|
line and column — once the workbench loads.
|
||||||
|
|
||||||
|
`payload` is a URL-encoded JSON array of `[key, value]` string pairs. The
|
||||||
|
`openFile` key takes a `vscode-remote://<host>/<absolute path>` URI, where
|
||||||
|
`<host>` is the host you use to reach code-server. Add
|
||||||
|
`["gotoLineMode","true"]` to have a trailing `:line[:column]` suffix on the
|
||||||
|
path interpreted as a cursor position:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://code.example.com/?folder=/home/coder/project&payload=[["gotoLineMode","true"],["openFile","vscode-remote://code.example.com/home/coder/project/src/app.py:10:5"]]
|
||||||
|
```
|
||||||
|
|
||||||
|
(with the `payload` value URL-encoded). Notes:
|
||||||
|
|
||||||
|
- Paths must be absolute; there is no form relative to `folder`.
|
||||||
|
- This is upstream VS Code web behavior (the same mechanism vscode.dev uses),
|
||||||
|
so it works without any code-server-specific configuration.
|
||||||
|
|
||||||
|
For example, to generate links from a shell:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
# usage: code-link <absolute-file> [line[:column]]
|
||||||
|
HOST=code.example.com
|
||||||
|
payload="[[\"gotoLineMode\",\"true\"],[\"openFile\",\"vscode-remote://$HOST$1${2:+:$2}\"]]"
|
||||||
|
printf 'https://%s/?folder=%s&payload=%s\n' "$HOST" "$(dirname "$1")" \
|
||||||
|
"$(printf '%s' "$payload" | jq -sRr @uri)"
|
||||||
|
```
|
||||||
|
|
||||||
## How do I access my Documents/Downloads/Desktop folders in code-server on macOS?
|
## How do I access my Documents/Downloads/Desktop folders in code-server on macOS?
|
||||||
|
|
||||||
Newer versions of macOS require permission through a non-UNIX mechanism for
|
Newer versions of macOS require permission through a non-UNIX mechanism for
|
||||||
@@ -526,3 +561,41 @@ To fix this, you must either:
|
|||||||
create and trust a certificate manually).
|
create and trust a certificate manually).
|
||||||
- Disable security if your browser allows it. For example, in Chromium see
|
- Disable security if your browser allows it. For example, in Chromium see
|
||||||
`chrome://flags/#unsafely-treat-insecure-origin-as-secure`
|
`chrome://flags/#unsafely-treat-insecure-origin-as-secure`
|
||||||
|
|
||||||
|
## Can I run code-server with systemd socket activation?
|
||||||
|
|
||||||
|
Yes. Pass the inherited socket to code-server with `--socket-fd`. systemd
|
||||||
|
passes the first listening socket as file descriptor `3`.
|
||||||
|
|
||||||
|
Create a socket unit, `~/.config/systemd/user/code-server.socket`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Socket]
|
||||||
|
ListenStream=8080
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=sockets.target
|
||||||
|
```
|
||||||
|
|
||||||
|
And a matching service unit, `~/.config/systemd/user/code-server.service`:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/code-server --socket-fd 3
|
||||||
|
```
|
||||||
|
|
||||||
|
Then enable and start the socket:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
systemctl --user enable --now code-server.socket
|
||||||
|
```
|
||||||
|
|
||||||
|
code-server will start on the first connection and listen on the socket
|
||||||
|
systemd created. `--socket-fd` takes precedence over `--socket` and
|
||||||
|
`--bind-addr`/`--port`/`--host`, and `--socket-mode` is ignored because
|
||||||
|
systemd owns the socket's permissions.
|
||||||
|
|
||||||
|
Socket activation only changes how code-server binds; your usual
|
||||||
|
authentication still applies (it keeps prompting for the configured password
|
||||||
|
unless you set `--auth none`), so keep authentication enabled when exposing the
|
||||||
|
server.
|
||||||
|
|||||||
+3
-3
@@ -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
|
6. Exit the terminal using `exit` and then reopen the terminal
|
||||||
7. Install and use Node.js 22:
|
7. Install and use Node.js 24:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
nvm install 22
|
nvm install 24
|
||||||
nvm use 22
|
nvm use 24
|
||||||
```
|
```
|
||||||
|
|
||||||
8. Install code-server globally on device with: `npm install --global code-server`
|
8. Install code-server globally on device with: `npm install --global code-server`
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
- [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx)
|
- [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx)
|
||||||
- [Using a self-signed certificate](#using-a-self-signed-certificate)
|
- [Using a self-signed certificate](#using-a-self-signed-certificate)
|
||||||
- [TLS 1.3 and Safari](#tls-13-and-safari)
|
- [TLS 1.3 and Safari](#tls-13-and-safari)
|
||||||
|
- [Cloudflare Rocket Loader](#cloudflare-rocket-loader)
|
||||||
- [External authentication](#external-authentication)
|
- [External authentication](#external-authentication)
|
||||||
- [HTTPS and self-signed certificates](#https-and-self-signed-certificates)
|
- [HTTPS and self-signed certificates](#https-and-self-signed-certificates)
|
||||||
- [Accessing web services](#accessing-web-services)
|
- [Accessing web services](#accessing-web-services)
|
||||||
@@ -269,6 +270,26 @@ than TLS 1.3 you will need to add support for TLS 1.2 since Safari does not
|
|||||||
support TLS 1.3 for web sockets at the time of writing. If this is the case you
|
support TLS 1.3 for web sockets at the time of writing. If this is the case you
|
||||||
should see OSSStatus: 9836 in the browser console.
|
should see OSSStatus: 9836 in the browser console.
|
||||||
|
|
||||||
|
### Cloudflare Rocket Loader
|
||||||
|
|
||||||
|
If you serve code-server through Cloudflare, disable Rocket Loader for that
|
||||||
|
hostname. Rocket Loader rewrites inline `<script>` tags at the edge and
|
||||||
|
re-injects them from its own loader, and the re-injected scripts do not carry
|
||||||
|
the nonce in code-server's Content Security Policy, so the browser blocks them.
|
||||||
|
The result is a blank page: every request returns HTTP 200 and the server logs
|
||||||
|
look healthy, and the only console output is `Cannot determine URI for module
|
||||||
|
id!`.
|
||||||
|
|
||||||
|
Scope it with a Configuration Rule rather than turning it off zone-wide:
|
||||||
|
|
||||||
|
```
|
||||||
|
Expression: (http.host eq "code.example.com")
|
||||||
|
Setting: Rocket Loader -> Off
|
||||||
|
```
|
||||||
|
|
||||||
|
Adding `'unsafe-inline'` to the policy does not help, because CSP ignores it
|
||||||
|
whenever a nonce or hash is present.
|
||||||
|
|
||||||
## External authentication
|
## External authentication
|
||||||
|
|
||||||
If you want to use external authentication mechanism (e.g., Sign in with
|
If you want to use external authentication mechanism (e.g., Sign in with
|
||||||
|
|||||||
+15
-7
@@ -1,6 +1,6 @@
|
|||||||
# code-server Helm Chart
|
# 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.8.0-informational?style=flat-square)
|
[](https://img.shields.io/badge/Version-3.54.0-informational?style=flat-square) [](https://img.shields.io/badge/Type-application-informational?style=flat-square) [](https://img.shields.io/badge/AppVersion-4.139.1-informational?style=flat-square)
|
||||||
|
|
||||||
[code-server](https://github.com/coder/code-server) code-server is VS Code running
|
[code-server](https://github.com/coder/code-server) code-server is VS Code running
|
||||||
on a remote server, accessible through the browser.
|
on a remote server, accessible through the browser.
|
||||||
@@ -62,10 +62,12 @@ and their default values.
|
|||||||
| Key | Type | Default |
|
| Key | Type | Default |
|
||||||
| ------------------------------------------- | ------ | ------------------------ |
|
| ------------------------------------------- | ------ | ------------------------ |
|
||||||
| affinity | object | `{}` |
|
| affinity | object | `{}` |
|
||||||
|
| annotations | object | `{}` |
|
||||||
| extraArgs | list | `[]` |
|
| extraArgs | list | `[]` |
|
||||||
| extraConfigmapMounts | list | `[]` |
|
| extraConfigmapMounts | list | `[]` |
|
||||||
| extraContainers | string | `""` |
|
| extraContainers | string | `""` |
|
||||||
| extraInitContainers | string | `""` |
|
| extraInitContainers | string | `""` |
|
||||||
|
| extraPorts | list | `[]` |
|
||||||
| extraSecretMounts | list | `[]` |
|
| extraSecretMounts | list | `[]` |
|
||||||
| extraVars | list | `[]` |
|
| extraVars | list | `[]` |
|
||||||
| extraVolumeMounts | list | `[]` |
|
| extraVolumeMounts | list | `[]` |
|
||||||
@@ -73,26 +75,32 @@ and their default values.
|
|||||||
| hostnameOverride | string | `""` |
|
| hostnameOverride | string | `""` |
|
||||||
| image.pullPolicy | string | `"Always"` |
|
| image.pullPolicy | string | `"Always"` |
|
||||||
| image.repository | string | `"codercom/code-server"` |
|
| image.repository | string | `"codercom/code-server"` |
|
||||||
| image.tag | string | `"4.8.0"` |
|
| image.tag | string | `"4.139.1"` |
|
||||||
| imagePullSecrets | list | `[]` |
|
| imagePullSecrets | list | `[]` |
|
||||||
| ingress.enabled | bool | `false` |
|
| ingress.enabled | bool | `false` |
|
||||||
|
| ingress.ingressClassName | string | `""` |
|
||||||
|
| lifecycle.enabled | bool | `false` |
|
||||||
|
| livenessProbe.enabled | bool | `true` |
|
||||||
| nameOverride | string | `""` |
|
| nameOverride | string | `""` |
|
||||||
| nodeSelector | object | `{}` |
|
| nodeSelector | object | `{}` |
|
||||||
| persistence.accessMode | string | `"ReadWriteOnce"` |
|
| persistence.accessMode | string | `"ReadWriteOnce"` |
|
||||||
| persistence.annotations | object | `{}` |
|
| persistence.annotations | object | `{}` |
|
||||||
| persistence.enabled | bool | `true` |
|
| persistence.enabled | bool | `true` |
|
||||||
| persistence.size | string | `"1Gi"` |
|
| persistence.size | string | `"10Gi"` |
|
||||||
| podAnnotations | object | `{}` |
|
| podAnnotations | object | `{}` |
|
||||||
| podSecurityContext | object | `{}` |
|
| podSecurityContext | object | `{}` |
|
||||||
|
| priorityClassName | string | `""` |
|
||||||
|
| readinessProbe.enabled | bool | `true` |
|
||||||
| replicaCount | int | `1` |
|
| replicaCount | int | `1` |
|
||||||
| resources | object | `{}` |
|
| resources | object | `{}` |
|
||||||
| securityContext.enabled | bool | `true` |
|
| securityContext.enabled | bool | `true` |
|
||||||
| securityContext.fsGroup | int | `1000` |
|
| securityContext.fsGroup | int | `1000` |
|
||||||
| securityContext.runAsUser | int | `1000` |
|
| securityContext.runAsUser | int | `1000` |
|
||||||
| service.port | int | `8443` |
|
| service.port | int | `8080` |
|
||||||
| service.type | string | `"ClusterIP"` |
|
| service.type | string | `"ClusterIP"` |
|
||||||
|
| serviceAccount.annotations | object | `{}` |
|
||||||
| serviceAccount.create | bool | `true` |
|
| serviceAccount.create | bool | `true` |
|
||||||
| serviceAccount.name | string | `nil` |
|
| serviceAccount.name | string | `""` |
|
||||||
| tolerations | list | `[]` |
|
| tolerations | list | `[]` |
|
||||||
| volumePermissions.enabled | bool | `true` |
|
| volumePermissions.enabled | bool | `true` |
|
||||||
| volumePermissions.securityContext.runAsUser | int | `0` |
|
| volumePermissions.securityContext.runAsUser | int | `0` |
|
||||||
@@ -105,7 +113,7 @@ $ helm upgrade --install code-server \
|
|||||||
--set persistence.enabled=false
|
--set persistence.enabled=false
|
||||||
```
|
```
|
||||||
|
|
||||||
The above command sets the the persistence storage to false.
|
The above command sets the persistence storage to false.
|
||||||
|
|
||||||
Alternatively, a YAML file that specifies the values for the above parameters
|
Alternatively, a YAML file that specifies the values for the above parameters
|
||||||
can be provided while installing the chart. For example,
|
can be provided while installing the chart. For example,
|
||||||
@@ -114,7 +122,7 @@ can be provided while installing the chart. For example,
|
|||||||
$ helm upgrade --install code-server ci/helm-chart -f values.yaml
|
$ helm upgrade --install code-server ci/helm-chart -f values.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Tip**: You can use the default [values.yaml](values.yaml)
|
> **Tip**: You can use the default [values.yaml](../ci/helm-chart/values.yaml)
|
||||||
|
|
||||||
# Extra Containers
|
# Extra Containers
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -101,9 +101,8 @@ _exact_ same commands presented in the rest of this document.
|
|||||||
We recommend installing with `npm` when:
|
We recommend installing with `npm` when:
|
||||||
|
|
||||||
1. You aren't using a machine with `amd64` or `arm64`.
|
1. You aren't using a machine with `amd64` or `arm64`.
|
||||||
2. You are installing code-server on Windows.
|
2. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
|
||||||
3. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
|
3. You're running Alpine Linux or are using a non-glibc libc. See
|
||||||
4. You're running Alpine Linux or are using a non-glibc libc. See
|
|
||||||
[#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198)
|
[#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
@@ -296,8 +295,7 @@ You can install code-server using the [Helm package manager](https://coder.com/d
|
|||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
We currently [do not publish Windows
|
We currently [do not publish Windows
|
||||||
releases](https://github.com/coder/code-server/issues/1397). We recommend
|
releases](https://github.com/coder/code-server/issues/1397).
|
||||||
installing code-server onto Windows with [`npm`](#npm).
|
|
||||||
|
|
||||||
## Raspberry Pi
|
## Raspberry Pi
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -29,8 +29,7 @@ includes installing instructions based on your operating system.
|
|||||||
|
|
||||||
## Node.js version
|
## Node.js version
|
||||||
|
|
||||||
We use the same major version of Node.js shipped with Code's remote, which is
|
We use Node.js `24.x`. VS Code also [lists Node.js
|
||||||
currently `22.x`. VS Code also [lists Node.js
|
|
||||||
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||||
|
|
||||||
Using other versions of Node.js [may lead to unexpected
|
Using other versions of Node.js [may lead to unexpected
|
||||||
@@ -78,7 +77,7 @@ Proceed to [installing](#installing)
|
|||||||
## FreeBSD
|
## FreeBSD
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkg install -y git python npm-node22 pkgconf
|
pkg install -y git python npm-node24 pkgconf
|
||||||
pkg install -y libinotify
|
pkg install -y libinotify
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ npm config set python python3
|
|||||||
node -v
|
node -v
|
||||||
```
|
```
|
||||||
|
|
||||||
you will get Node version `v22`
|
you will get Node version `v24`
|
||||||
|
|
||||||
5. Now install code-server following our guide on [installing with npm](./npm.md)
|
5. Now install code-server following our guide on [installing with npm](./npm.md)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -436,7 +436,7 @@ install_npm() {
|
|||||||
fi
|
fi
|
||||||
echoh "Installing with npm."
|
echoh "Installing with npm."
|
||||||
echoh
|
echoh
|
||||||
"$sh_c" "$NPM_PATH" install -g "code-server@$VERSION" --unsafe-perm
|
"$sh_c" "$NPM_PATH" install -g "code-server@$VERSION"
|
||||||
NPM_BIN_DIR="\$($NPM_PATH bin -g)" echo_npm_postinstall
|
NPM_BIN_DIR="\$($NPM_PATH bin -g)" echo_npm_postinstall
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|||||||
+1
-1
Submodule lib/vscode updated: cfbea10c5f...2a59476c9b
Generated
+455
-316
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -39,14 +39,13 @@
|
|||||||
"@eslint/compat": "^1.2.0",
|
"@eslint/compat": "^1.2.0",
|
||||||
"@eslint/eslintrc": "^3.1.0",
|
"@eslint/eslintrc": "^3.1.0",
|
||||||
"@eslint/js": "^9.12.0",
|
"@eslint/js": "^9.12.0",
|
||||||
"@schemastore/package": "^0.0.10",
|
|
||||||
"@types/compression": "^1.7.3",
|
"@types/compression": "^1.7.3",
|
||||||
"@types/cookie-parser": "^1.4.4",
|
"@types/cookie-parser": "^1.4.4",
|
||||||
"@types/eslint__js": "^8.42.3",
|
"@types/eslint__js": "^8.42.3",
|
||||||
"@types/express": "^5.0.0",
|
"@types/express": "^5.0.0",
|
||||||
"@types/http-proxy": "1.17.7",
|
"@types/http-proxy": "1.17.7",
|
||||||
"@types/js-yaml": "^4.0.6",
|
"@types/js-yaml": "^4.0.6",
|
||||||
"@types/node": "22.x",
|
"@types/node": "24.x",
|
||||||
"@types/pem": "^1.14.1",
|
"@types/pem": "^1.14.1",
|
||||||
"@types/proxy-from-env": "^1.0.1",
|
"@types/proxy-from-env": "^1.0.1",
|
||||||
"@types/safe-compare": "^1.1.0",
|
"@types/safe-compare": "^1.1.0",
|
||||||
@@ -59,9 +58,9 @@
|
|||||||
"eslint-import-resolver-typescript": "^4.4.4",
|
"eslint-import-resolver-typescript": "^4.4.4",
|
||||||
"eslint-plugin-import": "^2.28.1",
|
"eslint-plugin-import": "^2.28.1",
|
||||||
"eslint-plugin-prettier": "^5.0.0",
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
"globals": "^16.1.0",
|
"globals": "^17.6.0",
|
||||||
"prettier": "3.6.2",
|
"prettier": "3.9.4",
|
||||||
"prettier-plugin-sh": "^0.18.0",
|
"prettier-plugin-sh": "^0.20.2",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "^5.6.2",
|
"typescript": "^5.6.2",
|
||||||
"typescript-eslint": "^8.8.0"
|
"typescript-eslint": "^8.8.0"
|
||||||
@@ -70,14 +69,15 @@
|
|||||||
"@coder/logger": "^3.0.1",
|
"@coder/logger": "^3.0.1",
|
||||||
"argon2": "^0.44.0",
|
"argon2": "^0.44.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
|
"cookie": "^1.1.1",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"express": "^5.0.1",
|
"express": "^5.0.1",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
"httpolyglot": "^0.1.2",
|
"httpolyglot": "^0.1.2",
|
||||||
"i18next": "^25.8.3",
|
"i18next": "^26.3.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^5.2.3",
|
||||||
"limiter": "^2.1.0",
|
"limiter": "^4.1.0",
|
||||||
"pem": "^1.14.8",
|
"pem": "^1.14.8",
|
||||||
"proxy-agent": "^6.3.1",
|
"proxy-agent": "^6.3.1",
|
||||||
"qs": "^6.15.0",
|
"qs": "^6.15.0",
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
"xdg-basedir": "^4.0.0"
|
"xdg-basedir": "^4.0.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "22.x"
|
"@types/node": "24.x"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"code-server": "out/node/entry.js"
|
"code-server": "out/node/entry.js"
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
"remote-development"
|
"remote-development"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "22"
|
"node": "24"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"transform": {
|
"transform": {
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
Apply --app-name to VS Code web page titles
|
||||||
|
|
||||||
|
VS Code's `${appName}` title variable comes from `productService.nameLong` in the
|
||||||
|
web client. code-server already injects per-request product configuration into
|
||||||
|
VS Code's web bootstrap, so set `nameShort`/`nameLong` from the existing
|
||||||
|
`--app-name` CLI arg there.
|
||||||
|
|
||||||
|
This keeps the patch minimal and makes browser tab titles honor `--app-name`
|
||||||
|
without changing unrelated product metadata.
|
||||||
|
|
||||||
|
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
|
@@ -40,6 +40,7 @@ export const serverOptions: OptionDescri
|
||||||
|
'disable-getting-started-override': { type: 'boolean' },
|
||||||
|
'locale': { type: 'string' },
|
||||||
|
'link-protection-trusted-domains': { type: 'string[]' },
|
||||||
|
+ 'app-name': { type: 'string' },
|
||||||
|
|
||||||
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
|
@@ -140,6 +141,7 @@ export interface ServerParsedArgs {
|
||||||
|
'disable-getting-started-override'?: boolean,
|
||||||
|
'locale'?: string
|
||||||
|
'link-protection-trusted-domains'?: string[],
|
||||||
|
+ 'app-name'?: string,
|
||||||
|
|
||||||
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
|
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
|
@@ -407,8 +407,11 @@ export class WebClientServer {
|
||||||
|
linkProtectionTrustedDomains.push(...this._productService.linkProtectionTrustedDomains);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ const appName = this._environmentService.args['app-name'];
|
||||||
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
|
+ nameShort: appName,
|
||||||
|
+ nameLong: appName,
|
||||||
|
rootEndpoint: rootBase,
|
||||||
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
+44
-43
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/network.ts
|
+++ code-server/lib/vscode/src/vs/base/common/network.ts
|
||||||
@@ -245,7 +245,9 @@ class RemoteAuthoritiesImpl {
|
@@ -256,7 +256,9 @@ class RemoteAuthoritiesImpl {
|
||||||
return URI.from({
|
return URI.from({
|
||||||
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
||||||
authority: `${host}:${port}`,
|
authority: `${host}:${port}`,
|
||||||
@@ -36,8 +36,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
|||||||
|
|
||||||
<!-- Disable pinch zooming -->
|
<!-- 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">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||||
@@ -27,9 +27,9 @@
|
@@ -29,9 +29,9 @@
|
||||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
<meta id="vscode-workbench-css-modules" data-settings="{{WORKBENCH_DEV_CSS_MODULES}}">
|
||||||
|
|
||||||
<!-- Workbench Icon/Manifest/CSS -->
|
<!-- Workbench Icon/Manifest/CSS -->
|
||||||
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||||
@@ -48,16 +48,16 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
|||||||
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
|
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
|
||||||
<style id="vscode-css-modules" type="text/css" media="screen"></style>
|
<style id="vscode-css-modules" type="text/css" media="screen"></style>
|
||||||
|
|
||||||
</head>
|
<!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
|
||||||
@@ -39,7 +39,7 @@
|
@@ -92,7 +92,7 @@
|
||||||
|
|
||||||
<!-- Startup (do not modify order of script tags!) -->
|
<!-- Startup (do not modify order of script tags!) -->
|
||||||
<script>
|
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||||
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
|
- const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location.origin).toString();
|
||||||
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
|
+ const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location).toString();
|
||||||
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
|
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||||
@@ -73,7 +73,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
|||||||
|
|
||||||
<!-- Disable pinch zooming -->
|
<!-- 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">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||||
@@ -24,9 +24,9 @@
|
@@ -25,9 +25,9 @@
|
||||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||||
|
|
||||||
<!-- Workbench Icon/Manifest/CSS -->
|
<!-- Workbench Icon/Manifest/CSS -->
|
||||||
@@ -85,16 +85,16 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
|||||||
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
|
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
|
||||||
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
|
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
|
||||||
|
|
||||||
</head>
|
<!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
|
||||||
@@ -36,7 +36,7 @@
|
@@ -88,7 +88,7 @@
|
||||||
|
|
||||||
<!-- Startup (do not modify order of script tags!) -->
|
<!-- Startup (do not modify order of script tags!) -->
|
||||||
<script>
|
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||||
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
|
- const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location.origin).toString();
|
||||||
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
|
+ const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location).toString();
|
||||||
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
|
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||||
Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
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.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
||||||
@@ -111,21 +111,31 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -246,7 +246,9 @@ export class WebClientServer {
|
@@ -146,7 +146,7 @@ export function createWorkbenchContentSe
|
||||||
|
'default-src \'self\';',
|
||||||
|
'img-src \'self\' https: data: blob:;',
|
||||||
|
'media-src \'self\';',
|
||||||
|
- `script-src 'self' 'unsafe-eval' ${nlsBaseUrl ?? ''} blob: 'nonce-${scriptNonce}' '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||||
|
+ `script-src 'self' 'unsafe-eval' ${nlsBaseUrl ?? ''} blob: 'nonce-${scriptNonce}' '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : ``};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||||
|
'child-src \'self\';',
|
||||||
|
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
||||||
|
'worker-src \'self\' data: blob:;',
|
||||||
|
@@ -307,8 +307,10 @@ export class WebClientServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prefix routes with basePath for clients
|
// Prefix routes with basePath for clients
|
||||||
- const basePath = getFirstHeader('x-forwarded-prefix') || this._basePath;
|
|
||||||
+ const rootBase = relativeRoot(getOriginalUrl(req))
|
+ const rootBase = relativeRoot(getOriginalUrl(req))
|
||||||
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
||||||
+ const basePath = vscodeBase || getFirstHeader('x-forwarded-prefix') || this._basePath;
|
const forwardedPrefix = getFirstHeader('x-forwarded-prefix');
|
||||||
|
- const basePath = forwardedPrefix && isSafeBasePath(forwardedPrefix) ? forwardedPrefix : this._basePath;
|
||||||
|
+ const basePath = vscodeBase || (forwardedPrefix && isSafeBasePath(forwardedPrefix) ? forwardedPrefix : this._basePath);
|
||||||
|
|
||||||
const queryConnectionToken = parsedUrl.query[connectionTokenQueryName];
|
const queryConnectionTokens = parsedUrl.searchParams.getAll(connectionTokenQueryName);
|
||||||
if (typeof queryConnectionToken === 'string') {
|
if (queryConnectionTokens.length === 1) {
|
||||||
@@ -285,10 +287,14 @@ export class WebClientServer {
|
@@ -345,10 +347,14 @@ export class WebClientServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
|
const useTestResolver = (!this._environmentService.isBuilt && !!this._environmentService.args['use-test-resolver']);
|
||||||
+ // For now we are getting the remote authority from the client to avoid
|
+ // For now we are getting the remote authority from the client to avoid
|
||||||
+ // needing specific configuration for reverse proxies to work. Set this to
|
+ // needing specific configuration for reverse proxies to work. Set this to
|
||||||
+ // something invalid to make sure we catch code that is using this value
|
+ // something invalid to make sure we catch code that is using this value
|
||||||
@@ -138,35 +148,26 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
);
|
);
|
||||||
if (!remoteAuthority) {
|
if (!remoteAuthority) {
|
||||||
return serveError(req, res, 400, `Bad request.`);
|
return serveError(req, res, 400, `Bad request.`);
|
||||||
@@ -335,6 +341,7 @@ export class WebClientServer {
|
@@ -395,6 +401,7 @@ export class WebClientServer {
|
||||||
|
|
||||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
+ rootEndpoint: rootBase,
|
+ rootEndpoint: rootBase,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||||
...this._productService.extensionsGallery,
|
@@ -446,7 +453,9 @@ export class WebClientServer {
|
||||||
@@ -388,7 +395,9 @@ export class WebClientServer {
|
|
||||||
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
|
|
||||||
WORKBENCH_WEB_BASE_URL: staticRoute,
|
WORKBENCH_WEB_BASE_URL: staticRoute,
|
||||||
WORKBENCH_NLS_URL,
|
WORKBENCH_NLS_URL,
|
||||||
- WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`
|
WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`,
|
||||||
+ WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`,
|
- WORKBENCH_SCRIPT_NONCE: scriptNonce
|
||||||
|
+ WORKBENCH_SCRIPT_NONCE: scriptNonce,
|
||||||
+ BASE: rootBase,
|
+ BASE: rootBase,
|
||||||
+ VS_BASE: basePath,
|
+ VS_BASE: basePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
// DEV ---------------------------------------------------------------------------------------
|
// DEV ---------------------------------------------------------------------------------------
|
||||||
@@ -425,7 +434,7 @@ export class WebClientServer {
|
@@ -542,3 +551,70 @@ export class WebClientServer {
|
||||||
'default-src \'self\';',
|
|
||||||
'img-src \'self\' https: data: blob:;',
|
|
||||||
'media-src \'self\';',
|
|
||||||
- `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
|
||||||
+ `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : ``};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
|
||||||
'child-src \'self\';',
|
|
||||||
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
|
||||||
'worker-src \'self\' data: blob:;',
|
|
||||||
@@ -498,3 +507,70 @@ export class WebClientServer {
|
|
||||||
return void res.end(data);
|
return void res.end(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,7 +242,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -66,6 +66,7 @@ export type ExtensionVirtualWorkspaceSup
|
@@ -98,6 +98,7 @@ export interface IDictationRuntimeProduc
|
||||||
|
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
readonly codeServerVersion?: string
|
readonly codeServerVersion?: string
|
||||||
@@ -263,7 +264,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
}
|
}
|
||||||
|
|
||||||
private startListening(): void {
|
private startListening(): void {
|
||||||
@@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
|
@@ -590,17 +591,6 @@ class WorkspaceProvider implements IWork
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,8 +281,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
-
|
-
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
// Find config by checking for DOM
|
// This script running at all means the page scripts were not blocked or rewritten.
|
||||||
@@ -604,8 +594,8 @@ function readCookie(name: string): strin
|
@@ -614,8 +604,8 @@ function readCookie(name: string): strin
|
||||||
if (!configElement || !configElementAttribute) {
|
if (!configElement || !configElementAttribute) {
|
||||||
throw new Error('Missing web configuration element');
|
throw new Error('Missing web configuration element');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||||
@@ -143,6 +143,7 @@ export interface NativeParsedArgs {
|
@@ -148,6 +148,7 @@ export interface NativeParsedArgs {
|
||||||
'disable-chromium-sandbox'?: boolean;
|
'disable-chromium-sandbox'?: boolean;
|
||||||
sandbox?: boolean;
|
sandbox?: boolean;
|
||||||
'enable-coi'?: boolean;
|
'enable-coi'?: boolean;
|
||||||
@@ -90,7 +90,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/node/argv.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||||
@@ -115,6 +115,7 @@ export const OPTIONS: OptionDescriptions
|
@@ -116,6 +116,7 @@ export const OPTIONS: OptionDescriptions
|
||||||
'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
|
'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
|
||||||
'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") },
|
'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") },
|
||||||
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
||||||
@@ -102,7 +102,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||||
@@ -77,6 +77,7 @@ const isSupportedForPipe = (optionId: ke
|
@@ -78,6 +78,7 @@ const isSupportedForPipe = (optionId: ke
|
||||||
case 'verbose':
|
case 'verbose':
|
||||||
case 'remote':
|
case 'remote':
|
||||||
case 'locate-shell-integration-path':
|
case 'locate-shell-integration-path':
|
||||||
@@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
|||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -300,6 +301,22 @@ export async function main(desc: Product
|
@@ -307,6 +308,22 @@ export async function main(desc: Product
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
Index: code-server/lib/vscode/build/gulpfile.extensions.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/build/gulpfile.extensions.ts
|
||||||
|
+++ code-server/lib/vscode/build/gulpfile.extensions.ts
|
||||||
|
@@ -291,6 +291,29 @@ export const compileCopilotExtensionBuil
|
||||||
|
task.task(compileCopilotExtensionBuildTask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
+ * Compiles the built-in copilot extension with proper `.vscodeignore` filtering
|
||||||
|
+ * and materializes native dependency shims (`node-pty`, `ripgrep`).
|
||||||
|
+ * Produces output equivalent to what CI ships from the pre-built VSIX.
|
||||||
|
+ *
|
||||||
|
+ * The result is placed in `.build/extensions/copilot/` and can be copied
|
||||||
|
+ * directly into a VS Code Insiders installation at:
|
||||||
|
+ * `<insiders>/resources/app/extensions/copilot/`
|
||||||
|
+ */
|
||||||
|
+export const compileCopilotExtensionFullBuildTask = task.define('compile-copilot-extension-full-build', task.series(
|
||||||
|
+ // Step 1: Clean previous copilot build output
|
||||||
|
+ task.define('clean-copilot-build', util.rimraf('.build/extensions/copilot')),
|
||||||
|
+ // Step 2: Build and package with proper `.vscodeignore` filtering
|
||||||
|
+ task.define('package-copilot-extension-full', () => ext.packageCopilotExtensionFullStream().pipe(gulp.dest('.build'))),
|
||||||
|
+ // Step 3: Materialize native dependency shims (`node-pty`, `ripgrep`)
|
||||||
|
+ task.define('copilot-extension-native-shims', () => {
|
||||||
|
+ const copilotExtDir = path.join(root, '.build', 'extensions', 'copilot');
|
||||||
|
+ ext.prepareCopilotExtensionNativeShims(copilotExtDir);
|
||||||
|
+ return Promise.resolve();
|
||||||
|
+ })
|
||||||
|
+));
|
||||||
|
+task.task(compileCopilotExtensionFullBuildTask);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
* Compiles the extensions for the build.
|
||||||
|
* This is essentially a helper task that combines {@link cleanExtensionsBuildTask}, {@link compileNonNativeExtensionsBuildTask} and {@link compileNativeExtensionsBuildTask}
|
||||||
|
*/
|
||||||
|
Index: code-server/lib/vscode/build/lib/extensions.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/build/lib/extensions.ts
|
||||||
|
+++ code-server/lib/vscode/build/lib/extensions.ts
|
||||||
|
@@ -21,6 +21,7 @@ import { getProductionDependencies } fro
|
||||||
|
import { type IExtensionDefinition, getExtensionStream } from './builtInExtensions.ts';
|
||||||
|
import { fetchUrls, fetchGithub } from './fetch.ts';
|
||||||
|
import { createTsgoStream, spawnTsgo } from './tsgo.ts';
|
||||||
|
+import { prepareBuiltInCopilotRipgrepShim } from './copilot.ts';
|
||||||
|
import watcher from './watch/index.ts';
|
||||||
|
|
||||||
|
import { createRequire } from 'module';
|
||||||
|
@@ -487,6 +488,116 @@ export function packageCopilotExtensionS
|
||||||
|
).pipe(util2.setExecutableBit(['**/*.sh']));
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * Package the built-in copilot extension as a properly filtered VSIX-equivalent.
|
||||||
|
+ * Unlike {@link packageCopilotExtensionStream}, this uses vsce.listFiles with
|
||||||
|
+ * PackageManager.Npm so that .vscodeignore is respected for dependency filtering,
|
||||||
|
+ * producing output equivalent to what CI ships from the pre-built VSIX.
|
||||||
|
+ */
|
||||||
|
+export function packageCopilotExtensionFullStream(): Stream {
|
||||||
|
+ const vsce = require('@vscode/vsce') as typeof import('@vscode/vsce');
|
||||||
|
+ const extensionPath = path.join(root, 'extensions', 'copilot');
|
||||||
|
+ if (!fs.existsSync(extensionPath)) {
|
||||||
|
+ return es.readArray([]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const esbuildConfigFileName = '.esbuild.mts';
|
||||||
|
+ const esbuildScript = path.join(extensionPath, esbuildConfigFileName);
|
||||||
|
+ if (!fs.existsSync(esbuildScript)) {
|
||||||
|
+ throw new Error(`Copilot esbuild script not found at ${esbuildScript}`);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const result = es.through();
|
||||||
|
+
|
||||||
|
+ // Step 1: Run esbuild to compile the extension
|
||||||
|
+ new Promise<void>((resolve, reject) => {
|
||||||
|
+ const proc = cp.execFile(process.argv[0], [esbuildScript], { cwd: extensionPath }, (error, _stdout, stderr) => {
|
||||||
|
+ if (error) {
|
||||||
|
+ return reject(error);
|
||||||
|
+ }
|
||||||
|
+ const matches = (stderr || '').match(/\> (.+): error: (.+)?/g);
|
||||||
|
+ fancyLog(`Bundled extension: ${ansiColors.yellow(path.join('copilot', esbuildConfigFileName))} with ${matches ? matches.length : 0} errors.`);
|
||||||
|
+ for (const match of matches || []) {
|
||||||
|
+ fancyLog.error(match);
|
||||||
|
+ }
|
||||||
|
+ return resolve();
|
||||||
|
+ });
|
||||||
|
+ proc.stdout!.on('data', (data) => {
|
||||||
|
+ fancyLog(`${ansiColors.green('esbuilding copilot')}: ${data.toString('utf8')}`);
|
||||||
|
+ });
|
||||||
|
+ }).then(() => {
|
||||||
|
+ // Step 2: Use `vsce.listFiles` with Npm package manager so `.vscodeignore`
|
||||||
|
+ // is applied to both source files AND `node_modules` dependencies.
|
||||||
|
+ // This is the key difference from `packageCopilotExtensionStream` which
|
||||||
|
+ // uses `PackageManager.None` and then blindly merges all production deps.
|
||||||
|
+ return vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Npm });
|
||||||
|
+ }).then(fileNames => {
|
||||||
|
+ const files = fileNames
|
||||||
|
+ .map(fileName => path.join(extensionPath, fileName))
|
||||||
|
+ .map(filePath => new File({
|
||||||
|
+ path: filePath,
|
||||||
|
+ stat: fs.statSync(filePath),
|
||||||
|
+ base: extensionPath,
|
||||||
|
+ contents: fs.createReadStream(filePath)
|
||||||
|
+ }));
|
||||||
|
+
|
||||||
|
+ es.readArray(files).pipe(result);
|
||||||
|
+ }).catch(err => {
|
||||||
|
+ console.error('Failed to package copilot extension:', err);
|
||||||
|
+ result.emit('error', err);
|
||||||
|
+ });
|
||||||
|
+
|
||||||
|
+ // Apply the same package.json cleanup as bundled extensions get
|
||||||
|
+ const cleaned = updateExtensionPackageJSON(
|
||||||
|
+ result.pipe(rename(p => p.dirname = `extensions/copilot/${p.dirname}`)),
|
||||||
|
+ (data: any) => {
|
||||||
|
+ delete data.scripts;
|
||||||
|
+ delete data.dependencies;
|
||||||
|
+ delete data.devDependencies;
|
||||||
|
+ if (data.main) {
|
||||||
|
+ data.main = data.main.replace('/out/', '/dist/');
|
||||||
|
+ }
|
||||||
|
+ return data;
|
||||||
|
+ }
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ return minifyExtensionResources(cleaned)
|
||||||
|
+ .pipe(util2.setExecutableBit(['**/*.sh']));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * Materializes native dependency shims (`node-pty`, `ripgrep`) into the copilot
|
||||||
|
+ * extension output at {@link outputDir}. Uses the root `node_modules` as the
|
||||||
|
+ * source for native binaries, targeting the current platform/arch.
|
||||||
|
+ *
|
||||||
|
+ * This is the equivalent of what {@link copyCopilotNativeDepsTask} in
|
||||||
|
+ * `gulpfile.vscode.ts` does during a full product build, but scoped to
|
||||||
|
+ * just the standalone copilot extension output.
|
||||||
|
+ *
|
||||||
|
+ * Failures are logged as warnings rather than throwing, since the copilot
|
||||||
|
+ * extension can still create shims at runtime if they are missing.
|
||||||
|
+ */
|
||||||
|
+export function prepareCopilotExtensionNativeShims(outputDir: string): void {
|
||||||
|
+ const platform = process.platform;
|
||||||
|
+ const arch = process.arch;
|
||||||
|
+ const appNodeModulesDir = path.join(root, 'node_modules');
|
||||||
|
+
|
||||||
|
+ if (!fs.existsSync(outputDir)) {
|
||||||
|
+ fancyLog.warn('[prepareCopilotExtensionNativeShims] Copilot extension not found at', outputDir, '- skipping shims');
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ prepareBuiltInCopilotRipgrepShim(platform, arch, outputDir, appNodeModulesDir);
|
||||||
|
+ fancyLog(`[prepareCopilotExtensionNativeShims] Materialized native shims for ${platform}-${arch}`);
|
||||||
|
+ } catch (err) {
|
||||||
|
+ // Downgrade to a warning for local builds since the extension
|
||||||
|
+ // can still function without shims (it creates them at runtime).
|
||||||
|
+ fancyLog.warn(`[prepareCopilotExtensionNativeShims] Failed to materialize shims: ${err}`);
|
||||||
|
+ fancyLog.warn('[prepareCopilotExtensionNativeShims] The extension will still work but will create shims at runtime.');
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
export function packageMarketplaceExtensionsStream(forWeb: boolean): Stream {
|
||||||
|
const marketplaceExtensionsDescriptions = [
|
||||||
|
...builtInExtensions.filter(({ name }) => (forWeb ? !marketplaceWebExtensionsExclude.has(name) : true)),
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||||
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||||
|
@@ -5,7 +5,7 @@
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
|
<meta http-equiv="Content-Security-Policy"
|
||||||
|
- content="default-src 'none'; script-src 'sha256-FFQoOVVa2tOE3uqUvirwaMNT20TZmrHcL2aaOjJ8BUo=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||||
|
+ content="default-src 'none'; script-src 'sha256-24QqbpzqcqSyIGvg/ZwFRy5pPlhmVBa8CkUREEIUnBw=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||||
|
|
||||||
|
<!-- Disable pinch zooming -->
|
||||||
|
<meta name="viewport"
|
||||||
|
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-daEgfo2VIXpx2Np71KqCCbkeQwv+68vPrx54XRcbdcs=' https: http://localhost:* blob:;
|
||||||
|
+ script-src 'self' 'unsafe-eval' 'sha256-gfjiOVjAlxqrivZAfTq2d83mOaz0fnAxbGaFpj5IjD8=' https: http://localhost:* blob:;
|
||||||
|
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
@@ -7,8 +7,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||||
@@ -342,6 +342,10 @@ export class Extension implements IExten
|
@@ -343,6 +343,10 @@ export class Extension implements IExten
|
||||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
+ // Do not update builtin extensions.
|
+ // Do not update builtin extensions.
|
||||||
|
|||||||
@@ -9,16 +9,16 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||||
@@ -12,7 +12,7 @@ import * as path from '../../base/common
|
@@ -13,7 +13,7 @@ import { IURITransformer } from '../../b
|
||||||
import { IURITransformer } from '../../base/common/uriIpc.js';
|
import { generateUuid } from '../../base/common/uuid.js';
|
||||||
import { getMachineId, getSqmMachineId, getDevDeviceId } from '../../base/node/id.js';
|
import { getMachineId, getSqmMachineId, getDevDeviceId } from '../../base/node/id.js';
|
||||||
import { Promises } from '../../base/node/pfs.js';
|
import { Promises } from '../../base/node/pfs.js';
|
||||||
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
|
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
|
||||||
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
|
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
|
||||||
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
||||||
|
import { createRandomIPCHandle } from '../../base/parts/ipc/node/ipc.net.js';
|
||||||
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||||
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
|
@@ -418,6 +418,9 @@ export async function setupServerService
|
||||||
@@ -297,6 +297,9 @@ export async function setupServerService
|
|
||||||
|
|
||||||
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));
|
socketServer.registerChannel('mcpManagement', new McpManagementChannel(mcpManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)));
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ Index: code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
|||||||
import type { INLSConfiguration } from '../../nls.js';
|
import type { INLSConfiguration } from '../../nls.js';
|
||||||
@@ -33,7 +35,94 @@ export async function getNLSConfiguratio
|
@@ -33,7 +35,94 @@ export async function getNLSConfiguratio
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = resolveNLSConfiguration({ userLocale: language, osLocale: language, commit: product.commit, userDataPath, nlsMetadataPath });
|
result = resolveNLSConfiguration({ userLocale: language, osLocale: language, commit: product.commit, nlsMetadataHash: product.nlsMetadataHash, userDataPath, nlsMetadataPath });
|
||||||
nlsConfigurationCache.set(cacheKey, result);
|
nlsConfigurationCache.set(cacheKey, result);
|
||||||
+ // If the language pack does not yet exist, it defaults to English, which is
|
+ // If the language pack does not yet exist, it defaults to English, which is
|
||||||
+ // then cached and you have to restart even if you then install the pack.
|
+ // then cached and you have to restart even if you then install the pack.
|
||||||
@@ -153,7 +153,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -25,6 +25,7 @@ import { URI } from '../../base/common/u
|
@@ -24,6 +24,7 @@ import { URI } from '../../base/common/u
|
||||||
import { streamToBuffer } from '../../base/common/buffer.js';
|
import { streamToBuffer } from '../../base/common/buffer.js';
|
||||||
import { IProductConfiguration } from '../../base/common/product.js';
|
import { IProductConfiguration } from '../../base/common/product.js';
|
||||||
import { isString, Mutable } from '../../base/common/types.js';
|
import { isString, Mutable } from '../../base/common/types.js';
|
||||||
@@ -161,7 +161,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
import { CharCode } from '../../base/common/charCode.js';
|
import { CharCode } from '../../base/common/charCode.js';
|
||||||
import { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
|
import { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
|
||||||
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
|
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
|
||||||
@@ -386,14 +387,22 @@ export class WebClientServer {
|
@@ -442,14 +443,22 @@ export class WebClientServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
const cookies = cookie.parse(req.headers.cookie || '');
|
const cookies = cookie.parse(req.headers.cookie || '');
|
||||||
@@ -171,7 +171,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
let WORKBENCH_NLS_URL: string;
|
let WORKBENCH_NLS_URL: string;
|
||||||
if (!locale.startsWith('en') && this._productService.nlsCoreBaseUrl) {
|
if (!locale.startsWith('en') && this._productService.nlsCoreBaseUrl) {
|
||||||
WORKBENCH_NLS_BASE_URL = this._productService.nlsCoreBaseUrl;
|
WORKBENCH_NLS_BASE_URL = this._productService.nlsCoreBaseUrl;
|
||||||
WORKBENCH_NLS_URL = `${WORKBENCH_NLS_BASE_URL}${this._productService.commit}/${this._productService.version}/${locale}/nls.messages.js`;
|
WORKBENCH_NLS_URL = createNlsUrl(WORKBENCH_NLS_BASE_URL, this._productService.commit, this._productService.version, locale);
|
||||||
} else {
|
} else {
|
||||||
- WORKBENCH_NLS_URL = ''; // fallback will apply
|
- WORKBENCH_NLS_URL = ''; // fallback will apply
|
||||||
+ try {
|
+ try {
|
||||||
@@ -181,16 +181,16 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
+ : '';
|
+ : '';
|
||||||
+ } catch (error) {
|
+ } catch (error) {
|
||||||
+ console.error("Failed to generate translations", error);
|
+ console.error("Failed to generate translations", error);
|
||||||
+ WORKBENCH_NLS_URL = '';
|
+ WORKBENCH_NLS_URL = ''; // fallback will apply
|
||||||
+ }
|
+ }
|
||||||
}
|
}
|
||||||
|
|
||||||
const values: { [key: string]: string } = {
|
const scriptNonce = createScriptNonce();
|
||||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -22,6 +22,7 @@ export const serverOptions: OptionDescri
|
@@ -38,6 +38,7 @@ export const serverOptions: OptionDescri
|
||||||
'disable-file-downloads': { type: 'boolean' },
|
'disable-file-downloads': { type: 'boolean' },
|
||||||
'disable-file-uploads': { type: 'boolean' },
|
'disable-file-uploads': { type: 'boolean' },
|
||||||
'disable-getting-started-override': { type: 'boolean' },
|
'disable-getting-started-override': { type: 'boolean' },
|
||||||
@@ -198,7 +198,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ export interface ServerParsedArgs {
|
@@ -136,6 +137,7 @@ export interface ServerParsedArgs {
|
||||||
'disable-file-downloads'?: boolean;
|
'disable-file-downloads'?: boolean;
|
||||||
'disable-file-uploads'?: boolean;
|
'disable-file-uploads'?: boolean;
|
||||||
'disable-getting-started-override'?: boolean,
|
'disable-getting-started-override'?: boolean,
|
||||||
@@ -272,7 +272,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||||
@@ -474,9 +474,6 @@ export class InstallAction extends Exten
|
@@ -479,9 +479,6 @@ export class InstallAction extends Exten
|
||||||
if (this.extension.isBuiltin) {
|
if (this.extension.isBuiltin) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
if (this.extension.state !== ExtensionState.Uninstalled) {
|
if (this.extension.state !== ExtensionState.Uninstalled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -781,7 +778,7 @@ export abstract class InstallInOtherServ
|
@@ -786,7 +783,7 @@ export abstract class InstallInOtherServ
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
||||||
@@ -291,7 +291,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prefers to run on UI
|
// Prefers to run on UI
|
||||||
@@ -2072,17 +2069,6 @@ export class SetLanguageAction extends E
|
@@ -2285,17 +2282,6 @@ export class SetLanguageAction extends E
|
||||||
update(): void {
|
update(): void {
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.class = SetLanguageAction.DisabledClass;
|
this.class = SetLanguageAction.DisabledClass;
|
||||||
@@ -309,7 +309,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
}
|
}
|
||||||
|
|
||||||
override async run(): Promise<any> {
|
override async run(): Promise<any> {
|
||||||
@@ -2099,7 +2085,6 @@ export class ClearLanguageAction extends
|
@@ -2312,7 +2298,6 @@ export class ClearLanguageAction extends
|
||||||
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
|
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -317,7 +317,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
|||||||
@ILocaleService private readonly localeService: ILocaleService,
|
@ILocaleService private readonly localeService: ILocaleService,
|
||||||
) {
|
) {
|
||||||
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
||||||
@@ -2109,17 +2094,6 @@ export class ClearLanguageAction extends
|
@@ -2322,17 +2307,6 @@ export class ClearLanguageAction extends
|
||||||
update(): void {
|
update(): void {
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.class = ClearLanguageAction.DisabledClass;
|
this.class = ClearLanguageAction.DisabledClass;
|
||||||
|
|||||||
@@ -27,7 +27,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.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||||
@@ -303,6 +303,16 @@ export interface IWorkbenchConstructionO
|
@@ -319,6 +319,16 @@ export interface IWorkbenchConstructionO
|
||||||
*/
|
*/
|
||||||
readonly userDataPath?: string
|
readonly userDataPath?: string
|
||||||
|
|
||||||
@@ -48,8 +48,8 @@ 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.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
@@ -34,6 +34,16 @@ export interface IBrowserWorkbenchEnviro
|
@@ -39,6 +39,16 @@ export interface IBrowserWorkbenchEnviro
|
||||||
readonly options?: IWorkbenchConstructionOptions;
|
readonly sessionTitle?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
+ * Enable downloading files via menu actions.
|
+ * Enable downloading files via menu actions.
|
||||||
@@ -65,7 +65,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
|||||||
* Gets whether a resolver extension is expected for the environment.
|
* Gets whether a resolver extension is expected for the environment.
|
||||||
*/
|
*/
|
||||||
readonly expectsResolverExtension: boolean;
|
readonly expectsResolverExtension: boolean;
|
||||||
@@ -111,6 +121,20 @@ export class BrowserWorkbenchEnvironment
|
@@ -116,6 +126,20 @@ export class BrowserWorkbenchEnvironment
|
||||||
return this.options.userDataPath;
|
return this.options.userDataPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -19,6 +19,8 @@ export const serverOptions: OptionDescri
|
@@ -35,6 +35,8 @@ export const serverOptions: OptionDescri
|
||||||
/* ----- code-server ----- */
|
/* ----- code-server ----- */
|
||||||
'disable-update-check': { type: 'boolean' },
|
'disable-update-check': { type: 'boolean' },
|
||||||
'auth': { type: 'string' },
|
'auth': { type: 'string' },
|
||||||
@@ -99,7 +99,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -110,6 +112,8 @@ export interface ServerParsedArgs {
|
@@ -130,6 +132,8 @@ export interface ServerParsedArgs {
|
||||||
/* ----- code-server ----- */
|
/* ----- code-server ----- */
|
||||||
'disable-update-check'?: boolean;
|
'disable-update-check'?: boolean;
|
||||||
'auth'?: string;
|
'auth'?: string;
|
||||||
@@ -112,7 +112,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -370,6 +370,8 @@ export class WebClientServer {
|
@@ -425,6 +425,8 @@ export class WebClientServer {
|
||||||
serverBasePath: basePath,
|
serverBasePath: basePath,
|
||||||
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||||
userDataPath: this._environmentService.userDataPath,
|
userDataPath: this._environmentService.userDataPath,
|
||||||
@@ -128,9 +128,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
|||||||
@@ -6,10 +6,10 @@
|
@@ -6,10 +6,10 @@
|
||||||
import { Disposable } from '../../base/common/lifecycle.js';
|
import { Disposable } from '../../base/common/lifecycle.js';
|
||||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
||||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
|
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext, IsChromeOSContext } from '../../platform/contextkey/common/contextkeys.js';
|
||||||
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
|
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
|
||||||
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
|
+import { IsEnabledFileDownloads, IsEnabledFileUploads, SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
|
||||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
|
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
|
||||||
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||||
-import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
|
-import { IWorkbenchEnvironmentService } from '../services/environment/common/environmentService.js';
|
||||||
@@ -138,7 +138,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
|||||||
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js';
|
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from '../../platform/workspace/common/workspace.js';
|
||||||
import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js';
|
import { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.js';
|
||||||
import { getRemoteName } from '../../platform/remote/common/remoteHosts.js';
|
import { getRemoteName } from '../../platform/remote/common/remoteHosts.js';
|
||||||
@@ -69,7 +69,7 @@ export class WorkbenchContextKeysHandler
|
@@ -70,7 +70,7 @@ export class WorkbenchContextKeysHandler
|
||||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||||
@@ -147,7 +147,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
|||||||
@IProductService private readonly productService: IProductService,
|
@IProductService private readonly productService: IProductService,
|
||||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||||
@IEditorService private readonly editorService: IEditorService,
|
@IEditorService private readonly editorService: IEditorService,
|
||||||
@@ -201,6 +201,10 @@ export class WorkbenchContextKeysHandler
|
@@ -206,6 +206,10 @@ export class WorkbenchContextKeysHandler
|
||||||
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
|
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
|
||||||
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
|
this.auxiliaryBarMaximizedContext.set(this.layoutService.isAuxiliaryBarMaximized());
|
||||||
|
|
||||||
@@ -166,12 +166,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
|
|||||||
import { AutoSaveAfterShortDelayContext } from '../../../services/filesConfiguration/common/filesConfigurationService.js';
|
import { AutoSaveAfterShortDelayContext } from '../../../services/filesConfiguration/common/filesConfigurationService.js';
|
||||||
import { WorkbenchListDoubleSelection } from '../../../../platform/list/browser/listService.js';
|
import { WorkbenchListDoubleSelection } from '../../../../platform/list/browser/listService.js';
|
||||||
import { Schemas } from '../../../../base/common/network.js';
|
import { Schemas } from '../../../../base/common/network.js';
|
||||||
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
|
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsSessionsWindowContext, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ActiveEditorDirtyContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
|
||||||
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
|
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsSessionsWindowContext, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ActiveEditorDirtyContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
|
||||||
import { IsWebContext } from '../../../../platform/contextkey/common/contextkeys.js';
|
import { IsWebContext } from '../../../../platform/contextkey/common/contextkeys.js';
|
||||||
import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
|
import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
|
||||||
import { ThemeIcon } from '../../../../base/common/themables.js';
|
import { ThemeIcon } from '../../../../base/common/themables.js';
|
||||||
@@ -571,13 +571,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
@@ -573,13 +573,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||||
id: DOWNLOAD_COMMAND_ID,
|
id: DOWNLOAD_COMMAND_ID,
|
||||||
title: DOWNLOAD_LABEL
|
title: DOWNLOAD_LABEL
|
||||||
},
|
},
|
||||||
@@ -195,7 +195,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
|
|||||||
)
|
)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -589,6 +592,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
@@ -591,6 +594,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||||
title: UPLOAD_LABEL,
|
title: UPLOAD_LABEL,
|
||||||
},
|
},
|
||||||
when: ContextKeyExpr.and(
|
when: ContextKeyExpr.and(
|
||||||
@@ -207,7 +207,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
@@ -41,6 +41,9 @@ export const EmbedderIdentifierContext =
|
@@ -42,6 +42,9 @@ export const EmbedderIdentifierContext =
|
||||||
|
|
||||||
export const InAutomationContext = new RawContextKey<boolean>('inAutomation', false, localize('inAutomation', "Whether VS Code is running under automation/smoke test"));
|
export const InAutomationContext = new RawContextKey<boolean>('inAutomation', false, localize('inAutomation', "Whether VS Code is running under automation/smoke test"));
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
|||||||
import { renderFormattedText } from '../../../../base/browser/formattedTextRenderer.js';
|
import { renderFormattedText } from '../../../../base/browser/formattedTextRenderer.js';
|
||||||
import { status } from '../../../../base/browser/ui/aria/aria.js';
|
import { status } from '../../../../base/browser/ui/aria/aria.js';
|
||||||
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
|
import { StandardKeyboardEvent } from '../../../../base/browser/keyboardEvent.js';
|
||||||
@@ -54,7 +54,7 @@ import { IRecentFolder, IRecentWorkspace
|
@@ -55,7 +55,7 @@ import { IRecentFolder, IRecentWorkspace
|
||||||
import { OpenRecentAction } from '../../../browser/actions/windowActions.js';
|
import { OpenRecentAction } from '../../../browser/actions/windowActions.js';
|
||||||
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from '../../../browser/actions/workspaceActions.js';
|
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from '../../../browser/actions/workspaceActions.js';
|
||||||
import { EditorPane } from '../../../browser/parts/editor/editorPane.js';
|
import { EditorPane } from '../../../browser/parts/editor/editorPane.js';
|
||||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
|||||||
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
|
import { IEditorOpenContext, IEditorSerializer } from '../../../common/editor.js';
|
||||||
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
|
import { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
|
||||||
import './gettingStartedColors.js';
|
import './gettingStartedColors.js';
|
||||||
@@ -924,6 +924,72 @@ export class GettingStartedPage extends
|
@@ -930,6 +930,72 @@ export class GettingStartedPage extends
|
||||||
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
|
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
|||||||
const leftColumn = $('.categories-column.categories-column-left', {},);
|
const leftColumn = $('.categories-column.categories-column-left', {},);
|
||||||
const rightColumn = $('.categories-column.categories-column-right', {},);
|
const rightColumn = $('.categories-column.categories-column-right', {},);
|
||||||
|
|
||||||
@@ -959,6 +1025,9 @@ export class GettingStartedPage extends
|
@@ -980,6 +1046,9 @@ export class GettingStartedPage extends
|
||||||
recentList.setLimit(5);
|
recentList.setLimit(5);
|
||||||
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,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.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||||
@@ -313,6 +313,11 @@ export interface IWorkbenchConstructionO
|
@@ -329,6 +329,11 @@ export interface IWorkbenchConstructionO
|
||||||
*/
|
*/
|
||||||
readonly isEnabledFileUploads?: boolean
|
readonly isEnabledFileUploads?: boolean
|
||||||
|
|
||||||
@@ -151,7 +151,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.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
@@ -44,6 +44,11 @@ export interface IBrowserWorkbenchEnviro
|
@@ -49,6 +49,11 @@ export interface IBrowserWorkbenchEnviro
|
||||||
readonly isEnabledFileUploads?: boolean;
|
readonly isEnabledFileUploads?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,7 +163,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
|||||||
* Gets whether a resolver extension is expected for the environment.
|
* Gets whether a resolver extension is expected for the environment.
|
||||||
*/
|
*/
|
||||||
readonly expectsResolverExtension: boolean;
|
readonly expectsResolverExtension: boolean;
|
||||||
@@ -135,6 +140,13 @@ export class BrowserWorkbenchEnvironment
|
@@ -140,6 +145,13 @@ export class BrowserWorkbenchEnvironment
|
||||||
return this.options.isEnabledFileUploads;
|
return this.options.isEnabledFileUploads;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -21,6 +21,7 @@ export const serverOptions: OptionDescri
|
@@ -37,6 +37,7 @@ export const serverOptions: OptionDescri
|
||||||
'auth': { type: 'string' },
|
'auth': { type: 'string' },
|
||||||
'disable-file-downloads': { type: 'boolean' },
|
'disable-file-downloads': { type: 'boolean' },
|
||||||
'disable-file-uploads': { type: 'boolean' },
|
'disable-file-uploads': { type: 'boolean' },
|
||||||
@@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -114,6 +115,7 @@ export interface ServerParsedArgs {
|
@@ -134,6 +135,7 @@ export interface ServerParsedArgs {
|
||||||
'auth'?: string;
|
'auth'?: string;
|
||||||
'disable-file-downloads'?: boolean;
|
'disable-file-downloads'?: boolean;
|
||||||
'disable-file-uploads'?: boolean;
|
'disable-file-uploads'?: boolean;
|
||||||
@@ -201,7 +201,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -374,6 +374,7 @@ export class WebClientServer {
|
@@ -429,6 +429,7 @@ export class WebClientServer {
|
||||||
userDataPath: this._environmentService.userDataPath,
|
userDataPath: this._environmentService.userDataPath,
|
||||||
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||||
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
||||||
@@ -216,13 +216,13 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
|||||||
@@ -6,7 +6,7 @@
|
@@ -6,7 +6,7 @@
|
||||||
import { Disposable } from '../../base/common/lifecycle.js';
|
import { Disposable } from '../../base/common/lifecycle.js';
|
||||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
||||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
|
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext, IsChromeOSContext } from '../../platform/contextkey/common/contextkeys.js';
|
||||||
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
|
-import { IsEnabledFileDownloads, IsEnabledFileUploads, SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
|
||||||
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js';
|
+import { IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SecondarySideBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsSessionsWindowContext } from '../common/contextkeys.js';
|
||||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
|
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from '../services/editor/common/editorGroupsService.js';
|
||||||
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||||
import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';
|
import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';
|
||||||
@@ -204,6 +204,7 @@ export class WorkbenchContextKeysHandler
|
@@ -209,6 +209,7 @@ export class WorkbenchContextKeysHandler
|
||||||
// code-server
|
// code-server
|
||||||
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
||||||
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
|
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
|
||||||
@@ -234,7 +234,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||||
@@ -43,6 +43,7 @@ export const InAutomationContext = new R
|
@@ -44,6 +44,7 @@ export const InAutomationContext = new R
|
||||||
|
|
||||||
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||||
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
||||||
|
|||||||
+47
-24
@@ -19,20 +19,19 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
|||||||
import { parseArgs, ErrorReporter } from '../../platform/environment/node/argv.js';
|
import { parseArgs, ErrorReporter } from '../../platform/environment/node/argv.js';
|
||||||
import { join, dirname } from '../../base/common/path.js';
|
import { join, dirname } from '../../base/common/path.js';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
-import { serverOptions } from './serverEnvironmentService.js';
|
-import { agentHostBridgeConnectionTokenEnvironmentVariable, serverOptions } from './serverEnvironmentService.js';
|
||||||
+import { serverOptions, ServerParsedArgs } from './serverEnvironmentService.js';
|
+import { agentHostBridgeConnectionTokenEnvironmentVariable, serverOptions, ServerParsedArgs } from './serverEnvironmentService.js';
|
||||||
import product from '../../platform/product/common/product.js';
|
import product from '../../platform/product/common/product.js';
|
||||||
import * as perf from '../../base/common/performance.js';
|
import * as perf from '../../base/common/performance.js';
|
||||||
|
|
||||||
@@ -34,38 +34,47 @@ const errorReporter: ErrorReporter = {
|
@@ -34,40 +34,49 @@ const errorReporter: ErrorReporter = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
-const args = parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
-const args = parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
||||||
+function parse(): ServerParsedArgs {
|
-const agentHostBridgeConnectionToken = process.env[agentHostBridgeConnectionTokenEnvironmentVariable];
|
||||||
+ return parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
-delete process.env[agentHostBridgeConnectionTokenEnvironmentVariable];
|
||||||
+}
|
-
|
||||||
|
|
||||||
-const REMOTE_DATA_FOLDER = args['server-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote');
|
-const REMOTE_DATA_FOLDER = args['server-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote');
|
||||||
-const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
|
-const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
|
||||||
-const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
|
-const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
|
||||||
@@ -52,6 +51,10 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
|||||||
- }
|
- }
|
||||||
- } catch (err) { console.error(err); }
|
- } catch (err) { console.error(err); }
|
||||||
-});
|
-});
|
||||||
|
+function parse(): ServerParsedArgs {
|
||||||
|
+ return parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
||||||
|
+}
|
||||||
|
+
|
||||||
+function createDirs(args: ServerParsedArgs): string {
|
+function createDirs(args: ServerParsedArgs): string {
|
||||||
+ const REMOTE_DATA_FOLDER = args['server-data-dir'] || args['user-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote');
|
+ const REMOTE_DATA_FOLDER = args['server-data-dir'] || args['user-data-dir'] || process.env['VSCODE_AGENT_FOLDER'] || join(os.homedir(), product.serverDataFolderName || '.vscode-remote');
|
||||||
+ const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data');
|
+ const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data');
|
||||||
@@ -80,7 +83,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
|||||||
*/
|
*/
|
||||||
-export function spawnCli() {
|
-export function spawnCli() {
|
||||||
- runCli(args, REMOTE_DATA_FOLDER, serverOptions);
|
- runCli(args, REMOTE_DATA_FOLDER, serverOptions);
|
||||||
+function spawnCli(args = parse()): Promise<void> {
|
+function spawnCli(args = parse()) {
|
||||||
+ return runCli(args, createDirs(args), serverOptions);
|
+ return runCli(args, createDirs(args), serverOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,9 +91,11 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
|||||||
* invoked by server-main.js
|
* invoked by server-main.js
|
||||||
*/
|
*/
|
||||||
-export function createServer(address: string | net.AddressInfo | null): Promise<IServerAPI> {
|
-export function createServer(address: string | net.AddressInfo | null): Promise<IServerAPI> {
|
||||||
- return doCreateServer(address, args, REMOTE_DATA_FOLDER);
|
- return doCreateServer(address, args, REMOTE_DATA_FOLDER, agentHostBridgeConnectionToken);
|
||||||
+function createServer(address: string | net.AddressInfo | null, args = parse()): Promise<IServerAPI> {
|
+function createServer(address: string | net.AddressInfo | null, args = parse()): Promise<IServerAPI> {
|
||||||
+ return doCreateServer(address, args, createDirs(args));
|
+ const agentHostBridgeConnectionToken = process.env[agentHostBridgeConnectionTokenEnvironmentVariable];
|
||||||
|
+ delete process.env[agentHostBridgeConnectionTokenEnvironmentVariable];
|
||||||
|
+ return doCreateServer(address, args, createDirs(args), agentHostBridgeConnectionToken);
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+// The aliases prevent the names getting mangled during minification which would
|
+// The aliases prevent the names getting mangled during minification which would
|
||||||
@@ -164,7 +169,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||||
@@ -65,6 +65,7 @@ import { IOpenerService } from '../../pl
|
@@ -64,6 +64,7 @@ import { IOpenerService } from '../../pl
|
||||||
import { mixin, safeStringify } from '../../base/common/objects.js';
|
import { mixin, safeStringify } from '../../base/common/objects.js';
|
||||||
import { IndexedDB } from '../../base/browser/indexedDB.js';
|
import { IndexedDB } from '../../base/browser/indexedDB.js';
|
||||||
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
|
import { WebFileSystemAccess } from '../../platform/files/browser/webFileSystemAccess.js';
|
||||||
@@ -186,8 +191,8 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -65,6 +65,8 @@ export type ExtensionVirtualWorkspaceSup
|
@@ -97,6 +97,8 @@ export interface IDictationRuntimeProduc
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
+ readonly codeServerVersion?: string
|
+ readonly codeServerVersion?: string
|
||||||
@@ -209,8 +214,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
|||||||
|
|
||||||
<!-- Disable pinch zooming -->
|
<!-- 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">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||||
@@ -26,8 +27,9 @@
|
@@ -28,8 +29,9 @@
|
||||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
<meta id="vscode-workbench-css-modules" data-settings="{{WORKBENCH_DEV_CSS_MODULES}}">
|
||||||
|
|
||||||
<!-- Workbench Icon/Manifest/CSS -->
|
<!-- Workbench Icon/Manifest/CSS -->
|
||||||
- <link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
|
- <link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
|
||||||
@@ -220,7 +225,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
|||||||
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||||
<style id="vscode-css-modules" type="text/css" media="screen"></style>
|
<style id="vscode-css-modules" type="text/css" media="screen"></style>
|
||||||
|
|
||||||
</head>
|
<!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
|
||||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||||
@@ -235,7 +240,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
|||||||
|
|
||||||
<!-- Disable pinch zooming -->
|
<!-- 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">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||||
@@ -23,8 +24,9 @@
|
@@ -24,8 +25,9 @@
|
||||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||||
|
|
||||||
<!-- Workbench Icon/Manifest/CSS -->
|
<!-- Workbench Icon/Manifest/CSS -->
|
||||||
@@ -246,24 +251,24 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
|||||||
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||||
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
|
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
|
||||||
|
|
||||||
</head>
|
<!-- Startup fallback: shown only if the scripts below never run, e.g. because a proxy,
|
||||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -334,6 +334,7 @@ export class WebClientServer {
|
@@ -394,6 +394,7 @@ export class WebClientServer {
|
||||||
} : undefined;
|
} : undefined;
|
||||||
|
|
||||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
+ codeServerVersion: this._productService.codeServerVersion,
|
+ codeServerVersion: this._productService.codeServerVersion,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||||
...this._productService.extensionsGallery,
|
|
||||||
Index: code-server/lib/vscode/src/server-main.ts
|
Index: code-server/lib/vscode/src/server-main.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/server-main.ts
|
--- code-server.orig/lib/vscode/src/server-main.ts
|
||||||
+++ code-server/lib/vscode/src/server-main.ts
|
+++ code-server/lib/vscode/src/server-main.ts
|
||||||
@@ -22,6 +22,9 @@ import { IServerAPI } from './vs/server/
|
@@ -23,6 +23,9 @@ import { IServerAPI } from './vs/server/
|
||||||
perf.mark('code/server/start');
|
perf.mark('code/server/start');
|
||||||
(globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now();
|
(globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now();
|
||||||
|
|
||||||
@@ -273,7 +278,16 @@ Index: code-server/lib/vscode/src/server-main.ts
|
|||||||
// Do a quick parse to determine if a server or the cli needs to be started
|
// Do a quick parse to determine if a server or the cli needs to be started
|
||||||
const parsedArgs = minimist(process.argv.slice(2), {
|
const parsedArgs = minimist(process.argv.slice(2), {
|
||||||
boolean: ['start-server', 'list-extensions', 'print-ip-address', 'help', 'version', 'accept-server-license-terms', 'update-extensions'],
|
boolean: ['start-server', 'list-extensions', 'print-ip-address', 'help', 'version', 'accept-server-license-terms', 'update-extensions'],
|
||||||
@@ -150,6 +153,7 @@ if (shouldSpawnCli) {
|
@@ -50,7 +53,7 @@ if (shouldSpawnCli) {
|
||||||
|
mod.spawnCli();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
- installServerProcessExitDiagnostics();
|
||||||
|
+ installServerProcessExitDiagnostics(parsedArgs);
|
||||||
|
|
||||||
|
let _remoteExtensionHostAgentServer: IServerAPI | null = null;
|
||||||
|
let _remoteExtensionHostAgentServerPromise: Promise<IServerAPI> | null = null;
|
||||||
|
@@ -153,6 +156,7 @@ if (shouldSpawnCli) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -281,7 +295,16 @@ Index: code-server/lib/vscode/src/server-main.ts
|
|||||||
|
|
||||||
function sanitizeStringArg(val: unknown): string | undefined {
|
function sanitizeStringArg(val: unknown): string | undefined {
|
||||||
if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array
|
if (Array.isArray(val)) { // if an argument is passed multiple times, minimist creates an array
|
||||||
@@ -283,3 +287,22 @@ function prompt(question: string): Promi
|
@@ -173,7 +177,7 @@ function sanitizeStringArg(val: unknown)
|
||||||
|
* provided) so they survive process teardown (an async stdio write from an
|
||||||
|
* `exit` handler does not).
|
||||||
|
*/
|
||||||
|
-function installServerProcessExitDiagnostics(): void {
|
||||||
|
+function installServerProcessExitDiagnostics(parsedArgs: minimist.ParsedArgs): void {
|
||||||
|
if (!process.env['VSCODE_SERVER_EXIT_DIAGNOSTICS']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
@@ -406,3 +410,22 @@ function prompt(question: string): Promi
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -308,7 +331,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
|
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
|
||||||
@@ -47,8 +47,11 @@ export function createWorkbenchDialogOpt
|
@@ -54,8 +54,11 @@ export function createWorkbenchDialogOpt
|
||||||
|
|
||||||
export function createBrowserAboutDialogDetails(productService: IProductService): { title: string; details: string; detailsToCopy: string } {
|
export function createBrowserAboutDialogDetails(productService: IProductService): { title: string; details: string; detailsToCopy: string } {
|
||||||
const detailString = (useAgo: boolean): string => {
|
const detailString = (useAgo: boolean): string => {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -365,6 +365,7 @@ export class WebClientServer {
|
@@ -420,6 +420,7 @@ export class WebClientServer {
|
||||||
remoteAuthority,
|
remoteAuthority,
|
||||||
serverBasePath: basePath,
|
serverBasePath: basePath,
|
||||||
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||||
@@ -30,7 +30,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.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||||
@@ -298,6 +298,11 @@ export interface IWorkbenchConstructionO
|
@@ -314,6 +314,11 @@ export interface IWorkbenchConstructionO
|
||||||
*/
|
*/
|
||||||
readonly configurationDefaults?: Record<string, unknown>;
|
readonly configurationDefaults?: Record<string, unknown>;
|
||||||
|
|
||||||
@@ -46,7 +46,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.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
@@ -102,7 +102,14 @@ export class BrowserWorkbenchEnvironment
|
@@ -107,7 +107,14 @@ export class BrowserWorkbenchEnvironment
|
||||||
get logFile(): URI { return joinPath(this.windowLogsPath, 'window.log'); }
|
get logFile(): URI { return joinPath(this.windowLogsPath, 'window.log'); }
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
@@ -66,7 +66,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||||
@@ -148,8 +148,10 @@ export class WorkspaceService extends Di
|
@@ -150,8 +150,10 @@ export class WorkspaceService extends Di
|
||||||
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
|
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
|
||||||
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
|
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
|
||||||
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
|
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
|
||||||
@@ -79,7 +79,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -561,6 +563,12 @@ export class WorkspaceService extends Di
|
@@ -563,6 +565,12 @@ export class WorkspaceService extends Di
|
||||||
previousFolders = this.workspace.folders;
|
previousFolders = this.workspace.folders;
|
||||||
this.workspace.update(workspace);
|
this.workspace.update(workspace);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+5
-5
@@ -8,7 +8,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -68,6 +68,7 @@ export interface IProductConfiguration {
|
@@ -100,6 +100,7 @@ export interface IProductConfiguration {
|
||||||
readonly codeServerVersion?: string
|
readonly codeServerVersion?: string
|
||||||
readonly rootEndpoint?: string
|
readonly rootEndpoint?: string
|
||||||
readonly updateEndpoint?: string
|
readonly updateEndpoint?: string
|
||||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -18,6 +18,7 @@ import { ProtocolConstants } from '../..
|
@@ -34,6 +34,7 @@ export function getRedactedServerParsedA
|
||||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||||
/* ----- code-server ----- */
|
/* ----- code-server ----- */
|
||||||
'disable-update-check': { type: 'boolean' },
|
'disable-update-check': { type: 'boolean' },
|
||||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -108,6 +109,7 @@ export const serverOptions: OptionDescri
|
@@ -128,6 +129,7 @@ export const serverOptions: OptionDescri
|
||||||
export interface ServerParsedArgs {
|
export interface ServerParsedArgs {
|
||||||
/* ----- code-server ----- */
|
/* ----- code-server ----- */
|
||||||
'disable-update-check'?: boolean;
|
'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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -342,6 +342,7 @@ export class WebClientServer {
|
@@ -402,6 +402,7 @@ export class WebClientServer {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
rootEndpoint: rootBase,
|
rootEndpoint: rootBase,
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
};
|
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
@@ -49,6 +49,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
@@ -65,6 +65,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||||
version: pkg.version
|
Object.assign(product, { copilotVersions: { runtime: packageConfiguration.copilotRuntimeVersion, sdk } });
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+ Object.assign(product, {
|
+ Object.assign(product, {
|
||||||
@@ -41,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -327,7 +327,6 @@ export class WebClientServer {
|
@@ -387,7 +387,6 @@ export class WebClientServer {
|
||||||
|
|
||||||
const staticRoute = posix.join(basePath, this._productPath, STATIC_PATH);
|
const staticRoute = posix.join(basePath, this._productPath, STATIC_PATH);
|
||||||
const callbackRoute = posix.join(basePath, this._productPath, CALLBACK_PATH);
|
const callbackRoute = posix.join(basePath, this._productPath, CALLBACK_PATH);
|
||||||
@@ -49,10 +49,10 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
|
|
||||||
const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority });
|
const resolveWorkspaceURI = (defaultLocation?: string) => defaultLocation && URI.file(resolve(defaultLocation)).with({ scheme: Schemas.vscodeRemote, authority: remoteAuthority });
|
||||||
|
|
||||||
@@ -343,14 +342,7 @@ export class WebClientServer {
|
@@ -404,14 +403,7 @@ export class WebClientServer {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
|
||||||
rootEndpoint: rootBase,
|
rootEndpoint: rootBase,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||||
- ...this._productService.extensionsGallery,
|
- ...this._productService.extensionsGallery,
|
||||||
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
|
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
|
||||||
@@ -64,7 +64,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
+ extensionsGallery: this._productService.extensionsGallery,
|
+ extensionsGallery: this._productService.extensionsGallery,
|
||||||
};
|
};
|
||||||
|
|
||||||
const proposedApi = this._environmentService.args['enable-proposed-api'];
|
if (!this._environmentService.isBuilt) {
|
||||||
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
Bump the bundled Node.js version
|
||||||
|
|
||||||
|
Pull in Node.js security fixes (Brotli decoder RCE) ahead of upstream. Drop
|
||||||
|
this patch once upstream targets this version or newer.
|
||||||
|
|
||||||
|
Index: code-server/lib/vscode/remote/.npmrc
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/remote/.npmrc
|
||||||
|
+++ code-server/lib/vscode/remote/.npmrc
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
disturl="https://nodejs.org/dist"
|
||||||
|
-target="24.21.0"
|
||||||
|
+target="24.22.1"
|
||||||
|
ms_build_id="474716"
|
||||||
|
runtime="node"
|
||||||
|
build_from_source="true"
|
||||||
|
Index: code-server/lib/vscode/build/checksums/nodejs.txt
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/build/checksums/nodejs.txt
|
||||||
|
+++ code-server/lib/vscode/build/checksums/nodejs.txt
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
-bed7eea5325e1108f32ce5228ddd6a5f0f08a499ee42aa7442aea583702f6057 node-v24.21.0-darwin-arm64.tar.gz
|
||||||
|
-1462cb3b3046b815cf8ea436d3da450ec1a9f11dac7e5a46b0ada5305d7e8097 node-v24.21.0-darwin-x64.tar.gz
|
||||||
|
-724282c3b43aec998aa9527380465b45d229e021b58035f5f4f63095eabfe5d5 node-v24.21.0-linux-arm64.tar.gz
|
||||||
|
-6e1db87ef58b8819e5d5402eff1536491b18edd8eb7bee5ef7897876e88dc5ff node-v24.21.0-linux-x64.tar.gz
|
||||||
|
-dff59da18b6ffe1bf1ca99e1d2af4906080c481740619f5b5098c0fca28bd9b7 win-arm64/node.exe
|
||||||
|
-ba4e6d110e8c1592a1ecd390f6b05f3da124b13871a5be62b341a07a853c6c32 win-x64/node.exe
|
||||||
|
+89c682593d76cd44233fa53b1563264e7de9cbb189cad169135c5b4fadfbc0a7 node-v24.22.1-darwin-arm64.tar.gz
|
||||||
|
+d132557e7ee2b85af08b0c8c34338e65c6430f2238d01f727728ef42dc83b035 node-v24.22.1-darwin-x64.tar.gz
|
||||||
|
+33c37be234ba8bee041961047b19160f4d7d0f164e8e246f78bdd10feff148b3 node-v24.22.1-linux-arm64.tar.gz
|
||||||
|
+eb6728e77c576a35162c122c45ccadf224d89ff00abc8dae46cc2897c6002d7c node-v24.22.1-linux-x64.tar.gz
|
||||||
|
+8bea91dc437fe01e7d92ef0efc6c9eaf654369aaba9b2d3e9841552ea7b95a00 win-arm64/node.exe
|
||||||
|
+d702daa815eabbff763c7d3808e235cf031cf2ca70211b56847bc72f51e240e5 win-x64/node.exe
|
||||||
@@ -10,18 +10,17 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||||
@@ -321,10 +321,7 @@ function extensionDescriptionArrayToMap(
|
@@ -321,6 +321,10 @@ function extensionDescriptionArrayToMap(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||||
- if (!extension.enabledApiProposals) {
|
+ return true;
|
||||||
- return false;
|
+}
|
||||||
- }
|
+
|
||||||
- return true;// extension.enabledApiProposals.includes(proposal);
|
+export function _isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||||
+ return true
|
if (!extension.enabledApiProposals) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
export function checkProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): void {
|
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||||
|
|||||||
+19
-8
@@ -13,12 +13,18 @@ This has e2e tests.
|
|||||||
For the `asExternalUri` changes, you'll need to test manually by:
|
For the `asExternalUri` changes, you'll need to test manually by:
|
||||||
1. running code-server with the test extension
|
1. running code-server with the test extension
|
||||||
2. Command Palette > code-server: asExternalUri test
|
2. Command Palette > code-server: asExternalUri test
|
||||||
3. input a url like http://localhost:3000
|
3. input a url like http://localhost:3000/my/path?token=abc#section
|
||||||
4. it should show a notification and show output as <code-server>/proxy/3000
|
4. it should show a notification and show output as
|
||||||
|
<code-server>/proxy/3000/my/path?token%3Dabc#section
|
||||||
|
|
||||||
Do the same thing but set `VSCODE_PROXY_URI: "https://{{port}}-main-workspace-name-user-name.coder.com"`
|
Do the same thing but set `VSCODE_PROXY_URI: "https://{{port}}-main-workspace-name-user-name.coder.com"`
|
||||||
and the output should replace `{{port}}` with port used in input url.
|
and the output should replace `{{port}}` with port used in input url.
|
||||||
|
|
||||||
|
The rewritten URI must preserve the original path, query, and fragment (see
|
||||||
|
#7668). Append the original path to the proxy path using URI components so
|
||||||
|
encoded characters are not decoded or encoded twice. This also works with
|
||||||
|
proxy templates that do not have a trailing slash.
|
||||||
|
|
||||||
This also enables the forwared ports view panel by default.
|
This also enables the forwared ports view panel by default.
|
||||||
|
|
||||||
Lastly, it adds a tunnelProvider so that ports are forwarded using code-server's
|
Lastly, it adds a tunnelProvider so that ports are forwarded using code-server's
|
||||||
@@ -30,7 +36,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -69,6 +69,7 @@ export interface IProductConfiguration {
|
@@ -101,6 +101,7 @@ export interface IProductConfiguration {
|
||||||
readonly rootEndpoint?: string
|
readonly rootEndpoint?: string
|
||||||
readonly updateEndpoint?: string
|
readonly updateEndpoint?: string
|
||||||
readonly logoutEndpoint?: string
|
readonly logoutEndpoint?: string
|
||||||
@@ -71,14 +77,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.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -343,6 +343,7 @@ export class WebClientServer {
|
@@ -403,6 +403,7 @@ export class WebClientServer {
|
||||||
rootEndpoint: rootBase,
|
rootEndpoint: rootBase,
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
};
|
|
||||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||||
@@ -104,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
|
import type { IURLCallbackProvider } from '../../../workbench/services/url/browser/urlService.js';
|
||||||
import { create } from '../../../workbench/workbench.web.main.internal.js';
|
import { create } from '../../../workbench/workbench.web.main.internal.js';
|
||||||
|
|
||||||
@@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
|
@@ -616,6 +617,44 @@ class WorkspaceProvider implements IWork
|
||||||
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
||||||
workspaceProvider: WorkspaceProvider.create(config),
|
workspaceProvider: WorkspaceProvider.create(config),
|
||||||
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
||||||
@@ -116,7 +122,12 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
|||||||
+ const renderedTemplate = config.productConfiguration.proxyEndpointTemplate
|
+ const renderedTemplate = config.productConfiguration.proxyEndpointTemplate
|
||||||
+ .replace('{{port}}', localhostMatch.port.toString())
|
+ .replace('{{port}}', localhostMatch.port.toString())
|
||||||
+ .replace('{{host}}', window.location.host)
|
+ .replace('{{host}}', window.location.host)
|
||||||
+ resolvedUri = URI.parse(new URL(renderedTemplate, window.location.href).toString())
|
+ const proxyUri = URI.parse(new URL(renderedTemplate, window.location.href).toString())
|
||||||
|
+ resolvedUri = proxyUri.with({
|
||||||
|
+ path: proxyUri.path.replace(/\/$/, '') + uri.path,
|
||||||
|
+ query: uri.query,
|
||||||
|
+ fragment: uri.fragment,
|
||||||
|
+ })
|
||||||
+ } else {
|
+ } else {
|
||||||
+ throw new Error(`Failed to resolve external URI: ${uri.toString()}. Could not determine base url because productConfiguration missing.`)
|
+ throw new Error(`Failed to resolve external URI: ${uri.toString()}. Could not determine base url because productConfiguration missing.`)
|
||||||
+ }
|
+ }
|
||||||
@@ -148,7 +159,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||||
@@ -83,8 +83,8 @@ export class ForwardedPortsView extends
|
@@ -100,8 +100,8 @@ export class ForwardedPortsView extends
|
||||||
private async enableForwardedPortsFeatures() {
|
private async enableForwardedPortsFeatures() {
|
||||||
this.contextKeyListener.clear();
|
this.contextKeyListener.clear();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
AI: store secrets on remote for VS Code Web
|
||||||
|
Index: code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/platform/secrets/common/secrets.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/platform/secrets/common/secrets.ts
|
||||||
|
@@ -144,8 +144,13 @@ export class BaseSecretStorageService ex
|
||||||
|
return await readEncryptedSecret(
|
||||||
|
key,
|
||||||
|
(fullKey) => this.getValueFromStorage(key, fullKey, storageService),
|
||||||
|
- // If the storage service is in-memory, we don't need to decrypt
|
||||||
|
- this._type === 'in-memory' ? (v) => Promise.resolve(v) : (v) => this._encryptionService.decrypt(v),
|
||||||
|
+ // Don't decrypt if storage is in-memory or if encryption service is not available
|
||||||
|
+ async (v) => {
|
||||||
|
+ if (this._type === 'in-memory' || !await this._encryptionService.isEncryptionAvailable()) {
|
||||||
|
+ return v;
|
||||||
|
+ }
|
||||||
|
+ return this._encryptionService.decrypt(v);
|
||||||
|
+ },
|
||||||
|
this._logService,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
@@ -168,8 +173,13 @@ export class BaseSecretStorageService ex
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
(fullKey, encrypted) => this.setValueInStorage(key, fullKey, encrypted, storageService),
|
||||||
|
- // If the storage service is in-memory, we don't need to encrypt
|
||||||
|
- this._type === 'in-memory' ? (v) => Promise.resolve(v) : (v) => this._encryptionService.encrypt(v),
|
||||||
|
+ // Don't encrypt if storage is in-memory or if encryption service is not available
|
||||||
|
+ async (v) => {
|
||||||
|
+ if (this._type === 'in-memory' || !await this._encryptionService.isEncryptionAvailable()) {
|
||||||
|
+ return v;
|
||||||
|
+ }
|
||||||
|
+ return this._encryptionService.encrypt(v);
|
||||||
|
+ },
|
||||||
|
this._logService,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
@@ -224,8 +234,9 @@ export class BaseSecretStorageService ex
|
||||||
|
|
||||||
|
private async initialize(): Promise<IStorageService> {
|
||||||
|
let storageService;
|
||||||
|
- if (!this._useInMemoryStorage && await this._encryptionService.isEncryptionAvailable()) {
|
||||||
|
- this._logService.trace(`[SecretStorageService] Encryption is available, using persisted storage`);
|
||||||
|
+ if (!this._useInMemoryStorage) {
|
||||||
|
+ // Use persisted storage when not forced to use in-memory
|
||||||
|
+ this._logService.trace(`[SecretStorageService] Using persisted storage`);
|
||||||
|
this._type = 'persisted';
|
||||||
|
storageService = this._storageService;
|
||||||
|
} else {
|
||||||
|
@@ -233,7 +244,7 @@ export class BaseSecretStorageService ex
|
||||||
|
if (this._type === 'in-memory') {
|
||||||
|
return this._storageService;
|
||||||
|
}
|
||||||
|
- this._logService.trace('[SecretStorageService] Encryption is not available, falling back to in-memory storage');
|
||||||
|
+ this._logService.trace('[SecretStorageService] Falling back to in-memory storage');
|
||||||
|
this._type = 'in-memory';
|
||||||
|
storageService = this._register(new InMemoryStorageService());
|
||||||
|
}
|
||||||
|
Index: code-server/lib/vscode/src/vs/workbench/services/secrets/browser/secretStorageService.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/secrets/browser/secretStorageService.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/workbench/services/secrets/browser/secretStorageService.ts
|
||||||
|
@@ -22,9 +22,9 @@ export class BrowserSecretStorageService
|
||||||
|
@IBrowserWorkbenchEnvironmentService environmentService: IBrowserWorkbenchEnvironmentService,
|
||||||
|
@ILogService logService: ILogService
|
||||||
|
) {
|
||||||
|
- // We don't have encryption in the browser so instead we use the
|
||||||
|
- // in-memory base class implementation instead.
|
||||||
|
- super(true, storageService, encryptionService, logService);
|
||||||
|
+ // Use remote storage if enabled, otherwise use in-memory storage
|
||||||
|
+ const useRemoteStorage = environmentService.options?.remoteStorageEnabled ?? false;
|
||||||
|
+ super(!useRemoteStorage, storageService, encryptionService, logService);
|
||||||
|
|
||||||
|
if (environmentService.options?.secretStorageProvider) {
|
||||||
|
this._secretStorageProvider = environmentService.options.secretStorageProvider;
|
||||||
|
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
|
||||||
|
@@ -655,8 +655,8 @@ class WorkspaceProvider implements IWork
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
- secretStorageProvider: config.remoteAuthority && !secretStorageKeyPath
|
||||||
|
- ? undefined /* with a remote without embedder-preferred storage, store on the remote */
|
||||||
|
+ secretStorageProvider: config.remoteStorageEnabled || (config.remoteAuthority && !secretStorageKeyPath)
|
||||||
|
+ ? undefined /* with remote storage enabled, or without embedder-prefered storage, store on the remote */
|
||||||
|
: new LocalStorageSecretStorageProvider(secretStorageCrypto),
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -0,0 +1,246 @@
|
|||||||
|
Reuse VS Code's Electron storage service for remote persistence
|
||||||
|
|
||||||
|
Index: code-server/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/platform/storage/electron-main/storageMainService.ts
|
||||||
|
@@ -11,7 +11,12 @@ import { IStorage } from '../../../base/
|
||||||
|
import { INativeEnvironmentService } from '../../environment/common/environment.js';
|
||||||
|
import { IFileService } from '../../files/common/files.js';
|
||||||
|
import { createDecorator } from '../../instantiation/common/instantiation.js';
|
||||||
|
-import { ILifecycleMainService, LifecycleMainPhase, ShutdownReason } from '../../lifecycle/electron-main/lifecycleMainService.js';
|
||||||
|
+import type { ILifecycleMainService, ShutdownReason } from '../../lifecycle/electron-main/lifecycleMainService.js';
|
||||||
|
+
|
||||||
|
+// Keep these values local so the server does not load lifecycleMainService at runtime;
|
||||||
|
+// that module imports Electron, which is not present in the code-server server image.
|
||||||
|
+const LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN = 3;
|
||||||
|
+const SHUTDOWN_REASON_KILL = 2;
|
||||||
|
import { ILogService } from '../../log/common/log.js';
|
||||||
|
import { AbstractStorageService, isProfileUsingDefaultStorage, IStorageService, StorageScope, StorageTarget } from '../common/storage.js';
|
||||||
|
import { ApplicationStorageMain, ApplicationSharedStorageMain, ProfileStorageMain, InMemoryStorageMain, IStorageMain, IStorageMainOptions, WorkspaceStorageMain, IStorageChangeEvent } from './storageMain.js';
|
||||||
|
@@ -92,7 +97,7 @@ export class StorageMainService extends
|
||||||
|
@ILogService private readonly logService: ILogService,
|
||||||
|
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
|
||||||
|
@IUserDataProfilesMainService private readonly userDataProfilesService: IUserDataProfilesMainService,
|
||||||
|
- @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||||
|
+ private readonly lifecycleMainService: ILifecycleMainService,
|
||||||
|
@IFileService private readonly fileService: IFileService,
|
||||||
|
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
|
||||||
|
) {
|
||||||
|
@@ -114,7 +119,7 @@ export class StorageMainService extends
|
||||||
|
|
||||||
|
// Application Storage: Warmup when any window opens
|
||||||
|
(async () => {
|
||||||
|
- await this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen);
|
||||||
|
+ await this.lifecycleMainService.when(LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN);
|
||||||
|
|
||||||
|
this.applicationStorage.init();
|
||||||
|
this.applicationSharedStorage.init();
|
||||||
|
@@ -253,7 +258,7 @@ export class StorageMainService extends
|
||||||
|
}
|
||||||
|
|
||||||
|
private createProfileStorage(profile: IUserDataProfile): IStorageMain {
|
||||||
|
- if (this.shutdownReason === ShutdownReason.KILL) {
|
||||||
|
+ if (this.shutdownReason === SHUTDOWN_REASON_KILL) {
|
||||||
|
|
||||||
|
// Workaround for native crashes that we see when
|
||||||
|
// SQLite DBs are being created even after shutdown
|
||||||
|
@@ -292,7 +297,7 @@ export class StorageMainService extends
|
||||||
|
}
|
||||||
|
|
||||||
|
private createWorkspaceStorage(workspace: IAnyWorkspaceIdentifier): IStorageMain {
|
||||||
|
- if (this.shutdownReason === ShutdownReason.KILL) {
|
||||||
|
+ if (this.shutdownReason === SHUTDOWN_REASON_KILL) {
|
||||||
|
|
||||||
|
// Workaround for native crashes that we see when
|
||||||
|
// SQLite DBs are being created even after shutdown
|
||||||
|
Index: code-server/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/workbench/services/storage/electron-browser/storageService.ts
|
||||||
|
@@ -3,7 +3,7 @@
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
-import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js';
|
||||||
|
+import { IRemoteService } from '../../../../platform/ipc/common/services.js';
|
||||||
|
import { IStorage, Storage, MigratingStorage } from '../../../../base/parts/storage/common/storage.js';
|
||||||
|
import { RemoteStorageService } from '../../../../platform/storage/common/storageService.js';
|
||||||
|
import { FallbackApplicationStorageDatabaseClient, ApplicationSharedStorageDatabaseClient } from '../../../../platform/storage/common/storageIpc.js';
|
||||||
|
@@ -19,10 +19,10 @@ export class NativeWorkbenchStorageServi
|
||||||
|
workspace: IAnyWorkspaceIdentifier | undefined,
|
||||||
|
private readonly userDataProfileService: IUserDataProfileService,
|
||||||
|
userDataProfilesService: IUserDataProfilesService,
|
||||||
|
- mainProcessService: IMainProcessService,
|
||||||
|
+ remoteService: Pick<IRemoteService, 'getChannel'>,
|
||||||
|
private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
|
||||||
|
) {
|
||||||
|
- super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, mainProcessService, workbenchEnvironmentService);
|
||||||
|
+ super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, remoteService as IRemoteService, workbenchEnvironmentService);
|
||||||
|
|
||||||
|
this.registerListeners();
|
||||||
|
}
|
||||||
|
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
|
||||||
|
@@ -66,6 +66,7 @@ export const serverOptions: OptionDescri
|
||||||
|
'disable-experiments': OPTIONS['disable-experiments'],
|
||||||
|
'disable-workspace-trust': OPTIONS['disable-workspace-trust'],
|
||||||
|
'file-watcher-polling': { type: 'string', deprecates: ['fileWatcherPolling'] },
|
||||||
|
+ 'enable-remote-storage': { type: 'boolean', cat: 'o', description: nls.localize('enable-remote-storage', 'Persist browser storage (settings, state, etc.) on the server instead of browser IndexedDB. Enables state portability across browsers/devices.') },
|
||||||
|
'log': OPTIONS['log'],
|
||||||
|
'logsPath': OPTIONS['logsPath'],
|
||||||
|
'force-disable-user-env': OPTIONS['force-disable-user-env'],
|
||||||
|
@@ -212,6 +213,7 @@ export interface ServerParsedArgs {
|
||||||
|
'logsPath'?: string;
|
||||||
|
|
||||||
|
'force-disable-user-env'?: boolean;
|
||||||
|
+ 'enable-remote-storage'?: boolean;
|
||||||
|
'enable-proposed-api'?: string[];
|
||||||
|
|
||||||
|
/* ----- vs code web options ----- */
|
||||||
|
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
|
||||||
|
@@ -105,6 +105,10 @@ import { McpManagementChannel } from '..
|
||||||
|
import { AllowedMcpServersService } from '../../platform/mcp/common/allowedMcpServersService.js';
|
||||||
|
import { IMcpGalleryManifestService } from '../../platform/mcp/common/mcpGalleryManifest.js';
|
||||||
|
import { McpGalleryManifestIPCService } from '../../platform/mcp/common/mcpGalleryManifestServiceIpc.js';
|
||||||
|
+import { StorageDatabaseChannel } from '../../platform/storage/electron-main/storageIpc.js';
|
||||||
|
+import { StorageMainService } from '../../platform/storage/electron-main/storageMainService.js';
|
||||||
|
+import type { ILifecycleMainService } from '../../platform/lifecycle/electron-main/lifecycleMainService.js';
|
||||||
|
+import type { IUserDataProfilesMainService } from '../../platform/userDataProfile/electron-main/userDataProfile.js';
|
||||||
|
import { SANDBOX_HELPER_CHANNEL_NAME, SandboxHelperChannel } from '../../platform/sandbox/common/sandboxHelperIpc.js';
|
||||||
|
import { SandboxHelperService } from '../../platform/sandbox/node/sandboxHelper.js';
|
||||||
|
|
||||||
|
@@ -238,6 +242,21 @@ export async function setupServerService
|
||||||
|
services.set(IMcpGatewayService, new SyncDescriptor(McpGatewayService));
|
||||||
|
|
||||||
|
const instantiationService: IInstantiationService = new InstantiationService(services);
|
||||||
|
+ // Reuse the Electron storage service on the remote. The server has no
|
||||||
|
+ // windows, so its lifecycle is always ready and never loads a window.
|
||||||
|
+ const storageMainService = disposables.add(new StorageMainService(
|
||||||
|
+ logService,
|
||||||
|
+ environmentService,
|
||||||
|
+ userDataProfilesService as unknown as IUserDataProfilesMainService,
|
||||||
|
+ {
|
||||||
|
+ when: () => Promise.resolve(),
|
||||||
|
+ onWillLoadWindow: Event.None,
|
||||||
|
+ onWillShutdown: Event.None,
|
||||||
|
+ } as unknown as ILifecycleMainService,
|
||||||
|
+ fileService,
|
||||||
|
+ uriIdentityService,
|
||||||
|
+ ));
|
||||||
|
+
|
||||||
|
services.set(ILanguagePackService, instantiationService.createInstance(NativeLanguagePackService));
|
||||||
|
|
||||||
|
const ptyHostStarter = instantiationService.createInstance(
|
||||||
|
@@ -420,6 +439,7 @@ export async function setupServerService
|
||||||
|
|
||||||
|
const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService), disposables);
|
||||||
|
socketServer.registerChannel('languagePacks', languagePackChannel);
|
||||||
|
+ socketServer.registerChannel('storage', disposables.add(new StorageDatabaseChannel(logService, storageMainService)));
|
||||||
|
|
||||||
|
// clean up extensions folder
|
||||||
|
remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp());
|
||||||
|
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
|
||||||
|
@@ -451,7 +451,8 @@ export class WebClientServer {
|
||||||
|
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
|
||||||
|
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
|
||||||
|
productConfiguration,
|
||||||
|
- callbackRoute: callbackRoute
|
||||||
|
+ callbackRoute: callbackRoute,
|
||||||
|
+ remoteStorageEnabled: this._environmentService.args['enable-remote-storage'] ? true : undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const cookies = cookie.parse(req.headers.cookie || '');
|
||||||
|
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
|
||||||
|
@@ -411,6 +411,11 @@ export interface IWorkbenchConstructionO
|
||||||
|
readonly authenticationProviders?: readonly IAuthenticationProvider[];
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
+ /**
|
||||||
|
+ * Persist workbench storage on the remote server instead of browser IndexedDB.
|
||||||
|
+ */
|
||||||
|
+ readonly remoteStorageEnabled?: boolean;
|
||||||
|
+
|
||||||
|
|
||||||
|
//#region Development options
|
||||||
|
|
||||||
|
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
|
||||||
|
@@ -33,6 +33,7 @@ import { ISignService } from '../../plat
|
||||||
|
import { SignService } from '../../platform/sign/browser/signService.js';
|
||||||
|
import { IWorkbenchConstructionOptions, IWorkbench, IWorkspace, ITunnel } from './web.api.js';
|
||||||
|
import { BrowserStorageService } from '../services/storage/browser/storageService.js';
|
||||||
|
+import { NativeWorkbenchStorageService } from '../services/storage/electron-browser/storageService.js';
|
||||||
|
import { IStorageService } from '../../platform/storage/common/storage.js';
|
||||||
|
import { toLocalISOString } from '../../base/common/date.js';
|
||||||
|
import { isWorkspaceToOpen, isFolderToOpen } from '../../platform/window/common/window.js';
|
||||||
|
@@ -482,7 +483,7 @@ export class BrowserMain extends Disposa
|
||||||
|
serviceCollection.set(IWorkbenchConfigurationService, service);
|
||||||
|
return service;
|
||||||
|
}),
|
||||||
|
- this.createStorageService(workspace, logService, userDataProfileService).then(service => {
|
||||||
|
+ this.createStorageService(workspace, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService).then(service => {
|
||||||
|
serviceCollection.set(IStorageService, service);
|
||||||
|
return service;
|
||||||
|
})
|
||||||
|
@@ -604,7 +605,21 @@ export class BrowserMain extends Disposa
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
- protected async createStorageService(workspace: IAnyWorkspaceIdentifier, logService: ILogService, userDataProfileService: IUserDataProfileService): Promise<IStorageService> {
|
||||||
|
+ protected async createStorageService(workspace: IAnyWorkspaceIdentifier, environmentService: IBrowserWorkbenchEnvironmentService, logService: ILogService, userDataProfileService: IUserDataProfileService, userDataProfilesService: IUserDataProfilesService, remoteAgentService: IRemoteAgentService): Promise<IStorageService> {
|
||||||
|
+ const connection = remoteAgentService.getConnection();
|
||||||
|
+ if (this.configuration.remoteStorageEnabled && connection) {
|
||||||
|
+ const storageService = new NativeWorkbenchStorageService(workspace, userDataProfileService, userDataProfilesService, connection, environmentService);
|
||||||
|
+
|
||||||
|
+ try {
|
||||||
|
+ await storageService.initialize();
|
||||||
|
+ this.onWillShutdownDisposables.add(toDisposable(() => storageService.close()));
|
||||||
|
+ return storageService;
|
||||||
|
+ } catch (error) {
|
||||||
|
+ onUnexpectedError(error);
|
||||||
|
+ logService.error('Remote storage service initialization failed, falling back to browser storage', error);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
const storageService = new BrowserStorageService(workspace, userDataProfileService, logService);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Index: code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
|
||||||
|
===================================================================
|
||||||
|
--- code-server.orig/lib/vscode/src/vs/sessions/browser/web.main.ts
|
||||||
|
+++ code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
|
||||||
|
@@ -39,9 +39,9 @@ export class SessionsBrowserMain extends
|
||||||
|
_workspace: IAnyWorkspaceIdentifier,
|
||||||
|
environmentService: IBrowserWorkbenchEnvironmentService,
|
||||||
|
userDataProfileService: IUserDataProfileService,
|
||||||
|
- _userDataProfilesService: BrowserUserDataProfilesService,
|
||||||
|
+ userDataProfilesService: BrowserUserDataProfilesService,
|
||||||
|
fileService: FileService,
|
||||||
|
- _remoteAgentService: IRemoteAgentService,
|
||||||
|
+ remoteAgentService: IRemoteAgentService,
|
||||||
|
uriIdentityService: IUriIdentityService,
|
||||||
|
policyService: IPolicyService,
|
||||||
|
logService: ILogService,
|
||||||
|
@@ -82,7 +82,7 @@ export class SessionsBrowserMain extends
|
||||||
|
serviceCollection.set(IWorkbenchConfigurationService, configurationService);
|
||||||
|
|
||||||
|
// Storage
|
||||||
|
- const storageService = await this.createStorageService(workspaceIdentifier, logService, userDataProfileService);
|
||||||
|
+ const storageService = await this.createStorageService(workspaceIdentifier, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService);
|
||||||
|
serviceCollection.set(IStorageService, storageService);
|
||||||
|
|
||||||
|
// Workspace Trust Service
|
||||||
@@ -22,3 +22,9 @@ clipboard.diff
|
|||||||
display-language.diff
|
display-language.diff
|
||||||
trusted-domains.diff
|
trusted-domains.diff
|
||||||
signature-verification.diff
|
signature-verification.diff
|
||||||
|
copilot.diff
|
||||||
|
app-name.diff
|
||||||
|
remote-storage.diff
|
||||||
|
remote-secret-storage.diff
|
||||||
|
csp-hashes.diff
|
||||||
|
node-version.diff
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -70,6 +70,10 @@ export interface IProductConfiguration {
|
@@ -102,6 +102,10 @@ export interface IProductConfiguration {
|
||||||
readonly updateEndpoint?: string
|
readonly updateEndpoint?: string
|
||||||
readonly logoutEndpoint?: string
|
readonly logoutEndpoint?: string
|
||||||
readonly proxyEndpointTemplate?: string
|
readonly proxyEndpointTemplate?: string
|
||||||
@@ -54,7 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -344,6 +344,10 @@ export class WebClientServer {
|
@@ -404,6 +404,10 @@ export class WebClientServer {
|
||||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
||||||
@@ -63,5 +63,5 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
+ path: rootBase + '/_static/out/browser/serviceWorker.js',
|
+ path: rootBase + '/_static/out/browser/serviceWorker.js',
|
||||||
+ },
|
+ },
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
};
|
|
||||||
|
|||||||
+12
-30
@@ -1,43 +1,25 @@
|
|||||||
Make sourcemaps self-hosted
|
Remove sourcemaps URL
|
||||||
|
|
||||||
Normally source maps get removed as part of the build process so prevent that
|
These will not work since we patch VS Code.
|
||||||
from happening. Also avoid using the windows.net host since obviously we can
|
|
||||||
not host our source maps there and want them to be self-hosted even if we could.
|
|
||||||
|
|
||||||
To test try debugging/browsing the source of a build in a browser.
|
|
||||||
|
|
||||||
Index: code-server/lib/vscode/build/gulpfile.reh.ts
|
Index: code-server/lib/vscode/build/gulpfile.reh.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.ts
|
--- code-server.orig/lib/vscode/build/gulpfile.reh.ts
|
||||||
+++ code-server/lib/vscode/build/gulpfile.reh.ts
|
+++ code-server/lib/vscode/build/gulpfile.reh.ts
|
||||||
@@ -263,8 +263,7 @@ function packageTask(type: string, platf
|
@@ -260,10 +260,15 @@ function packageTask(type: string, platf
|
||||||
|
const destination = path.join(BUILD_ROOT, destinationFolderName);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
+ const jsFilterMain = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path));
|
||||||
|
+
|
||||||
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
||||||
.pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
.pipe(rename(function (path) { path.dirname = path.dirname!.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
||||||
- .pipe(util.setExecutableBit(['**/*.sh']))
|
.pipe(util.setExecutableBit(['**/*.sh']))
|
||||||
- .pipe(filter(['**', '!**/*.{js,css}.map']));
|
- .pipe(filter(['**', '!**/*.{js,css}.map']));
|
||||||
+ .pipe(util.setExecutableBit(['**/*.sh']));
|
+ .pipe(filter(['**', '!**/*.{js,css}.map']))
|
||||||
|
+ .pipe(jsFilterMain)
|
||||||
|
+ .pipe(util.stripSourceMappingURL())
|
||||||
|
+ .pipe(jsFilterMain.restore);
|
||||||
|
|
||||||
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
||||||
const isUIExtension = (manifest: { extensionKind?: string; main?: string; contributes?: Record<string, unknown> }) => {
|
const isUIExtension = (manifest: { extensionKind?: string; main?: string; contributes?: Record<string, unknown> }) => {
|
||||||
@@ -304,9 +303,9 @@ function packageTask(type: string, platf
|
|
||||||
.map(name => `.build/extensions/${name}/**`);
|
|
||||||
|
|
||||||
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
|
|
||||||
- const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true });
|
|
||||||
- const sources = es.merge(src, extensions, extensionsCommonDependencies)
|
|
||||||
+ const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true })
|
|
||||||
.pipe(filter(['**', '!**/*.{js,css}.map'], { dot: true }));
|
|
||||||
+ const sources = es.merge(src, extensions, extensionsCommonDependencies);
|
|
||||||
|
|
||||||
let version = packageJson.version;
|
|
||||||
const quality = (product as typeof product & { quality?: string }).quality;
|
|
||||||
@@ -501,7 +500,7 @@ function tweakProductForServerWeb(produc
|
|
||||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
|
||||||
bundleTask,
|
|
||||||
util.rimraf(`out-vscode-${type}-min`),
|
|
||||||
- optimize.minifyTask(`out-vscode-${type}`, `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
|
|
||||||
+ optimize.minifyTask(`out-vscode-${type}`, ``)
|
|
||||||
));
|
|
||||||
gulp.task(minifyTask);
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.
|
|||||||
import { ExtHostDiskFileSystemProvider } from './extHostDiskFileSystemProvider.js';
|
import { ExtHostDiskFileSystemProvider } from './extHostDiskFileSystemProvider.js';
|
||||||
import nodeModule from 'node:module';
|
import nodeModule from 'node:module';
|
||||||
import { assertType } from '../../../base/common/types.js';
|
import { assertType } from '../../../base/common/types.js';
|
||||||
@@ -226,6 +228,52 @@ export class ExtHostExtensionService ext
|
@@ -176,6 +178,52 @@ export class ExtHostExtensionService ext
|
||||||
|
|
||||||
performance.mark('code/extHost/didInitAPI');
|
performance.mark('code/extHost/didInitAPI');
|
||||||
|
|
||||||
|
|||||||
+8
-16
@@ -12,15 +12,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||||
@@ -4,6 +4,7 @@
|
@@ -68,6 +68,7 @@ import { IExtensionsScannerService } fro
|
||||||
*--------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
import { hostname, release } from 'os';
|
|
||||||
+import { promises as fs } from 'fs';
|
|
||||||
import { Emitter, Event } from '../../base/common/event.js';
|
|
||||||
import { DisposableStore, toDisposable } from '../../base/common/lifecycle.js';
|
|
||||||
import { Schemas } from '../../base/common/network.js';
|
|
||||||
@@ -65,6 +66,7 @@ import { IExtensionsScannerService } fro
|
|
||||||
import { ExtensionsScannerService } from './extensionsScannerService.js';
|
import { ExtensionsScannerService } from './extensionsScannerService.js';
|
||||||
import { IExtensionsProfileScannerService } from '../../platform/extensionManagement/common/extensionsProfileScannerService.js';
|
import { IExtensionsProfileScannerService } from '../../platform/extensionManagement/common/extensionsProfileScannerService.js';
|
||||||
import { IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.js';
|
import { IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.js';
|
||||||
@@ -28,18 +20,18 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
|||||||
import { NullPolicyService } from '../../platform/policy/common/policy.js';
|
import { NullPolicyService } from '../../platform/policy/common/policy.js';
|
||||||
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
|
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
|
||||||
import { LoggerService } from '../../platform/log/node/loggerService.js';
|
import { LoggerService } from '../../platform/log/node/loggerService.js';
|
||||||
@@ -172,11 +174,23 @@ export async function setupServerService
|
@@ -179,11 +180,23 @@ export async function setupServerService
|
||||||
const requestService = new RequestService('remote', configurationService, environmentService, logService);
|
const requestService = new RequestService('remote', configurationService, environmentService, logService);
|
||||||
services.set(IRequestService, requestService);
|
services.set(IRequestService, requestService);
|
||||||
|
|
||||||
+ let isContainer = undefined;
|
+ let isContainer = undefined;
|
||||||
+ try {
|
+ try {
|
||||||
+ await fs.stat('/run/.containerenv');
|
+ await fs.promises.stat('/run/.containerenv');
|
||||||
+ isContainer = true;
|
+ isContainer = true;
|
||||||
+ } catch (error) { /* Does not exist, probably. */ }
|
+ } catch (error) { /* Does not exist, probably. */ }
|
||||||
+ if (!isContainer) {
|
+ if (!isContainer) {
|
||||||
+ try {
|
+ try {
|
||||||
+ const content = await fs.readFile('/proc/self/cgroup', 'utf8')
|
+ const content = await fs.promises.readFile('/proc/self/cgroup', 'utf8')
|
||||||
+ isContainer = content.includes('docker');
|
+ isContainer = content.includes('docker');
|
||||||
+ } catch (error) { /* Permission denied, probably. */ }
|
+ } catch (error) { /* Permission denied, probably. */ }
|
||||||
+ }
|
+ }
|
||||||
@@ -134,20 +126,20 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -348,6 +348,8 @@ export class WebClientServer {
|
@@ -408,6 +408,8 @@ export class WebClientServer {
|
||||||
scope: vscodeBase + '/',
|
scope: vscodeBase + '/',
|
||||||
path: rootBase + '/_static/out/browser/serviceWorker.js',
|
path: rootBase + '/_static/out/browser/serviceWorker.js',
|
||||||
},
|
},
|
||||||
+ enableTelemetry: this._productService.enableTelemetry,
|
+ enableTelemetry: this._productService.enableTelemetry,
|
||||||
+ telemetryEndpoint: this._productService.telemetryEndpoint,
|
+ telemetryEndpoint: this._productService.telemetryEndpoint,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
};
|
|
||||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -74,6 +74,7 @@ export interface IProductConfiguration {
|
@@ -106,6 +106,7 @@ export interface IProductConfiguration {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
readonly scope: string;
|
readonly scope: string;
|
||||||
}
|
}
|
||||||
@@ -159,7 +151,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||||
@@ -58,7 +58,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
@@ -74,7 +74,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||||
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
|
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
|
||||||
controlUrl: "",
|
controlUrl: "",
|
||||||
recommendationsUrl: "",
|
recommendationsUrl: "",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -23,6 +23,7 @@ export const serverOptions: OptionDescri
|
@@ -39,6 +39,7 @@ export const serverOptions: OptionDescri
|
||||||
'disable-file-uploads': { type: 'boolean' },
|
'disable-file-uploads': { type: 'boolean' },
|
||||||
'disable-getting-started-override': { type: 'boolean' },
|
'disable-getting-started-override': { type: 'boolean' },
|
||||||
'locale': { type: 'string' },
|
'locale': { type: 'string' },
|
||||||
@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -118,6 +119,7 @@ export interface ServerParsedArgs {
|
@@ -138,6 +139,7 @@ export interface ServerParsedArgs {
|
||||||
'disable-file-uploads'?: boolean;
|
'disable-file-uploads'?: boolean;
|
||||||
'disable-getting-started-override'?: boolean,
|
'disable-getting-started-override'?: boolean,
|
||||||
'locale'?: string
|
'locale'?: string
|
||||||
@@ -24,7 +24,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -339,6 +339,14 @@ export class WebClientServer {
|
@@ -399,6 +399,14 @@ export class WebClientServer {
|
||||||
scopes: [['user:email'], ['repo']]
|
scopes: [['user:email'], ['repo']]
|
||||||
} : undefined;
|
} : undefined;
|
||||||
|
|
||||||
@@ -39,11 +39,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
rootEndpoint: rootBase,
|
rootEndpoint: rootBase,
|
||||||
@@ -353,6 +361,7 @@ export class WebClientServer {
|
@@ -414,6 +422,7 @@ export class WebClientServer {
|
||||||
telemetryEndpoint: this._productService.telemetryEndpoint,
|
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
+ linkProtectionTrustedDomains,
|
+ linkProtectionTrustedDomains,
|
||||||
};
|
};
|
||||||
|
|
||||||
const proposedApi = this._environmentService.args['enable-proposed-api'];
|
if (!this._environmentService.isBuilt) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
|
|||||||
|
|
||||||
export class BrowserStorageService extends AbstractStorageService {
|
export class BrowserStorageService extends AbstractStorageService {
|
||||||
|
|
||||||
@@ -300,7 +301,11 @@ export class IndexedDBStorageDatabase ex
|
@@ -354,7 +355,11 @@ export class IndexedDBStorageDatabase ex
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {
|
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {
|
||||||
|
|||||||
+12
-12
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||||
@@ -67,6 +67,7 @@ export type ExtensionVirtualWorkspaceSup
|
@@ -99,6 +99,7 @@ export interface IDictationRuntimeProduc
|
||||||
export interface IProductConfiguration {
|
export interface IProductConfiguration {
|
||||||
readonly codeServerVersion?: string
|
readonly codeServerVersion?: string
|
||||||
readonly rootEndpoint?: string
|
readonly rootEndpoint?: string
|
||||||
@@ -101,32 +101,32 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
|||||||
|
|
||||||
readonly version: string;
|
readonly version: string;
|
||||||
readonly date?: string;
|
readonly date?: string;
|
||||||
@@ -115,6 +116,7 @@ export interface IProductConfiguration {
|
@@ -148,6 +149,7 @@ export interface IProductConfiguration {
|
||||||
readonly resourceUrlTemplate: string;
|
|
||||||
readonly nlsBaseUrl: string;
|
|
||||||
readonly accessSKUs?: string[];
|
|
||||||
+ readonly authorizationHeaderToken?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
readonly mcpGallery?: {
|
readonly extensionsGallery?: {
|
||||||
|
+ readonly authorizationHeaderToken?: string;
|
||||||
|
readonly serviceUrl: string;
|
||||||
|
readonly controlUrl: string;
|
||||||
|
readonly extensionUrlTemplate: string;
|
||||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -341,6 +341,7 @@ export class WebClientServer {
|
@@ -401,6 +401,7 @@ export class WebClientServer {
|
||||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||||
codeServerVersion: this._productService.codeServerVersion,
|
codeServerVersion: this._productService.codeServerVersion,
|
||||||
rootEndpoint: rootBase,
|
rootEndpoint: rootBase,
|
||||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||||
embedderIdentifier: 'server-distro',
|
embedderIdentifier: 'server-distro',
|
||||||
|
voiceWsUrl: this._productService.voiceWsUrl,
|
||||||
extensionsGallery: this._productService.extensionsGallery,
|
extensionsGallery: this._productService.extensionsGallery,
|
||||||
};
|
|
||||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||||
@@ -16,6 +16,8 @@ import { join } from '../../base/common/
|
@@ -32,6 +32,8 @@ export function getRedactedServerParsedA
|
||||||
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
}
|
||||||
|
|
||||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||||
+ /* ----- code-server ----- */
|
+ /* ----- code-server ----- */
|
||||||
@@ -134,7 +134,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
|||||||
|
|
||||||
/* ----- server setup ----- */
|
/* ----- server setup ----- */
|
||||||
|
|
||||||
@@ -104,6 +106,8 @@ export const serverOptions: OptionDescri
|
@@ -124,6 +126,8 @@ export const serverOptions: OptionDescri
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface ServerParsedArgs {
|
export interface ServerParsedArgs {
|
||||||
|
|||||||
+10
-41
@@ -3,9 +3,6 @@ Serve webviews from the same origin
|
|||||||
Normally webviews are served from vscode-webview.net but we would rather them be
|
Normally webviews are served from vscode-webview.net but we would rather them be
|
||||||
self-hosted.
|
self-hosted.
|
||||||
|
|
||||||
When doing this CSP will block resources (for example when viewing images) so
|
|
||||||
add 'self' to the CSP to fix that.
|
|
||||||
|
|
||||||
Additionally the service worker defaults to handling *all* requests made to the
|
Additionally the service worker defaults to handling *all* requests made to the
|
||||||
current host but when self-hosting the webview this will end up including the
|
current host but when self-hosting the webview this will end up including the
|
||||||
webview HTML itself which means these requests will fail since the communication
|
webview HTML itself which means these requests will fail since the communication
|
||||||
@@ -20,16 +17,6 @@ webview host is separate by default but we serve on the same host).
|
|||||||
|
|
||||||
To test, open a few types of webviews (images, markdown, extension details, etc).
|
To test, open a few types of webviews (images, markdown, extension details, etc).
|
||||||
|
|
||||||
Make sure to update the hash. To do so:
|
|
||||||
1. run code-server
|
|
||||||
2. open any webview (i.e. preview Markdown)
|
|
||||||
3. see error in console and copy hash
|
|
||||||
|
|
||||||
That will test the hash change in pre/index.html
|
|
||||||
|
|
||||||
Double-check the console to make sure there are no console errors for the webWorkerExtensionHostIframe
|
|
||||||
which also requires a hash change.
|
|
||||||
|
|
||||||
parentOriginHash changes
|
parentOriginHash changes
|
||||||
|
|
||||||
This fixes webviews from not working properly due to a change upstream.
|
This fixes webviews from not working properly due to a change upstream.
|
||||||
@@ -41,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||||
@@ -220,7 +220,7 @@ export class BrowserWorkbenchEnvironment
|
@@ -239,7 +239,7 @@ export class BrowserWorkbenchEnvironment
|
||||||
|
|
||||||
@memoize
|
@memoize
|
||||||
get webviewExternalEndpoint(): string {
|
get webviewExternalEndpoint(): string {
|
||||||
@@ -54,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||||
@@ -361,6 +361,7 @@ export class WebClientServer {
|
@@ -416,6 +416,7 @@ export class WebClientServer {
|
||||||
const workbenchWebConfiguration = {
|
const workbenchWebConfiguration = {
|
||||||
remoteAuthority,
|
remoteAuthority,
|
||||||
serverBasePath: basePath,
|
serverBasePath: basePath,
|
||||||
@@ -66,25 +53,16 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
--- code-server.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
|
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
|
||||||
@@ -5,7 +5,7 @@
|
@@ -253,7 +253,7 @@
|
||||||
<meta charset="UTF-8">
|
|
||||||
|
|
||||||
<meta http-equiv="Content-Security-Policy"
|
|
||||||
- content="default-src 'none'; script-src 'sha256-TaWGDzV7c9rUH2q/5ygOyYUHSyHIqBMYfucPh3lnKvU=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
|
||||||
+ content="default-src 'none'; script-src 'sha256-nQZh+9dHKZP2cHbhYlCbWDtqxxJtGjRGBx57zNP2DZM=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
|
||||||
|
|
||||||
<!-- Disable pinch zooming -->
|
|
||||||
<meta name="viewport"
|
|
||||||
@@ -256,7 +256,7 @@
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`);
|
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}&platform=${searchParams.get('platform')}`);
|
||||||
- navigator.serviceWorker.register(swPath, { type: 'module' })
|
- navigator.serviceWorker.register(swPath, { type: 'module', updateViaCache: 'none' })
|
||||||
+ navigator.serviceWorker.register(swPath)
|
+ navigator.serviceWorker.register(swPath)
|
||||||
.then(async registration => {
|
.then(async registration => {
|
||||||
/**
|
if (navigator.serviceWorker.controller) {
|
||||||
* @param {MessageEvent} event
|
// A previous SW is already controlling. Force an update
|
||||||
@@ -370,6 +370,12 @@
|
@@ -332,6 +332,12 @@
|
||||||
|
|
||||||
const hostname = location.hostname;
|
const hostname = location.hostname;
|
||||||
|
|
||||||
@@ -101,17 +79,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
|
|||||||
===================================================================
|
===================================================================
|
||||||
--- code-server.orig/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
|
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||||
@@ -4,7 +4,7 @@
|
@@ -34,6 +34,13 @@
|
||||||
<meta http-equiv="Content-Security-Policy" content="
|
}
|
||||||
default-src 'none';
|
|
||||||
child-src 'self' data: blob:;
|
|
||||||
- script-src 'self' 'unsafe-eval' 'sha256-cl8ijlOzEe+0GRCQNJQu2k6nUQ0fAYNYIuuKEm72JDs=' https: http://localhost:* blob:;
|
|
||||||
+ script-src 'self' 'unsafe-eval' 'sha256-yhZXuB8LS6t73dvNg6rtLX8y4PHLnqRm5+6DdOGkOcw=' https: http://localhost:* blob:;
|
|
||||||
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
@@ -25,6 +25,13 @@
|
|
||||||
// validation not requested
|
|
||||||
return start();
|
return start();
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
|
|||||||
+11
-4
@@ -13,7 +13,8 @@ import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSo
|
|||||||
import { handleUpgrade } from "./wsRouter"
|
import { handleUpgrade } from "./wsRouter"
|
||||||
|
|
||||||
type SocketOptions = { socket: string; "socket-mode"?: string }
|
type SocketOptions = { socket: string; "socket-mode"?: string }
|
||||||
type ListenOptions = DefaultedArgs | SocketOptions
|
type FdOptions = { "socket-fd": number }
|
||||||
|
type ListenOptions = DefaultedArgs | SocketOptions | FdOptions
|
||||||
|
|
||||||
export interface App extends Disposable {
|
export interface App extends Disposable {
|
||||||
/** Handles regular HTTP requests. */
|
/** Handles regular HTTP requests. */
|
||||||
@@ -30,8 +31,12 @@ const isSocketOpts = (opts: ListenOptions): opts is SocketOptions => {
|
|||||||
return !!(opts as SocketOptions).socket || !(opts as DefaultedArgs).host
|
return !!(opts as SocketOptions).socket || !(opts as DefaultedArgs).host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const isFdOpts = (opts: ListenOptions): opts is FdOptions => {
|
||||||
|
return typeof (opts as FdOptions)["socket-fd"] === "number"
|
||||||
|
}
|
||||||
|
|
||||||
export const listen = async (server: http.Server, opts: ListenOptions) => {
|
export const listen = async (server: http.Server, opts: ListenOptions) => {
|
||||||
if (isSocketOpts(opts)) {
|
if (!isFdOpts(opts) && isSocketOpts(opts)) {
|
||||||
try {
|
try {
|
||||||
await fs.unlink(opts.socket)
|
await fs.unlink(opts.socket)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
@@ -46,7 +51,9 @@ export const listen = async (server: http.Server, opts: ListenOptions) => {
|
|||||||
server.on("error", (err) => util.logError(logger, "http server error", err))
|
server.on("error", (err) => util.logError(logger, "http server error", err))
|
||||||
resolve()
|
resolve()
|
||||||
}
|
}
|
||||||
if (isSocketOpts(opts)) {
|
if (isFdOpts(opts)) {
|
||||||
|
server.listen({ fd: opts["socket-fd"] }, onListen)
|
||||||
|
} else if (isSocketOpts(opts)) {
|
||||||
server.listen(opts.socket, onListen)
|
server.listen(opts.socket, onListen)
|
||||||
} else {
|
} else {
|
||||||
// [] is the correct format when using :: but Node errors with them.
|
// [] is the correct format when using :: but Node errors with them.
|
||||||
@@ -56,7 +63,7 @@ export const listen = async (server: http.Server, opts: ListenOptions) => {
|
|||||||
|
|
||||||
// NOTE@jsjoeio: we need to chmod after the server is finished
|
// NOTE@jsjoeio: we need to chmod after the server is finished
|
||||||
// listening. Otherwise, the socket may not have been created yet.
|
// listening. Otherwise, the socket may not have been created yet.
|
||||||
if (isSocketOpts(opts)) {
|
if (!isFdOpts(opts) && isSocketOpts(opts)) {
|
||||||
if (opts["socket-mode"]) {
|
if (opts["socket-mode"]) {
|
||||||
await fs.chmod(opts.socket, opts["socket-mode"])
|
await fs.chmod(opts.socket, opts["socket-mode"])
|
||||||
}
|
}
|
||||||
|
|||||||
+103
-13
@@ -1,8 +1,9 @@
|
|||||||
import { field, Level, logger } from "@coder/logger"
|
import { field, Level, logger } from "@coder/logger"
|
||||||
|
import * as crypto from "crypto"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
import { load } from "js-yaml"
|
import { load } from "js-yaml"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { generateCertificate, generatePassword, paths, splitOnFirstEquals } from "./util"
|
import { expandTilde, generateCertificate, generatePassword, paths, splitOnFirstEquals } from "./util"
|
||||||
import { EditorSessionManagerClient } from "./vscodeSocket"
|
import { EditorSessionManagerClient } from "./vscodeSocket"
|
||||||
|
|
||||||
export enum Feature {
|
export enum Feature {
|
||||||
@@ -46,6 +47,7 @@ export interface UserProvidedCodeArgs {
|
|||||||
"show-versions"?: boolean
|
"show-versions"?: boolean
|
||||||
category?: string
|
category?: string
|
||||||
"github-auth"?: string
|
"github-auth"?: string
|
||||||
|
"enable-remote-storage"?: boolean
|
||||||
"disable-update-check"?: boolean
|
"disable-update-check"?: boolean
|
||||||
"disable-file-downloads"?: boolean
|
"disable-file-downloads"?: boolean
|
||||||
"disable-file-uploads"?: boolean
|
"disable-file-uploads"?: boolean
|
||||||
@@ -83,6 +85,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
|||||||
open?: boolean
|
open?: boolean
|
||||||
"bind-addr"?: string
|
"bind-addr"?: string
|
||||||
socket?: string
|
socket?: string
|
||||||
|
"socket-fd"?: number
|
||||||
"socket-mode"?: string
|
"socket-mode"?: string
|
||||||
"trusted-origins"?: string[]
|
"trusted-origins"?: string[]
|
||||||
version?: boolean
|
version?: boolean
|
||||||
@@ -97,6 +100,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
|||||||
"abs-proxy-base-path"?: string
|
"abs-proxy-base-path"?: string
|
||||||
i18n?: string
|
i18n?: string
|
||||||
"idle-timeout-seconds"?: number
|
"idle-timeout-seconds"?: number
|
||||||
|
"vscode-option"?: string[]
|
||||||
/* Positional arguments. */
|
/* Positional arguments. */
|
||||||
_?: string[]
|
_?: string[]
|
||||||
}
|
}
|
||||||
@@ -235,6 +239,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
|||||||
port: { type: "number", description: "" },
|
port: { type: "number", description: "" },
|
||||||
|
|
||||||
socket: { type: "string", path: true, description: "Path to a socket (bind-addr will be ignored)." },
|
socket: { type: "string", path: true, description: "Path to a socket (bind-addr will be ignored)." },
|
||||||
|
"socket-fd": {
|
||||||
|
type: "number",
|
||||||
|
description: "File descriptor of a pre-bound, listening socket to use (for systemd socket activation).",
|
||||||
|
},
|
||||||
"socket-mode": { type: "string", description: "File mode of the socket." },
|
"socket-mode": { type: "string", description: "File mode of the socket." },
|
||||||
"trusted-origins": {
|
"trusted-origins": {
|
||||||
type: "string[]",
|
type: "string[]",
|
||||||
@@ -268,6 +276,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
|||||||
type: "string",
|
type: "string",
|
||||||
description: "GitHub authentication token (can only be passed in via $GITHUB_TOKEN or the config file).",
|
description: "GitHub authentication token (can only be passed in via $GITHUB_TOKEN or the config file).",
|
||||||
},
|
},
|
||||||
|
"enable-remote-storage": {
|
||||||
|
type: "boolean",
|
||||||
|
description: "Persist VS Code workbench storage on the remote server instead of browser storage.",
|
||||||
|
},
|
||||||
"proxy-domain": { type: "string[]", description: "Domain used for proxying ports." },
|
"proxy-domain": { type: "string[]", description: "Domain used for proxying ports." },
|
||||||
"skip-auth-preflight": {
|
"skip-auth-preflight": {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
@@ -322,6 +334,13 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
|||||||
"Override the reconnection grace time in seconds. Clients who disconnect for longer than this duration will need to \n" +
|
"Override the reconnection grace time in seconds. Clients who disconnect for longer than this duration will need to \n" +
|
||||||
"reload the window. Defaults to 10800 (3 hours).",
|
"reload the window. Defaults to 10800 (3 hours).",
|
||||||
},
|
},
|
||||||
|
"vscode-option": {
|
||||||
|
type: "string[]",
|
||||||
|
description:
|
||||||
|
"Pass an option straight through to the VS Code server as flag=value, or as a bare flag for a \n" +
|
||||||
|
"boolean. Repeatable; repeating the same flag builds an array. Use this to reach VS Code options \n" +
|
||||||
|
"code-server does not model itself, e.g. --vscode-option enable-sandbox --vscode-option agents=true.",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
|
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
|
||||||
@@ -415,13 +434,13 @@ export const parse = (
|
|||||||
throw new Error("--github-auth can only be set in the config file or passed in via $GITHUB_TOKEN")
|
throw new Error("--github-auth can only be set in the config file or passed in via $GITHUB_TOKEN")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === "idle-timeout-seconds" && Number(value) <= 60) {
|
|
||||||
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
|
|
||||||
}
|
|
||||||
|
|
||||||
const option = options[key]
|
const option = options[key]
|
||||||
if (option.type === "boolean") {
|
if (option.type === "boolean") {
|
||||||
;(args[key] as boolean) = true
|
// Booleans set to false (for example `--flag=false`, which is also how
|
||||||
|
// false values from the config file are passed in) are ignored.
|
||||||
|
if (value !== "false") {
|
||||||
|
;(args[key] as boolean) = true
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,12 +457,16 @@ export const parse = (
|
|||||||
throw error(`--${key} requires a value`)
|
throw error(`--${key} requires a value`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === "idle-timeout-seconds" && Number(value) <= 60) {
|
||||||
|
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
|
||||||
|
}
|
||||||
|
|
||||||
if (option.type === OptionalString && value === "false") {
|
if (option.type === OptionalString && value === "false") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option.path) {
|
if (option.path) {
|
||||||
value = path.resolve(value)
|
value = path.resolve(expandTilde(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (option.type) {
|
switch (option.type) {
|
||||||
@@ -548,7 +571,7 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!args["session-socket"]) {
|
if (!args["session-socket"]) {
|
||||||
args["session-socket"] = path.join(args["user-data-dir"], "code-server-ipc.sock")
|
args["session-socket"] = defaultSessionSocket(args["user-data-dir"])
|
||||||
}
|
}
|
||||||
process.env.CODE_SERVER_SESSION_SOCKET = args["session-socket"]
|
process.env.CODE_SERVER_SESSION_SOCKET = args["session-socket"]
|
||||||
|
|
||||||
@@ -643,6 +666,15 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
|||||||
args["reconnection-grace-time"] = process.env.CODE_SERVER_RECONNECTION_GRACE_TIME
|
args["reconnection-grace-time"] = process.env.CODE_SERVER_RECONNECTION_GRACE_TIME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Space-separated, like NODE_OPTIONS. Appended to any flags rather than
|
||||||
|
// replacing them so the two can be combined.
|
||||||
|
if (process.env.VSCODE_OPTIONS) {
|
||||||
|
args["vscode-option"] = [
|
||||||
|
...(args["vscode-option"] ?? []),
|
||||||
|
...process.env.VSCODE_OPTIONS.split(/\s+/).filter((option) => option),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
if (process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) {
|
if (process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS) {
|
||||||
if (isNaN(Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS))) {
|
if (isNaN(Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS))) {
|
||||||
logger.info("CODE_SERVER_IDLE_TIMEOUT_SECONDS must be a number")
|
logger.info("CODE_SERVER_IDLE_TIMEOUT_SECONDS must be a number")
|
||||||
@@ -677,9 +709,7 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
|||||||
}
|
}
|
||||||
args["proxy-domain"] = finalProxies
|
args["proxy-domain"] = finalProxies
|
||||||
|
|
||||||
if (!args["app-name"]) {
|
args["app-name"] ??= process.env.CODE_SERVER_APP_NAME || "code-server"
|
||||||
args["app-name"] = "code-server"
|
|
||||||
}
|
|
||||||
|
|
||||||
args._ = getResolvedPathsFromArgs(args)
|
args._ = getResolvedPathsFromArgs(args)
|
||||||
|
|
||||||
@@ -690,6 +720,25 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
|||||||
} as DefaultedArgs // TODO: Technically no guarantee this is fulfilled.
|
} as DefaultedArgs // TODO: Technically no guarantee this is fulfilled.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The session socket to use when one was not given.
|
||||||
|
*
|
||||||
|
* Windows has no Unix sockets, so there it is a named pipe, which lives in its
|
||||||
|
* own namespace rather than on disk and so cannot be placed inside the user
|
||||||
|
* data directory. The name is derived from that directory anyway, so that two
|
||||||
|
* instances with separate data directories do not collide and a later
|
||||||
|
* invocation with the same one finds the first. Windows paths are compared
|
||||||
|
* without regard to case, so the name is folded before it is hashed; otherwise
|
||||||
|
* the same directory typed two ways would produce two pipes.
|
||||||
|
*/
|
||||||
|
export function defaultSessionSocket(userDataDir: string, platform: NodeJS.Platform = process.platform): string {
|
||||||
|
if (platform !== "win32") {
|
||||||
|
return path.join(userDataDir, "code-server-ipc.sock")
|
||||||
|
}
|
||||||
|
const name = crypto.createHash("sha256").update(path.resolve(userDataDir).toLowerCase()).digest("hex").slice(0, 16)
|
||||||
|
return String.raw`\\.\pipe\code-server-ipc-${name}`
|
||||||
|
}
|
||||||
|
|
||||||
export function getResolvedPathsFromArgs(args: UserProvidedArgs): string[] {
|
export function getResolvedPathsFromArgs(args: UserProvidedArgs): string[] {
|
||||||
return (args._ ?? []).map((p) => path.resolve(p))
|
return (args._ ?? []).map((p) => path.resolve(p))
|
||||||
}
|
}
|
||||||
@@ -911,17 +960,58 @@ export interface CodeArgs extends UserProvidedCodeArgs {
|
|||||||
log?: string[]
|
log?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand --vscode-option entries into VS Code server arguments.
|
||||||
|
*
|
||||||
|
* An entry is `flag=value`, or a bare `flag` meaning true. A leading `--` on
|
||||||
|
* the flag is optional, so both spellings people reach for work. Repeating a
|
||||||
|
* flag collects the values into an array, since several VS Code options take
|
||||||
|
* one.
|
||||||
|
*
|
||||||
|
* `true` and `false` become booleans rather than strings. VS Code tests these
|
||||||
|
* flags for truthiness and the string "false" is truthy, so passing it along
|
||||||
|
* verbatim would quietly do the opposite of what was asked.
|
||||||
|
*/
|
||||||
|
export const parseVscodeOptions = (entries: string[]): Record<string, string | boolean | string[]> => {
|
||||||
|
const parsed: Record<string, string | boolean | string[]> = {}
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const [flag, rawValue] = splitOnFirstEquals(entry.replace(/^--/, ""))
|
||||||
|
if (!flag) {
|
||||||
|
throw new Error(`--vscode-option requires a flag name (got "${entry}")`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const value: string | boolean =
|
||||||
|
typeof rawValue === "undefined" || rawValue === "true" ? true : rawValue === "false" ? false : rawValue
|
||||||
|
|
||||||
|
const existing = parsed[flag]
|
||||||
|
if (typeof existing === "undefined") {
|
||||||
|
parsed[flag] = value
|
||||||
|
} else if (Array.isArray(existing)) {
|
||||||
|
existing.push(String(value))
|
||||||
|
} else {
|
||||||
|
parsed[flag] = [String(existing), String(value)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert our arguments to equivalent VS Code server arguments.
|
* Convert our arguments to equivalent VS Code server arguments.
|
||||||
* Does not add any extra arguments.
|
* Does not add any extra arguments.
|
||||||
*/
|
*/
|
||||||
export const toCodeArgs = async (args: DefaultedArgs): Promise<CodeArgs> => {
|
export const toCodeArgs = async (args: DefaultedArgs): Promise<CodeArgs> => {
|
||||||
|
// The passthrough option is ours; VS Code has no idea what it is.
|
||||||
|
const { "vscode-option": vscodeOptions, ...rest } = args
|
||||||
return {
|
return {
|
||||||
...args,
|
...rest,
|
||||||
/** Type casting. */
|
/** Type casting. */
|
||||||
help: !!args.help,
|
help: !!args.help,
|
||||||
version: !!args.version,
|
version: !!args.version,
|
||||||
port: args.port?.toString(),
|
port: args.port?.toString(),
|
||||||
log: args.log ? [args.log] : undefined,
|
log: args.log ? [args.log] : undefined,
|
||||||
}
|
// Last, so that reaching an option code-server does model still works.
|
||||||
|
...parseVscodeOptions(vscodeOptions ?? []),
|
||||||
|
} as CodeArgs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import { logger } from "@coder/logger"
|
import { logger } from "@coder/logger"
|
||||||
import type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"
|
|
||||||
import * as os from "os"
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
|
|
||||||
export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles {
|
type PackageJson = {
|
||||||
|
version: string
|
||||||
|
commit: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPackageJson(relativePath: string): PackageJson {
|
||||||
let pkg = {}
|
let pkg = {}
|
||||||
try {
|
try {
|
||||||
pkg = require(relativePath)
|
pkg = require(relativePath)
|
||||||
@@ -11,7 +15,7 @@ export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJso
|
|||||||
logger.warn(error.message)
|
logger.warn(error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pkg
|
return pkg as PackageJson
|
||||||
}
|
}
|
||||||
|
|
||||||
export const rootPath = path.resolve(__dirname, "../..")
|
export const rootPath = path.resolve(__dirname, "../..")
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import i18next, { init } from "i18next"
|
|||||||
import * as en from "./locales/en.json"
|
import * as en from "./locales/en.json"
|
||||||
import * as ja from "./locales/ja.json"
|
import * as ja from "./locales/ja.json"
|
||||||
import * as th from "./locales/th.json"
|
import * as th from "./locales/th.json"
|
||||||
|
import * as tr from "./locales/tr.json"
|
||||||
import * as ur from "./locales/ur.json"
|
import * as ur from "./locales/ur.json"
|
||||||
import * as zhCn from "./locales/zh-cn.json"
|
import * as zhCn from "./locales/zh-cn.json"
|
||||||
|
|
||||||
@@ -16,6 +17,9 @@ const defaultResources = {
|
|||||||
th: {
|
th: {
|
||||||
translation: th,
|
translation: th,
|
||||||
},
|
},
|
||||||
|
tr: {
|
||||||
|
translation: tr,
|
||||||
|
},
|
||||||
ja: {
|
ja: {
|
||||||
translation: ja,
|
translation: ja,
|
||||||
},
|
},
|
||||||
@@ -54,7 +58,6 @@ init({
|
|||||||
lowerCaseLng: true,
|
lowerCaseLng: true,
|
||||||
debug: process.env.NODE_ENV === "development",
|
debug: process.env.NODE_ENV === "development",
|
||||||
resources: defaultResources,
|
resources: defaultResources,
|
||||||
showSupportNotice: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export default i18next
|
export default i18next
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"LOGIN_TITLE": "{{app}} girişi",
|
||||||
|
"LOGIN_BELOW": "Lütfen aşağıdan giriş yapın.",
|
||||||
|
"WELCOME": "{{app}} uygulamasına hoş geldiniz",
|
||||||
|
"LOGIN_PASSWORD": "Parola için yapılandırma dosyasını kontrol edin.",
|
||||||
|
"LOGIN_USING_ENV_PASSWORD": "Parola $PASSWORD ortam değişkeninden ayarlandı.",
|
||||||
|
"LOGIN_USING_HASHED_PASSWORD": "Parola $HASHED_PASSWORD ortam değişkeninden ayarlandı.",
|
||||||
|
"SUBMIT": "GÖNDER",
|
||||||
|
"PASSWORD_PLACEHOLDER": "PAROLA",
|
||||||
|
"LOGIN_RATE_LIMIT": "Giriş denemesi sınırına ulaşıldı!",
|
||||||
|
"MISS_PASSWORD": "Parola eksik",
|
||||||
|
"INCORRECT_PASSWORD": "Parola yanlış."
|
||||||
|
}
|
||||||
+30
-1
@@ -1,5 +1,7 @@
|
|||||||
|
import * as cookie from "cookie"
|
||||||
|
import type { Request } from "express"
|
||||||
import proxyServer from "http-proxy"
|
import proxyServer from "http-proxy"
|
||||||
import { HttpCode } from "../common/http"
|
import { getCookieSessionName, HttpCode } from "../common/http"
|
||||||
|
|
||||||
export const proxy = proxyServer.createProxyServer({})
|
export const proxy = proxyServer.createProxyServer({})
|
||||||
|
|
||||||
@@ -18,6 +20,33 @@ proxy.on("error", (error, _, res) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function identity<T>(val: T): T {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip the code-server cookie if it exists to avoid transmitting the cookie
|
||||||
|
// to potentially malicious local ports.
|
||||||
|
proxy.on("proxyReq", (preq, req) => {
|
||||||
|
if (req.headers.cookie) {
|
||||||
|
const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"])
|
||||||
|
// Encoding and decoding are no-ops; we just want to remove the token
|
||||||
|
// without changing anything else about the cookies because not all
|
||||||
|
// applications encode/decode the same way `cookie` here does.
|
||||||
|
preq.setHeader(
|
||||||
|
"Cookie",
|
||||||
|
cookie.stringifyCookie(
|
||||||
|
{
|
||||||
|
...cookie.parseCookie(req.headers.cookie, { decode: identity }),
|
||||||
|
[cookieSessionName]: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
encode: identity,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Intercept the response to rewrite absolute redirects against the base path.
|
// Intercept the response to rewrite absolute redirects against the base path.
|
||||||
// Is disabled when the request has no base path which means /absproxy is in use.
|
// Is disabled when the request has no base path which means /absproxy is in use.
|
||||||
proxy.on("proxyRes", (res, req) => {
|
proxy.on("proxyRes", (res, req) => {
|
||||||
|
|||||||
@@ -132,8 +132,10 @@ export const register = async (
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
app.router.use(express.json())
|
// Reject compressed request bodies so unauthenticated requests cannot reach
|
||||||
app.router.use(express.urlencoded({ extended: true }))
|
// the zlib/Brotli decoders. Browsers never compress request bodies.
|
||||||
|
app.router.use(express.json({ inflate: false }))
|
||||||
|
app.router.use(express.urlencoded({ extended: true, inflate: false }))
|
||||||
|
|
||||||
app.router.use(
|
app.router.use(
|
||||||
"/_static",
|
"/_static",
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ router.get("/manifest.json", async (req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let mintKeyPromise: Promise<Buffer> | undefined
|
let mintKeyPromise: Promise<Buffer> | undefined
|
||||||
router.post("/mint-key", async (req, res) => {
|
router.post("/mint-key", ensureAuthenticated, async (req, res) => {
|
||||||
if (!mintKeyPromise) {
|
if (!mintKeyPromise) {
|
||||||
mintKeyPromise = new Promise(async (resolve) => {
|
mintKeyPromise = new Promise(async (resolve) => {
|
||||||
const keyPath = path.join(req.args["user-data-dir"], "serve-web-key-half")
|
const keyPath = path.join(req.args["user-data-dir"], "serve-web-key-half")
|
||||||
|
|||||||
@@ -511,3 +511,18 @@ export function splitOnFirstEquals(str: string): [string, string | undefined] {
|
|||||||
const split = str.split(/=(.+)?/, 2)
|
const split = str.split(/=(.+)?/, 2)
|
||||||
return [split[0], split[1]]
|
return [split[0], split[1]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand a leading `~` to the home directory. The shell does this for
|
||||||
|
* command-line arguments but values from the config file are not expanded.
|
||||||
|
* `~user` forms are left alone.
|
||||||
|
*/
|
||||||
|
export function expandTilde(p: string): string {
|
||||||
|
if (p === "~") {
|
||||||
|
return os.homedir()
|
||||||
|
}
|
||||||
|
if (p.startsWith("~/") || p.startsWith(`~${path.sep}`)) {
|
||||||
|
return path.join(os.homedir(), p.slice(2))
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export async function makeEditorSessionManagerServer(
|
|||||||
): Promise<http.Server> {
|
): Promise<http.Server> {
|
||||||
const router = express()
|
const router = express()
|
||||||
|
|
||||||
router.use(express.json())
|
router.use(express.json({ inflate: false }))
|
||||||
|
|
||||||
router.get<{}, GetSessionResponse | string | unknown, undefined, { filePath?: string }>(
|
router.get<{}, GetSessionResponse | string | unknown, undefined, { filePath?: string }>(
|
||||||
"/session",
|
"/session",
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { version } from "../../src/node/constants"
|
||||||
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
|
const appName = "testnäme"
|
||||||
|
describe("--app-name", [`--app-name=${appName}`], {}, () => {
|
||||||
|
test("should use app-name for the title", async ({ codeServerPage }) => {
|
||||||
|
expect(await codeServerPage.page.title()).toContain(appName)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -32,7 +32,7 @@ describe("code-server", ["--disable-workspace-trust"], {}, () => {
|
|||||||
|
|
||||||
test("should show the Integrated Terminal", async ({ codeServerPage }) => {
|
test("should show the Integrated Terminal", async ({ codeServerPage }) => {
|
||||||
await codeServerPage.focusTerminal()
|
await codeServerPage.focusTerminal()
|
||||||
expect(await codeServerPage.page.isVisible("#terminal")).toBe(true)
|
await expect(codeServerPage.page.locator("#terminal")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should open a file", async ({ codeServerPage }) => {
|
test("should open a file", async ({ codeServerPage }) => {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
|
|||||||
// Action
|
// Action
|
||||||
await codeServerPage.openContextMenu("text=unique-file.txt")
|
await codeServerPage.openContextMenu("text=unique-file.txt")
|
||||||
|
|
||||||
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(true)
|
await expect(codeServerPage.page.locator("text=Download...")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should see the 'Show Local' button on Save As", async ({ codeServerPage }) => {
|
test("should see the 'Show Local' button on Save As", async ({ codeServerPage }) => {
|
||||||
@@ -32,12 +32,11 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
|
|||||||
await codeServerPage.page.waitForSelector(`text=${fileName}`)
|
await codeServerPage.page.waitForSelector(`text=${fileName}`)
|
||||||
|
|
||||||
await codeServerPage.openFile(fileName)
|
await codeServerPage.openFile(fileName)
|
||||||
await codeServerPage.page.click(".tab")
|
|
||||||
await codeServerPage.navigateMenus(["File", "Auto Save"])
|
await codeServerPage.navigateMenus(["File", "Auto Save"])
|
||||||
await codeServerPage.page.keyboard.type("Making some edits.")
|
await codeServerPage.page.keyboard.type("Making some edits.")
|
||||||
await codeServerPage.navigateMenus(["File", "Save As..."])
|
await codeServerPage.navigateMenus(["File", "Save As..."])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
|
test("should see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
|
||||||
@@ -46,14 +45,14 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
|
|||||||
await codeServerPage.waitForTab("Untitled-1")
|
await codeServerPage.waitForTab("Untitled-1")
|
||||||
await codeServerPage.navigateMenus(["File", "Save"])
|
await codeServerPage.navigateMenus(["File", "Save"])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
|
test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
|
||||||
// Action
|
// Action
|
||||||
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
|
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -72,7 +71,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
|
|||||||
// Action
|
// Action
|
||||||
await codeServerPage.openContextMenu("text=unique-file.txt")
|
await codeServerPage.openContextMenu("text=unique-file.txt")
|
||||||
|
|
||||||
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(false)
|
await expect(codeServerPage.page.locator("text=Download...")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should not see the 'Show Local' button on Save as", async ({ codeServerPage }) => {
|
test("should not see the 'Show Local' button on Save as", async ({ codeServerPage }) => {
|
||||||
@@ -85,9 +84,9 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
|
|||||||
// Action
|
// Action
|
||||||
await codeServerPage.page.waitForSelector(`text=${fileName}`)
|
await codeServerPage.page.waitForSelector(`text=${fileName}`)
|
||||||
await codeServerPage.openFile(fileName)
|
await codeServerPage.openFile(fileName)
|
||||||
await codeServerPage.page.click(".tab")
|
|
||||||
await codeServerPage.navigateMenus(["File", "Save As..."])
|
await codeServerPage.navigateMenus(["File", "Save As..."])
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
|
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should not see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
|
test("should not see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
|
||||||
@@ -96,13 +95,13 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
|
|||||||
await codeServerPage.waitForTab("Untitled-1")
|
await codeServerPage.waitForTab("Untitled-1")
|
||||||
await codeServerPage.navigateMenus(["File", "Save"])
|
await codeServerPage.navigateMenus(["File", "Save"])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
|
test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
|
||||||
// Action
|
// Action
|
||||||
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
|
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,8 +13,58 @@ function runTestExtensionTests() {
|
|||||||
|
|
||||||
// Remove end slash in address.
|
// Remove end slash in address.
|
||||||
const normalizedAddress = address.replace(/\/+$/, "")
|
const normalizedAddress = address.replace(/\/+$/, "")
|
||||||
await codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)
|
await expect(codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
runExternalUriTests()
|
||||||
|
}
|
||||||
|
|
||||||
|
function runExternalUriTests(proxyEndpointTemplate?: string) {
|
||||||
|
const cases = [
|
||||||
|
{
|
||||||
|
name: "path",
|
||||||
|
input: "http://127.0.0.1:1234/my/path",
|
||||||
|
suffix: "/my/path",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query and fragment",
|
||||||
|
input: "http://localhost:1234/my/path?token=abc&mode=preview#section",
|
||||||
|
suffix: "/my/path?token%3Dabc%26mode%3Dpreview#section",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "encoded components",
|
||||||
|
input: "http://0.0.0.0:1234/my%20path/%23file?token=a%20b#my%20section",
|
||||||
|
suffix: "/my%20path/%23file?token%3Da%20b#my%20section",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "root path",
|
||||||
|
input: "http://127.0.0.1:1234/",
|
||||||
|
suffix: "/",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const { name, input, suffix } of cases) {
|
||||||
|
test(`asExternalUri should preserve ${name}`, async ({ codeServerPage }) => {
|
||||||
|
const address = await getMaybeProxiedCodeServer(codeServerPage)
|
||||||
|
const normalizedAddress = address.replace(/\/+$/, "")
|
||||||
|
const proxyBase = proxyEndpointTemplate
|
||||||
|
? new URL(proxyEndpointTemplate.replace("{{port}}", "1234"), `${normalizedAddress}/`).toString()
|
||||||
|
: `${normalizedAddress}/proxy/1234/`
|
||||||
|
|
||||||
|
await codeServerPage.waitForTestExtensionLoaded()
|
||||||
|
await codeServerPage.executeCommandViaMenus("code-server: asExternalUri test")
|
||||||
|
|
||||||
|
await codeServerPage.page.waitForSelector(".quick-input-widget:focus-within")
|
||||||
|
await codeServerPage.page.keyboard.type(input)
|
||||||
|
await codeServerPage.page.keyboard.press("Enter")
|
||||||
|
|
||||||
|
// The test extension displays URI.toString(), which also encodes query delimiters.
|
||||||
|
const output = `${proxyBase.replace(/\/$/, "")}${suffix}`
|
||||||
|
await expect(
|
||||||
|
codeServerPage.page.getByText(`Info: input: ${input} output: ${output}`, { exact: true }),
|
||||||
|
).toBeVisible()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const flags = ["--disable-workspace-trust", "--extensions-dir", path.join(__dirname, "./extensions")]
|
const flags = ["--disable-workspace-trust", "--extensions-dir", path.join(__dirname, "./extensions")]
|
||||||
@@ -23,6 +73,17 @@ describe("Extensions", flags, {}, () => {
|
|||||||
runTestExtensionTests()
|
runTestExtensionTests()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for (const proxyEndpointTemplate of ["./proxy/{{port}}", "https://{{port}}-workspace.example.com"]) {
|
||||||
|
describe(
|
||||||
|
`Extensions with VSCODE_PROXY_URI=${proxyEndpointTemplate}`,
|
||||||
|
flags,
|
||||||
|
{ VSCODE_PROXY_URI: proxyEndpointTemplate },
|
||||||
|
() => {
|
||||||
|
runExternalUriTests(proxyEndpointTemplate)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (process.env.USE_PROXY !== "1") {
|
if (process.env.USE_PROXY !== "1") {
|
||||||
describe("Extensions with --cert", [...flags, "--cert"], {}, () => {
|
describe("Extensions with --cert", [...flags, "--cert"], {}, () => {
|
||||||
runTestExtensionTests()
|
runTestExtensionTests()
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import * as vscode from "vscode"
|
|||||||
|
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
vscode.window.showInformationMessage("test extension loaded")
|
vscode.window.showInformationMessage("test extension loaded")
|
||||||
// Test extension
|
|
||||||
|
// Prints the current proxy URI into a notification.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("codeServerTest.proxyUri", () => {
|
vscode.commands.registerCommand("codeServerTest.proxyUri", () => {
|
||||||
if (process.env.VSCODE_PROXY_URI) {
|
if (process.env.VSCODE_PROXY_URI) {
|
||||||
@@ -13,7 +14,8 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
// asExternalUri extension
|
// Asks for a URI, then runs it through asExternalUri and prints the result
|
||||||
|
// into a notification.
|
||||||
context.subscriptions.push(
|
context.subscriptions.push(
|
||||||
vscode.commands.registerCommand("codeServerTest.asExternalUri", async () => {
|
vscode.commands.registerCommand("codeServerTest.asExternalUri", async () => {
|
||||||
const input = await vscode.window.showInputBox({
|
const input = await vscode.window.showInputBox({
|
||||||
@@ -28,4 +30,29 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const secretKey = "code-server-test-secret"
|
||||||
|
|
||||||
|
// Asks for a string, then stores it as a secret.
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.commands.registerCommand("codeServerTest.setSecret", async () => {
|
||||||
|
const input = await vscode.window.showInputBox({
|
||||||
|
prompt: "Secret to store",
|
||||||
|
})
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
await context.secrets.store(secretKey, input)
|
||||||
|
vscode.window.showInformationMessage(`set secret: ${input}`)
|
||||||
|
} else {
|
||||||
|
vscode.window.showErrorMessage(`Failed to run test case. No input provided.`)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
// Prints the current secret, if any.
|
||||||
|
context.subscriptions.push(
|
||||||
|
vscode.commands.registerCommand("codeServerTest.getSecret", async () => {
|
||||||
|
vscode.window.showInformationMessage(`get secret: ${await context.secrets.get(secretKey)}`)
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,16 @@
|
|||||||
"command": "codeServerTest.asExternalUri",
|
"command": "codeServerTest.asExternalUri",
|
||||||
"title": "asExternalUri test",
|
"title": "asExternalUri test",
|
||||||
"category": "code-server"
|
"category": "code-server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "codeServerTest.setSecret",
|
||||||
|
"title": "Set test secret",
|
||||||
|
"category": "code-server"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "codeServerTest.getSecret",
|
||||||
|
"title": "Get test secret",
|
||||||
|
"category": "code-server"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ if (process.env.GITHUB_TOKEN) {
|
|||||||
await codeServerPage.page.click("text=Allow")
|
await codeServerPage.page.click("text=Allow")
|
||||||
// It should ask to select an account, one of which will be the one we
|
// It should ask to select an account, one of which will be the one we
|
||||||
// pre-injected.
|
// pre-injected.
|
||||||
expect(await codeServerPage.page.isVisible("text=Select an account")).toBe(false)
|
await expect(codeServerPage.page.locator("text=Select an account")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ if (process.env.GITHUB_TOKEN) {
|
|||||||
await codeServerPage.page.click("text=Allow")
|
await codeServerPage.page.click("text=Allow")
|
||||||
// Since there is no account it will ask directly for the token (because
|
// Since there is no account it will ask directly for the token (because
|
||||||
// we are on localhost; otherwise it would initiate the oauth flow).
|
// we are on localhost; otherwise it would initiate the oauth flow).
|
||||||
expect(await codeServerPage.page.isVisible("text=GitHub Personal Access Token")).toBe(false)
|
await expect(codeServerPage.page.locator("text=GitHub Personal Access Token")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
|
|||||||
// Skip entering password
|
// Skip entering password
|
||||||
// Click the submit button and login
|
// Click the submit button and login
|
||||||
await codeServerPage.page.click(".submit")
|
await codeServerPage.page.click(".submit")
|
||||||
await codeServerPage.page.waitForLoadState("networkidle")
|
// The required input blocks empty submits, so the server-side error can't render.
|
||||||
expect(await codeServerPage.page.isVisible("text=Missing password"))
|
await expect(codeServerPage.page.locator("input.password:invalid")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should see an error message for incorrect password", async ({ codeServerPage }) => {
|
test("should see an error message for incorrect password", async ({ codeServerPage }) => {
|
||||||
@@ -34,28 +34,29 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
|
|||||||
// Click the submit button and login
|
// Click the submit button and login
|
||||||
await codeServerPage.page.click(".submit")
|
await codeServerPage.page.click(".submit")
|
||||||
await codeServerPage.page.waitForLoadState("networkidle")
|
await codeServerPage.page.waitForLoadState("networkidle")
|
||||||
expect(await codeServerPage.page.isVisible("text=Incorrect password"))
|
await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should hit the rate limiter for too many unsuccessful logins", async ({ codeServerPage }) => {
|
test("should hit the rate limiter for too many unsuccessful logins", async ({ codeServerPage }) => {
|
||||||
// Type in password
|
test.slow()
|
||||||
await codeServerPage.page.fill(".password", "password123")
|
|
||||||
// Click the submit button and login
|
// Click the submit button and login
|
||||||
// The current RateLimiter allows 2 logins per minute plus
|
// The current RateLimiter allows 2 logins per minute plus
|
||||||
// 12 logins per hour for a total of 14
|
// 12 logins per hour for a total of 14
|
||||||
// See: src/node/routes/login.ts
|
// See: src/node/routes/login.ts
|
||||||
for (let i = 1; i <= 14; i++) {
|
for (let i = 1; i <= 14; i++) {
|
||||||
|
await codeServerPage.page.fill(".password", "password123")
|
||||||
await codeServerPage.page.click(".submit")
|
await codeServerPage.page.click(".submit")
|
||||||
await codeServerPage.page.waitForLoadState("networkidle")
|
await codeServerPage.page.waitForLoadState("networkidle")
|
||||||
// We double-check that the correct error message shows
|
// We double-check that the correct error message shows
|
||||||
// which should be for incorrect password
|
// which should be for incorrect password
|
||||||
expect(await codeServerPage.page.isVisible("text=Incorrect password"))
|
await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The 15th should fail for a different reason:
|
// The 15th should fail for a different reason:
|
||||||
// login rate
|
// login rate
|
||||||
|
await codeServerPage.page.fill(".password", "password123")
|
||||||
await codeServerPage.page.click(".submit")
|
await codeServerPage.page.click(".submit")
|
||||||
await codeServerPage.page.waitForLoadState("networkidle")
|
await codeServerPage.page.waitForLoadState("networkidle")
|
||||||
expect(await codeServerPage.page.isVisible("text=Login rate limited!"))
|
await expect(codeServerPage.page.locator("text=Login rate limited!")).toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -77,11 +77,14 @@ export class CodeServer {
|
|||||||
*/
|
*/
|
||||||
private async createWorkspace(): Promise<string> {
|
private async createWorkspace(): Promise<string> {
|
||||||
const dir = await this.workspaceDir
|
const dir = await this.workspaceDir
|
||||||
await fs.mkdir(path.join(dir, "Machine"), { recursive: true })
|
await fs.mkdir(path.join(dir, "User"), { recursive: true })
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
path.join(dir, "Machine/settings.json"),
|
path.join(dir, "User/settings.json"),
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
"workbench.startupEditor": "none",
|
"workbench.startupEditor": "none",
|
||||||
|
// Disable the welcome popup so we can avoid having to click through it
|
||||||
|
// on every test.
|
||||||
|
"workbench.welcomePage.experimentalOnboarding": false,
|
||||||
}),
|
}),
|
||||||
"utf8",
|
"utf8",
|
||||||
)
|
)
|
||||||
@@ -360,13 +363,14 @@ export class CodeServerPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the test extension loaded
|
* Checks if the test extension loaded by waiting for its notification. Once
|
||||||
|
* it appears, dismiss the notification.
|
||||||
*/
|
*/
|
||||||
async waitForTestExtensionLoaded(): Promise<void> {
|
async waitForTestExtensionLoaded(): Promise<void> {
|
||||||
const selector = "text=test extension loaded"
|
|
||||||
this.codeServer.logger.debug("Waiting for test extension to load...")
|
this.codeServer.logger.debug("Waiting for test extension to load...")
|
||||||
|
const locator = this.page.getByRole("dialog", { name: "Info: test extension loaded" })
|
||||||
await this.page.waitForSelector(selector)
|
await locator.hover()
|
||||||
|
await locator.getByLabel("Clear Notification (Del)").click()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -434,6 +438,7 @@ export class CodeServerPage {
|
|||||||
async executeCommandViaMenus(command: string) {
|
async executeCommandViaMenus(command: string) {
|
||||||
await this.navigateMenus(["View", "Command Palette..."])
|
await this.navigateMenus(["View", "Command Palette..."])
|
||||||
|
|
||||||
|
await this.page.waitForSelector(".quick-input-widget:focus-within")
|
||||||
await this.page.keyboard.type(command)
|
await this.page.keyboard.type(command)
|
||||||
|
|
||||||
await this.page.hover(`text=${command}`)
|
await this.page.hover(`text=${command}`)
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { clean } from "../utils/helpers"
|
||||||
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
|
describe("settings", ["--disable-workspace-trust"], {}, () => {
|
||||||
|
const testName = "settings-local"
|
||||||
|
test.beforeAll(async () => {
|
||||||
|
await clean(testName)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should see startup editor set to none", async ({ codeServerPage }) => {
|
||||||
|
await codeServerPage.navigateMenus(["File", "Preferences", "Settings"])
|
||||||
|
await codeServerPage.page.waitForSelector(".settings-editor")
|
||||||
|
await codeServerPage.page.keyboard.type("startupEditor")
|
||||||
|
const el = codeServerPage.page.getByLabel("workbench.startupEditor")
|
||||||
|
await expect(el).toHaveValue("none")
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { promises as fs } from "fs"
|
||||||
|
import * as path from "path"
|
||||||
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
|
const tests = [
|
||||||
|
{
|
||||||
|
name: "browser storage",
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "remote storage",
|
||||||
|
args: ["--enable-remote-storage"],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const tc of tests) {
|
||||||
|
const args = ["--disable-workspace-trust", "--extensions-dir", path.join(__dirname, "./extensions"), ...tc.args]
|
||||||
|
describe(tc.name, args, {}, () => {
|
||||||
|
test("should store workbench state and secrets", async ({ codeServerPage }) => {
|
||||||
|
// Create and open a file.
|
||||||
|
const dir = await codeServerPage.workspaceDir
|
||||||
|
const file = path.join(dir, "foo")
|
||||||
|
await fs.writeFile(file, "bar")
|
||||||
|
await codeServerPage.openFile(file)
|
||||||
|
|
||||||
|
// Store a secret.
|
||||||
|
const secret = "foo-bar-baz"
|
||||||
|
await codeServerPage.waitForTestExtensionLoaded()
|
||||||
|
await codeServerPage.executeCommandViaMenus("code-server: Set test secret")
|
||||||
|
await codeServerPage.page.waitForSelector(".quick-input-widget:focus-within")
|
||||||
|
await codeServerPage.page.keyboard.type(secret)
|
||||||
|
await codeServerPage.page.keyboard.press("Enter")
|
||||||
|
await expect(codeServerPage.page.getByText(`Info: set secret: ${secret}`)).toBeVisible()
|
||||||
|
|
||||||
|
// There should be a workspace storage directory.
|
||||||
|
const userDir = path.join(dir, "User/workspaceStorage")
|
||||||
|
const dirs = await fs.readdir(userDir)
|
||||||
|
expect(dirs.length).toBe(1)
|
||||||
|
|
||||||
|
const storageFile = path.join(userDir, dirs[0], "state.vscdb")
|
||||||
|
if (tc.args.includes("--enable-remote-storage")) {
|
||||||
|
// The sqlite database should exist.
|
||||||
|
fs.stat(storageFile)
|
||||||
|
} else {
|
||||||
|
// But no sqlite database.
|
||||||
|
expect(() => fs.stat(storageFile)).rejects.toThrow("ENOENT")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload using a command so it has a chance to flush storage.
|
||||||
|
await codeServerPage.executeCommandViaMenus("Developer: Reload Window")
|
||||||
|
await codeServerPage.waitForTestExtensionLoaded()
|
||||||
|
|
||||||
|
// Should see the same file.
|
||||||
|
await codeServerPage.waitForTab(file)
|
||||||
|
|
||||||
|
// Should be able to retrieve the secret.
|
||||||
|
await codeServerPage.executeCommandViaMenus("code-server: Get test secret")
|
||||||
|
await expect(codeServerPage.page.getByText(`Info: get secret: ${secret}`)).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { promises as fs } from "fs"
|
||||||
|
import * as path from "path"
|
||||||
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
|
const args = ["--disable-workspace-trust"]
|
||||||
|
|
||||||
|
describe("typescript extension", args, {}, () => {
|
||||||
|
test("should load as a workspace extension", async ({ codeServerPage }) => {
|
||||||
|
const dir = await codeServerPage.workspaceDir
|
||||||
|
const file = path.join(dir, "foo.ts")
|
||||||
|
await fs.writeFile(file, 'const n: number = "x"')
|
||||||
|
await codeServerPage.openFile(file)
|
||||||
|
|
||||||
|
await codeServerPage.executeCommandViaMenus("Developer: Show Running Extensions")
|
||||||
|
await expect(
|
||||||
|
codeServerPage.page.getByLabel("typescript-language-features").getByText(/localhost:\d+/),
|
||||||
|
).toBeVisible()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -18,14 +18,14 @@ describe("Uploads (enabled)", ["--disable-workspace-trust"], {}, () => {
|
|||||||
// Action
|
// Action
|
||||||
await codeServerPage.openContextMenu('span:has-text("test-directory")')
|
await codeServerPage.openContextMenu('span:has-text("test-directory")')
|
||||||
|
|
||||||
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(true)
|
await expect(codeServerPage.page.locator("text=Upload...")).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
|
test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
|
||||||
// Action
|
// Action
|
||||||
await codeServerPage.navigateMenus(["File", "Open File..."])
|
await codeServerPage.navigateMenus(["File", "Open File..."])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -44,13 +44,13 @@ describe("Uploads (disabled)", ["--disable-workspace-trust", "--disable-file-upl
|
|||||||
// Action
|
// Action
|
||||||
await codeServerPage.openContextMenu('span:has-text("test-directory")')
|
await codeServerPage.openContextMenu('span:has-text("test-directory")')
|
||||||
|
|
||||||
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(false)
|
await expect(codeServerPage.page.locator("text=Upload...")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
|
test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
|
||||||
// Action
|
// Action
|
||||||
await codeServerPage.navigateMenus(["File", "Open File..."])
|
await codeServerPage.navigateMenus(["File", "Open File..."])
|
||||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Generated
+196
-314
@@ -7,7 +7,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@jest-mock/express": "^1.4.5",
|
"@jest-mock/express": "^1.4.5",
|
||||||
"@playwright/test": "^1.56.1",
|
"@playwright/test": "^1.61.0",
|
||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/jsdom": "^16.2.13",
|
"@types/jsdom": "^16.2.13",
|
||||||
"@types/node-fetch": "^2.5.8",
|
"@types/node-fetch": "^2.5.8",
|
||||||
@@ -18,43 +18,30 @@
|
|||||||
"jest-fetch-mock": "^3.0.3",
|
"jest-fetch-mock": "^3.0.3",
|
||||||
"jsdom": "^16.4.0",
|
"jsdom": "^16.4.0",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.6.7",
|
||||||
"playwright": "^1.56.1",
|
"playwright": "^1.61.0",
|
||||||
"ts-jest": "^27.0.7",
|
"ts-jest": "^27.0.7",
|
||||||
"wtfnode": "^0.9.1"
|
"wtfnode": "^0.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
|
||||||
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
|
||||||
"@jridgewell/trace-mapping": "^0.3.24"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz",
|
||||||
"integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==",
|
"integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/highlight": "^7.25.7",
|
"@babel/helper-validator-identifier": "^7.29.7",
|
||||||
"picocolors": "^1.0.0"
|
"js-tokens": "^4.0.0",
|
||||||
|
"picocolors": "^1.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/compat-data": {
|
"node_modules/@babel/compat-data": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz",
|
||||||
"integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==",
|
"integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -62,22 +49,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/core": {
|
"node_modules/@babel/core": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz",
|
||||||
"integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==",
|
"integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ampproject/remapping": "^2.2.0",
|
"@babel/code-frame": "^7.29.7",
|
||||||
"@babel/code-frame": "^7.25.7",
|
"@babel/generator": "^7.29.7",
|
||||||
"@babel/generator": "^7.25.7",
|
"@babel/helper-compilation-targets": "^7.29.7",
|
||||||
"@babel/helper-compilation-targets": "^7.25.7",
|
"@babel/helper-module-transforms": "^7.29.7",
|
||||||
"@babel/helper-module-transforms": "^7.25.7",
|
"@babel/helpers": "^7.29.7",
|
||||||
"@babel/helpers": "^7.25.7",
|
"@babel/parser": "^7.29.7",
|
||||||
"@babel/parser": "^7.25.7",
|
"@babel/template": "^7.29.7",
|
||||||
"@babel/template": "^7.25.7",
|
"@babel/traverse": "^7.29.7",
|
||||||
"@babel/traverse": "^7.25.7",
|
"@babel/types": "^7.29.7",
|
||||||
"@babel/types": "^7.25.7",
|
"@jridgewell/remapping": "^2.3.5",
|
||||||
"convert-source-map": "^2.0.0",
|
"convert-source-map": "^2.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"gensync": "^1.0.0-beta.2",
|
"gensync": "^1.0.0-beta.2",
|
||||||
@@ -110,15 +97,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/generator": {
|
"node_modules/@babel/generator": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz",
|
||||||
"integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==",
|
"integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.25.7",
|
"@babel/parser": "^7.29.8",
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@babel/types": "^7.29.8",
|
||||||
"@jridgewell/trace-mapping": "^0.3.25",
|
"@jridgewell/gen-mapping": "^0.3.12",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.28",
|
||||||
"jsesc": "^3.0.2"
|
"jsesc": "^3.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -126,14 +114,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-compilation-targets": {
|
"node_modules/@babel/helper-compilation-targets": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
|
||||||
"integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==",
|
"integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.25.7",
|
"@babel/compat-data": "^7.29.7",
|
||||||
"@babel/helper-validator-option": "^7.25.7",
|
"@babel/helper-validator-option": "^7.29.7",
|
||||||
"browserslist": "^4.24.0",
|
"browserslist": "^4.24.0",
|
||||||
"lru-cache": "^5.1.1",
|
"lru-cache": "^5.1.1",
|
||||||
"semver": "^6.3.1"
|
"semver": "^6.3.1"
|
||||||
@@ -152,31 +140,40 @@
|
|||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/helper-globals": {
|
||||||
|
"version": "7.29.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
|
||||||
|
"integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/helper-module-imports": {
|
"node_modules/@babel/helper-module-imports": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
|
||||||
"integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==",
|
"integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/traverse": "^7.25.7",
|
"@babel/traverse": "^7.29.7",
|
||||||
"@babel/types": "^7.25.7"
|
"@babel/types": "^7.29.7"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-module-transforms": {
|
"node_modules/@babel/helper-module-transforms": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
|
||||||
"integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==",
|
"integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-module-imports": "^7.25.7",
|
"@babel/helper-module-imports": "^7.29.7",
|
||||||
"@babel/helper-simple-access": "^7.25.7",
|
"@babel/helper-validator-identifier": "^7.29.7",
|
||||||
"@babel/helper-validator-identifier": "^7.25.7",
|
"@babel/traverse": "^7.29.7"
|
||||||
"@babel/traverse": "^7.25.7"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -195,24 +192,10 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-simple-access": {
|
|
||||||
"version": "7.25.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz",
|
|
||||||
"integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/traverse": "^7.25.7",
|
|
||||||
"@babel/types": "^7.25.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/helper-string-parser": {
|
"node_modules/@babel/helper-string-parser": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
|
||||||
"integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==",
|
"integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -220,9 +203,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-validator-identifier": {
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
|
||||||
"integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==",
|
"integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -230,9 +213,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-validator-option": {
|
"node_modules/@babel/helper-validator-option": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
|
||||||
"integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==",
|
"integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -240,121 +223,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helpers": {
|
"node_modules/@babel/helpers": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz",
|
||||||
"integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==",
|
"integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/template": "^7.25.7",
|
"@babel/template": "^7.29.7",
|
||||||
"@babel/types": "^7.25.7"
|
"@babel/types": "^7.29.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/highlight": {
|
|
||||||
"version": "7.25.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz",
|
|
||||||
"integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/helper-validator-identifier": "^7.25.7",
|
|
||||||
"chalk": "^2.4.2",
|
|
||||||
"js-tokens": "^4.0.0",
|
|
||||||
"picocolors": "^1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/ansi-styles": {
|
|
||||||
"version": "3.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/color-convert": {
|
|
||||||
"version": "1.9.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
|
||||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"color-name": "1.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/color-name": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/has-flag": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/highlight/node_modules/supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz",
|
||||||
"integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==",
|
"integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.25.7"
|
"@babel/types": "^7.29.8"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@@ -587,49 +476,48 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/template": {
|
"node_modules/@babel/template": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz",
|
||||||
"integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==",
|
"integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.25.7",
|
"@babel/code-frame": "^7.29.7",
|
||||||
"@babel/parser": "^7.25.7",
|
"@babel/parser": "^7.29.7",
|
||||||
"@babel/types": "^7.25.7"
|
"@babel/types": "^7.29.7"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/traverse": {
|
"node_modules/@babel/traverse": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.10",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz",
|
||||||
"integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==",
|
"integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.25.7",
|
"@babel/code-frame": "^7.29.7",
|
||||||
"@babel/generator": "^7.25.7",
|
"@babel/generator": "^7.29.8",
|
||||||
"@babel/parser": "^7.25.7",
|
"@babel/helper-globals": "^7.29.7",
|
||||||
"@babel/template": "^7.25.7",
|
"@babel/parser": "^7.29.9",
|
||||||
"@babel/types": "^7.25.7",
|
"@babel/template": "^7.29.7",
|
||||||
"debug": "^4.3.1",
|
"@babel/types": "^7.29.8",
|
||||||
"globals": "^11.1.0"
|
"debug": "^4.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.25.7",
|
"version": "7.29.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
|
||||||
"integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==",
|
"integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.25.7",
|
"@babel/helper-string-parser": "^7.29.7",
|
||||||
"@babel/helper-validator-identifier": "^7.25.7",
|
"@babel/helper-validator-identifier": "^7.29.7"
|
||||||
"to-fast-properties": "^2.0.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
@@ -935,18 +823,25 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/gen-mapping": {
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
"version": "0.3.5",
|
"version": "0.3.13",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/set-array": "^1.2.1",
|
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
"@jridgewell/trace-mapping": "^0.3.24"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/remapping": {
|
||||||
|
"version": "2.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
|
||||||
|
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
"@jridgewell/trace-mapping": "^0.3.24"
|
"@jridgewell/trace-mapping": "^0.3.24"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/resolve-uri": {
|
"node_modules/@jridgewell/resolve-uri": {
|
||||||
@@ -959,27 +854,17 @@
|
|||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/set-array": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
|
||||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jridgewell/sourcemap-codec": {
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
"version": "1.5.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz",
|
||||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
"integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.25",
|
"version": "0.3.31",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
|
||||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -998,13 +883,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@playwright/test": {
|
"node_modules/@playwright/test": {
|
||||||
"version": "1.56.1",
|
"version": "1.61.0",
|
||||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz",
|
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.61.0.tgz",
|
||||||
"integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
|
"integrity": "sha512-cKA5B6lpFEMyMGjxF54QihfYpB4FkEGH+qZhtArDEG+wezQAJY8Pq6C7T1SjWz+FFzt3TbyoXBQYk/0292TdJA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright": "1.56.1"
|
"playwright": "1.61.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
@@ -1497,10 +1382,23 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/baseline-browser-mapping": {
|
||||||
|
"version": "2.11.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.27.tgz",
|
||||||
|
"integrity": "sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"baseline-browser-mapping": "dist/cli.cjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.21",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1529,9 +1427,9 @@
|
|||||||
"license": "BSD-2-Clause"
|
"license": "BSD-2-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/browserslist": {
|
"node_modules/browserslist": {
|
||||||
"version": "4.24.0",
|
"version": "4.29.3",
|
||||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz",
|
||||||
"integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==",
|
"integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1549,10 +1447,11 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"caniuse-lite": "^1.0.30001663",
|
"baseline-browser-mapping": "^2.11.26",
|
||||||
"electron-to-chromium": "^1.5.28",
|
"caniuse-lite": "^1.0.30001813",
|
||||||
"node-releases": "^2.0.18",
|
"electron-to-chromium": "^1.5.439",
|
||||||
"update-browserslist-db": "^1.1.0"
|
"node-releases": "^2.0.57",
|
||||||
|
"update-browserslist-db": "^1.3.3"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"browserslist": "cli.js"
|
"browserslist": "cli.js"
|
||||||
@@ -1636,9 +1535,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001667",
|
"version": "1.0.30001815",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001815.tgz",
|
||||||
"integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==",
|
"integrity": "sha512-uDybUEyfgbyJJ93J1vikTylBX31AkdVYeVPeffMQpf8XN7hSfr0oZOn4VFOIMNvtU5+rHvC5Udg2TgtJKHm23Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1980,9 +1879,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.32",
|
"version": "1.5.451",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.32.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.451.tgz",
|
||||||
"integrity": "sha512-M+7ph0VGBQqqpTT2YrabjNKSQ2fEl9PVx6AK3N558gDH9NO8O6XN9SXXFWRo9u9PbEg/bWq+tjXQr+eXmxubCw==",
|
"integrity": "sha512-vUNKPrUzw8ByEMOxloq0a71iD/mPuPxVkbDm3G5YhnxTzOw/I6qAg2MUS0cYj/c267lWmw26yW4Vv7foxTxPLg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@@ -2289,17 +2188,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
|
||||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
"hasown": "^2.0.2",
|
"hasown": "^2.0.4",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.35"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
@@ -2444,16 +2343,6 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/globals": {
|
|
||||||
"version": "11.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
|
||||||
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
@@ -2514,9 +2403,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3494,9 +3383,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "3.14.2",
|
"version": "3.15.2",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz",
|
||||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
"integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3555,16 +3444,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsdom/node_modules/form-data": {
|
"node_modules/jsdom/node_modules/form-data": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.5.tgz",
|
||||||
"integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==",
|
"integrity": "sha512-j23EibVLnp4zNXGW7LjryXYa2X6U/M96yoOX+ybZxwkYajdxRNEqYY3zhh7y0i6kfISKS2jr+EJq1YTUDEv5+w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
"hasown": "^2.0.2",
|
"hasown": "^2.0.4",
|
||||||
"mime-types": "^2.1.35"
|
"mime-types": "^2.1.35"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -3645,9 +3534,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.23",
|
"version": "4.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
|
||||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -3852,11 +3741,14 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/node-releases": {
|
"node_modules/node-releases": {
|
||||||
"version": "2.0.18",
|
"version": "2.0.57",
|
||||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
|
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.57.tgz",
|
||||||
"integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
|
"integrity": "sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
@@ -4024,16 +3916,16 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||||
"integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
|
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4067,13 +3959,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright": {
|
"node_modules/playwright": {
|
||||||
"version": "1.56.1",
|
"version": "1.61.0",
|
||||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz",
|
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.0.tgz",
|
||||||
"integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==",
|
"integrity": "sha512-Z+7BeeqQPRRzklHsVFP4KTGIyMxKUmfeRA4WisM6G3/XW6nwGeX6fX9qYaDa+CiUqpOkb2f6X3nar05R3kSuJQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"playwright-core": "1.56.1"
|
"playwright-core": "1.61.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"playwright": "cli.js"
|
"playwright": "cli.js"
|
||||||
@@ -4086,9 +3978,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/playwright-core": {
|
"node_modules/playwright-core": {
|
||||||
"version": "1.56.1",
|
"version": "1.61.0",
|
||||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
|
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.0.tgz",
|
||||||
"integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
|
"integrity": "sha512-caX7TrY3Ml6egyDX0WUcTHDxodl/b51y5wJOdCEA36QviK/s2g081hvmGs8eaE3DWb6NYZQ6BjO/QkNRPenoPA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -4578,16 +4470,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/to-fast-properties": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
@@ -4740,9 +4622,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.1.1",
|
"version": "1.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz",
|
||||||
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
|
"integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -4761,7 +4643,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"escalade": "^3.2.0",
|
"escalade": "^3.2.0",
|
||||||
"picocolors": "^1.1.0"
|
"picocolors": "^1.1.1"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"update-browserslist-db": "cli.js"
|
"update-browserslist-db": "cli.js"
|
||||||
@@ -4937,9 +4819,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "7.5.10",
|
"version": "7.5.13",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.13.tgz",
|
||||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
"integrity": "sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
+2
-2
@@ -3,7 +3,7 @@
|
|||||||
"#": "We must put jest in a sub-directory otherwise VS Code somehow picks up the types and generates conflicts with mocha.",
|
"#": "We must put jest in a sub-directory otherwise VS Code somehow picks up the types and generates conflicts with mocha.",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@jest-mock/express": "^1.4.5",
|
"@jest-mock/express": "^1.4.5",
|
||||||
"@playwright/test": "^1.56.1",
|
"@playwright/test": "^1.61.0",
|
||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/jsdom": "^16.2.13",
|
"@types/jsdom": "^16.2.13",
|
||||||
"@types/node-fetch": "^2.5.8",
|
"@types/node-fetch": "^2.5.8",
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
"jest-fetch-mock": "^3.0.3",
|
"jest-fetch-mock": "^3.0.3",
|
||||||
"jsdom": "^16.4.0",
|
"jsdom": "^16.4.0",
|
||||||
"node-fetch": "^2.6.7",
|
"node-fetch": "^2.6.7",
|
||||||
"playwright": "^1.56.1",
|
"playwright": "^1.61.0",
|
||||||
"ts-jest": "^27.0.7",
|
"ts-jest": "^27.0.7",
|
||||||
"wtfnode": "^0.9.1"
|
"wtfnode": "^0.9.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import path from "path"
|
|||||||
// The default configuration runs all tests in three browsers with workers equal
|
// The default configuration runs all tests in three browsers with workers equal
|
||||||
// to half the available threads. See 'npm run test:e2e --help' to customize
|
// to half the available threads. See 'npm run test:e2e --help' to customize
|
||||||
// from the command line. For example:
|
// from the command line. For example:
|
||||||
// npm run test:e2e --workers 1 # Run with one worker
|
// npm run test:e2e -- --workers 1 # Run with one worker
|
||||||
// npm run test:e2e --project Chromium # Only run on Chromium
|
// npm run test:e2e -- --project Chromium # Only run on Chromium
|
||||||
// npm run test:e2e --grep login # Run tests matching "login"
|
// npm run test:e2e -- --grep login # Run tests matching "login"
|
||||||
// PWDEBUG=1 npm run test:e2e # Run Playwright inspector
|
// PWDEBUG=1 npm run test:e2e # Run Playwright inspector
|
||||||
const config: PlaywrightTestConfig = {
|
const config: PlaywrightTestConfig = {
|
||||||
testDir: path.join(__dirname, "e2e"), // Search for tests in this directory.
|
testDir: path.join(__dirname, "e2e"), // Search for tests in this directory.
|
||||||
timeout: 60000, // Each test is given 60 seconds.
|
timeout: 60000, // Each test is given 60 seconds.
|
||||||
@@ -33,10 +33,12 @@ const config: PlaywrightTestConfig = {
|
|||||||
// name: "Firefox",
|
// name: "Firefox",
|
||||||
// use: { browserName: "firefox" },
|
// use: { browserName: "firefox" },
|
||||||
// },
|
// },
|
||||||
{
|
// Keeps failing with "Underlying ArrayBuffer has been detached from the view or out-of-bounds"
|
||||||
name: "WebKit",
|
// Not sure what we can do about it...so skip for now.
|
||||||
use: { browserName: "webkit" },
|
// {
|
||||||
},
|
// name: "WebKit",
|
||||||
|
// use: { browserName: "webkit" },
|
||||||
|
// },
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { promises } from "fs"
|
|||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
import * as https from "https"
|
import * as https from "https"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { createApp, ensureAddress, handleArgsSocketCatchError, listen } from "../../../src/node/app"
|
import { createApp, ensureAddress, handleArgsSocketCatchError, isFdOpts, listen } from "../../../src/node/app"
|
||||||
import { OptionalString, setDefaults } from "../../../src/node/cli"
|
import { OptionalString, setDefaults } from "../../../src/node/cli"
|
||||||
import { generateCertificate } from "../../../src/node/util"
|
import { generateCertificate } from "../../../src/node/util"
|
||||||
import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers"
|
import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers"
|
||||||
@@ -261,3 +261,47 @@ describe("listen", () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("listen (socket-fd)", () => {
|
||||||
|
// Wrap a bound-but-not-yet-listening TCP socket so we get a real file
|
||||||
|
// descriptor that listen({ fd }) can adopt, mirroring the systemd socket
|
||||||
|
// activation case where the process inherits an fd and calls listen(2) on it.
|
||||||
|
// Using a live net.Server's fd instead fails with EEXIST because the socket
|
||||||
|
// is already listening in-process.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const { TCP, constants: TCPConstants } = (process as any).binding("tcp_wrap")
|
||||||
|
|
||||||
|
let inherited: any
|
||||||
|
let httpServer: http.Server
|
||||||
|
let unlinkSpy: jest.SpyInstance
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
mockLogger()
|
||||||
|
unlinkSpy = jest.spyOn(promises, "unlink")
|
||||||
|
inherited = new TCP(TCPConstants.SERVER)
|
||||||
|
inherited.bind("127.0.0.1", 0)
|
||||||
|
httpServer = http.createServer()
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
httpServer.close()
|
||||||
|
try {
|
||||||
|
inherited.close()
|
||||||
|
} catch {
|
||||||
|
// The fd is adopted by httpServer.close() above; ignore double-close.
|
||||||
|
}
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("isFdOpts detects a numeric socket-fd", () => {
|
||||||
|
expect(isFdOpts({ "socket-fd": 3 })).toBe(true)
|
||||||
|
expect(isFdOpts({ socket: "/tmp/x.sock" } as any)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("listens on an inherited fd without unlinking", async () => {
|
||||||
|
const fd = inherited.fd as number
|
||||||
|
await listen(httpServer, { "socket-fd": fd })
|
||||||
|
expect(httpServer.address()).not.toBeNull()
|
||||||
|
expect(unlinkSpy).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
+114
-1
@@ -1,10 +1,12 @@
|
|||||||
import { Level, logger } from "@coder/logger"
|
import { Level, logger } from "@coder/logger"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import {
|
import {
|
||||||
UserProvidedArgs,
|
UserProvidedArgs,
|
||||||
bindAddrFromArgs,
|
bindAddrFromArgs,
|
||||||
defaultConfigFile,
|
defaultConfigFile,
|
||||||
|
defaultSessionSocket,
|
||||||
parse,
|
parse,
|
||||||
parseConfigFile,
|
parseConfigFile,
|
||||||
setDefaults,
|
setDefaults,
|
||||||
@@ -37,7 +39,7 @@ const defaults = {
|
|||||||
usingEnvHashedPassword: false,
|
usingEnvHashedPassword: false,
|
||||||
"extensions-dir": path.join(paths.data, "extensions"),
|
"extensions-dir": path.join(paths.data, "extensions"),
|
||||||
"user-data-dir": paths.data,
|
"user-data-dir": paths.data,
|
||||||
"session-socket": path.join(paths.data, "code-server-ipc.sock"),
|
"session-socket": defaultSessionSocket(paths.data),
|
||||||
"app-name": "code-server",
|
"app-name": "code-server",
|
||||||
_: [],
|
_: [],
|
||||||
}
|
}
|
||||||
@@ -51,6 +53,7 @@ describe("parser", () => {
|
|||||||
delete process.env.CODE_SERVER_RECONNECTION_GRACE_TIME
|
delete process.env.CODE_SERVER_RECONNECTION_GRACE_TIME
|
||||||
delete process.env.VSCODE_PROXY_URI
|
delete process.env.VSCODE_PROXY_URI
|
||||||
delete process.env.CS_DISABLE_PROXY
|
delete process.env.CS_DISABLE_PROXY
|
||||||
|
delete process.env.VSCODE_OPTIONS
|
||||||
console.log = jest.fn()
|
console.log = jest.fn()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -266,6 +269,16 @@ describe("parser", () => {
|
|||||||
expect(() => parse(["--log", "invalid"])).toThrowError(/--log valid values: \[trace, debug, info, warn, error\]/)
|
expect(() => parse(["--log", "invalid"])).toThrowError(/--log valid values: \[trace, debug, info, warn, error\]/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should error if idle-timeout-seconds is too low", () => {
|
||||||
|
expect(() => parse(["--idle-timeout-seconds=60"])).toThrowError(
|
||||||
|
/--idle-timeout-seconds must be greater than 60 seconds/,
|
||||||
|
)
|
||||||
|
expect(() => parse(["--idle-timeout-seconds", "60"])).toThrowError(
|
||||||
|
/--idle-timeout-seconds must be greater than 60 seconds/,
|
||||||
|
)
|
||||||
|
expect(parse(["--idle-timeout-seconds", "61"])).toEqual({ "idle-timeout-seconds": 61 })
|
||||||
|
})
|
||||||
|
|
||||||
it("should error if the option doesn't exist", () => {
|
it("should error if the option doesn't exist", () => {
|
||||||
expect(() => parse(["--foo"])).toThrowError(/Unknown option --foo/)
|
expect(() => parse(["--foo"])).toThrowError(/Unknown option --foo/)
|
||||||
})
|
})
|
||||||
@@ -413,6 +426,17 @@ describe("parser", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should use env var VSCODE_OPTIONS", async () => {
|
||||||
|
process.env.VSCODE_OPTIONS = "--enable-sandbox agents=true"
|
||||||
|
const args = parse(["--vscode-option", "verbose-logging"])
|
||||||
|
|
||||||
|
const defaultArgs = await setDefaults(args)
|
||||||
|
expect(defaultArgs).toEqual({
|
||||||
|
...defaults,
|
||||||
|
"vscode-option": ["verbose-logging", "--enable-sandbox", "agents=true"],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it("should use env var CS_DISABLE_GETTING_STARTED_OVERRIDE", async () => {
|
it("should use env var CS_DISABLE_GETTING_STARTED_OVERRIDE", async () => {
|
||||||
process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE = "1"
|
process.env.CS_DISABLE_GETTING_STARTED_OVERRIDE = "1"
|
||||||
const args = parse([])
|
const args = parse([])
|
||||||
@@ -552,9 +576,33 @@ describe("parser", () => {
|
|||||||
"install-extension": ["extension.number1", "extension.number2"],
|
"install-extension": ["extension.number1", "extension.number2"],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
it("should expand ~ in path options from the config file", () => {
|
||||||
|
const configContents = `
|
||||||
|
user-data-dir: ~/.config/code-server-data
|
||||||
|
extensions-dir: ~/extensions
|
||||||
|
`
|
||||||
|
expect(parseConfigFile(configContents, "/fake-config-path")).toEqual({
|
||||||
|
config: "/fake-config-path",
|
||||||
|
"user-data-dir": path.join(os.homedir(), ".config/code-server-data"),
|
||||||
|
"extensions-dir": path.join(os.homedir(), "extensions"),
|
||||||
|
})
|
||||||
|
})
|
||||||
it("should ignore optional strings set to false", async () => {
|
it("should ignore optional strings set to false", async () => {
|
||||||
expect(parse(["--cert=false"])).toEqual({})
|
expect(parse(["--cert=false"])).toEqual({})
|
||||||
})
|
})
|
||||||
|
it("should ignore booleans set to false", async () => {
|
||||||
|
expect(parse(["--disable-telemetry=false"])).toEqual({})
|
||||||
|
})
|
||||||
|
it("should parse booleans set to false in the config file", () => {
|
||||||
|
const configContents = `
|
||||||
|
disable-telemetry: false
|
||||||
|
disable-update-check: true
|
||||||
|
`
|
||||||
|
expect(parseConfigFile(configContents, "/fake-config-path")).toEqual({
|
||||||
|
config: "/fake-config-path",
|
||||||
|
"disable-update-check": true,
|
||||||
|
})
|
||||||
|
})
|
||||||
it("should use last flag", async () => {
|
it("should use last flag", async () => {
|
||||||
expect(parse(["--port", "8081", "--port", "8082"])).toEqual({
|
expect(parse(["--port", "8081", "--port", "8082"])).toEqual({
|
||||||
port: 8082,
|
port: 8082,
|
||||||
@@ -965,6 +1013,26 @@ describe("bindAddrFromArgs", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("defaultSessionSocket", () => {
|
||||||
|
const dataDir = path.join("/home/coder/.local/share", "code-server")
|
||||||
|
|
||||||
|
it("should put the socket in the user data directory", () => {
|
||||||
|
expect(defaultSessionSocket(dataDir, "linux")).toBe(path.join(dataDir, "code-server-ipc.sock"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should use a named pipe on windows", () => {
|
||||||
|
expect(defaultSessionSocket(dataDir, "win32")).toMatch(/^\\\\\.\\pipe\\code-server-ipc-[0-9a-f]{16}$/)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should give separate data directories separate pipes", () => {
|
||||||
|
expect(defaultSessionSocket(dataDir, "win32")).not.toBe(defaultSessionSocket(dataDir + "-other", "win32"))
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should give one data directory one pipe however it is spelled", () => {
|
||||||
|
expect(defaultSessionSocket(dataDir.toUpperCase(), "win32")).toBe(defaultSessionSocket(dataDir, "win32"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("defaultConfigFile", () => {
|
describe("defaultConfigFile", () => {
|
||||||
it("should return the default config file as a string", async () => {
|
it("should return the default config file as a string", async () => {
|
||||||
const password = await generatePassword()
|
const password = await generatePassword()
|
||||||
@@ -1006,6 +1074,51 @@ describe("toCodeArgs", () => {
|
|||||||
_: [file],
|
_: [file],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should pass through --vscode-option", async () => {
|
||||||
|
const args = parse([
|
||||||
|
"--vscode-option",
|
||||||
|
"enable-sandbox",
|
||||||
|
"--vscode-option",
|
||||||
|
"agents=true",
|
||||||
|
"--vscode-option",
|
||||||
|
"enable-smoke-test-driver=false",
|
||||||
|
])
|
||||||
|
expect(await toCodeArgs(await setDefaults(args))).toStrictEqual({
|
||||||
|
...vscodeDefaults,
|
||||||
|
"enable-sandbox": true,
|
||||||
|
agents: true,
|
||||||
|
"enable-smoke-test-driver": false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should pass through --enable-remote-storage", async () => {
|
||||||
|
expect(await toCodeArgs(await setDefaults(parse(["--enable-remote-storage"])))).toStrictEqual({
|
||||||
|
...vscodeDefaults,
|
||||||
|
"enable-remote-storage": true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should collect a repeated --vscode-option into an array", async () => {
|
||||||
|
const args = parse([
|
||||||
|
"--vscode-option",
|
||||||
|
"locate-extension=a",
|
||||||
|
"--vscode-option",
|
||||||
|
"locate-extension=b",
|
||||||
|
"--vscode-option",
|
||||||
|
"locate-extension=c",
|
||||||
|
])
|
||||||
|
expect(await toCodeArgs(await setDefaults(args))).toStrictEqual({
|
||||||
|
...vscodeDefaults,
|
||||||
|
"locate-extension": ["a", "b", "c"],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should error if --vscode-option has no flag", async () => {
|
||||||
|
await expect(toCodeArgs(await setDefaults(parse(["--vscode-option", "=nothing"])))).rejects.toThrow(
|
||||||
|
"--vscode-option requires a flag name",
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("optionDescriptions", () => {
|
describe("optionDescriptions", () => {
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { logger } from "@coder/logger"
|
import { logger } from "@coder/logger"
|
||||||
import { readFile, writeFile, stat, utimes } from "fs/promises"
|
import { readFile, writeFile, stat, utimes } from "fs/promises"
|
||||||
|
import { setImmediate } from "timers"
|
||||||
import { Heart } from "../../../src/node/heart"
|
import { Heart } from "../../../src/node/heart"
|
||||||
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
|
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
|
||||||
|
|
||||||
const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo)
|
|
||||||
|
|
||||||
describe("Heart", () => {
|
describe("Heart", () => {
|
||||||
const testName = "heartTests"
|
const testName = "heartTests"
|
||||||
let testDir = ""
|
let testDir = ""
|
||||||
@@ -15,12 +14,15 @@ describe("Heart", () => {
|
|||||||
await clean(testName)
|
await clean(testName)
|
||||||
testDir = await tmpdir(testName)
|
testDir = await tmpdir(testName)
|
||||||
})
|
})
|
||||||
beforeEach(() => {
|
|
||||||
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
|
|
||||||
})
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.restoreAllMocks()
|
jest.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
heart = new Heart(`${testDir}/shutdown.txt`, jest.fn().mockResolvedValue(true))
|
||||||
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks()
|
jest.resetAllMocks()
|
||||||
jest.useRealTimers()
|
jest.useRealTimers()
|
||||||
@@ -28,6 +30,7 @@ describe("Heart", () => {
|
|||||||
heart.dispose()
|
heart.dispose()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should write to a file when given a valid file path", async () => {
|
it("should write to a file when given a valid file path", async () => {
|
||||||
// Set up heartbeat file with contents
|
// Set up heartbeat file with contents
|
||||||
const text = "test"
|
const text = "test"
|
||||||
@@ -42,7 +45,7 @@ describe("Heart", () => {
|
|||||||
|
|
||||||
expect(fileContents).toBe(text)
|
expect(fileContents).toBe(text)
|
||||||
|
|
||||||
heart = new Heart(pathToFile, mockIsActive(true))
|
heart = new Heart(pathToFile, jest.fn().mockResolvedValue(true))
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
// Check that the heart wrote to the heartbeatFilePath and overwrote our text
|
// Check that the heart wrote to the heartbeatFilePath and overwrote our text
|
||||||
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
|
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
|
||||||
@@ -51,31 +54,30 @@ describe("Heart", () => {
|
|||||||
const fileStatusAfterEdit = await stat(pathToFile)
|
const fileStatusAfterEdit = await stat(pathToFile)
|
||||||
expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0)
|
expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should log a warning when given an invalid file path", async () => {
|
it("should log a warning when given an invalid file path", async () => {
|
||||||
heart = new Heart(`fakeDir/fake.txt`, mockIsActive(false))
|
heart = new Heart(`fakeDir/fake.txt`, jest.fn().mockResolvedValue(false))
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
expect(logger.warn).toHaveBeenCalled()
|
expect(logger.warn).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should be active after calling beat", async () => {
|
it("should be active after calling beat", async () => {
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
|
|
||||||
const isAlive = heart.alive()
|
const isAlive = heart.alive()
|
||||||
expect(isAlive).toBe(true)
|
expect(isAlive).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not be active after dispose is called", () => {
|
it("should not be active after dispose is called", () => {
|
||||||
heart.dispose()
|
heart.dispose()
|
||||||
|
|
||||||
const isAlive = heart.alive()
|
const isAlive = heart.alive()
|
||||||
expect(isAlive).toBe(false)
|
expect(isAlive).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should beat twice without warnings", async () => {
|
it("should beat twice without warnings", async () => {
|
||||||
// Use fake timers so we can speed up setTimeout
|
heart = new Heart(`${testDir}/hello.txt`, jest.fn().mockResolvedValue(true))
|
||||||
jest.useFakeTimers()
|
|
||||||
heart = new Heart(`${testDir}/hello.txt`, mockIsActive(true))
|
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
// we need to speed up clocks, timeouts
|
|
||||||
// call heartbeat again (and it won't be alive I think)
|
|
||||||
// then assert no warnings were called
|
|
||||||
jest.runAllTimers()
|
jest.runAllTimers()
|
||||||
expect(logger.warn).not.toHaveBeenCalled()
|
expect(logger.warn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
@@ -84,40 +86,48 @@ describe("Heart", () => {
|
|||||||
describe("heartbeatTimer", () => {
|
describe("heartbeatTimer", () => {
|
||||||
const testName = "heartbeatTimer"
|
const testName = "heartbeatTimer"
|
||||||
let testDir = ""
|
let testDir = ""
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await clean(testName)
|
await clean(testName)
|
||||||
testDir = await tmpdir(testName)
|
testDir = await tmpdir(testName)
|
||||||
mockLogger()
|
mockLogger()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.restoreAllMocks()
|
jest.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.useFakeTimers()
|
jest.useFakeTimers()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks()
|
jest.resetAllMocks()
|
||||||
jest.clearAllTimers()
|
jest.clearAllTimers()
|
||||||
jest.useRealTimers()
|
jest.useRealTimers()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should call isActive when timeout expires", async () => {
|
it("should call isActive when timeout expires", async () => {
|
||||||
const isActive = true
|
const mockIsActive = jest.fn().mockResolvedValue(true)
|
||||||
const mockIsActive = jest.fn().mockResolvedValue(isActive)
|
|
||||||
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
|
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
jest.advanceTimersByTime(60 * 1000)
|
jest.advanceTimersByTime(60 * 1000)
|
||||||
expect(mockIsActive).toHaveBeenCalled()
|
expect(mockIsActive).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should log a warning when isActive rejects", async () => {
|
it("should log a warning when isActive rejects", async () => {
|
||||||
const errorMsg = "oh no"
|
const error = new Error("oh no")
|
||||||
const error = new Error(errorMsg)
|
|
||||||
const mockIsActive = jest.fn().mockRejectedValue(error)
|
const mockIsActive = jest.fn().mockRejectedValue(error)
|
||||||
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
|
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
jest.advanceTimersByTime(60 * 1000)
|
jest.advanceTimersByTime(60 * 1000)
|
||||||
|
|
||||||
expect(mockIsActive).toHaveBeenCalled()
|
expect(mockIsActive).toHaveBeenCalled()
|
||||||
expect(logger.warn).toHaveBeenCalledWith(errorMsg)
|
|
||||||
|
// The timer callback waits on mockIsActive, so we need to yield to let the
|
||||||
|
// callback finish.
|
||||||
|
await new Promise((resolve) => setImmediate(resolve))
|
||||||
|
|
||||||
|
expect(logger.warn).toHaveBeenCalledWith(error.message)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -125,38 +135,54 @@ describe("stateChange", () => {
|
|||||||
const testName = "stateChange"
|
const testName = "stateChange"
|
||||||
let testDir = ""
|
let testDir = ""
|
||||||
let heart: Heart
|
let heart: Heart
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await clean(testName)
|
await clean(testName)
|
||||||
testDir = await tmpdir(testName)
|
testDir = await tmpdir(testName)
|
||||||
mockLogger()
|
mockLogger()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
jest.restoreAllMocks()
|
jest.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers()
|
||||||
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks()
|
jest.resetAllMocks()
|
||||||
|
jest.useRealTimers()
|
||||||
if (heart) {
|
if (heart) {
|
||||||
heart.dispose()
|
heart.dispose()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should change to alive after a beat", async () => {
|
it("should change to alive after a beat", async () => {
|
||||||
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
|
const mockIsActive = jest.fn().mockResolvedValue(true)
|
||||||
|
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
|
||||||
const mockOnChange = jest.fn()
|
const mockOnChange = jest.fn()
|
||||||
heart.onChange(mockOnChange)
|
heart.onChange(mockOnChange)
|
||||||
|
|
||||||
await heart.beat()
|
await heart.beat()
|
||||||
|
|
||||||
expect(mockOnChange.mock.calls[0][0]).toBe("alive")
|
expect(mockOnChange.mock.calls[0][0]).toBe("alive")
|
||||||
})
|
})
|
||||||
it.only("should change to expired when not active", async () => {
|
|
||||||
jest.useFakeTimers()
|
it("should change to expired when not active", async () => {
|
||||||
heart = new Heart(`${testDir}/shutdown.txt`, () => new Promise((resolve) => resolve(false)))
|
const mockIsActive = jest.fn().mockResolvedValue(false)
|
||||||
|
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
|
||||||
const mockOnChange = jest.fn()
|
const mockOnChange = jest.fn()
|
||||||
heart.onChange(mockOnChange)
|
heart.onChange(mockOnChange)
|
||||||
await heart.beat()
|
|
||||||
|
|
||||||
await jest.advanceTimersByTime(60 * 1000)
|
await heart.beat()
|
||||||
|
jest.advanceTimersByTime(60 * 1000)
|
||||||
|
expect(mockIsActive).toHaveBeenCalled()
|
||||||
|
|
||||||
|
// The timer callback waits on the isActive promise, so we need to yield to
|
||||||
|
// let the callback finish.
|
||||||
|
await new Promise((resolve) => setImmediate(resolve))
|
||||||
|
|
||||||
expect(mockOnChange.mock.calls[1][0]).toBe("expired")
|
expect(mockOnChange.mock.calls[1][0]).toBe("expired")
|
||||||
jest.clearAllTimers()
|
|
||||||
jest.useRealTimers()
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
import * as os from "os"
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { loadCustomStrings } from "../../../src/node/i18n"
|
import i18n, { loadCustomStrings } from "../../../src/node/i18n"
|
||||||
|
|
||||||
describe("i18n", () => {
|
describe("i18n", () => {
|
||||||
|
it("includes Turkish translations", () => {
|
||||||
|
expect(i18n.getResource("tr", "translation", "WELCOME")).toBe("{{app}} uygulamasına hoş geldiniz")
|
||||||
|
})
|
||||||
|
|
||||||
let tempDir: string
|
let tempDir: string
|
||||||
let validJsonFile: string
|
let validJsonFile: string
|
||||||
let invalidJsonFile: string
|
let invalidJsonFile: string
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import * as http from "http"
|
|
||||||
import nodeFetch from "node-fetch"
|
|
||||||
import { HttpCode } from "../../../src/common/http"
|
import { HttpCode } from "../../../src/common/http"
|
||||||
import { proxy } from "../../../src/node/proxy"
|
|
||||||
import { wss, Router as WsRouter } from "../../../src/node/wsRouter"
|
import { wss, Router as WsRouter } from "../../../src/node/wsRouter"
|
||||||
import { getAvailablePort, mockLogger } from "../../utils/helpers"
|
import { mockLogger } from "../../utils/helpers"
|
||||||
import * as httpserver from "../../utils/httpserver"
|
import * as httpserver from "../../utils/httpserver"
|
||||||
import * as integration from "../../utils/integration"
|
import * as integration from "../../utils/integration"
|
||||||
|
|
||||||
describe("proxy", () => {
|
describe("proxy", () => {
|
||||||
const nhooyrDevServer = new httpserver.HttpServer()
|
const proxyTarget = new httpserver.HttpServer()
|
||||||
const wsApp = express.default()
|
const wsApp = express.default()
|
||||||
const wsRouter = WsRouter()
|
const wsRouter = WsRouter()
|
||||||
let codeServer: httpserver.HttpServer | undefined
|
let codeServer: httpserver.HttpServer | undefined
|
||||||
@@ -19,21 +16,22 @@ describe("proxy", () => {
|
|||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
wsApp.use("/", wsRouter.router)
|
wsApp.use("/", wsRouter.router)
|
||||||
await nhooyrDevServer.listen((req, res) => {
|
await proxyTarget.listen((req, res) => {
|
||||||
e(req, res)
|
e(req, res)
|
||||||
})
|
})
|
||||||
nhooyrDevServer.listenUpgrade(wsApp)
|
proxyTarget.listenUpgrade(wsApp)
|
||||||
proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
|
proxyPath = `/proxy/${proxyTarget.port()}/wsup`
|
||||||
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
|
absProxyPath = proxyPath.replace("/proxy/", "/absproxy/")
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await nhooyrDevServer.dispose()
|
await proxyTarget.dispose()
|
||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
e = express.default()
|
e = express.default()
|
||||||
mockLogger()
|
mockLogger()
|
||||||
|
delete process.env.PASSWORD
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@@ -283,65 +281,61 @@ describe("proxy", () => {
|
|||||||
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
|
const resp = await codeServer.fetch(proxyPath, { method: "OPTIONS" })
|
||||||
expect(resp.status).toBe(200)
|
expect(resp.status).toBe(200)
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// NOTE@jsjoeio
|
it("should return a 500 when no target is running ", async () => {
|
||||||
// Both this test suite and the one above it are very similar
|
const target = new httpserver.HttpServer()
|
||||||
// The main difference is this one uses http and node-fetch
|
await target.listen(() => {})
|
||||||
// and specifically tests the proxy in isolation vs. using
|
const port = target.port()
|
||||||
// the httpserver abstraction we've built.
|
target.dispose()
|
||||||
//
|
codeServer = await integration.setup(["--auth=none"], "")
|
||||||
// Leaving this as a separate test suite for now because
|
const resp = await codeServer.fetch(`/proxy/${port}/wsup`)
|
||||||
// we may consider refactoring the httpserver abstraction
|
expect(resp.status).toBe(HttpCode.ServerError)
|
||||||
// in the future.
|
expect(resp.statusText).toBe("Internal Server Error")
|
||||||
//
|
})
|
||||||
// If you're writing a test specifically for code in
|
|
||||||
// src/node/proxy.ts, you should probably add it to
|
|
||||||
// this test suite.
|
|
||||||
describe("proxy (standalone)", () => {
|
|
||||||
let URL = ""
|
|
||||||
let PROXY_URL = ""
|
|
||||||
let testServer: http.Server
|
|
||||||
let proxyTarget: http.Server
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
it("should strip token cookie", async () => {
|
||||||
const PORT = await getAvailablePort()
|
const token = "my-super-secure-token"
|
||||||
const PROXY_PORT = await getAvailablePort()
|
process.env.HASHED_PASSWORD = token
|
||||||
URL = `http://localhost:${PORT}`
|
codeServer = await integration.setup(["--auth=password"])
|
||||||
PROXY_URL = `http://localhost:${PROXY_PORT}`
|
|
||||||
// Define server and a proxy server
|
e.get("/wsup/cookies", (req, res) => {
|
||||||
testServer = http.createServer((req, res) => {
|
res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" })
|
||||||
proxy.web(req, res, {
|
res.end(req.headers.cookie)
|
||||||
target: PROXY_URL,
|
})
|
||||||
|
|
||||||
|
const cookies = [
|
||||||
|
"cookie2=hello",
|
||||||
|
// Cookies should pass through unchanged, neither encoded nor decoded.
|
||||||
|
`cookie1=${encodeURIComponent("hello=there")}`,
|
||||||
|
"cookie3=foo|bar",
|
||||||
|
`cookie4=${encodeURIComponent("foo|bar")}`,
|
||||||
|
`cookie5=${encodeURIComponent("bar;baz")}`,
|
||||||
|
]
|
||||||
|
|
||||||
|
// Test each slot to ensure the token is found anywhere.
|
||||||
|
for (let i = 0; i <= cookies.length; ++i) {
|
||||||
|
const left = cookies.slice(0, i)
|
||||||
|
const right = cookies.slice(i)
|
||||||
|
const resp = await codeServer.fetch(proxyPath + "/cookies", {
|
||||||
|
headers: {
|
||||||
|
cookie: [...left, `code-server-session=${token}`, ...right].join("; "),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
expect(resp.status).toBe(200)
|
||||||
|
expect(await resp.text()).toBe(cookies.join("; "))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should proxy when no cookies", async () => {
|
||||||
|
codeServer = await integration.setup(["--auth=none"])
|
||||||
|
|
||||||
|
e.get("/wsup/cookies", (req, res) => {
|
||||||
|
res.writeHead(HttpCode.Ok, { "Content-Type": "text/plain" })
|
||||||
|
res.end(req.headers.cookie || "no cookies")
|
||||||
})
|
})
|
||||||
|
|
||||||
proxyTarget = http.createServer((req, res) => {
|
const resp = await codeServer.fetch(proxyPath + "/cookies")
|
||||||
res.writeHead(200, { "Content-Type": "text/plain" })
|
|
||||||
res.end()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Start both servers
|
|
||||||
proxyTarget.listen(PROXY_PORT)
|
|
||||||
testServer.listen(PORT)
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(async () => {
|
|
||||||
testServer.close()
|
|
||||||
proxyTarget.close()
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return a 500 when proxy target errors ", async () => {
|
|
||||||
// Close the proxy target so that proxy errors
|
|
||||||
proxyTarget.close()
|
|
||||||
const errorResp = await nodeFetch(`${URL}/error`)
|
|
||||||
expect(errorResp.status).toBe(HttpCode.ServerError)
|
|
||||||
expect(errorResp.statusText).toBe("Internal Server Error")
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should proxy correctly", async () => {
|
|
||||||
const resp = await nodeFetch(`${URL}/route`)
|
|
||||||
expect(resp.status).toBe(200)
|
expect(resp.status).toBe(200)
|
||||||
expect(resp.statusText).toBe("OK")
|
expect(await resp.text()).toBe("no cookies")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -75,6 +75,17 @@ describe("login", () => {
|
|||||||
expect(htmlContent).toContain("Missing password")
|
expect(htmlContent).toContain("Missing password")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should reject compressed request bodies", async () => {
|
||||||
|
for (const encoding of ["br", "gzip", "deflate"]) {
|
||||||
|
const resp = await codeServer().fetch("/login", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/x-www-form-urlencoded", "Content-Encoding": encoding },
|
||||||
|
body: "password=test",
|
||||||
|
})
|
||||||
|
expect(resp.status).toBe(415)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it("should return HTML with 'Incorrect password' message", async () => {
|
it("should return HTML with 'Incorrect password' message", async () => {
|
||||||
const params = new URLSearchParams()
|
const params = new URLSearchParams()
|
||||||
params.append("password", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
params.append("password", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
||||||
|
|||||||
@@ -4,11 +4,19 @@ import * as integration from "../../../utils/integration"
|
|||||||
|
|
||||||
describe("vscode", () => {
|
describe("vscode", () => {
|
||||||
let codeServer: httpserver.HttpServer | undefined
|
let codeServer: httpserver.HttpServer | undefined
|
||||||
|
// TODO: Support setting this as an argument for tests.
|
||||||
|
const previousEnvPassword = process.env.PASSWORD
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
process.env.PASSWORD = "test"
|
||||||
mockLogger()
|
mockLogger()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
|
if (typeof previousEnvPassword !== "undefined") {
|
||||||
|
process.env.PASSWORD = previousEnvPassword
|
||||||
|
} else {
|
||||||
|
delete process.env.PASSWORD
|
||||||
|
}
|
||||||
if (codeServer) {
|
if (codeServer) {
|
||||||
await codeServer.dispose()
|
await codeServer.dispose()
|
||||||
codeServer = undefined
|
codeServer = undefined
|
||||||
@@ -27,4 +35,10 @@ describe("vscode", () => {
|
|||||||
})
|
})
|
||||||
}).rejects.toThrow()
|
}).rejects.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should require auth", async () => {
|
||||||
|
codeServer = await integration.setup(["--auth=password"], "")
|
||||||
|
const resp = await codeServer.fetch("/mint-key", { method: "POST" })
|
||||||
|
expect(resp.status).toBe(401)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as cp from "child_process"
|
import * as cp from "child_process"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { generateUuid } from "../../../src/common/util"
|
import { generateUuid } from "../../../src/common/util"
|
||||||
import { tmpdir } from "../../../src/node/constants"
|
import { tmpdir } from "../../../src/node/constants"
|
||||||
@@ -623,3 +624,18 @@ describe("splitOnFirstEquals", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("expandTilde", () => {
|
||||||
|
it("should expand a bare ~", () => {
|
||||||
|
expect(util.expandTilde("~")).toBe(os.homedir())
|
||||||
|
})
|
||||||
|
it("should expand a leading ~/", () => {
|
||||||
|
expect(util.expandTilde("~/.config/code-server")).toBe(path.join(os.homedir(), ".config/code-server"))
|
||||||
|
})
|
||||||
|
it("should leave other paths alone", () => {
|
||||||
|
expect(util.expandTilde("/tmp/~/data")).toBe("/tmp/~/data")
|
||||||
|
expect(util.expandTilde("relative/~")).toBe("relative/~")
|
||||||
|
expect(util.expandTilde("~user/data")).toBe("~user/data")
|
||||||
|
expect(util.expandTilde("")).toBe("")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user