mirror of
https://github.com/coder/code-server.git
synced 2026-11-03 06:19:13 +01:00
Compare commits
285 Commits
v4.108.1
...
b4b95712e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4b95712e7 | ||
|
|
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 | ||
|
|
b27ceeb106 | ||
|
|
be062d06c1 | ||
|
|
f733ccaed1 | ||
|
|
6f69f28379 | ||
|
|
6b36d4e421 | ||
|
|
9dcb1d7da0 | ||
|
|
840a9430cd | ||
|
|
9143a299a4 | ||
|
|
41b0e45f91 | ||
|
|
b5611efe1a | ||
|
|
a5c1b6a196 | ||
|
|
2743655ab5 | ||
|
|
8d9a44a024 | ||
|
|
ada3489acf | ||
|
|
4d615f18a9 | ||
|
|
d544846caa | ||
|
|
44fc46316f | ||
|
|
d7599ae360 | ||
|
|
13ca0e4731 | ||
|
|
b7c7a62049 | ||
|
|
24ea70ac88 | ||
|
|
a6d80dc434 | ||
|
|
b43e772707 | ||
|
|
1af5ce5ab6 | ||
|
|
62afaf261b | ||
|
|
b6e0c844a9 | ||
|
|
83d2935223 | ||
|
|
9e3794487f | ||
|
|
65b0f0e1bb | ||
|
|
841ec45573 | ||
|
|
3eada681d3 | ||
|
|
52f1542621 | ||
|
|
b5e2c42183 | ||
|
|
980e009b6d | ||
|
|
36b00d37ff | ||
|
|
355546d0a5 | ||
|
|
e9c577549f | ||
|
|
98a2a0064b | ||
|
|
d58aaa7b34 | ||
|
|
9184b645cc | ||
|
|
639c3202eb | ||
|
|
65299492b6 | ||
|
|
954ceae6e0 | ||
|
|
e90504b8cf | ||
|
|
3c0b449c6e | ||
|
|
7f2112c1c9 | ||
|
|
7ec0be6995 | ||
|
|
1dd0741c94 | ||
|
|
aa210cdad4 | ||
|
|
9e97cd1278 | ||
|
|
352636408c | ||
|
|
f223d301a2 | ||
|
|
809abfbbe0 | ||
|
|
f5dc5436da | ||
|
|
94a533e540 |
8
.github/dependabot.yaml
vendored
8
.github/dependabot.yaml
vendored
@@ -6,9 +6,9 @@ updates:
|
||||
interval: "monthly"
|
||||
time: "06:00"
|
||||
timezone: "America/Chicago"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
labels: []
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
@@ -16,8 +16,8 @@ updates:
|
||||
interval: "monthly"
|
||||
time: "06:00"
|
||||
timezone: "America/Chicago"
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
labels: []
|
||||
ignore:
|
||||
# Ignore patch updates for all dependencies
|
||||
|
||||
66
.github/semantic.yaml
vendored
66
.github/semantic.yaml
vendored
@@ -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
|
||||
208
.github/workflows/build.yaml
vendored
208
.github/workflows/build.yaml
vendored
@@ -15,26 +15,19 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
# Note: if: success() is used in several jobs -
|
||||
# this ensures that it only executes if all previous jobs succeeded.
|
||||
|
||||
# if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
# will skip running `npm install` if it successfully fetched from cache
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ci: ${{ steps.filter.outputs.ci }}
|
||||
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 }}
|
||||
helm: ${{ steps.filter.outputs.helm }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
- name: Check changed files
|
||||
uses: dorny/paths-filter@v3
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
@@ -50,11 +43,12 @@ jobs:
|
||||
code:
|
||||
- "src/**"
|
||||
- "test/**"
|
||||
deps:
|
||||
- "lib/**"
|
||||
- "patches/**"
|
||||
npm:
|
||||
- "package-lock.json"
|
||||
- "test/package-lock.json"
|
||||
vscode:
|
||||
- "lib/**"
|
||||
- "patches/**"
|
||||
- id: debug
|
||||
run: |
|
||||
echo "${{ toJSON(steps.filter )}}"
|
||||
@@ -62,10 +56,9 @@ jobs:
|
||||
prettier:
|
||||
name: Run prettier check
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
@@ -78,12 +71,11 @@ jobs:
|
||||
doctoc:
|
||||
name: Doctoc markdown files
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
needs: changes
|
||||
if: needs.changes.outputs.docs == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
@@ -96,26 +88,23 @@ jobs:
|
||||
lint-helm:
|
||||
name: Lint Helm chart
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
needs: changes
|
||||
if: needs.changes.outputs.helm == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: azure/setup-helm@v4
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: bmuschko/setup-kubeconform@e5d264ec1eafe2314e750c429a9da7639dd5a003 # v1.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: helm plugin install https://github.com/instrumenta/helm-kubeval
|
||||
- run: helm kubeval ci/helm-chart
|
||||
kubeconform-version: "0.8.0"
|
||||
- run: kubeconform ci/helm-chart
|
||||
|
||||
lint-ts:
|
||||
name: Lint TypeScript files
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
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:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
@@ -132,7 +121,7 @@ jobs:
|
||||
if: needs.changes.outputs.ci == 'true'
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- name: Check workflow files
|
||||
run: |
|
||||
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
|
||||
@@ -142,12 +131,11 @@ jobs:
|
||||
test-unit:
|
||||
name: Run unit tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
needs: changes
|
||||
if: needs.changes.outputs.code == 'true'
|
||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
@@ -156,84 +144,95 @@ jobs:
|
||||
test/package-lock.json
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
- run: npm run test:unit
|
||||
- uses: codecov/codecov-action@v5
|
||||
- uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1
|
||||
if: success()
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
build:
|
||||
name: Build code-server
|
||||
name: linux-x64
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 70
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
DISABLE_V8_COMPILE_CACHE: 1
|
||||
VERSION: 0.0.0
|
||||
VSCODE_ARCH: x64
|
||||
VSCODE_TARGET: linux-x64
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
|
||||
with:
|
||||
packages: quilt
|
||||
version: 1.0
|
||||
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
with:
|
||||
submodules: true
|
||||
- run: quilt push -a
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
- run: npm run build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Get Code's git hash. When this changes it means the content is
|
||||
# different and we need to rebuild.
|
||||
- name: Get latest lib/vscode rev
|
||||
id: vscode-rev
|
||||
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
|
||||
# We need to rebuild when we have a new version of Code, when any of
|
||||
# the patches changed, or when the code-server version changes (since
|
||||
# it gets embedded into the code). Use VSCODE_CACHE_VERSION to
|
||||
# force a rebuild.
|
||||
- name: Fetch prebuilt Code package from cache
|
||||
|
||||
# We need to rebuild when we have a new version of Code, when any of the
|
||||
# patches changed, or when the code-server version changes (since it gets
|
||||
# embedded into the code). Use VSCODE_CACHE_VERSION to force a rebuild.
|
||||
- name: Fetch prebuilt linux-x64 Code package from cache
|
||||
id: cache-vscode
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: lib/vscode-reh-web-*
|
||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
||||
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') }}
|
||||
- name: Build vscode
|
||||
env:
|
||||
VERSION: "0.0.0"
|
||||
if: steps.cache-vscode.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
pushd lib/vscode
|
||||
cd lib/vscode/build
|
||||
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
|
||||
# The release package does not contain any native modules
|
||||
# and is neutral to architecture/os/libc version.
|
||||
- run: npm run release
|
||||
if: success()
|
||||
# https://github.com/actions/upload-artifact/issues/38
|
||||
|
||||
# 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.
|
||||
- run: KEEP_MODULES=1 npm run release
|
||||
- run: tar -czf package.tar.gz release
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||
with:
|
||||
name: npm-package
|
||||
name: linux-x64-package
|
||||
path: ./package.tar.gz
|
||||
|
||||
test-e2e:
|
||||
name: Run e2e tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
LOG_LEVEL: debug
|
||||
needs: [changes, build]
|
||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
|
||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
@@ -241,70 +240,71 @@ jobs:
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: npm-package
|
||||
- run: tar -xzf package.tar.gz
|
||||
- run: cd release && npm install --unsafe-perm --omit=dev
|
||||
- name: Install Playwright OS dependencies
|
||||
run: |
|
||||
./test/node_modules/.bin/playwright install-deps
|
||||
./test/node_modules/.bin/playwright install
|
||||
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: linux-x64-package
|
||||
- run: tar -xzf package.tar.gz
|
||||
|
||||
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||
if: always()
|
||||
with:
|
||||
name: failed-test-videos
|
||||
path: ./test/test-results
|
||||
- run: rm -rf ./release ./test/test-results
|
||||
|
||||
test-e2e-proxy:
|
||||
name: Run e2e tests behind proxy
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 25
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
LOG_LEVEL: debug
|
||||
needs: [changes, build]
|
||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
|
||||
if: needs.changes.outputs.code == 'true' || needs.changes.outputs.npm == 'true' || needs.changes.outputs.vscode == 'true' || needs.changes.outputs.ci == 'true'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
- uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: npm-package
|
||||
- run: tar -xzf package.tar.gz
|
||||
- run: cd release && npm install --unsafe-perm --omit=dev
|
||||
- name: Install Playwright OS dependencies
|
||||
run: |
|
||||
./test/node_modules/.bin/playwright install-deps
|
||||
./test/node_modules/.bin/playwright install
|
||||
- name: Cache Caddy
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
id: caddy-cache
|
||||
with:
|
||||
path: |
|
||||
~/.cache/caddy
|
||||
key: cache-caddy-2.5.2
|
||||
- name: Install Caddy
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: steps.caddy-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
|
||||
mkdir -p ~/.cache/caddy
|
||||
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
|
||||
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
- name: Install Playwright OS dependencies
|
||||
run: |
|
||||
./test/node_modules/.bin/playwright install-deps
|
||||
./test/node_modules/.bin/playwright install
|
||||
|
||||
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: linux-x64-package
|
||||
- run: tar -xzf package.tar.gz
|
||||
|
||||
- run: ~/.cache/caddy/caddy start --config ./ci/Caddyfile
|
||||
- run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
|
||||
- run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
|
||||
if: always()
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
||||
if: always()
|
||||
with:
|
||||
name: failed-test-videos-proxy
|
||||
|
||||
6
.github/workflows/installer.yaml
vendored
6
.github/workflows/installer.yaml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
- name: Install code-server
|
||||
run: ./install.sh
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
container: "alpine:3.17"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
- name: Install curl
|
||||
run: apk add curl
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
- name: Install code-server
|
||||
run: ./install.sh
|
||||
|
||||
151
.github/workflows/publish.yaml
vendored
151
.github/workflows/publish.yaml
vendored
@@ -6,7 +6,6 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: The version to publish (include "v", i.e. "v4.9.1").
|
||||
type: string
|
||||
required: true
|
||||
|
||||
@@ -23,144 +22,146 @@ concurrency:
|
||||
jobs:
|
||||
npm:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v6
|
||||
env:
|
||||
TAG: ${{ inputs.version || github.ref_name }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_ENVIRONMENT: "production"
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
steps:
|
||||
- name: Set version to tag without leading v
|
||||
run: |
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
- name: Download npm package from release artifacts
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
- uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
|
||||
with:
|
||||
repository: "coder/code-server"
|
||||
tag: ${{ github.event.inputs.version || github.ref_name }}
|
||||
tag: ${{ env.TAG }}
|
||||
fileName: "package.tar.gz"
|
||||
out-file-path: "release-npm-package"
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- run: npm run publish:npm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_ENVIRONMENT: "production"
|
||||
- run: tar -xzf release-npm-package/package.tar.gz
|
||||
- run: |
|
||||
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||
pushd release
|
||||
npm publish --tag latest --access public
|
||||
|
||||
aur:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
TAG: ${{ inputs.version || github.ref_name }}
|
||||
|
||||
steps:
|
||||
# We need to checkout code-server so we can get the version
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: "./code-server"
|
||||
- name: Set version to tag without leading v
|
||||
run: |
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout code-server-aur repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
with:
|
||||
repository: "cdrci/code-server-aur"
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
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
|
||||
run: |
|
||||
git config --global user.name cdrci
|
||||
git config --global user.email opensource@coder.com
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
- name: Fetch and reset master
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
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
|
||||
uses: heyhusen/archlinux-package-action@v2.4.0
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
uses: heyhusen/archlinux-package-action@3f7aaada28c782497bfe02d6d6ea365b25fdea12 # v3.0.1
|
||||
with:
|
||||
pkgver: ${{ env.VERSION }}
|
||||
updpkgsums: true
|
||||
srcinfo: true
|
||||
|
||||
- name: Open PR
|
||||
# We need to git push -u otherwise gh will prompt
|
||||
# asking where to push the branch.
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
git checkout -b update-version-${{ env.VERSION }}
|
||||
git add .
|
||||
git commit -m "chore: updating version to ${{ env.VERSION }}"
|
||||
git commit -m "Update to ${{ env.VERSION }}"
|
||||
git push -u origin $(git branch --show)
|
||||
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
||||
gh pr create --repo coder/code-server-aur --title "Update to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
||||
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ inputs.version || github.ref_name }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v6
|
||||
- name: Set version to tag without leading v
|
||||
run: |
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
- uses: docker/setup-qemu-action@1f40c72289eff860ee54a304f1438e3cff362e0a # v4.3.0
|
||||
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Download deb artifacts
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
- uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
|
||||
with:
|
||||
repository: "coder/code-server"
|
||||
tag: v${{ env.VERSION }}
|
||||
fileName: "*.deb"
|
||||
out-file-path: "release-packages"
|
||||
|
||||
- name: Download rpm artifacts
|
||||
uses: robinraju/release-downloader@v1.12
|
||||
- uses: robinraju/release-downloader@28fc21f50d76778e7023361aa1f863e717d3d56f # v1.13
|
||||
with:
|
||||
repository: "coder/code-server"
|
||||
tag: v${{ env.VERSION }}
|
||||
fileName: "*.rpm"
|
||||
out-file-path: "release-packages"
|
||||
|
||||
- name: Publish to Docker
|
||||
run: ./ci/steps/docker-buildx-push.sh
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- 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"
|
||||
|
||||
540
.github/workflows/release.yaml
vendored
540
.github/workflows/release.yaml
vendored
@@ -4,9 +4,13 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: The version to publish (include "v", i.e. "v4.9.1").
|
||||
type: string
|
||||
required: true
|
||||
pull_request_target:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write # For creating releases.
|
||||
@@ -19,186 +23,158 @@ concurrency:
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
package-linux-cross:
|
||||
name: ${{ matrix.prefix }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
container: "python:3.8-slim-buster"
|
||||
package-linux:
|
||||
name: ${{ format('linux-{0}', matrix.vscode_arch) }}
|
||||
runs-on: ubuntu-22.04
|
||||
if: >-
|
||||
(github.event_name == 'workflow_dispatch') ||
|
||||
(github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- prefix: x86_64-linux-gnu
|
||||
npm_arch: x64
|
||||
apt_arch: amd64
|
||||
- npm_arch: x64
|
||||
vscode_arch: x64
|
||||
package_arch: amd64
|
||||
- prefix: aarch64-linux-gnu
|
||||
npm_arch: arm64
|
||||
apt_arch: arm64
|
||||
- npm_arch: arm64
|
||||
vscode_arch: arm64
|
||||
package_arch: arm64
|
||||
- prefix: arm-linux-gnueabihf
|
||||
npm_arch: armv7l
|
||||
apt_arch: armhf
|
||||
package_arch: armv7l
|
||||
|
||||
env:
|
||||
AR: ${{ format('{0}-ar', matrix.prefix) }}
|
||||
AS: ${{ format('{0}-as', matrix.prefix) }}
|
||||
CC: ${{ format('{0}-gcc', matrix.prefix) }}
|
||||
CPP: ${{ format('{0}-cpp', matrix.prefix) }}
|
||||
CXX: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
FC: ${{ format('{0}-gfortran', matrix.prefix) }}
|
||||
LD: ${{ format('{0}-ld', matrix.prefix) }}
|
||||
STRIP: ${{ format('{0}-strip', matrix.prefix) }}
|
||||
PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
|
||||
TARGET_ARCH: ${{ matrix.apt_arch }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
TAG: ${{ inputs.version || github.event.pull_request.head.ref || github.ref_name }}
|
||||
# Set release package name.
|
||||
ARCH: ${{ matrix.package_arch }}
|
||||
# Cross-compile target.
|
||||
VSCODE_ARCH: ${{ matrix.vscode_arch }}
|
||||
npm_config_arch: ${{ matrix.npm_arch }}
|
||||
PKG_ARCH: ${{ matrix.package_arch }}
|
||||
# Not building from source results in an x86_64 argon2, as if
|
||||
# npm_config_arch is being ignored.
|
||||
# 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.
|
||||
# TODO: Pull from VSCODE_ARCH instead.
|
||||
VSCODE_TARGET: ${{ format('linux-{0}', matrix.vscode_arch) }}
|
||||
|
||||
steps:
|
||||
- run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
- uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # latest
|
||||
with:
|
||||
packages: quilt
|
||||
version: 1.0
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
mkdir -p ~/.local/bin
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- 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
|
||||
- run: quilt push -a
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
cd lib/vscode/build
|
||||
npm ci
|
||||
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
|
||||
cd ../..
|
||||
npm ci
|
||||
npm run build
|
||||
npm run build:vscode
|
||||
|
||||
# Platform-agnostic NPM package.
|
||||
- run: npm run release
|
||||
if: ${{ matrix.vscode_arch == 'x64' }}
|
||||
- run: tar -czf package.tar.gz release
|
||||
if: ${{ matrix.vscode_arch == 'x64' }}
|
||||
- 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' }}
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: package.tar.gz
|
||||
tag_name: v${{ env.VERSION }}
|
||||
name: v${{ env.VERSION }}
|
||||
body_path: .cache/release-notes
|
||||
|
||||
# Platform-specific release.
|
||||
- run: KEEP_MODULES=1 npm run release
|
||||
- run: npm run package
|
||||
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./release-packages/*
|
||||
tag_name: v${{ env.VERSION }}
|
||||
name: v${{ env.VERSION }}
|
||||
|
||||
package-macos:
|
||||
name: ${{ matrix.vscode_target }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: >-
|
||||
(github.event_name == 'workflow_dispatch') ||
|
||||
(github.event_name == 'pull_request_target' && github.event.pull_request.merged == true && startsWith(github.head_ref, 'update/'))
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- os: macos-15-intel
|
||||
vscode_target: darwin-x64
|
||||
- os: macos-latest
|
||||
vscode_target: darwin-arm64
|
||||
env:
|
||||
VSCODE_TARGET: ${{ matrix.vscode_target }}
|
||||
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
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
|
||||
- name: Install cross-compiler and system dependencies
|
||||
run: |
|
||||
sed -i 's/deb\.debian\.org/archive.debian.org/g' /etc/apt/sources.list
|
||||
dpkg --add-architecture $TARGET_ARCH
|
||||
apt update && apt install -y --no-install-recommends \
|
||||
crossbuild-essential-$TARGET_ARCH \
|
||||
libx11-dev:$TARGET_ARCH \
|
||||
libx11-xcb-dev:$TARGET_ARCH \
|
||||
libxkbfile-dev:$TARGET_ARCH \
|
||||
libsecret-1-dev:$TARGET_ARCH \
|
||||
libkrb5-dev:$TARGET_ARCH \
|
||||
ca-certificates \
|
||||
curl wget rsync gettext-base
|
||||
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
mkdir -p ~/.local/bin
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: npm-release-package
|
||||
|
||||
- run: tar -xzf package.tar.gz
|
||||
- run: npm run release:standalone
|
||||
|
||||
- name: Replace node with cross-compile equivalent
|
||||
run: |
|
||||
node_version=$(node --version)
|
||||
wget https://nodejs.org/dist/${node_version}/node-${node_version}-linux-${npm_config_arch}.tar.xz
|
||||
tar -xf node-${node_version}-linux-${npm_config_arch}.tar.xz node-${node_version}-linux-${npm_config_arch}/bin/node --strip-components=2
|
||||
mv ./node ./release-standalone/lib/node
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: npm run package $PKG_ARCH
|
||||
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./release-packages/*
|
||||
|
||||
package-macos-amd64:
|
||||
name: x86-64 macOS build
|
||||
runs-on: macos-15-intel
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
mkdir -p ~/.local/bin
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
# The version of node-gyp we use depends on distutils but it was removed
|
||||
# in Python 3.12. It seems to be fixed in the latest node-gyp so when we
|
||||
# next update Node we can probably remove this. For now, install
|
||||
# setuptools since it contains distutils.
|
||||
- run: brew install python-setuptools
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: npm-release-package
|
||||
|
||||
- run: tar -xzf package.tar.gz
|
||||
- run: npm run release:standalone
|
||||
- run: npm run test:native
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
- run: brew install python-setuptools quilt
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
mkdir -p ~/.local/bin
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Build packages with nfpm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: npm run package
|
||||
- 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: softprops/action-gh-release@v1
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./release-packages/*
|
||||
|
||||
package-macos-arm64:
|
||||
name: arm64 macOS build
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
submodules: true
|
||||
- run: quilt push -a
|
||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: npm
|
||||
@@ -206,104 +182,166 @@ jobs:
|
||||
package-lock.json
|
||||
test/package-lock.json
|
||||
|
||||
- run: SKIP_SUBMODULE_DEPS=1 npm ci
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
mkdir -p ~/.local/bin
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
# The version of node-gyp we use depends on distutils but it was removed
|
||||
# in Python 3.12. It seems to be fixed in the latest node-gyp so when we
|
||||
# next update Node we can probably remove this. For now, install
|
||||
# setuptools since it contains distutils.
|
||||
- run: brew install python-setuptools
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: npm-release-package
|
||||
|
||||
- run: tar -xzf package.tar.gz
|
||||
- run: npm run release:standalone
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm run build:vscode
|
||||
- run: KEEP_MODULES=1 npm run release
|
||||
- run: npm run test:native
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build packages with nfpm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: npm run package
|
||||
|
||||
- uses: softprops/action-gh-release@v1
|
||||
- run: npm run package
|
||||
- uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
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
|
||||
|
||||
npm-package:
|
||||
name: Upload npm package
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
steps:
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: npm-release-package
|
||||
# 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
|
||||
|
||||
- uses: softprops/action-gh-release@v1
|
||||
- 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
|
||||
|
||||
# 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: ./package.tar.gz
|
||||
|
||||
npm-version:
|
||||
name: Modify package.json version
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@v11
|
||||
id: download
|
||||
with:
|
||||
branch: ${{ github.ref }}
|
||||
workflow: build.yaml
|
||||
workflow_conclusion: completed
|
||||
name: npm-package
|
||||
check_artifacts: false
|
||||
if_no_artifact_found: fail
|
||||
|
||||
- run: tar -xzf package.tar.gz
|
||||
|
||||
# Strip out the v (v4.9.1 -> 4.9.1).
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Modify version
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
echo "Updating version in root package.json"
|
||||
npm version --prefix release "$VERSION"
|
||||
|
||||
echo "Updating version in lib/vscode/product.json"
|
||||
tmp=$(mktemp)
|
||||
jq ".codeServerVersion = \"$VERSION\"" release/lib/vscode/product.json > "$tmp" && mv "$tmp" release/lib/vscode/product.json
|
||||
# Ensure it has the same permissions as before
|
||||
chmod 644 release/lib/vscode/product.json
|
||||
|
||||
- run: tar -czf package.tar.gz release
|
||||
|
||||
- name: Upload npm package artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: npm-release-package
|
||||
path: ./package.tar.gz
|
||||
files: ./release-packages/*
|
||||
tag_name: v${{ env.VERSION }}
|
||||
name: v${{ env.VERSION }}
|
||||
|
||||
4
.github/workflows/scripts.yaml
vendored
4
.github/workflows/scripts.yaml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
container: "alpine:3.17"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
- name: Install test utilities
|
||||
run: apk add bats checkbashisms
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
- name: Install lint utilities
|
||||
run: sudo apt install shellcheck
|
||||
|
||||
18
.github/workflows/security.yaml
vendored
18
.github/workflows/security.yaml
vendored
@@ -25,12 +25,12 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
@@ -46,12 +46,12 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
|
||||
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
|
||||
with:
|
||||
scan-type: "fs"
|
||||
scan-ref: "."
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
||||
with:
|
||||
sarif_file: "trivy-repo-results.sarif"
|
||||
|
||||
@@ -76,17 +76,17 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
with:
|
||||
config-file: ./.github/codeql-config.yml
|
||||
languages: javascript
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2
|
||||
|
||||
8
.github/workflows/trivy-docker.yaml
vendored
8
.github/workflows/trivy-docker.yaml
vendored
@@ -18,8 +18,6 @@ on:
|
||||
- .github/workflows/trivy-docker.yaml
|
||||
|
||||
schedule:
|
||||
# Run at 10:15 am UTC (3:15am PT/5:15am CT)
|
||||
# Run at 0 minutes 0 hours of every day.
|
||||
- cron: "15 10 * * *"
|
||||
|
||||
workflow_dispatch:
|
||||
@@ -48,10 +46,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
|
||||
|
||||
- name: Run Trivy vulnerability scanner in image mode
|
||||
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8
|
||||
uses: aquasecurity/trivy-action@d2a0b60797ff03db6132bd4e2b293f9b37081297 # latest
|
||||
with:
|
||||
image-ref: "docker.io/codercom/code-server:latest"
|
||||
ignore-unfixed: true
|
||||
@@ -60,6 +58,6 @@ jobs:
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
||||
with:
|
||||
sarif_file: "trivy-image-results.sarif"
|
||||
|
||||
72
.github/workflows/update.yaml
vendored
Normal file
72
.github/workflows/update.yaml
vendored
Normal file
@@ -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
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,8 +2,6 @@
|
||||
.cache
|
||||
/out*/
|
||||
release/
|
||||
release-npm-package/
|
||||
release-standalone/
|
||||
release-packages/
|
||||
release-gcp/
|
||||
release-images/
|
||||
@@ -13,6 +11,7 @@ node_modules
|
||||
.home
|
||||
coverage
|
||||
**/.DS_Store
|
||||
*.bak
|
||||
|
||||
# Code packages itself here.
|
||||
/lib/vscode-reh-web-*
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.21.1
|
||||
24.21.0
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
lib/vscode
|
||||
lib/vscode-reh-web-linux-x64
|
||||
release-standalone
|
||||
lib
|
||||
release-packages
|
||||
release
|
||||
helm-chart
|
||||
|
||||
364
CHANGELOG.md
364
CHANGELOG.md
@@ -22,6 +22,370 @@ Code v99.99.999
|
||||
|
||||
## Unreleased
|
||||
|
||||
## [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
|
||||
|
||||
Code v1.112.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.112.0
|
||||
|
||||
## [4.111.0](https://github.com/coder/code-server/releases/tag/v4.111.0) - 2026-03-11
|
||||
|
||||
Code v1.111.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.111.0
|
||||
- `--app-name` now affects the error page title.
|
||||
|
||||
## [4.110.1](https://github.com/coder/code-server/releases/tag/v4.110.1) - 2026-03-10
|
||||
|
||||
Code v1.110.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.110.1
|
||||
|
||||
## [4.110.0](https://github.com/coder/code-server/releases/tag/v4.110.0) - 2026-03-09
|
||||
|
||||
Code v1.110.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.110.0
|
||||
|
||||
## [4.109.5](https://github.com/coder/code-server/releases/tag/v4.109.5) - 2026-03-02
|
||||
|
||||
Code v1.109.5
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.109.5
|
||||
|
||||
## [4.109.2](https://github.com/coder/code-server/releases/tag/v4.109.2) - 2026-02-12
|
||||
|
||||
Code v1.109.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.109.2
|
||||
|
||||
## [4.109.0](https://github.com/coder/code-server/releases/tag/v4.109.0) - 2026-02-12
|
||||
|
||||
Code v1.109.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.109.0
|
||||
|
||||
## [4.108.2](https://github.com/coder/code-server/releases/tag/v4.108.2) - 2026-01-26
|
||||
|
||||
Code v1.108.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.108.2
|
||||
|
||||
## [4.108.1](https://github.com/coder/code-server/releases/tag/v4.108.1) - 2026-01-16
|
||||
|
||||
Code v1.108.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.108.1
|
||||
|
||||
## [4.108.0](https://github.com/coder/code-server/releases/tag/v4.108.0) - 2026-01-12
|
||||
|
||||
Code v1.108.0
|
||||
|
||||
112
ci/README.md
112
ci/README.md
@@ -1,112 +0,0 @@
|
||||
# ci
|
||||
|
||||
This directory contains scripts used for code-server's continuous integration infrastructure.
|
||||
|
||||
Some of these scripts contain more detailed documentation and options
|
||||
in header comments.
|
||||
|
||||
Any file or directory in this subdirectory should be documented here.
|
||||
|
||||
- [./ci/lib.sh](./lib.sh)
|
||||
- Contains code duplicated across these scripts.
|
||||
|
||||
## dev
|
||||
|
||||
This directory contains scripts used for the development of code-server.
|
||||
|
||||
- [./ci/dev/image](./dev/image)
|
||||
- See [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md) for docs on the development container.
|
||||
- [./ci/dev/fmt.sh](./dev/fmt.sh) (`npm run fmt`)
|
||||
- Runs formatters.
|
||||
- [./ci/dev/lint.sh](./dev/lint.sh) (`npm run lint`)
|
||||
- Runs linters.
|
||||
- [./ci/dev/test-unit.sh](./dev/test-unit.sh) (`npm run test:unit`)
|
||||
- Runs unit tests.
|
||||
- [./ci/dev/test-e2e.sh](./dev/test-e2e.sh) (`npm run test:e2e`)
|
||||
- Runs end-to-end tests.
|
||||
- [./ci/dev/watch.ts](./dev/watch.ts) (`npm run watch`)
|
||||
- Starts a process to build and launch code-server and restart on any code changes.
|
||||
- Example usage in [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md).
|
||||
- [./ci/dev/gen_icons.sh](./dev/gen_icons.sh) (`npm run icons`)
|
||||
- Generates the various icons from a single `.svg` favicon in
|
||||
`src/browser/media/favicon.svg`.
|
||||
- Requires [imagemagick](https://imagemagick.org/index.php)
|
||||
|
||||
## build
|
||||
|
||||
This directory contains the scripts used to build and release code-server.
|
||||
You can disable minification by setting `MINIFY=`.
|
||||
|
||||
- [./ci/build/build-code-server.sh](./build/build-code-server.sh) (`npm run build`)
|
||||
- Builds code-server into `./out` and bundles the frontend into `./dist`.
|
||||
- [./ci/build/build-vscode.sh](./build/build-vscode.sh) (`npm run build:vscode`)
|
||||
- Builds vscode into `./lib/vscode/out-vscode`.
|
||||
- [./ci/build/build-release.sh](./build/build-release.sh) (`npm run release`)
|
||||
- Bundles the output of the above two scripts into a single node module at `./release`.
|
||||
- [./ci/build/clean.sh](./build/clean.sh) (`npm run clean`)
|
||||
- Removes all build artifacts.
|
||||
- Useful to do a clean build.
|
||||
- [./ci/build/code-server.sh](./build/code-server.sh)
|
||||
- Copied into standalone releases to run code-server with the bundled node binary.
|
||||
- [./ci/build/test-standalone-release.sh](./build/test-standalone-release.sh) (`npm run test:standalone-release`)
|
||||
- Ensures code-server in the `./release-standalone` directory works by installing an extension.
|
||||
- [./ci/build/build-packages.sh](./build/build-packages.sh) (`npm run package`)
|
||||
- Packages `./release-standalone` into a `.tar.gz` archive in `./release-packages`.
|
||||
- If on linux, [nfpm](https://github.com/goreleaser/nfpm) is used to generate `.deb` and `.rpm`.
|
||||
- [./ci/build/nfpm.yaml](./build/nfpm.yaml)
|
||||
- Used to configure [nfpm](https://github.com/goreleaser/nfpm) to generate `.deb` and `.rpm`.
|
||||
- [./ci/build/code-server-nfpm.sh](./build/code-server-nfpm.sh)
|
||||
- Entrypoint script for code-server for `.deb` and `.rpm`.
|
||||
- [./ci/build/code-server.service](./build/code-server.service)
|
||||
- systemd user service packaged into the `.deb` and `.rpm`.
|
||||
- [./ci/build/release-github-draft.sh](./build/release-github-draft.sh) (`npm run release:github-draft`)
|
||||
- Uses [gh](https://github.com/cli/cli) to create a draft release with a template description.
|
||||
- [./ci/build/release-github-assets.sh](./build/release-github-assets.sh) (`npm run release:github-assets`)
|
||||
- Downloads the release-package artifacts for the current commit from CI.
|
||||
- Uses [gh](https://github.com/cli/cli) to upload the artifacts to the release
|
||||
specified in `package.json`.
|
||||
- [./ci/build/npm-postinstall.sh](./build/npm-postinstall.sh)
|
||||
- Post install script for the npm package.
|
||||
- Bundled by`npm run release`.
|
||||
|
||||
## release-image
|
||||
|
||||
This directory contains the release docker container image.
|
||||
|
||||
- [./ci/steps/build-docker-buildx-push.sh](./steps/docker-buildx-push.sh)
|
||||
- Builds the release containers with tags `codercom/code-server-$ARCH:$VERSION` for amd64 and arm64 with `docker buildx` and pushes them.
|
||||
- Assumes debian releases are ready in `./release-packages`.
|
||||
|
||||
## images
|
||||
|
||||
This directory contains the images for CI.
|
||||
|
||||
## steps
|
||||
|
||||
This directory contains the scripts used in CI.
|
||||
Helps avoid clobbering the CI configuration.
|
||||
|
||||
- [./steps/fmt.sh](./steps/fmt.sh)
|
||||
- Runs `npm run fmt`.
|
||||
- [./steps/lint.sh](./steps/lint.sh)
|
||||
- Runs `npm run lint`.
|
||||
- [./steps/test-unit.sh](./steps/test-unit.sh)
|
||||
- Runs `npm run test:unit`.
|
||||
- [./steps/test-integration.sh](./steps/test-integration.sh)
|
||||
- Runs `npm run test:integration`.
|
||||
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
|
||||
- Runs `npm run test:e2e`.
|
||||
- [./steps/release.sh](./steps/release.sh)
|
||||
- Runs the release process.
|
||||
- Generates the npm package at `./release`.
|
||||
- [./steps/release-packages.sh](./steps/release-packages.sh)
|
||||
- Takes the output of the previous script and generates a standalone release and
|
||||
release packages into `./release-packages`.
|
||||
- [./steps/publish-npm.sh](./steps/publish-npm.sh)
|
||||
- Grabs the `npm-package` release artifact for the current commit and publishes it on npm.
|
||||
- [./steps/docker-buildx-push.sh](./steps/docker-buildx-push.sh)
|
||||
- Builds the docker image and then pushes it.
|
||||
- [./steps/push-docker-manifest.sh](./steps/push-docker-manifest.sh)
|
||||
- Loads all images in `./release-images` and then builds and pushes a multi architecture
|
||||
docker manifest for the amd64 and arm64 images to `codercom/code-server:$VERSION` and
|
||||
`codercom/code-server:latest`.
|
||||
@@ -1,21 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Given a platform-specific release found in ./release-standalone, generate an
|
||||
# compressed archives and bundles (as appropriate for the platform) named after
|
||||
# the platform's architecture and OS and place them in ./release-packages and
|
||||
# ./release-gcp.
|
||||
# Given a release found in $RELEASE_PATH, generate a deb, rpm, and tarball each
|
||||
# named after $ARCH (derived from uname -m but can be overridden for
|
||||
# cross-compilation) and $OS (derived from uname and cannot be overridden) and
|
||||
# place them in ./release-packages and ./release-gcp.
|
||||
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
source ./ci/lib.sh
|
||||
source ./ci/build/build-lib.sh
|
||||
|
||||
# Allow us to override architecture
|
||||
# we use this for our Linux ARM64 cross compile builds
|
||||
if [ "$#" -eq 1 ] && [ "$1" ]; then
|
||||
ARCH=$1
|
||||
fi
|
||||
VERSION=$(jq -r .version "$RELEASE_PATH/package.json")
|
||||
export VERSION # for nfpm to use
|
||||
|
||||
mkdir -p release-packages
|
||||
|
||||
@@ -28,10 +25,10 @@ main() {
|
||||
|
||||
release_archive() {
|
||||
local release_name="code-server-$VERSION-$OS-$ARCH"
|
||||
if [[ $OS == "linux" ]]; then
|
||||
tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^\.\/release-standalone/$release_name/" ./release-standalone
|
||||
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"
|
||||
else
|
||||
tar -czf "release-packages/$release_name.tar.gz" -s "/^release-standalone/$release_name/" release-standalone
|
||||
tar -czf "release-packages/$release_name.tar.gz" -s "/^$RELEASE_PATH/$release_name/" "$RELEASE_PATH"
|
||||
fi
|
||||
|
||||
echo "done (release-packages/$release_name)"
|
||||
@@ -52,15 +49,13 @@ release_nfpm() {
|
||||
|
||||
export NFPM_ARCH
|
||||
|
||||
PKG_FORMAT="deb"
|
||||
NFPM_ARCH="$(get_nfpm_arch $PKG_FORMAT "$ARCH")"
|
||||
NFPM_ARCH="$(get_nfpm_arch deb "$ARCH")"
|
||||
nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
|
||||
echo "Building deb"
|
||||
echo "$nfpm_config" | head --lines=4
|
||||
nfpm pkg -f <(echo "$nfpm_config") --target "release-packages/code-server_${VERSION}_${NFPM_ARCH}.deb"
|
||||
|
||||
PKG_FORMAT="rpm"
|
||||
NFPM_ARCH="$(get_nfpm_arch $PKG_FORMAT "$ARCH")"
|
||||
NFPM_ARCH="$(get_nfpm_arch rpm "$ARCH")"
|
||||
nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
|
||||
echo "Building rpm"
|
||||
echo "$nfpm_config" | head --lines=4
|
||||
|
||||
@@ -4,13 +4,16 @@ set -euo pipefail
|
||||
# Once both code-server and VS Code have been built, use this script to copy
|
||||
# them into a single directory (./release), prepare the package.json and
|
||||
# product.json, and add shrinkwraps. This results in a generic NPM package that
|
||||
# we published to NPM and also use to compile platform-specific packages.
|
||||
# we can publish to NPM.
|
||||
|
||||
# MINIFY controls whether minified VS Code is bundled. It must match the value
|
||||
# used when VS Code was built.
|
||||
MINIFY="${MINIFY-true}"
|
||||
|
||||
# node_modules are not copied by default. Set KEEP_MODULES=1 to copy them.
|
||||
# Note these modules will be for the platform that built them, making the result
|
||||
# no longer generic (it can still be published though as the modules will be
|
||||
# ignored when pushing).
|
||||
KEEP_MODULES="${KEEP_MODULES-0}"
|
||||
|
||||
main() {
|
||||
@@ -31,6 +34,28 @@ main() {
|
||||
rsync ./docs/README.md "$RELEASE_PATH"
|
||||
rsync LICENSE "$RELEASE_PATH"
|
||||
rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
|
||||
|
||||
if [ "$KEEP_MODULES" = 1 ]; then
|
||||
# Copy the code-server launcher.
|
||||
mkdir -p "$RELEASE_PATH/bin"
|
||||
rsync ./ci/build/code-server.sh "$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.
|
||||
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/helpers/browser-darwin.sh"
|
||||
rm "$RELEASE_PATH/lib/vscode/bin/helpers/browser-linux.sh"
|
||||
if [ "$OS" != windows ] ; then
|
||||
rm "$RELEASE_PATH/lib/vscode/bin/remote-cli/code.cmd"
|
||||
rm "$RELEASE_PATH/lib/vscode/bin/helpers/browser.cmd"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
bundle_code_server() {
|
||||
@@ -48,6 +73,7 @@ bundle_code_server() {
|
||||
jq --slurp '(.[0] | del(.scripts,.jest,.devDependencies)) * .[1]' package.json <(
|
||||
cat << EOF
|
||||
{
|
||||
"version": "$(jq -r .codeServerVersion "./lib/vscode-reh-web-$VSCODE_TARGET/product.json")",
|
||||
"commit": "$(git rev-parse HEAD)",
|
||||
"scripts": {
|
||||
"postinstall": "sh ./postinstall.sh"
|
||||
@@ -57,17 +83,29 @@ EOF
|
||||
) > "$RELEASE_PATH/package.json"
|
||||
mv npm-shrinkwrap.json "$RELEASE_PATH"
|
||||
|
||||
rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"
|
||||
|
||||
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.
|
||||
pushd "$RELEASE_PATH"
|
||||
npm prune --production
|
||||
popd
|
||||
fi
|
||||
|
||||
rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"
|
||||
}
|
||||
|
||||
bundle_vscode() {
|
||||
mkdir -p "$VSCODE_OUT_PATH"
|
||||
|
||||
local rsync_opts=()
|
||||
local rsync_opts=(-a)
|
||||
if [[ ${DEBUG-} = 1 ]]; then
|
||||
rsync_opts+=(-vh)
|
||||
fi
|
||||
@@ -76,20 +114,33 @@ bundle_vscode() {
|
||||
# npm package so exclude any .gitignore files.
|
||||
rsync_opts+=(--exclude .gitignore)
|
||||
|
||||
# Exclude Node as we will add it ourselves for the standalone and will not
|
||||
# need it for the npm package.
|
||||
# Exclude Node since we want to place it in a directory above.
|
||||
rsync_opts+=(--exclude /node)
|
||||
rsync_opts+=(--exclude /node.exe)
|
||||
|
||||
# Exclude Node modules.
|
||||
# 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
|
||||
# post-processing to remove dev dependencies.
|
||||
if [[ $KEEP_MODULES = 0 ]]; then
|
||||
rsync_opts+=(--exclude node_modules)
|
||||
fi
|
||||
|
||||
rsync "${rsync_opts[@]}" ./lib/vscode-reh-web-*/ "$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
|
||||
# dependencies, since we want to ship this via NPM.
|
||||
jq --slurp '.[0] * .[1]' \
|
||||
# Also override the name to prevent vulnerability scanners from
|
||||
# misidentifying this package as VS Code (see #7071).
|
||||
jq --slurp '.[0] * .[1] | .name = "code-oss"' \
|
||||
"$VSCODE_SRC_PATH/remote/package.json" \
|
||||
"$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
|
||||
mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Once we have an NPM package, use this script to copy it to a separate
|
||||
# directory (./release-standalone) and install the dependencies. This new
|
||||
# directory can then be packaged as a platform-specific release.
|
||||
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
rsync "$RELEASE_PATH/" "$RELEASE_PATH-standalone"
|
||||
RELEASE_PATH+=-standalone
|
||||
|
||||
# Package managers may shim their own "node" wrapper into the PATH, so run
|
||||
# node and ask it for its true path.
|
||||
local node_path
|
||||
node_path="$(node -p process.execPath)"
|
||||
|
||||
mkdir -p "$RELEASE_PATH/bin"
|
||||
mkdir -p "$RELEASE_PATH/lib"
|
||||
rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
|
||||
rsync "$node_path" "$RELEASE_PATH/lib/node"
|
||||
|
||||
chmod 755 "$RELEASE_PATH/lib/node"
|
||||
|
||||
pushd "$RELEASE_PATH"
|
||||
npm install --unsafe-perm --omit=dev
|
||||
# Code deletes some files from the extension node_modules directory which
|
||||
# leaves broken symlinks in the corresponding .bin directory. nfpm will fail
|
||||
# on these broken symlinks so clean them up.
|
||||
rm -fr "./lib/vscode/extensions/node_modules/.bin"
|
||||
popd
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -6,33 +6,33 @@ set -euo pipefail
|
||||
# MINIFY controls whether a minified version of vscode is built.
|
||||
MINIFY=${MINIFY-true}
|
||||
|
||||
delete-bin-script() {
|
||||
rm -f "lib/vscode-reh-web-linux-x64/bin/$1"
|
||||
}
|
||||
|
||||
copy-bin-script() {
|
||||
local script="$1"
|
||||
local dest="lib/vscode-reh-web-linux-x64/bin/$script"
|
||||
cp "lib/vscode/resources/server/bin/$script" "$dest"
|
||||
sed -i.bak "s/@@VERSION@@/$(vscode_version)/g" "$dest"
|
||||
sed -i.bak "s/@@COMMIT@@/$BUILD_SOURCEVERSION/g" "$dest"
|
||||
sed -i.bak "s/@@APPNAME@@/code-server/g" "$dest"
|
||||
fix-bin-script() {
|
||||
local script="lib/vscode-reh-web-$VSCODE_TARGET/bin/$1"
|
||||
sed -i.bak "s/@@VERSION@@/$(vscode_version)/g" "$script"
|
||||
sed -i.bak "s/@@COMMIT@@/$BUILD_SOURCEVERSION/g" "$script"
|
||||
sed -i.bak "s/@@APPNAME@@/code-server/g" "$script"
|
||||
|
||||
# Fix Node path on Darwin and Linux.
|
||||
# We do not want expansion here; this text should make it to the file as-is.
|
||||
# shellcheck disable=SC2016
|
||||
sed -i.bak 's/^ROOT=\(.*\)$/VSROOT=\1\nROOT="$(dirname "$(dirname "$VSROOT")")"/g' "$dest"
|
||||
sed -i.bak 's/ROOT\/out/VSROOT\/out/g' "$dest"
|
||||
sed -i.bak 's/^ROOT=\(.*\)$/VSROOT=\1\nROOT="$(dirname "$(dirname "$VSROOT")")"/g' "$script"
|
||||
sed -i.bak 's/ROOT\/out/VSROOT\/out/g' "$script"
|
||||
# We do not want expansion here; this text should make it to the file as-is.
|
||||
# shellcheck disable=SC2016
|
||||
sed -i.bak 's/$ROOT\/node/${NODE_EXEC_PATH:-$ROOT\/lib\/node}/g' "$dest"
|
||||
sed -i.bak 's/$ROOT\/node/${NODE_EXEC_PATH:-$ROOT\/lib\/node}/g' "$script"
|
||||
|
||||
# Fix Node path on Windows.
|
||||
sed -i.bak 's/^set ROOT_DIR=\(.*\)$/set ROOT_DIR=%~dp0..\\..\\..\\..\r\nset VSROOT_DIR=\1/g' "$dest"
|
||||
sed -i.bak 's/%ROOT_DIR%\\out/%VSROOT_DIR%\\out/g' "$dest"
|
||||
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%\\node.exe/%ROOT_DIR%\\lib\\node.exe/g' "$script"
|
||||
|
||||
chmod +x "$dest"
|
||||
rm "$dest.bak"
|
||||
chmod +x "$script"
|
||||
rm "$script.bak"
|
||||
}
|
||||
|
||||
copy-bin-script() {
|
||||
cp "lib/vscode/resources/server/bin/$1" "lib/vscode-reh-web-$VSCODE_TARGET/bin/$1"
|
||||
fix-bin-script "$1"
|
||||
}
|
||||
|
||||
main() {
|
||||
@@ -108,13 +108,11 @@ main() {
|
||||
EOF
|
||||
) > product.json
|
||||
|
||||
# Any platform here works since we will do our own packaging. We have to do
|
||||
# this because we have an NPM package that could be installed on any platform.
|
||||
# The correct platform dependencies and scripts will be installed as part of
|
||||
# the post-install during `npm install` or when building a standalone release.
|
||||
node --max-old-space-size=16384 --optimize-for-size \
|
||||
./node_modules/gulp/bin/gulp.js \
|
||||
"vscode-reh-web-linux-x64${MINIFY:+-min}"
|
||||
|
||||
VSCODE_QUALITY=stable npm run gulp compile-copilot-extension-full-build
|
||||
|
||||
npm run gulp core-ci
|
||||
npm run gulp "vscode-reh-web-$VSCODE_TARGET${MINIFY:+-min}-ci"
|
||||
|
||||
# Reset so if you develop after building you will not be stuck with the wrong
|
||||
# commit (the dev client will use `oss-dev` but the dev server will still use
|
||||
@@ -123,7 +121,7 @@ EOF
|
||||
|
||||
popd
|
||||
|
||||
pushd lib/vscode-reh-web-linux-x64
|
||||
pushd "lib/vscode-reh-web-$VSCODE_TARGET"
|
||||
# Make sure Code took the version we set in the environment variable. Not
|
||||
# having a version will break display languages.
|
||||
if ! jq -e .commit product.json; then
|
||||
@@ -132,15 +130,28 @@ EOF
|
||||
fi
|
||||
popd
|
||||
|
||||
# Set vars and fix paths.
|
||||
case $OS in
|
||||
windows)
|
||||
fix-bin-script remote-cli/code-server.cmd
|
||||
fix-bin-script helpers/browser.cmd
|
||||
;;
|
||||
*)
|
||||
fix-bin-script remote-cli/code-server
|
||||
fix-bin-script helpers/browser.sh
|
||||
;;
|
||||
esac
|
||||
|
||||
# Include bin scripts for other platforms so we can use the right one in the
|
||||
# NPM post-install.
|
||||
|
||||
# These provide a `code-server` command in the integrated terminal to open
|
||||
# files in the current instance.
|
||||
delete-bin-script remote-cli/code-server
|
||||
copy-bin-script remote-cli/code-darwin.sh
|
||||
copy-bin-script remote-cli/code-linux.sh
|
||||
copy-bin-script remote-cli/code.cmd
|
||||
|
||||
# These provide a way for terminal applications to open browser windows.
|
||||
delete-bin-script helpers/browser.sh
|
||||
copy-bin-script helpers/browser-darwin.sh
|
||||
copy-bin-script helpers/browser-linux.sh
|
||||
copy-bin-script helpers/browser.cmd
|
||||
|
||||
8
ci/build/code-server.cmd
Normal file
8
ci/build/code-server.cmd
Normal file
@@ -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%" %*
|
||||
@@ -21,5 +21,5 @@ contents:
|
||||
- src: ./ci/build/code-server-user.service
|
||||
dst: /usr/lib/systemd/user/code-server.service
|
||||
|
||||
- src: ./release-standalone/*
|
||||
- src: ./release/*
|
||||
dst: /usr/lib/code-server
|
||||
|
||||
@@ -18,22 +18,11 @@ symlink() {
|
||||
dest="$2"
|
||||
rm -rf "$dest"
|
||||
case $OS in
|
||||
windows) mklink /J "$dest" "$source" ;;
|
||||
windows) cmd //c mklink //J "$dest" "$source" ;;
|
||||
*) ln -s "$source" "$dest" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# VS Code bundles some modules into an asar which is an archive format that
|
||||
# works like tar. It then seems to get unpacked into node_modules.asar.
|
||||
#
|
||||
# I don't know why they do this but all the dependencies they bundle already
|
||||
# exist in node_modules so just symlink it. We have to do this since not only
|
||||
# Code itself but also extensions will look specifically in this directory for
|
||||
# files (like the ripgrep binary or the oniguruma wasm).
|
||||
symlink_asar() {
|
||||
symlink node_modules node_modules.asar
|
||||
}
|
||||
|
||||
# Make a symlink at bin/$1/$3 pointing to the platform-specific version of the
|
||||
# script in $2. The extension of the link will be .cmd for Windows otherwise it
|
||||
# will be whatever is in $4 (or no extension if $4 is not set).
|
||||
@@ -76,9 +65,9 @@ main() {
|
||||
echo "USE AT YOUR OWN RISK!"
|
||||
fi
|
||||
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then
|
||||
echo "ERROR: code-server currently requires node v22."
|
||||
if [ -n "$FORCE_NODE_VERSION" ]; then
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-24}" ]; then
|
||||
echo "ERROR: code-server currently requires node v24."
|
||||
if [ -n "${FORCE_NODE_VERSION:-}" ]; then
|
||||
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
||||
fi
|
||||
echo "We have detected that you are on node v$major_node_version"
|
||||
@@ -87,20 +76,6 @@ main() {
|
||||
exit 1
|
||||
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
|
||||
echo "You may not have the required dependencies to build the native modules."
|
||||
@@ -121,7 +96,7 @@ install_with_yarn_or_npm() {
|
||||
# end-user we want to keep using whatever package manager is in use.
|
||||
case "${npm_config_user_agent-}" in
|
||||
npm*)
|
||||
if ! npm install --unsafe-perm --omit=dev; then
|
||||
if ! npm install --omit=dev; then
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
@@ -145,7 +120,6 @@ vscode_install() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
symlink_asar
|
||||
symlink_bin_script remote-cli code code-server
|
||||
symlink_bin_script helpers browser browser .sh
|
||||
|
||||
|
||||
96
ci/build/update-repo.sh
Executable file
96
ci/build/update-repo.sh
Executable file
@@ -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 "$@"
|
||||
162
ci/build/update-vscode.sh
Executable file
162
ci/build/update-vscode.sh
Executable file
@@ -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 "$@"
|
||||
@@ -2,13 +2,13 @@
|
||||
set -euo pipefail
|
||||
|
||||
help() {
|
||||
echo >&2 " You can build the standalone release with 'npm run release:standalone'"
|
||||
echo >&2 " You can build the release with 'KEEP_MODULES=1 npm run release'"
|
||||
echo >&2 " Or you can pass in a custom path."
|
||||
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
|
||||
}
|
||||
|
||||
# Make sure a code-server release works. You can pass in the path otherwise it
|
||||
# will look for release-standalone in the current directory.
|
||||
# will look for $RELEASE_PATH in the current directory.
|
||||
#
|
||||
# This is to make sure we don't have Node version errors or any other
|
||||
# compilation-related errors.
|
||||
@@ -17,7 +17,7 @@ main() {
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
local path="$RELEASE_PATH-standalone/bin/code-server"
|
||||
local path="$RELEASE_PATH/bin/code-server"
|
||||
if [[ ! ${CODE_SERVER_PATH-} ]]; then
|
||||
echo "Set CODE_SERVER_PATH to test another build of code-server"
|
||||
else
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
set -euo pipefail
|
||||
|
||||
help() {
|
||||
echo >&2 " You can build the standalone release with 'npm run release:standalone'"
|
||||
echo >&2 " You can build the release with 'KEEP_MODULES=1 npm run release'"
|
||||
echo >&2 " Or you can pass in a custom path."
|
||||
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
|
||||
}
|
||||
|
||||
# Make sure a code-server release works. You can pass in the path otherwise it
|
||||
# will look for release-standalone in the current directory.
|
||||
# will look for $RELEASE_PATH in the current directory.
|
||||
#
|
||||
# This is to make sure we don't have Node version errors or any other
|
||||
# compilation-related errors.
|
||||
@@ -17,7 +17,7 @@ main() {
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
local path="$RELEASE_PATH-standalone/bin/code-server"
|
||||
local path="$RELEASE_PATH/bin/code-server"
|
||||
if [[ ! ${CODE_SERVER_PATH-} ]]; then
|
||||
echo "Set CODE_SERVER_PATH to test another build of code-server"
|
||||
else
|
||||
|
||||
@@ -15,9 +15,9 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 3.32.0
|
||||
version: 3.55.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 4.108.0
|
||||
appVersion: 4.140.0
|
||||
|
||||
@@ -8,7 +8,9 @@ metadata:
|
||||
annotations: {{- toYaml .Values.annotations | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
replicas: {{ .Values.replicaCount | default 1 }}
|
||||
{{- if ne .Values.replicaCount nil }}
|
||||
replicas: {{ .Values.replicaCount }}
|
||||
{{- end }}
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
@@ -123,14 +125,18 @@ spec:
|
||||
containerPort: {{ .port }}
|
||||
protocol: {{ .protocol }}
|
||||
{{- end }}
|
||||
{{- if ne .Values.livenessProbe.enabled false }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
{{- end }}
|
||||
{{- if ne .Values.readinessProbe.enabled false }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
{{- end }}
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
|
||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: codercom/code-server
|
||||
tag: '4.108.0'
|
||||
tag: '4.140.0'
|
||||
pullPolicy: Always
|
||||
|
||||
# Specifies one or more secrets to be used when pulling images from a
|
||||
@@ -34,6 +34,10 @@ serviceAccount:
|
||||
# Specifies annotations for deployment
|
||||
annotations: {}
|
||||
|
||||
# code-server.labels -- The Deployment labels. See:
|
||||
# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
labels: {}
|
||||
|
||||
podAnnotations: {}
|
||||
|
||||
podSecurityContext: {}
|
||||
@@ -111,6 +115,12 @@ resources: {}
|
||||
# cpu: 100m
|
||||
# memory: 1000Mi
|
||||
|
||||
livenessProbe:
|
||||
enabled: true
|
||||
|
||||
readinessProbe:
|
||||
enabled: true
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
83
ci/lib.sh
83
ci/lib.sh
@@ -44,11 +44,84 @@ rsync() {
|
||||
command rsync -a --del "$@"
|
||||
}
|
||||
|
||||
ARCH="$(arch)"
|
||||
export ARCH
|
||||
OS=$(os)
|
||||
export OS
|
||||
if [[ ! ${ARCH-} ]]; then
|
||||
ARCH=$(arch)
|
||||
export ARCH
|
||||
fi
|
||||
|
||||
# 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)
|
||||
export OS
|
||||
fi
|
||||
|
||||
# RELEASE_PATH is the destination directory for the release from the root.
|
||||
# Defaults to release
|
||||
RELEASE_PATH="${RELEASE_PATH-release}"
|
||||
if [[ ! ${RELEASE_PATH-} ]]; then
|
||||
RELEASE_PATH="release"
|
||||
export RELEASE_PATH
|
||||
fi
|
||||
|
||||
nodeOS() {
|
||||
osname=$OS
|
||||
case $osname in
|
||||
macos) osname=darwin ;;
|
||||
windows) osname=win32 ;;
|
||||
esac
|
||||
echo "$osname"
|
||||
}
|
||||
|
||||
nodeArch() {
|
||||
cpu=$ARCH
|
||||
case $cpu in
|
||||
amd64) cpu=x64 ;;
|
||||
esac
|
||||
echo "$cpu"
|
||||
}
|
||||
|
||||
run-steps() {
|
||||
local -i failed=0
|
||||
mkdir -p .cache
|
||||
rm -f .cache/checklist
|
||||
while (( $# )) ; do
|
||||
local name=$1 ; shift
|
||||
local fn=$1 ; shift
|
||||
echo "$name..."
|
||||
# Only run if an earlier step has not failed.
|
||||
# For all failed steps, write out an empty checkbox.
|
||||
if [[ $failed == 0 ]] ; then
|
||||
if $fn | indent ; then
|
||||
echo "- [X] $name" >> .cache/checklist
|
||||
else
|
||||
((failed++))
|
||||
echo "- [ ] $name" >> .cache/checklist
|
||||
echo "Failed" | indent
|
||||
fi
|
||||
else
|
||||
echo "- [ ] $name" >> .cache/checklist
|
||||
echo "Skipped" | indent
|
||||
fi
|
||||
done
|
||||
if [[ $failed != 0 ]] ; then
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
quiet() {
|
||||
"$@" >/dev/null
|
||||
}
|
||||
|
||||
indent() {
|
||||
local count=2
|
||||
local space
|
||||
space=$(printf "%${count}s")
|
||||
sed "s/^/$space| /g"
|
||||
}
|
||||
|
||||
# See gulpfile.reh.ts for available targets.
|
||||
if [[ ! ${VSCODE_TARGET-} ]]; then
|
||||
VSCODE_TARGET="$(nodeOS)-$(nodeArch)"
|
||||
export VSCODE_TARGET
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:experimental
|
||||
|
||||
ARG BASE=debian:12
|
||||
ARG BASE=debian:13
|
||||
FROM scratch AS packages
|
||||
COPY release-packages/code-server*.deb /tmp/
|
||||
|
||||
|
||||
@@ -16,9 +16,11 @@ variable "GITHUB_REGISTRY" {
|
||||
|
||||
group "default" {
|
||||
targets = [
|
||||
"code-server-debian-13",
|
||||
"code-server-debian-12",
|
||||
"code-server-ubuntu-focal",
|
||||
"code-server-ubuntu-noble",
|
||||
"code-server-ubuntu-resolute",
|
||||
"code-server-fedora-39",
|
||||
"code-server-opensuse-tumbleweed",
|
||||
]
|
||||
@@ -48,20 +50,30 @@ function "gen_tags_for_docker_and_ghcr" {
|
||||
)
|
||||
}
|
||||
|
||||
target "code-server-debian-12" {
|
||||
target "code-server-debian-13" {
|
||||
dockerfile = "ci/release-image/Dockerfile"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr(""),
|
||||
gen_tags_for_docker_and_ghcr("debian"),
|
||||
gen_tags_for_docker_and_ghcr("trixie"),
|
||||
)
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
target "code-server-debian-12" {
|
||||
dockerfile = "ci/release-image/Dockerfile"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr("bookworm"),
|
||||
)
|
||||
args = {
|
||||
BASE = "debian:12"
|
||||
}
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
target "code-server-ubuntu-focal" {
|
||||
dockerfile = "ci/release-image/Dockerfile"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr("ubuntu"),
|
||||
gen_tags_for_docker_and_ghcr("focal"),
|
||||
)
|
||||
args = {
|
||||
@@ -74,6 +86,7 @@ target "code-server-ubuntu-noble" {
|
||||
dockerfile = "ci/release-image/Dockerfile"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr("noble"),
|
||||
gen_tags_for_docker_and_ghcr("ubuntu"),
|
||||
)
|
||||
args = {
|
||||
BASE = "ubuntu:noble"
|
||||
@@ -81,6 +94,17 @@ target "code-server-ubuntu-noble" {
|
||||
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" {
|
||||
dockerfile = "ci/release-image/Dockerfile.fedora"
|
||||
tags = concat(
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
main() {
|
||||
# Only sourcing this so we get access to $VERSION
|
||||
source ./ci/lib.sh
|
||||
source ./ci/steps/steps-lib.sh
|
||||
|
||||
echo "Checking environment variables"
|
||||
|
||||
# We need VERSION to bump the brew formula
|
||||
if ! is_env_var_set "VERSION"; then
|
||||
echo "VERSION is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We need HOMEBREW_GITHUB_API_TOKEN to push up commits
|
||||
if ! is_env_var_set "HOMEBREW_GITHUB_API_TOKEN"; then
|
||||
echo "HOMEBREW_GITHUB_API_TOKEN is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find the docs for bump-formula-pr here
|
||||
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
|
||||
local output
|
||||
if ! output=$(brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit --message="PR opened by @${GITHUB_ACTOR}" 2>&1); then
|
||||
if [[ $output == *"Duplicate PRs should not be opened"* ]]; then
|
||||
echo "$VERSION is already submitted"
|
||||
exit 0
|
||||
else
|
||||
echo "$output"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -1,149 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
source ./ci/lib.sh
|
||||
source ./ci/steps/steps-lib.sh
|
||||
|
||||
## Authentication tokens
|
||||
# Needed to publish on NPM
|
||||
if ! is_env_var_set "NPM_TOKEN"; then
|
||||
echo "NPM_TOKEN is not set. Cannot publish to npm without credentials."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## Publishing Information
|
||||
# All the variables below are used to determine how we should publish
|
||||
# the npm package. We also use this information for bumping the version.
|
||||
# This is because npm won't publish your package unless it's a new version.
|
||||
# i.e. for development, we bump the version to <current version>-<pr number>-<commit sha>
|
||||
# example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
||||
# We use this to grab the PR_NUMBER
|
||||
if ! is_env_var_set "GITHUB_REF"; then
|
||||
echo "GITHUB_REF is not set. Are you running this locally? We rely on values provided by GitHub."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We use this when setting NPM_VERSION
|
||||
if ! is_env_var_set "GITHUB_SHA"; then
|
||||
echo "GITHUB_SHA is not set. Are you running this locally? We rely on values provided by GitHub."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We use this to determine the NPM_ENVIRONMENT
|
||||
if ! is_env_var_set "GITHUB_EVENT_NAME"; then
|
||||
echo "GITHUB_EVENT_NAME is not set. Are you running this locally? We rely on values provided by GitHub."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check that we're using at least v7 of npm CLI
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "Couldn't find jq"
|
||||
echo "We need this in order to modify the package.json for dev builds."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# This allows us to publish to npm in CI workflows
|
||||
if [[ ${CI-} ]]; then
|
||||
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||
fi
|
||||
|
||||
## Environment
|
||||
# This string is used to determine how we should tag the npm release.
|
||||
# Environment can be one of three choices:
|
||||
# "development" - this means we tag with the PR number, allowing
|
||||
# a developer to install this version with `npm install code-server@<pr-number>`
|
||||
# "staging" - this means we tag with `beta`, allowing
|
||||
# a developer to install this version with `npm install code-server@beta`
|
||||
# "production" - this means we tag with `latest` (default), allowing
|
||||
# a developer to install this version with `npm install code-server@latest`
|
||||
if ! is_env_var_set "NPM_ENVIRONMENT"; then
|
||||
echo "NPM_ENVIRONMENT is not set."
|
||||
echo "Determining in script based on GITHUB environment variables."
|
||||
|
||||
if [[ "$GITHUB_EVENT_NAME" == 'push' && "$GITHUB_REF" == 'refs/heads/main' ]]; then
|
||||
NPM_ENVIRONMENT="staging"
|
||||
else
|
||||
NPM_ENVIRONMENT="development"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# NOTE@jsjoeio - this script assumes we have the artifact downloaded on disk
|
||||
# That happens in CI as a step before we run this.
|
||||
# https://github.com/actions/upload-artifact/issues/38
|
||||
tar -xzf release-npm-package/package.tar.gz
|
||||
|
||||
# We use this to set the name of the package in the
|
||||
# package.json
|
||||
PACKAGE_NAME="code-server"
|
||||
|
||||
# NOTES:@jsjoeio
|
||||
# We only need to run npm version for "development" and "staging".
|
||||
# This is because our release:prep script automatically bumps the version
|
||||
# in the package.json and we commit it as part of the release PR.
|
||||
if [[ "$NPM_ENVIRONMENT" == "production" ]]; then
|
||||
NPM_VERSION="$VERSION"
|
||||
# This means the npm version will be published as "stable"
|
||||
# and installed when a user runs `npm install code-server`
|
||||
NPM_TAG="latest"
|
||||
else
|
||||
COMMIT_SHA="$GITHUB_SHA"
|
||||
|
||||
if [[ "$NPM_ENVIRONMENT" == "staging" ]]; then
|
||||
NPM_VERSION="$VERSION-beta-$COMMIT_SHA"
|
||||
# This means the npm version will be tagged with "beta"
|
||||
# and installed when a user runs `npm install code-server@beta`
|
||||
NPM_TAG="beta"
|
||||
PACKAGE_NAME="@coder/code-server-pr"
|
||||
fi
|
||||
|
||||
if [[ "$NPM_ENVIRONMENT" == "development" ]]; then
|
||||
# Source: https://github.com/actions/checkout/issues/58#issuecomment-614041550
|
||||
PR_NUMBER=$(echo "$GITHUB_REF" | awk 'BEGIN { FS = "/" } ; { print $3 }')
|
||||
NPM_VERSION="$VERSION-$PR_NUMBER-$COMMIT_SHA"
|
||||
PACKAGE_NAME="@coder/code-server-pr"
|
||||
# This means the npm version will be tagged with "<pr number>"
|
||||
# and installed when a user runs `npm install code-server@<pr number>`
|
||||
NPM_TAG="$PR_NUMBER"
|
||||
fi
|
||||
|
||||
echo "- tag: $NPM_TAG"
|
||||
echo "- version: $NPM_VERSION"
|
||||
echo "- package name: $PACKAGE_NAME"
|
||||
echo "- npm environment: $NPM_ENVIRONMENT"
|
||||
|
||||
# We modify the version in the package.json
|
||||
# to be the current version + the PR number + commit SHA
|
||||
# or we use current version + beta + commit SHA
|
||||
# Example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
||||
# Example: "version": "4.0.1-beta-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
||||
pushd release
|
||||
npm version "$NPM_VERSION"
|
||||
# Use the development package name
|
||||
# This is so we don't clutter the code-server versions on npm
|
||||
# with development versions.
|
||||
# jq can't edit in place so we must store in memory and echo
|
||||
local contents
|
||||
contents="$(jq ".name |= \"$PACKAGE_NAME\"" package.json)"
|
||||
echo "${contents}" > package.json
|
||||
popd
|
||||
fi
|
||||
|
||||
# We need to make sure we haven't already published the version.
|
||||
# If we get error, continue with script because we want to publish
|
||||
# If version is valid, we check if we're publishing the same one
|
||||
local hasVersion
|
||||
if hasVersion=$(npm view "$PACKAGE_NAME@$NPM_VERSION" version 2> /dev/null) && [[ $hasVersion == "$NPM_VERSION" ]]; then
|
||||
echo "$NPM_VERSION is already published under $PACKAGE_NAME"
|
||||
return
|
||||
fi
|
||||
|
||||
# Since the dev builds are scoped to @coder
|
||||
# We pass --access public to ensure npm knows it's not private.
|
||||
cd release
|
||||
npm publish --tag "$NPM_TAG" --access public
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -9,7 +9,6 @@
|
||||
- [Version updates to Code](#version-updates-to-code)
|
||||
- [Patching Code](#patching-code)
|
||||
- [Build](#build)
|
||||
- [Creating a Standalone Release](#creating-a-standalone-release)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [I see "Forbidden access" when I load code-server in the browser](#i-see-forbidden-access-when-i-load-code-server-in-the-browser)
|
||||
- ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
|
||||
@@ -32,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).
|
||||
Here is what is needed:
|
||||
|
||||
- `node` v22.x
|
||||
- `node` v24.x
|
||||
- `git` v2.x or greater
|
||||
- [`git-lfs`](https://git-lfs.github.com)
|
||||
- [`npm`](https://www.npmjs.com/)
|
||||
@@ -94,17 +93,20 @@ commits first if you are doing this).
|
||||
|
||||
### Version updates to Code
|
||||
|
||||
1. Remove any patches with `quilt pop -a`.
|
||||
2. Update the `lib/vscode` submodule to the desired upstream version branch.
|
||||
1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
|
||||
2. `git add lib && git commit -m "chore: update to Code <version>"`
|
||||
3. Apply the patches one at a time (`quilt push`). If the application succeeds
|
||||
but the lines changed, update the patch with `quilt refresh`. If there are
|
||||
conflicts, then force apply with `quilt push -f`, manually add back the
|
||||
rejected code, then run `quilt refresh`.
|
||||
4. From the code-server **project root**, run `npm install`.
|
||||
5. Check the Node.js version that's used by Electron (which is shipped with VS
|
||||
Code. If necessary, update our version of Node.js to match.
|
||||
PRs will be automatically created with updates to VS Code. If a patch cannot be
|
||||
automatically resolved, it will be necessary to clone the branch, resolve the
|
||||
conflicts manually, and finish the update. To do this:
|
||||
|
||||
1. Apply as many patches as possible `quilt push -a`.
|
||||
2. Once you hit a conflict, force apply with `quilt push -f`, manually add back
|
||||
the rejected code, then run `quilt refresh`.
|
||||
3. Once all patches have been resolved, run `./ci/build/update.sh` to finish the
|
||||
update process.
|
||||
4. Commit all changes, push them up to the branch, and update the checklist in
|
||||
the PR description.
|
||||
|
||||
Once the PR is ready, manually verify that the unreleased changelog section
|
||||
contains all the changes going into this version before merging.
|
||||
|
||||
### Patching Code
|
||||
|
||||
@@ -122,7 +124,7 @@ commits first if you are doing this).
|
||||
|
||||
### Build
|
||||
|
||||
You can build a full production as follows:
|
||||
You can build a full production release as follows:
|
||||
|
||||
```shell
|
||||
git submodule update --init
|
||||
@@ -130,26 +132,32 @@ quilt push -a
|
||||
npm install
|
||||
npm run build
|
||||
VERSION=0.0.0 npm run build:vscode
|
||||
npm run release
|
||||
KEEP_MODULES=1 npm run release
|
||||
```
|
||||
|
||||
This does not keep `node_modules`. If you want them to be kept, use
|
||||
`KEEP_MODULES=1 npm run release`
|
||||
You can omit `KEEP_MODULES` if you intend to use this in a platform-agnostic way
|
||||
(like for publishing to NPM), but since the VS Code build process does
|
||||
post-processing deletion of the modules, it is recommended to keep the modules
|
||||
when possible, since if you install them later you will have more than is
|
||||
required. `KEEP_MODULES` will also bundle Node and the code-server entry script.
|
||||
|
||||
Run your build:
|
||||
|
||||
```shell
|
||||
./release/bin/code-server
|
||||
```
|
||||
|
||||
Or if you omitted `KEEP_MODULES`:
|
||||
|
||||
```shell
|
||||
cd release
|
||||
npm install --omit=dev # Skip if you used KEEP_MODULES=1
|
||||
# Runs the built JavaScript with Node.
|
||||
npm install --omit=dev
|
||||
node .
|
||||
```
|
||||
|
||||
Then, to build the release package:
|
||||
Then, to package the release:
|
||||
|
||||
```shell
|
||||
npm run release:standalone
|
||||
npm run test:integration
|
||||
npm run package
|
||||
```
|
||||
|
||||
@@ -158,22 +166,6 @@ npm run package
|
||||
> If you need your builds to support older distros, run the build commands
|
||||
> inside a Docker container with all the build requirements installed.
|
||||
|
||||
#### Creating a Standalone Release
|
||||
|
||||
Part of the build process involves creating standalone releases. At the time of
|
||||
writing, we do this for the following platforms/architectures:
|
||||
|
||||
- Linux amd64 (.tar.gz, .deb, and .rpm)
|
||||
- Linux arm64 (.tar.gz, .deb, and .rpm)
|
||||
- Linux arm7l (.tar.gz)
|
||||
- Linux armhf.deb
|
||||
- Linux armhf.rpm
|
||||
- macOS arm64.tar.gz
|
||||
|
||||
Currently, these are compiled in CI using the `npm run release:standalone`
|
||||
command in the `release.yaml` workflow. We then upload them to the draft release
|
||||
and distribute via GitHub Releases.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### I see "Forbidden access" when I load code-server in the browser
|
||||
|
||||
84
docs/FAQ.md
84
docs/FAQ.md
@@ -17,11 +17,13 @@
|
||||
- [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 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 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)
|
||||
- [What is the healthz endpoint?](#what-is-the-healthz-endpoint)
|
||||
- [What is the heartbeat file?](#what-is-the-heartbeat-file)
|
||||
- [How do I change the reconnection grace time?](#how-do-i-change-the-reconnection-grace-time)
|
||||
- [How do I change the password?](#how-do-i-change-the-password)
|
||||
- [Can I store my password hashed?](#can-i-store-my-password-hashed)
|
||||
- [Is multi-tenancy possible?](#is-multi-tenancy-possible)
|
||||
@@ -39,6 +41,7 @@
|
||||
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
|
||||
- [How do I disable file download?](#how-do-i-disable-file-download)
|
||||
- [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 -->
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -229,6 +232,39 @@ code-server tries the following in this order:
|
||||
3. The workspace or directory passed via the command line
|
||||
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?
|
||||
|
||||
Newer versions of macOS require permission through a non-UNIX mechanism for
|
||||
@@ -326,6 +362,16 @@ If you want to shutdown code-server if there hasn't been an active connection
|
||||
after a predetermined amount of time, you can use the --idle-timeout-seconds flag
|
||||
or set an `CODE_SERVER_IDLE_TIMEOUT_SECONDS` environment variable.
|
||||
|
||||
## How do I change the reconnection grace time?
|
||||
|
||||
Pass `--reconnection-grace-time <seconds>` to `code-server`, set
|
||||
`CODE_SERVER_RECONNECTION_GRACE_TIME=<seconds>`, or add
|
||||
`reconnection-grace-time: <seconds>` to
|
||||
`~/.config/code-server/config.yaml`.
|
||||
|
||||
The default is `10800` (3 hours). If a client stays disconnected longer than
|
||||
this, it must reload the window.
|
||||
|
||||
## How do I change the password?
|
||||
|
||||
Edit the `password` field in the code-server config file at
|
||||
@@ -515,3 +561,41 @@ To fix this, you must either:
|
||||
create and trust a certificate manually).
|
||||
- Disable security if your browser allows it. For example, in Chromium see
|
||||
`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.
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
- [Release Candidates](#release-candidates)
|
||||
- [AUR](#aur)
|
||||
- [Docker](#docker)
|
||||
- [Homebrew](#homebrew)
|
||||
- [nixpkgs](#nixpkgs)
|
||||
- [npm](#npm)
|
||||
- [Testing](#testing)
|
||||
@@ -27,20 +26,18 @@ Most of the work is keeping on top of issues and discussions.
|
||||
|
||||
1. Check that the changelog lists all the important changes.
|
||||
2. Make sure the changelog entry lists the current version of VS Code.
|
||||
3. Update the changelog with the release date.
|
||||
4. Go to GitHub Actions > Draft release > Run workflow on the commit you want to
|
||||
release. Make sure CI has finished the build workflow on that commit or this
|
||||
will fail. For the version we match VS Code's minor and patch version. The
|
||||
3. Go to GitHub Actions > Draft release > Run workflow on the commit you want to
|
||||
release. For the version we match VS Code's minor and patch version. The
|
||||
patch number may become temporarily out of sync if we need to put out a
|
||||
patch, but if we make our own minor change then we will not release it until
|
||||
the next minor VS Code release.
|
||||
5. CI will automatically grab the build artifact on that commit (which is why CI
|
||||
has to have completed), inject the provided version into the `package.json`,
|
||||
put together platform-specific packages, and upload those packages to a draft
|
||||
release.
|
||||
6. Update the resulting draft release with the changelog contents.
|
||||
7. Publish the draft release after validating it.
|
||||
8. Bump the Helm chart version once the Docker images have published.
|
||||
4. CI will build an NPM package and platform-specific packages, and upload those
|
||||
to a draft release.
|
||||
5. Update the resulting draft release with the changelog contents.
|
||||
6. Publish the draft release after validating it.
|
||||
7. Update the changelog with the release date and bump the Helm chart version
|
||||
once the Docker images have published.
|
||||
8. Merge the PR submitted to coder/code-server-aur repo.
|
||||
|
||||
#### Release Candidates
|
||||
|
||||
@@ -55,38 +52,34 @@ full-blown release. To do this follow the same steps as above but:
|
||||
|
||||
#### AUR
|
||||
|
||||
We publish to AUR as a package [here](https://aur.archlinux.org/packages/code-server/). This process is manual and can be done by following the steps in [this repo](https://github.com/coder/code-server-aur).
|
||||
We publish to AUR as a package
|
||||
[here](https://aur.archlinux.org/packages/code-server/). This process is manual
|
||||
and can be done by following the steps in [this
|
||||
repo](https://github.com/coder/code-server-aur).
|
||||
|
||||
#### Docker
|
||||
|
||||
We publish code-server as a Docker image [here](https://hub.docker.com/r/codercom/code-server), tagging it both with the version and latest.
|
||||
We publish code-server as a Docker image
|
||||
[here](https://hub.docker.com/r/codercom/code-server), tagging it both with the
|
||||
version and latest.
|
||||
|
||||
This is currently automated with the release process.
|
||||
|
||||
#### Homebrew
|
||||
|
||||
We publish code-server on Homebrew [here](https://github.com/Homebrew/homebrew-core/blob/master/Formula/code-server.rb).
|
||||
|
||||
This is currently automated with the release process (but may fail occasionally). If it does, run this locally:
|
||||
|
||||
```shell
|
||||
# Replace VERSION with version
|
||||
brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit
|
||||
```
|
||||
|
||||
#### nixpkgs
|
||||
|
||||
We publish code-server in nixpkgs but it must be updated manually.
|
||||
|
||||
#### npm
|
||||
|
||||
We publish code-server as a npm package [here](https://www.npmjs.com/package/code-server/v/latest).
|
||||
We publish code-server as a npm package
|
||||
[here](https://www.npmjs.com/package/code-server/v/latest).
|
||||
|
||||
This is currently automated with the release process.
|
||||
|
||||
## Testing
|
||||
|
||||
Our testing structure is laid out under our [Contributing docs](https://coder.com/docs/code-server/latest/CONTRIBUTING#test).
|
||||
Our testing structure is laid out under our [Contributing
|
||||
docs](https://coder.com/docs/code-server/latest/CONTRIBUTING#test).
|
||||
|
||||
If you're ever looking to add more tests, here are a few ways to get started:
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
```
|
||||
|
||||
6. Exit the terminal using `exit` and then reopen the terminal
|
||||
7. Install and use Node.js 22:
|
||||
7. Install and use Node.js 24:
|
||||
|
||||
```shell
|
||||
nvm install 22
|
||||
nvm use 22
|
||||
nvm install 24
|
||||
nvm use 24
|
||||
```
|
||||
|
||||
8. Install code-server globally on device with: `npm install --global code-server`
|
||||
|
||||
@@ -33,7 +33,7 @@ resource "coder_app" "code-server" {
|
||||
}
|
||||
```
|
||||
|
||||
Or use our official [`code-server`](https://registry.coder.com/modules/code-server) module from the Coder [module registry](htpps://registry.coder.com/modules):
|
||||
Or use our official [`code-server`](https://registry.coder.com/modules/code-server) module from the Coder [module registry](https://registry.coder.com/modules):
|
||||
|
||||
```terraform
|
||||
module "code-server" {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
- [Using Let's Encrypt with NGINX](#using-lets-encrypt-with-nginx)
|
||||
- [Using a self-signed certificate](#using-a-self-signed-certificate)
|
||||
- [TLS 1.3 and Safari](#tls-13-and-safari)
|
||||
- [Cloudflare Rocket Loader](#cloudflare-rocket-loader)
|
||||
- [External authentication](#external-authentication)
|
||||
- [HTTPS and self-signed certificates](#https-and-self-signed-certificates)
|
||||
- [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
|
||||
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
|
||||
|
||||
If you want to use external authentication mechanism (e.g., Sign in with
|
||||
|
||||
22
docs/helm.md
22
docs/helm.md
@@ -1,6 +1,6 @@
|
||||
# code-server Helm Chart
|
||||
|
||||
[](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [](https://img.shields.io/badge/Type-application-informational?style=flat-square) [](https://img.shields.io/badge/AppVersion-4.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
|
||||
on a remote server, accessible through the browser.
|
||||
@@ -62,10 +62,12 @@ and their default values.
|
||||
| Key | Type | Default |
|
||||
| ------------------------------------------- | ------ | ------------------------ |
|
||||
| affinity | object | `{}` |
|
||||
| annotations | object | `{}` |
|
||||
| extraArgs | list | `[]` |
|
||||
| extraConfigmapMounts | list | `[]` |
|
||||
| extraContainers | string | `""` |
|
||||
| extraInitContainers | string | `""` |
|
||||
| extraPorts | list | `[]` |
|
||||
| extraSecretMounts | list | `[]` |
|
||||
| extraVars | list | `[]` |
|
||||
| extraVolumeMounts | list | `[]` |
|
||||
@@ -73,26 +75,32 @@ and their default values.
|
||||
| hostnameOverride | string | `""` |
|
||||
| image.pullPolicy | string | `"Always"` |
|
||||
| image.repository | string | `"codercom/code-server"` |
|
||||
| image.tag | string | `"4.8.0"` |
|
||||
| image.tag | string | `"4.139.1"` |
|
||||
| imagePullSecrets | list | `[]` |
|
||||
| ingress.enabled | bool | `false` |
|
||||
| ingress.ingressClassName | string | `""` |
|
||||
| lifecycle.enabled | bool | `false` |
|
||||
| livenessProbe.enabled | bool | `true` |
|
||||
| nameOverride | string | `""` |
|
||||
| nodeSelector | object | `{}` |
|
||||
| persistence.accessMode | string | `"ReadWriteOnce"` |
|
||||
| persistence.annotations | object | `{}` |
|
||||
| persistence.enabled | bool | `true` |
|
||||
| persistence.size | string | `"1Gi"` |
|
||||
| persistence.size | string | `"10Gi"` |
|
||||
| podAnnotations | object | `{}` |
|
||||
| podSecurityContext | object | `{}` |
|
||||
| priorityClassName | string | `""` |
|
||||
| readinessProbe.enabled | bool | `true` |
|
||||
| replicaCount | int | `1` |
|
||||
| resources | object | `{}` |
|
||||
| securityContext.enabled | bool | `true` |
|
||||
| securityContext.fsGroup | int | `1000` |
|
||||
| securityContext.runAsUser | int | `1000` |
|
||||
| service.port | int | `8443` |
|
||||
| service.port | int | `8080` |
|
||||
| service.type | string | `"ClusterIP"` |
|
||||
| serviceAccount.annotations | object | `{}` |
|
||||
| serviceAccount.create | bool | `true` |
|
||||
| serviceAccount.name | string | `nil` |
|
||||
| serviceAccount.name | string | `""` |
|
||||
| tolerations | list | `[]` |
|
||||
| volumePermissions.enabled | bool | `true` |
|
||||
| volumePermissions.securityContext.runAsUser | int | `0` |
|
||||
@@ -105,7 +113,7 @@ $ helm upgrade --install code-server \
|
||||
--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
|
||||
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
|
||||
```
|
||||
|
||||
> **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
|
||||
|
||||
|
||||
@@ -101,9 +101,8 @@ _exact_ same commands presented in the rest of this document.
|
||||
We recommend installing with `npm` when:
|
||||
|
||||
1. You aren't using a machine with `amd64` or `arm64`.
|
||||
2. You are installing code-server on Windows.
|
||||
3. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
|
||||
4. You're running Alpine Linux or are using a non-glibc libc. See
|
||||
2. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
|
||||
3. You're running Alpine Linux or are using a non-glibc libc. See
|
||||
[#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198)
|
||||
for more information.
|
||||
|
||||
@@ -296,8 +295,7 @@ You can install code-server using the [Helm package manager](https://coder.com/d
|
||||
## Windows
|
||||
|
||||
We currently [do not publish Windows
|
||||
releases](https://github.com/coder/code-server/issues/1397). We recommend
|
||||
installing code-server onto Windows with [`npm`](#npm).
|
||||
releases](https://github.com/coder/code-server/issues/1397).
|
||||
|
||||
## Raspberry Pi
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ includes installing instructions based on your operating system.
|
||||
|
||||
## Node.js version
|
||||
|
||||
We use the same major version of Node.js shipped with Code's remote, which is
|
||||
currently `22.x`. VS Code also [lists Node.js
|
||||
We use Node.js `24.x`. VS Code also [lists Node.js
|
||||
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||
|
||||
Using other versions of Node.js [may lead to unexpected
|
||||
@@ -78,7 +77,7 @@ Proceed to [installing](#installing)
|
||||
## FreeBSD
|
||||
|
||||
```sh
|
||||
pkg install -y git python npm-node22 pkgconf
|
||||
pkg install -y git python npm-node24 pkgconf
|
||||
pkg install -y libinotify
|
||||
```
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ npm config set python python3
|
||||
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)
|
||||
|
||||
|
||||
@@ -436,7 +436,7 @@ install_npm() {
|
||||
fi
|
||||
echoh "Installing with npm."
|
||||
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
|
||||
return
|
||||
fi
|
||||
|
||||
Submodule lib/vscode updated: 585eba7c0c...07f806f999
3920
package-lock.json
generated
3920
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
29
package.json
29
package.json
@@ -14,7 +14,6 @@
|
||||
"build:vscode": "./ci/build/build-vscode.sh",
|
||||
"doctoc": "./ci/dev/doctoc.sh",
|
||||
"release": "./ci/build/build-release.sh",
|
||||
"release:standalone": "./ci/build/build-standalone-release.sh",
|
||||
"release:prep": "./ci/build/release-prep.sh",
|
||||
"test:e2e": "VSCODE_IPC_HOOK_CLI= ./ci/dev/test-e2e.sh",
|
||||
"test:e2e:proxy": "USE_PROXY=1 ./ci/dev/test-e2e.sh",
|
||||
@@ -40,14 +39,13 @@
|
||||
"@eslint/compat": "^1.2.0",
|
||||
"@eslint/eslintrc": "^3.1.0",
|
||||
"@eslint/js": "^9.12.0",
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"@types/compression": "^1.7.3",
|
||||
"@types/cookie-parser": "^1.4.4",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/http-proxy": "1.17.7",
|
||||
"@types/js-yaml": "^4.0.6",
|
||||
"@types/node": "22.x",
|
||||
"@types/node": "24.x",
|
||||
"@types/pem": "^1.14.1",
|
||||
"@types/proxy-from-env": "^1.0.1",
|
||||
"@types/safe-compare": "^1.1.0",
|
||||
@@ -55,33 +53,34 @@
|
||||
"@types/trusted-types": "^2.0.4",
|
||||
"@types/ws": "^8.5.5",
|
||||
"doctoc": "^2.2.1",
|
||||
"eslint": "^9.12.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint": "^10.11.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"globals": "^16.1.0",
|
||||
"prettier": "3.6.2",
|
||||
"prettier-plugin-sh": "^0.14.0",
|
||||
"globals": "^17.6.0",
|
||||
"prettier": "3.9.4",
|
||||
"prettier-plugin-sh": "^0.20.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.6.2",
|
||||
"typescript-eslint": "^8.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "^3.0.1",
|
||||
"argon2": "^0.31.1",
|
||||
"argon2": "^0.44.0",
|
||||
"compression": "^1.7.4",
|
||||
"cookie": "^1.1.1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"env-paths": "^2.2.1",
|
||||
"express": "^5.0.1",
|
||||
"http-proxy": "^1.18.1",
|
||||
"httpolyglot": "^0.1.2",
|
||||
"i18next": "^25.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"limiter": "^2.1.0",
|
||||
"i18next": "^26.3.1",
|
||||
"js-yaml": "^5.2.3",
|
||||
"limiter": "^4.1.0",
|
||||
"pem": "^1.14.8",
|
||||
"proxy-agent": "^6.3.1",
|
||||
"qs": "6.14.0",
|
||||
"qs": "^6.15.0",
|
||||
"rotating-file-stream": "^3.1.1",
|
||||
"safe-compare": "^1.1.4",
|
||||
"semver": "^7.5.4",
|
||||
@@ -89,7 +88,7 @@
|
||||
"xdg-basedir": "^4.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "22.x"
|
||||
"@types/node": "24.x"
|
||||
},
|
||||
"bin": {
|
||||
"code-server": "out/node/entry.js"
|
||||
@@ -104,7 +103,7 @@
|
||||
"remote-development"
|
||||
],
|
||||
"engines": {
|
||||
"node": "22"
|
||||
"node": "24"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
|
||||
46
patches/app-name.diff
Normal file
46
patches/app-name.diff
Normal file
@@ -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,
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
@@ -237,7 +237,9 @@ class RemoteAuthoritiesImpl {
|
||||
@@ -256,7 +256,9 @@ class RemoteAuthoritiesImpl {
|
||||
return URI.from({
|
||||
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
||||
authority: `${host}:${port}`,
|
||||
@@ -36,8 +36,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -27,9 +27,9 @@
|
||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
||||
@@ -29,9 +29,9 @@
|
||||
<meta id="vscode-workbench-css-modules" data-settings="{{WORKBENCH_DEV_CSS_MODULES}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
@@ -49,15 +49,15 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
<style id="vscode-css-modules" type="text/css" media="screen"></style>
|
||||
|
||||
</head>
|
||||
@@ -39,7 +39,7 @@
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<script>
|
||||
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
|
||||
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
|
||||
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||
- const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location.origin).toString();
|
||||
+ const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location).toString();
|
||||
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
|
||||
</script>
|
||||
<script>
|
||||
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||
Index: code-server/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 -->
|
||||
<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}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
@@ -86,15 +86,15 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
<link rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/code/browser/workbench/workbench.css">
|
||||
|
||||
</head>
|
||||
@@ -36,7 +36,7 @@
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<!-- Startup (do not modify order of script tags!) -->
|
||||
<script>
|
||||
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
|
||||
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
|
||||
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||
- const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location.origin).toString();
|
||||
+ const baseUrl = new URL(document.getElementById('vscode-workbench-web-base-url').getAttribute('data-settings'), window.location).toString();
|
||||
globalThis._VSCODE_FILE_ROOT = baseUrl + '/out/';
|
||||
</script>
|
||||
<script>
|
||||
<script nonce="{{WORKBENCH_SCRIPT_NONCE}}">
|
||||
Index: code-server/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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -245,7 +245,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
|
||||
- const basePath = getFirstHeader('x-forwarded-prefix') || this._basePath;
|
||||
+ const rootBase = relativeRoot(getOriginalUrl(req))
|
||||
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
+ const basePath = vscodeBase || getFirstHeader('x-forwarded-prefix') || this._basePath;
|
||||
const 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];
|
||||
if (typeof queryConnectionToken === 'string') {
|
||||
@@ -284,10 +286,14 @@ export class WebClientServer {
|
||||
const queryConnectionTokens = parsedUrl.searchParams.getAll(connectionTokenQueryName);
|
||||
if (queryConnectionTokens.length === 1) {
|
||||
@@ -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
|
||||
+ // needing specific configuration for reverse proxies to work. Set this to
|
||||
+ // 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) {
|
||||
return serveError(req, res, 400, `Bad request.`);
|
||||
@@ -334,6 +340,7 @@ export class WebClientServer {
|
||||
@@ -395,6 +401,7 @@ export class WebClientServer {
|
||||
|
||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
+ rootEndpoint: rootBase,
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -387,7 +394,9 @@ export class WebClientServer {
|
||||
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
|
||||
@@ -446,7 +453,9 @@ export class WebClientServer {
|
||||
WORKBENCH_WEB_BASE_URL: staticRoute,
|
||||
WORKBENCH_NLS_URL,
|
||||
- WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`
|
||||
+ WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`,
|
||||
WORKBENCH_NLS_FALLBACK_URL: `${staticRoute}/out/nls.messages.js`,
|
||||
- WORKBENCH_SCRIPT_NONCE: scriptNonce
|
||||
+ WORKBENCH_SCRIPT_NONCE: scriptNonce,
|
||||
+ BASE: rootBase,
|
||||
+ VS_BASE: basePath,
|
||||
};
|
||||
|
||||
// DEV ---------------------------------------------------------------------------------------
|
||||
@@ -424,7 +433,7 @@ export class WebClientServer {
|
||||
'default-src \'self\';',
|
||||
'img-src \'self\' https: data: blob:;',
|
||||
'media-src \'self\';',
|
||||
- `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+ `script-src 'self' 'unsafe-eval' ${WORKBENCH_NLS_BASE_URL ?? ''} blob: 'nonce-1nline-m4p' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' ${useTestResolver ? '' : ``};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
'child-src \'self\';',
|
||||
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
||||
'worker-src \'self\' data: blob:;',
|
||||
@@ -497,3 +506,70 @@ export class WebClientServer {
|
||||
@@ -542,3 +551,70 @@ export class WebClientServer {
|
||||
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/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 {
|
||||
readonly codeServerVersion?: string
|
||||
@@ -263,7 +264,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
}
|
||||
|
||||
private startListening(): void {
|
||||
@@ -584,17 +585,6 @@ class WorkspaceProvider implements IWork
|
||||
@@ -590,17 +591,6 @@ class WorkspaceProvider implements IWork
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
(function () {
|
||||
|
||||
// Find config by checking for DOM
|
||||
@@ -604,8 +594,8 @@ function readCookie(name: string): strin
|
||||
@@ -610,8 +600,8 @@ function readCookie(name: string): strin
|
||||
if (!configElement || !configElementAttribute) {
|
||||
throw new Error('Missing web configuration element');
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
@@ -107,10 +107,14 @@ class RemoteTerminalBackend extends Base
|
||||
@@ -108,10 +108,14 @@ class RemoteTerminalBackend extends Base
|
||||
}
|
||||
const reqId = e.reqId;
|
||||
const commandId = e.commandId;
|
||||
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands
|
||||
import { CommandsRegistry, ICommandService } from '../../../platform/commands/common/commands.js';
|
||||
import { IExtensionGalleryService, IExtensionManagementService } from '../../../platform/extensionManagement/common/extensionManagement.js';
|
||||
import { ExtensionManagementCLI } from '../../../platform/extensionManagement/common/extensionManagementCLI.js';
|
||||
@@ -95,6 +96,11 @@ CommandsRegistry.registerCommand('_remot
|
||||
@@ -96,6 +97,11 @@ CommandsRegistry.registerCommand('_remot
|
||||
|
||||
});
|
||||
|
||||
@@ -39,8 +39,8 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||
+export type PipeCommand = OpenCommandPipeArgs | StatusPipeArgs | OpenExternalCommandPipeArgs | ExtensionManagementPipeArgs | ClipboardPipeArgs;
|
||||
|
||||
export interface ICommandsExecuter {
|
||||
executeCommand<T>(id: string, ...args: any[]): Promise<T>;
|
||||
@@ -106,6 +111,9 @@ export class CLIServerBase {
|
||||
executeCommand<T>(id: string, ...args: unknown[]): Promise<T>;
|
||||
@@ -110,6 +115,9 @@ export class CLIServerBase {
|
||||
case 'extensionManagement':
|
||||
returnObj = await this.manageExtensions(data);
|
||||
break;
|
||||
@@ -50,7 +50,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||
default:
|
||||
sendResponse(404, `Unknown message type: ${data.type}`);
|
||||
break;
|
||||
@@ -173,6 +181,10 @@ export class CLIServerBase {
|
||||
@@ -180,6 +188,10 @@ export class CLIServerBase {
|
||||
return await this._commands.executeCommand<string | undefined>('_remoteCLI.getSystemStatus');
|
||||
}
|
||||
|
||||
@@ -59,26 +59,26 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||
+ }
|
||||
+
|
||||
dispose(): void {
|
||||
this._server.close();
|
||||
|
||||
this._disposed = true;
|
||||
this._server?.close();
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
@@ -98,7 +98,7 @@ class RemoteTerminalBackend extends Base
|
||||
@@ -99,7 +99,7 @@ class RemoteTerminalBackend extends Base
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
- const allowedCommands = ['_remoteCLI.openExternal', '_remoteCLI.windowOpen', '_remoteCLI.getSystemStatus', '_remoteCLI.manageExtensions'];
|
||||
+ const allowedCommands = ['_remoteCLI.openExternal', '_remoteCLI.windowOpen', '_remoteCLI.getSystemStatus', '_remoteCLI.manageExtensions', '_remoteCLI.setClipboard'];
|
||||
this._remoteTerminalChannel.onExecuteCommand(async e => {
|
||||
this._register(this._remoteTerminalChannel.onExecuteCommand(async e => {
|
||||
// Ensure this request for for this window
|
||||
const pty = this._ptys.get(e.persistentProcessId);
|
||||
Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||
@@ -137,6 +137,7 @@ export interface NativeParsedArgs {
|
||||
@@ -148,6 +148,7 @@ export interface NativeParsedArgs {
|
||||
'disable-chromium-sandbox'?: boolean;
|
||||
sandbox?: 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/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||
@@ -105,6 +105,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.") },
|
||||
'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") },
|
||||
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
||||
@@ -102,7 +102,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
@@ -77,6 +77,7 @@ const isSupportedForPipe = (optionId: ke
|
||||
@@ -78,6 +78,7 @@ const isSupportedForPipe = (optionId: ke
|
||||
case 'verbose':
|
||||
case 'remote':
|
||||
case 'locate-shell-integration-path':
|
||||
@@ -110,7 +110,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -300,6 +301,22 @@ export async function main(desc: Product
|
||||
@@ -307,6 +308,22 @@ export async function main(desc: Product
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
163
patches/copilot.diff
Normal file
163
patches/copilot.diff
Normal file
@@ -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)),
|
||||
26
patches/csp-hashes.diff
Normal file
26
patches/csp-hashes.diff
Normal file
@@ -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/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||
@@ -341,6 +341,10 @@ export class Extension implements IExten
|
||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
||||
@@ -343,6 +343,10 @@ export class Extension implements IExten
|
||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable' && !this.productService.builtInExtensionsEnabledWithAutoUpdates?.some(id => id.toLowerCase() === this.identifier.id.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
+ // 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/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -12,7 +12,7 @@ import * as path from '../../base/common
|
||||
import { IURITransformer } from '../../base/common/uriIpc.js';
|
||||
@@ -13,7 +13,7 @@ import { IURITransformer } from '../../b
|
||||
import { generateUuid } from '../../base/common/uuid.js';
|
||||
import { getMachineId, getSqmMachineId, getDevDeviceId } from '../../base/node/id.js';
|
||||
import { Promises } from '../../base/node/pfs.js';
|
||||
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
|
||||
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from '../../base/parts/ipc/common/ipc.js';
|
||||
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
||||
import { createRandomIPCHandle } from '../../base/parts/ipc/node/ipc.net.js';
|
||||
import { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||
import { ConfigurationService } from '../../platform/configuration/common/configurationService.js';
|
||||
@@ -272,6 +272,9 @@ export async function setupServerService
|
||||
@@ -418,6 +418,9 @@ export async function setupServerService
|
||||
|
||||
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';
|
||||
@@ -33,7 +35,94 @@ export async function getNLSConfiguratio
|
||||
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);
|
||||
+ // 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.
|
||||
@@ -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/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 { IProductConfiguration } from '../../base/common/product.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 { IExtensionManifest } from '../../platform/extensions/common/extensions.js';
|
||||
import { ICSSDevelopmentService } from '../../platform/cssDev/node/cssDevService.js';
|
||||
@@ -385,14 +386,22 @@ export class WebClientServer {
|
||||
@@ -442,14 +443,22 @@ export class WebClientServer {
|
||||
};
|
||||
|
||||
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;
|
||||
if (!locale.startsWith('en') && 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 {
|
||||
- WORKBENCH_NLS_URL = ''; // fallback will apply
|
||||
+ try {
|
||||
@@ -181,16 +181,16 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+ : '';
|
||||
+ } catch (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
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -22,6 +22,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -38,6 +38,7 @@ export const serverOptions: OptionDescri
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
'disable-file-uploads': { 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 ----- */
|
||||
|
||||
@@ -113,6 +114,7 @@ export interface ServerParsedArgs {
|
||||
@@ -136,6 +137,7 @@ export interface ServerParsedArgs {
|
||||
'disable-file-downloads'?: boolean;
|
||||
'disable-file-uploads'?: 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/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||
@@ -474,9 +474,6 @@ export class InstallAction extends Exten
|
||||
@@ -475,9 +475,6 @@ export class InstallAction extends Exten
|
||||
if (this.extension.isBuiltin) {
|
||||
return;
|
||||
}
|
||||
@@ -282,7 +282,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
if (this.extension.state !== ExtensionState.Uninstalled) {
|
||||
return;
|
||||
}
|
||||
@@ -781,7 +778,7 @@ export abstract class InstallInOtherServ
|
||||
@@ -782,7 +779,7 @@ export abstract class InstallInOtherServ
|
||||
}
|
||||
|
||||
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
|
||||
@@ -2072,17 +2069,6 @@ export class SetLanguageAction extends E
|
||||
@@ -2281,17 +2278,6 @@ export class SetLanguageAction extends E
|
||||
update(): void {
|
||||
this.enabled = false;
|
||||
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> {
|
||||
@@ -2099,7 +2085,6 @@ export class ClearLanguageAction extends
|
||||
@@ -2308,7 +2294,6 @@ export class ClearLanguageAction extends
|
||||
private static readonly DisabledClass = `${this.EnabledClass} disabled`;
|
||||
|
||||
constructor(
|
||||
@@ -317,7 +317,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
@ILocaleService private readonly localeService: ILocaleService,
|
||||
) {
|
||||
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
||||
@@ -2109,17 +2094,6 @@ export class ClearLanguageAction extends
|
||||
@@ -2318,17 +2303,6 @@ export class ClearLanguageAction extends
|
||||
update(): void {
|
||||
this.enabled = false;
|
||||
this.class = ClearLanguageAction.DisabledClass;
|
||||
@@ -335,12 +335,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
}
|
||||
|
||||
override async run(): Promise<any> {
|
||||
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
|
||||
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.internal.ts
|
||||
@@ -54,7 +54,7 @@ import './services/dialogs/browser/fileD
|
||||
import './services/host/browser/browserHostService.js';
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
@@ -55,7 +55,7 @@ import './services/host/browser/browserH
|
||||
import '../platform/meteredConnection/browser/meteredConnectionService.js';
|
||||
import './services/lifecycle/browser/lifecycleService.js';
|
||||
import './services/clipboard/browser/clipboardService.js';
|
||||
-import './services/localization/browser/localeService.js';
|
||||
|
||||
@@ -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/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
|
||||
|
||||
@@ -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/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -34,6 +34,16 @@ export interface IBrowserWorkbenchEnviro
|
||||
readonly options?: IWorkbenchConstructionOptions;
|
||||
@@ -39,6 +39,16 @@ export interface IBrowserWorkbenchEnviro
|
||||
readonly sessionTitle?: string;
|
||||
|
||||
/**
|
||||
+ * 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.
|
||||
*/
|
||||
readonly expectsResolverExtension: boolean;
|
||||
@@ -111,6 +121,20 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -116,6 +126,20 @@ export class BrowserWorkbenchEnvironment
|
||||
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/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 ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
@@ -99,7 +99,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -107,6 +109,8 @@ export interface ServerParsedArgs {
|
||||
@@ -130,6 +132,8 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string;
|
||||
@@ -112,7 +112,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -369,6 +369,8 @@ export class WebClientServer {
|
||||
@@ -425,6 +425,8 @@ export class WebClientServer {
|
||||
serverBasePath: basePath,
|
||||
webviewEndpoint: staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
@@ -128,9 +128,9 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@@ -6,10 +6,10 @@
|
||||
import { Disposable } from '../../base/common/lifecycle.js';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext } from '../common/contextkeys.js';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
|
||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext, IsChromeOSContext } from '../../platform/contextkey/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 { 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 { IConfigurationService } from '../../platform/configuration/common/configuration.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 { IWorkbenchLayoutService, Parts, positionToString } from '../services/layout/browser/layoutService.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,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@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,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@@ -199,6 +199,10 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -206,6 +206,10 @@ export class WorkbenchContextKeysHandler
|
||||
this.auxiliaryBarMaximizedContext = AuxiliaryBarMaximizedContext.bindTo(this.contextKeyService);
|
||||
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 { WorkbenchListDoubleSelection } from '../../../../platform/list/browser/listService.js';
|
||||
import { Schemas } from '../../../../base/common/network.js';
|
||||
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
|
||||
+import { IsEnabledFileDownloads, IsEnabledFileUploads, DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, SelectedEditorsInGroupFileOrUntitledResourceContextKey } from '../../../common/contextkeys.js';
|
||||
-import { 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, 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 { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.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,
|
||||
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,
|
||||
},
|
||||
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/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -39,6 +39,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"));
|
||||
|
||||
@@ -230,7 +230,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
|
||||
import { IRemoteAgentService } from '../../remote/common/remoteAgentService.js';
|
||||
import { IContextKeyService, IContextKey, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
|
||||
import { equalsIgnoreCase, format, startsWithIgnoreCase } from '../../../../base/common/strings.js';
|
||||
@@ -144,7 +144,7 @@ export class SimpleFileDialog extends Di
|
||||
@@ -152,7 +152,7 @@ export class SimpleFileDialog extends Di
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@ILanguageService private readonly languageService: ILanguageService,
|
||||
@@ -239,7 +239,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFi
|
||||
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
|
||||
@IPathService protected readonly pathService: IPathService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@@ -311,21 +311,23 @@ export class SimpleFileDialog extends Di
|
||||
@@ -362,21 +362,23 @@ export class SimpleFileDialog extends Di
|
||||
this.filePickBox.placeholder = nls.localize('remoteFileDialog.placeholder', "Folder path");
|
||||
this.filePickBox.ok = true;
|
||||
this.filePickBox.okLabel = typeof this.options.openLabel === 'string' ? this.options.openLabel : this.options.openLabel?.withoutMnemonic;
|
||||
@@ -290,7 +290,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
|
||||
import { WorkbenchCompressibleAsyncDataTree } from '../../../../../platform/list/browser/listService.js';
|
||||
import { ISearchService, QueryType, getExcludes, ISearchConfiguration, ISearchComplete, IFileQuery } from '../../../../services/search/common/search.js';
|
||||
import { CancellationToken } from '../../../../../base/common/cancellation.js';
|
||||
@@ -1597,7 +1598,8 @@ export class FileDragAndDrop implements
|
||||
@@ -1587,7 +1588,8 @@ export class FileDragAndDrop implements
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
|
||||
@@ -300,7 +300,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explo
|
||||
) {
|
||||
const updateDropEnablement = (e: IConfigurationChangeEvent | undefined) => {
|
||||
if (!e || e.affectsConfiguration('explorer.enableDragAndDrop')) {
|
||||
@@ -1822,15 +1824,17 @@ export class FileDragAndDrop implements
|
||||
@@ -1812,15 +1814,17 @@ export class FileDragAndDrop implements
|
||||
|
||||
// External file DND (Import/Upload file)
|
||||
if (data instanceof NativeDragAndDropData) {
|
||||
|
||||
@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
import { renderFormattedText } from '../../../../base/browser/formattedTextRenderer.js';
|
||||
import { status } from '../../../../base/browser/ui/aria/aria.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 { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from '../../../browser/actions/workspaceActions.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 { IWebviewElement, IWebviewService } from '../../webview/browser/webview.js';
|
||||
import './gettingStartedColors.js';
|
||||
@@ -920,6 +920,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"))
|
||||
);
|
||||
|
||||
@@ -101,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
const leftColumn = $('.categories-column.categories-column-left', {},);
|
||||
const rightColumn = $('.categories-column.categories-column-right', {},);
|
||||
|
||||
@@ -955,6 +1021,9 @@ export class GettingStartedPage extends
|
||||
@@ -980,6 +1046,9 @@ export class GettingStartedPage extends
|
||||
recentList.setLimit(5);
|
||||
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/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
|
||||
|
||||
@@ -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/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;
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
*/
|
||||
readonly expectsResolverExtension: boolean;
|
||||
@@ -135,6 +140,13 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -140,6 +145,13 @@ export class BrowserWorkbenchEnvironment
|
||||
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/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' },
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
'disable-file-uploads': { type: 'boolean' },
|
||||
@@ -189,7 +189,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -111,6 +112,7 @@ export interface ServerParsedArgs {
|
||||
@@ -134,6 +135,7 @@ export interface ServerParsedArgs {
|
||||
'auth'?: string;
|
||||
'disable-file-downloads'?: boolean;
|
||||
'disable-file-uploads'?: boolean;
|
||||
@@ -201,7 +201,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -373,6 +373,7 @@ export class WebClientServer {
|
||||
@@ -429,6 +429,7 @@ export class WebClientServer {
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
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 @@
|
||||
import { Disposable } from '../../base/common/lifecycle.js';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from '../../platform/contextkey/common/contextkey.js';
|
||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from '../../platform/contextkey/common/contextkeys.js';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads } from '../common/contextkeys.js';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, AuxiliaryBarMaximizedContext, InAutomationContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from '../common/contextkeys.js';
|
||||
import { IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext, IsChromeOSContext } from '../../platform/contextkey/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 { 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 { IConfigurationService } from '../../platform/configuration/common/configuration.js';
|
||||
import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService.js';
|
||||
@@ -202,6 +202,7 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -209,6 +209,7 @@ export class WorkbenchContextKeysHandler
|
||||
// code-server
|
||||
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
||||
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
|
||||
@@ -234,7 +234,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -41,6 +41,7 @@ export const InAutomationContext = new R
|
||||
@@ -44,6 +44,7 @@ export const InAutomationContext = new R
|
||||
|
||||
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
||||
|
||||
@@ -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 { join, dirname } from '../../base/common/path.js';
|
||||
import { performance } from 'perf_hooks';
|
||||
-import { serverOptions } from './serverEnvironmentService.js';
|
||||
+import { serverOptions, ServerParsedArgs } from './serverEnvironmentService.js';
|
||||
-import { agentHostBridgeConnectionTokenEnvironmentVariable, serverOptions } from './serverEnvironmentService.js';
|
||||
+import { agentHostBridgeConnectionTokenEnvironmentVariable, serverOptions, ServerParsedArgs } from './serverEnvironmentService.js';
|
||||
import product from '../../platform/product/common/product.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);
|
||||
+function parse(): ServerParsedArgs {
|
||||
+ return parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
||||
+}
|
||||
|
||||
-const agentHostBridgeConnectionToken = process.env[agentHostBridgeConnectionTokenEnvironmentVariable];
|
||||
-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 USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
|
||||
-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); }
|
||||
-});
|
||||
+function parse(): ServerParsedArgs {
|
||||
+ return parseArgs(process.argv.slice(2), serverOptions, errorReporter);
|
||||
+}
|
||||
+
|
||||
+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 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() {
|
||||
- runCli(args, REMOTE_DATA_FOLDER, serverOptions);
|
||||
+function spawnCli(args = parse()): Promise<void> {
|
||||
+function spawnCli(args = parse()) {
|
||||
+ 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
|
||||
*/
|
||||
-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> {
|
||||
+ 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
|
||||
@@ -172,7 +177,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
import { IProgressService } from '../../platform/progress/common/progress.js';
|
||||
import { DelayedLogChannel } from '../services/output/common/delayedLogChannel.js';
|
||||
import { dirname, joinPath } from '../../base/common/resources.js';
|
||||
@@ -133,6 +134,9 @@ export class BrowserMain extends Disposa
|
||||
@@ -140,6 +141,9 @@ export class BrowserMain extends Disposa
|
||||
// Startup
|
||||
const instantiationService = workbench.startup();
|
||||
|
||||
@@ -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/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 {
|
||||
+ readonly codeServerVersion?: string
|
||||
@@ -209,8 +214,8 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -26,8 +27,9 @@
|
||||
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
|
||||
@@ -28,8 +29,9 @@
|
||||
<meta id="vscode-workbench-css-modules" data-settings="{{WORKBENCH_DEV_CSS_MODULES}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
- <link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
|
||||
@@ -235,7 +240,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
|
||||
@@ -23,8 +24,9 @@
|
||||
@@ -24,8 +25,9 @@
|
||||
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
|
||||
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
@@ -251,19 +256,19 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -333,6 +333,7 @@ export class WebClientServer {
|
||||
@@ -394,6 +394,7 @@ export class WebClientServer {
|
||||
} : undefined;
|
||||
|
||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||
+ codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||
...this._productService.extensionsGallery,
|
||||
Index: code-server/lib/vscode/src/server-main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/server-main.ts
|
||||
+++ code-server/lib/vscode/src/server-main.ts
|
||||
@@ -22,6 +22,9 @@ import { IServerAPI } from './vs/server/
|
||||
@@ -23,6 +23,9 @@ import { IServerAPI } from './vs/server/
|
||||
perf.mark('code/server/start');
|
||||
(globalThis as { vscodeServerStartTime?: number }).vscodeServerStartTime = performance.now();
|
||||
|
||||
@@ -273,7 +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
|
||||
const parsedArgs = minimist(process.argv.slice(2), {
|
||||
boolean: ['start-server', 'list-extensions', 'print-ip-address', 'help', 'version', 'accept-server-license-terms', 'update-extensions'],
|
||||
@@ -150,6 +153,7 @@ if (shouldSpawnCli) {
|
||||
@@ -50,7 +53,7 @@ if (shouldSpawnCli) {
|
||||
mod.spawnCli();
|
||||
});
|
||||
} else {
|
||||
- installServerProcessExitDiagnostics();
|
||||
+ installServerProcessExitDiagnostics(parsedArgs);
|
||||
|
||||
let _remoteExtensionHostAgentServer: IServerAPI | null = null;
|
||||
let _remoteExtensionHostAgentServerPromise: Promise<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 {
|
||||
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
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -304,11 +327,11 @@ Index: code-server/lib/vscode/src/server-main.ts
|
||||
+if (!process.env.CODE_SERVER_PARENT_PID) {
|
||||
+ start();
|
||||
+}
|
||||
Index: code-server/lib/vscode/src/vs/platform/dialogs/browser/dialog.ts
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialog.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/dialogs/browser/dialog.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/dialogs/browser/dialog.ts
|
||||
@@ -45,8 +45,11 @@ export function createWorkbenchDialogOpt
|
||||
--- 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
|
||||
@@ -54,8 +54,11 @@ export function createWorkbenchDialogOpt
|
||||
|
||||
export function createBrowserAboutDialogDetails(productService: IProductService): { title: string; details: string; detailsToCopy: 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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -364,6 +364,7 @@ export class WebClientServer {
|
||||
@@ -420,6 +420,7 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
serverBasePath: basePath,
|
||||
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/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>;
|
||||
|
||||
@@ -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/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'); }
|
||||
|
||||
@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/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||
@@ -147,8 +147,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._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
|
||||
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
|
||||
@@ -79,7 +79,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/co
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -556,6 +558,12 @@ export class WorkspaceService extends Di
|
||||
@@ -563,6 +565,12 @@ export class WorkspaceService extends Di
|
||||
previousFolders = this.workspace.folders;
|
||||
this.workspace.update(workspace);
|
||||
} else {
|
||||
|
||||
@@ -8,7 +8,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -68,6 +68,7 @@ export interface IProductConfiguration {
|
||||
@@ -100,6 +100,7 @@ export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
readonly rootEndpoint?: string
|
||||
readonly updateEndpoint?: string
|
||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -18,6 +18,7 @@ import { ProtocolConstants } from '../..
|
||||
@@ -34,6 +34,7 @@ export function getRedactedServerParsedA
|
||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -105,6 +106,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -128,6 +129,7 @@ export const serverOptions: OptionDescri
|
||||
export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
@@ -40,14 +40,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -341,6 +341,7 @@ export class WebClientServer {
|
||||
@@ -402,6 +402,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: rootBase,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
};
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
|
||||
@@ -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/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
@@ -49,6 +49,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||
version: pkg.version
|
||||
});
|
||||
@@ -65,6 +65,17 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||
Object.assign(product, { copilotVersions: { runtime: packageConfiguration.copilotRuntimeVersion, sdk } });
|
||||
}
|
||||
}
|
||||
+
|
||||
+ 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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -326,7 +326,6 @@ export class WebClientServer {
|
||||
@@ -387,7 +387,6 @@ export class WebClientServer {
|
||||
|
||||
const staticRoute = posix.join(basePath, this._productPath, STATIC_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 });
|
||||
|
||||
@@ -342,14 +341,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
@@ -404,14 +403,7 @@ export class WebClientServer {
|
||||
rootEndpoint: rootBase,
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||
- ...this._productService.extensionsGallery,
|
||||
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
|
||||
@@ -64,7 +64,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+ extensionsGallery: this._productService.extensionsGallery,
|
||||
};
|
||||
|
||||
const proposedApi = this._environmentService.args['enable-proposed-api'];
|
||||
if (!this._environmentService.isBuilt) {
|
||||
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
|
||||
@@ -10,18 +10,17 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
@@ -321,10 +321,7 @@ function extensionDescriptionArrayToMap(
|
||||
@@ -321,6 +321,10 @@ function extensionDescriptionArrayToMap(
|
||||
}
|
||||
|
||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
- if (!extension.enabledApiProposals) {
|
||||
- return false;
|
||||
- }
|
||||
- return extension.enabledApiProposals.includes(proposal);
|
||||
+ return true
|
||||
}
|
||||
|
||||
export function checkProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): void {
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+export function _isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
if (!extension.enabledApiProposals) {
|
||||
return false;
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||
|
||||
@@ -13,12 +13,18 @@ This has e2e tests.
|
||||
For the `asExternalUri` changes, you'll need to test manually by:
|
||||
1. running code-server with the test extension
|
||||
2. Command Palette > code-server: asExternalUri test
|
||||
3. input a url like http://localhost:3000
|
||||
4. it should show a notification and show output as <code-server>/proxy/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/my/path?token%3Dabc#section
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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/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 updateEndpoint?: 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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -342,6 +342,7 @@ export class WebClientServer {
|
||||
@@ -403,6 +403,7 @@ export class WebClientServer {
|
||||
rootEndpoint: rootBase,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
};
|
||||
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
|
||||
@@ -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 { create } from '../../../workbench/workbench.web.main.internal.js';
|
||||
|
||||
@@ -606,6 +607,39 @@ class WorkspaceProvider implements IWork
|
||||
@@ -612,6 +613,44 @@ class WorkspaceProvider implements IWork
|
||||
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
||||
workspaceProvider: WorkspaceProvider.create(config),
|
||||
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
|
||||
+ .replace('{{port}}', localhostMatch.port.toString())
|
||||
+ .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 {
|
||||
+ 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/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
@@ -83,8 +83,8 @@ export class ForwardedPortsView extends
|
||||
@@ -99,8 +99,8 @@ export class ForwardedPortsView extends
|
||||
private async enableForwardedPortsFeatures() {
|
||||
this.contextKeyListener.clear();
|
||||
|
||||
|
||||
86
patches/remote-secret-storage.diff
Normal file
86
patches/remote-secret-storage.diff
Normal file
@@ -0,0 +1,86 @@
|
||||
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
|
||||
@@ -139,8 +139,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) {
|
||||
@@ -160,8 +165,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) {
|
||||
@@ -194,8 +204,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 {
|
||||
@@ -203,7 +214,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
|
||||
@@ -625,2 +625,2 @@
|
||||
- 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 */
|
||||
});
|
||||
})();
|
||||
122
patches/remote-storage.diff
Normal file
122
patches/remote-storage.diff
Normal file
@@ -0,0 +1,122 @@
|
||||
Reuse VS Code's Electron storage service for remote persistence
|
||||
|
||||
--- 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
|
||||
@@ -14 +14,6 @@
|
||||
-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;
|
||||
@@ -101 +101 @@
|
||||
- @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
+ private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@@ -117 +117 @@
|
||||
- await this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen);
|
||||
+ await this.lifecycleMainService.when(LIFECYCLE_MAIN_PHASE_AFTER_WINDOW_OPEN);
|
||||
@@ -256 +256 @@
|
||||
- if (this.shutdownReason === ShutdownReason.KILL) {
|
||||
+ if (this.shutdownReason === SHUTDOWN_REASON_KILL) {
|
||||
@@ -295 +295 @@
|
||||
- if (this.shutdownReason === ShutdownReason.KILL) {
|
||||
+ if (this.shutdownReason === SHUTDOWN_REASON_KILL) {
|
||||
|
||||
--- 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
|
||||
@@ -6 +6 @@
|
||||
-import { IMainProcessService } from '../../../../platform/ipc/common/mainProcessService.js';
|
||||
+import { IRemoteService } from '../../../../platform/ipc/common/services.js';
|
||||
@@ -22 +22 @@
|
||||
- mainProcessService: IMainProcessService,
|
||||
+ remoteService: Pick<IRemoteService, 'getChannel'>,
|
||||
@@ -25 +25 @@
|
||||
- super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, mainProcessService, workbenchEnvironmentService);
|
||||
+ super(workspace, { currentProfile: userDataProfileService.currentProfile, defaultProfile: userDataProfilesService.defaultProfile }, remoteService as IRemoteService, workbenchEnvironmentService);
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -68,0 +69 @@
|
||||
+ '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.') },
|
||||
@@ -214,0 +216 @@
|
||||
+ 'enable-remote-storage'?: boolean;
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -107,0 +108,4 @@
|
||||
+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';
|
||||
@@ -240,0 +245,15 @@
|
||||
+ // 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,
|
||||
+ ));
|
||||
+
|
||||
@@ -419,6 +439,7 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
|
||||
|
||||
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());
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -411 +411,2 @@
|
||||
- callbackRoute: callbackRoute
|
||||
+ callbackRoute: callbackRoute,
|
||||
+ remoteStorageEnabled: this._environmentService.args['enable-remote-storage'] ? true : undefined
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -413,0 +414,5 @@
|
||||
+ /**
|
||||
+ * Persist workbench storage on the remote server instead of browser IndexedDB.
|
||||
+ */
|
||||
+ readonly remoteStorageEnabled?: boolean;
|
||||
+
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
@@ -35,0 +36 @@
|
||||
+import { NativeWorkbenchStorageService } from '../services/storage/electron-browser/storageService.js';
|
||||
@@ -479 +480 @@
|
||||
- this.createStorageService(workspace, logService, userDataProfileService).then(service => {
|
||||
+ this.createStorageService(workspace, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService).then(service => {
|
||||
@@ -601 +602,15 @@
|
||||
- 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);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
--- code-server.orig/lib/vscode/src/vs/sessions/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/sessions/browser/web.main.ts
|
||||
@@ -42 +42 @@
|
||||
- _userDataProfilesService: BrowserUserDataProfilesService,
|
||||
+ userDataProfilesService: BrowserUserDataProfilesService,
|
||||
@@ -44 +44 @@
|
||||
- _remoteAgentService: IRemoteAgentService,
|
||||
+ remoteAgentService: IRemoteAgentService,
|
||||
@@ -85 +85 @@
|
||||
- const storageService = await this.createStorageService(workspaceIdentifier, logService, userDataProfileService);
|
||||
+ const storageService = await this.createStorageService(workspaceIdentifier, environmentService, logService, userDataProfileService, userDataProfilesService, remoteAgentService);
|
||||
@@ -22,3 +22,8 @@ clipboard.diff
|
||||
display-language.diff
|
||||
trusted-domains.diff
|
||||
signature-verification.diff
|
||||
copilot.diff
|
||||
app-name.diff
|
||||
csp-hashes.diff
|
||||
remote-storage.diff
|
||||
remote-secret-storage.diff
|
||||
|
||||
@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -70,6 +70,10 @@ export interface IProductConfiguration {
|
||||
@@ -102,6 +102,10 @@ export interface IProductConfiguration {
|
||||
readonly updateEndpoint?: string
|
||||
readonly logoutEndpoint?: 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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -343,6 +343,10 @@ export class WebClientServer {
|
||||
@@ -404,6 +404,10 @@ export class WebClientServer {
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? rootBase + '/logout' : undefined,
|
||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? rootBase + '/proxy/{{port}}/',
|
||||
@@ -63,5 +63,5 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+ path: rootBase + '/_static/out/browser/serviceWorker.js',
|
||||
+ },
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
};
|
||||
|
||||
@@ -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
|
||||
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.
|
||||
These will not work since we patch VS Code.
|
||||
|
||||
Index: code-server/lib/vscode/build/gulpfile.reh.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.ts
|
||||
+++ code-server/lib/vscode/build/gulpfile.reh.ts
|
||||
@@ -257,8 +257,7 @@ function packageTask(type: string, platf
|
||||
@@ -260,10 +260,15 @@ function packageTask(type: string, platf
|
||||
const destination = path.join(BUILD_ROOT, destinationFolderName);
|
||||
|
||||
return () => {
|
||||
+ const jsFilterMain = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path));
|
||||
+
|
||||
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
||||
.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(util.setExecutableBit(['**/*.sh']));
|
||||
+ .pipe(filter(['**', '!**/*.{js,css}.map']))
|
||||
+ .pipe(jsFilterMain)
|
||||
+ .pipe(util.stripSourceMappingURL())
|
||||
+ .pipe(jsFilterMain.restore);
|
||||
|
||||
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
||||
const isUIExtension = (manifest: { extensionKind?: string; main?: string; contributes?: Record<string, unknown> }) => {
|
||||
@@ -298,9 +297,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;
|
||||
@@ -453,7 +452,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 nodeModule from 'node:module';
|
||||
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');
|
||||
|
||||
@@ -94,7 +94,7 @@ Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
|
||||
+import * as _http from 'http';
|
||||
import minimist from 'minimist';
|
||||
import * as nativeWatchdog from 'native-watchdog';
|
||||
import * as nativeWatchdog from '@vscode/native-watchdog';
|
||||
import * as net from 'net';
|
||||
@@ -469,7 +470,28 @@ async function startExtensionHostProcess
|
||||
);
|
||||
|
||||
@@ -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/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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
|
||||
@@ -68,6 +68,7 @@ import { IExtensionsScannerService } fro
|
||||
import { ExtensionsScannerService } from './extensionsScannerService.js';
|
||||
import { IExtensionsProfileScannerService } from '../../platform/extensionManagement/common/extensionsProfileScannerService.js';
|
||||
import { IUserDataProfilesService } from '../../platform/userDataProfile/common/userDataProfile.js';
|
||||
@@ -28,18 +20,18 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
import { NullPolicyService } from '../../platform/policy/common/policy.js';
|
||||
import { OneDataSystemAppender } from '../../platform/telemetry/node/1dsAppender.js';
|
||||
import { LoggerService } from '../../platform/log/node/loggerService.js';
|
||||
@@ -166,11 +168,23 @@ export async function setupServerService
|
||||
@@ -179,11 +180,23 @@ export async function setupServerService
|
||||
const requestService = new RequestService('remote', configurationService, environmentService, logService);
|
||||
services.set(IRequestService, requestService);
|
||||
|
||||
+ let isContainer = undefined;
|
||||
+ try {
|
||||
+ await fs.stat('/run/.containerenv');
|
||||
+ await fs.promises.stat('/run/.containerenv');
|
||||
+ isContainer = true;
|
||||
+ } catch (error) { /* Does not exist, probably. */ }
|
||||
+ if (!isContainer) {
|
||||
+ try {
|
||||
+ const content = await fs.readFile('/proc/self/cgroup', 'utf8')
|
||||
+ const content = await fs.promises.readFile('/proc/self/cgroup', 'utf8')
|
||||
+ isContainer = content.includes('docker');
|
||||
+ } 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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -347,6 +347,8 @@ export class WebClientServer {
|
||||
@@ -408,6 +408,8 @@ export class WebClientServer {
|
||||
scope: vscodeBase + '/',
|
||||
path: rootBase + '/_static/out/browser/serviceWorker.js',
|
||||
},
|
||||
+ enableTelemetry: this._productService.enableTelemetry,
|
||||
+ telemetryEndpoint: this._productService.telemetryEndpoint,
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
};
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -74,6 +74,7 @@ export interface IProductConfiguration {
|
||||
@@ -106,6 +106,7 @@ export interface IProductConfiguration {
|
||||
readonly path: 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/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}",
|
||||
controlUrl: "",
|
||||
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/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-getting-started-override': { type: 'boolean' },
|
||||
'locale': { type: 'string' },
|
||||
@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -115,6 +116,7 @@ export interface ServerParsedArgs {
|
||||
@@ -138,6 +139,7 @@ export interface ServerParsedArgs {
|
||||
'disable-file-uploads'?: boolean;
|
||||
'disable-getting-started-override'?: boolean,
|
||||
'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/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -338,6 +338,14 @@ export class WebClientServer {
|
||||
@@ -399,6 +399,14 @@ export class WebClientServer {
|
||||
scopes: [['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
|
||||
@@ -39,11 +39,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: rootBase,
|
||||
@@ -352,6 +360,7 @@ export class WebClientServer {
|
||||
telemetryEndpoint: this._productService.telemetryEndpoint,
|
||||
@@ -414,6 +422,7 @@ export class WebClientServer {
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
+ 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 {
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -67,6 +67,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
@@ -99,6 +99,7 @@ export interface IDictationRuntimeProduc
|
||||
export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
readonly rootEndpoint?: string
|
||||
@@ -101,32 +101,32 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
@@ -113,6 +114,7 @@ export interface IProductConfiguration {
|
||||
readonly resourceUrlTemplate: string;
|
||||
readonly nlsBaseUrl: string;
|
||||
readonly accessSKUs?: string[];
|
||||
+ readonly authorizationHeaderToken?: string;
|
||||
@@ -148,6 +149,7 @@ export interface IProductConfiguration {
|
||||
};
|
||||
|
||||
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
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -340,6 +340,7 @@ export class WebClientServer {
|
||||
@@ -401,6 +401,7 @@ export class WebClientServer {
|
||||
const productConfiguration: Partial<Mutable<IProductConfiguration>> = {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: rootBase,
|
||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? rootBase + '/update/check' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
voiceWsUrl: this._productService.voiceWsUrl,
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
};
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -16,6 +16,8 @@ import { join } from '../../base/common/
|
||||
import { ProtocolConstants } from '../../base/parts/ipc/common/ipc.net.js';
|
||||
@@ -32,6 +32,8 @@ export function getRedactedServerParsedA
|
||||
}
|
||||
|
||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||
+ /* ----- code-server ----- */
|
||||
@@ -134,7 +134,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -101,6 +103,8 @@ export const serverOptions: OptionDescri
|
||||
@@ -124,6 +126,8 @@ export const serverOptions: OptionDescri
|
||||
};
|
||||
|
||||
export interface ServerParsedArgs {
|
||||
|
||||
@@ -3,9 +3,6 @@ Serve webviews from the same origin
|
||||
Normally webviews are served from vscode-webview.net but we would rather them be
|
||||
self-hosted.
|
||||
|
||||
When doing this CSP will block resources (for example when viewing images) so
|
||||
add 'self' to the CSP to fix that.
|
||||
|
||||
Additionally the service worker defaults to handling *all* requests made to the
|
||||
current host but when self-hosting the webview this will end up including the
|
||||
webview HTML itself which means these requests will fail since the communication
|
||||
@@ -20,16 +17,6 @@ webview host is separate by default but we serve on the same host).
|
||||
|
||||
To test, open a few types of webviews (images, markdown, extension details, etc).
|
||||
|
||||
Make sure to update the hash. To do so:
|
||||
1. run code-server
|
||||
2. open any webview (i.e. preview Markdown)
|
||||
3. see error in console and copy hash
|
||||
|
||||
That will test the hash change in pre/index.html
|
||||
|
||||
Double-check the console to make sure there are no console errors for the webWorkerExtensionHostIframe
|
||||
which also requires a hash change.
|
||||
|
||||
parentOriginHash changes
|
||||
|
||||
This fixes webviews from not working properly due to a change upstream.
|
||||
@@ -41,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -220,7 +220,7 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -239,7 +239,7 @@ export class BrowserWorkbenchEnvironment
|
||||
|
||||
@memoize
|
||||
get webviewExternalEndpoint(): string {
|
||||
@@ -54,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -360,6 +360,7 @@ export class WebClientServer {
|
||||
@@ -416,6 +416,7 @@ export class WebClientServer {
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
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/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-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 @@
|
||||
@@ -253,7 +253,7 @@
|
||||
}
|
||||
|
||||
const swPath = encodeURI(`service-worker.js?v=${expectedWorkerVersion}&vscode-resource-base-authority=${searchParams.get('vscode-resource-base-authority')}&remoteAuthority=${searchParams.get('remoteAuthority') ?? ''}`);
|
||||
- navigator.serviceWorker.register(swPath, { type: 'module' })
|
||||
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', updateViaCache: 'none' })
|
||||
+ navigator.serviceWorker.register(swPath)
|
||||
.then(async registration => {
|
||||
/**
|
||||
* @param {MessageEvent} event
|
||||
@@ -370,6 +370,12 @@
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// A previous SW is already controlling. Force an update
|
||||
@@ -332,6 +332,12 @@
|
||||
|
||||
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/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-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
|
||||
@@ -34,6 +34,13 @@
|
||||
}
|
||||
return start();
|
||||
}
|
||||
+
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
content="style-src 'self'; manifest-src 'self'; img-src 'self' data:; font-src 'self' data:;"
|
||||
/>
|
||||
<meta name="color-scheme" content="light dark" />
|
||||
<title>{{ERROR_TITLE}} - code-server</title>
|
||||
<title>{{ERROR_TITLE}} - {{APP_NAME}}</title>
|
||||
<link rel="icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon-dark-support.svg" />
|
||||
<link rel="alternate icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon.ico" />
|
||||
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
|
||||
|
||||
@@ -13,7 +13,8 @@ import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSo
|
||||
import { handleUpgrade } from "./wsRouter"
|
||||
|
||||
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 {
|
||||
/** Handles regular HTTP requests. */
|
||||
@@ -30,8 +31,12 @@ const isSocketOpts = (opts: ListenOptions): opts is SocketOptions => {
|
||||
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) => {
|
||||
if (isSocketOpts(opts)) {
|
||||
if (!isFdOpts(opts) && isSocketOpts(opts)) {
|
||||
try {
|
||||
await fs.unlink(opts.socket)
|
||||
} 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))
|
||||
resolve()
|
||||
}
|
||||
if (isSocketOpts(opts)) {
|
||||
if (isFdOpts(opts)) {
|
||||
server.listen({ fd: opts["socket-fd"] }, onListen)
|
||||
} else if (isSocketOpts(opts)) {
|
||||
server.listen(opts.socket, onListen)
|
||||
} else {
|
||||
// [] 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
|
||||
// listening. Otherwise, the socket may not have been created yet.
|
||||
if (isSocketOpts(opts)) {
|
||||
if (!isFdOpts(opts) && isSocketOpts(opts)) {
|
||||
if (opts["socket-mode"]) {
|
||||
await fs.chmod(opts.socket, opts["socket-mode"])
|
||||
}
|
||||
|
||||
116
src/node/cli.ts
116
src/node/cli.ts
@@ -1,4 +1,5 @@
|
||||
import { field, Level, logger } from "@coder/logger"
|
||||
import * as crypto from "crypto"
|
||||
import { promises as fs } from "fs"
|
||||
import { load } from "js-yaml"
|
||||
import * as path from "path"
|
||||
@@ -46,12 +47,14 @@ export interface UserProvidedCodeArgs {
|
||||
"show-versions"?: boolean
|
||||
category?: string
|
||||
"github-auth"?: string
|
||||
"enable-remote-storage"?: boolean
|
||||
"disable-update-check"?: boolean
|
||||
"disable-file-downloads"?: boolean
|
||||
"disable-file-uploads"?: boolean
|
||||
"disable-workspace-trust"?: boolean
|
||||
"disable-getting-started-override"?: boolean
|
||||
"disable-proxy"?: boolean
|
||||
"reconnection-grace-time"?: string
|
||||
"session-socket"?: string
|
||||
"cookie-suffix"?: string
|
||||
"link-protection-trusted-domains"?: string[]
|
||||
@@ -82,6 +85,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
open?: boolean
|
||||
"bind-addr"?: string
|
||||
socket?: string
|
||||
"socket-fd"?: number
|
||||
"socket-mode"?: string
|
||||
"trusted-origins"?: string[]
|
||||
version?: boolean
|
||||
@@ -96,6 +100,7 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
"abs-proxy-base-path"?: string
|
||||
i18n?: string
|
||||
"idle-timeout-seconds"?: number
|
||||
"vscode-option"?: string[]
|
||||
/* Positional arguments. */
|
||||
_?: string[]
|
||||
}
|
||||
@@ -234,6 +239,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
port: { type: "number", description: "" },
|
||||
|
||||
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." },
|
||||
"trusted-origins": {
|
||||
type: "string[]",
|
||||
@@ -267,6 +276,10 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
type: "string",
|
||||
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." },
|
||||
"skip-auth-preflight": {
|
||||
type: "boolean",
|
||||
@@ -315,6 +328,19 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
type: "number",
|
||||
description: "Timeout in seconds to wait before shutting down when idle.",
|
||||
},
|
||||
"reconnection-grace-time": {
|
||||
type: "string",
|
||||
description:
|
||||
"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).",
|
||||
},
|
||||
"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[] => {
|
||||
@@ -408,10 +434,6 @@ export const parse = (
|
||||
throw new Error("--github-auth can only be set in the config file or passed in via $GITHUB_TOKEN")
|
||||
}
|
||||
|
||||
if (key === "idle-timeout-seconds" && Number(value) <= 60) {
|
||||
throw new Error("--idle-timeout-seconds must be greater than 60 seconds.")
|
||||
}
|
||||
|
||||
const option = options[key]
|
||||
if (option.type === "boolean") {
|
||||
;(args[key] as boolean) = true
|
||||
@@ -431,6 +453,10 @@ export const parse = (
|
||||
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") {
|
||||
continue
|
||||
}
|
||||
@@ -519,6 +545,7 @@ export interface DefaultedArgs extends ConfigArgs {
|
||||
"extensions-dir": string
|
||||
"user-data-dir": string
|
||||
"session-socket": string
|
||||
"app-name": string
|
||||
/* Positional arguments. */
|
||||
_: string[]
|
||||
}
|
||||
@@ -540,7 +567,7 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
}
|
||||
|
||||
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"]
|
||||
|
||||
@@ -631,6 +658,19 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args["github-auth"] = process.env.GITHUB_TOKEN
|
||||
}
|
||||
|
||||
if (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 (isNaN(Number(process.env.CODE_SERVER_IDLE_TIMEOUT_SECONDS))) {
|
||||
logger.info("CODE_SERVER_IDLE_TIMEOUT_SECONDS must be a number")
|
||||
@@ -665,6 +705,8 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
}
|
||||
args["proxy-domain"] = finalProxies
|
||||
|
||||
args["app-name"] ??= process.env.CODE_SERVER_APP_NAME || "code-server"
|
||||
|
||||
args._ = getResolvedPathsFromArgs(args)
|
||||
|
||||
return {
|
||||
@@ -674,6 +716,25 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
} 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[] {
|
||||
return (args._ ?? []).map((p) => path.resolve(p))
|
||||
}
|
||||
@@ -895,17 +956,58 @@ export interface CodeArgs extends UserProvidedCodeArgs {
|
||||
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.
|
||||
* Does not add any extra arguments.
|
||||
*/
|
||||
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 {
|
||||
...args,
|
||||
...rest,
|
||||
/** Type casting. */
|
||||
help: !!args.help,
|
||||
version: !!args.version,
|
||||
port: args.port?.toString(),
|
||||
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 type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
|
||||
export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles {
|
||||
type PackageJson = {
|
||||
version: string
|
||||
commit: string
|
||||
}
|
||||
|
||||
export function getPackageJson(relativePath: string): PackageJson {
|
||||
let pkg = {}
|
||||
try {
|
||||
pkg = require(relativePath)
|
||||
@@ -11,7 +15,7 @@ export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJso
|
||||
logger.warn(error.message)
|
||||
}
|
||||
|
||||
return pkg
|
||||
return pkg as PackageJson
|
||||
}
|
||||
|
||||
export const rootPath = path.resolve(__dirname, "../..")
|
||||
|
||||
@@ -351,6 +351,25 @@ export function ensureOrigin(req: express.Request, _?: express.Response, next?:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the origin matches any trusted origin. Entries are matched
|
||||
* as exact strings, the special wildcard `"*"`, or `*.example.com`-style
|
||||
* domain wildcards (same as --proxy-domain).
|
||||
*/
|
||||
export function isTrustedOrigin(origin: string, trustedOrigins: string[]): boolean {
|
||||
return trustedOrigins.some((trusted) => {
|
||||
if (trusted === "*" || trusted === origin) {
|
||||
return true
|
||||
}
|
||||
// *.example.com style: match origin if it is the domain or a subdomain
|
||||
if (trusted.startsWith("*.")) {
|
||||
const domain = trusted.slice(2).toLowerCase()
|
||||
return origin === domain || origin.endsWith("." + domain)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the request origin against the host. Throw if invalid.
|
||||
*/
|
||||
@@ -370,7 +389,7 @@ export function authenticateOrigin(req: express.Request): void {
|
||||
}
|
||||
|
||||
const trustedOrigins = req.args["trusted-origins"] || []
|
||||
if (trustedOrigins.includes(origin) || trustedOrigins.includes("*")) {
|
||||
if (isTrustedOrigin(origin, trustedOrigins)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"LOGIN_TITLE": "{{app}} login",
|
||||
"LOGIN_BELOW": "Please log in below.",
|
||||
"WELCOME": "Welcome to {{app}}",
|
||||
"LOGIN_PASSWORD": "Check the config file at {{configFile}} for the password.",
|
||||
"LOGIN_PASSWORD": "Check the config file for the password.",
|
||||
"LOGIN_USING_ENV_PASSWORD": "Password was set from $PASSWORD.",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "Password was set from $HASHED_PASSWORD.",
|
||||
"SUBMIT": "SUBMIT",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"LOGIN_TITLE": "{{app}} ログイン",
|
||||
"LOGIN_BELOW": "以下によりログインしてください。",
|
||||
"WELCOME": "ようこそ {{app}} へ!",
|
||||
"LOGIN_PASSWORD": "パスワードは設定ファイル( {{configFile}} )を確認してください。",
|
||||
"LOGIN_PASSWORD": "パスワードは設定ファイルを確認してください。",
|
||||
"LOGIN_USING_ENV_PASSWORD": "パスワードは環境変数 $PASSWORD で設定されています。",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "パスワードは環境変数 $HASHED_PASSWORD で設定されています。",
|
||||
"SUBMIT": "実行",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"LOGIN_TITLE": "เข้าสู่ระบบ {{app}}",
|
||||
"LOGIN_BELOW": "กรุณาเข้าสู่ระบบด้านล่าง",
|
||||
"WELCOME": "ยินดีต้อนรับสู่ {{app}}",
|
||||
"LOGIN_PASSWORD": "ตรวจสอบไฟล์กำหนดค่าที่ {{configFile}} เพื่อดูรหัสผ่าน",
|
||||
"LOGIN_PASSWORD": "ตรวจสอบไฟล์กำหนดค่าเพื่อดูรหัสผ่าน",
|
||||
"LOGIN_USING_ENV_PASSWORD": "รหัสผ่านถูกกำหนดเป็น $PASSWORD",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "รรหัสผ่านถูกกำหนดเป็น $HASHED_PASSWORD",
|
||||
"SUBMIT": "ส่ง",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"LOGIN_TITLE": "{{app}} لاگ ان کریں",
|
||||
"LOGIN_BELOW": "براہ کرم نیچے لاگ ان کریں۔",
|
||||
"WELCOME": "میں خوش آمدید {{app}}",
|
||||
"LOGIN_PASSWORD": "پاس ورڈ کے لیے {{configFile}} پر کنفگ فائل چیک کریں۔",
|
||||
"LOGIN_PASSWORD": "پاس ورڈ کے لیے کنفگ فائل چیک کریں۔",
|
||||
"LOGIN_USING_ENV_PASSWORD": "پاس ورڈ $PASSWORD سے سیٹ کیا گیا تھا۔",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "پاس ورڈ $HASHED_PASSWORD سے سیٹ کیا گیا تھا۔",
|
||||
"SUBMIT": "جمع کرائیں",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"LOGIN_TITLE": "{{app}} 登录",
|
||||
"LOGIN_BELOW": "请在下面登录。",
|
||||
"WELCOME": "欢迎来到 {{app}}",
|
||||
"LOGIN_PASSWORD": "查看配置文件 {{configFile}} 中的密码。",
|
||||
"LOGIN_PASSWORD": "查看配置文件中的密码。",
|
||||
"LOGIN_USING_ENV_PASSWORD": "密码在 $PASSWORD 中设置。",
|
||||
"LOGIN_USING_HASHED_PASSWORD": "密码在 $HASHED_PASSWORD 中设置。",
|
||||
"SUBMIT": "提交",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as cookie from "cookie"
|
||||
import type { Request } from "express"
|
||||
import proxyServer from "http-proxy"
|
||||
import { HttpCode } from "../common/http"
|
||||
import { getCookieSessionName, HttpCode } from "../common/http"
|
||||
|
||||
export const proxy = proxyServer.createProxyServer({})
|
||||
|
||||
@@ -18,6 +20,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.
|
||||
// Is disabled when the request has no base path which means /absproxy is in use.
|
||||
proxy.on("proxyRes", (res, req) => {
|
||||
|
||||
@@ -28,6 +28,12 @@ export const errorHasCode = (error: any): error is ErrorWithCode => {
|
||||
|
||||
const notFoundCodes = [404, "ENOENT", "EISDIR"]
|
||||
|
||||
/**
|
||||
* Final HTTP error handler.
|
||||
*
|
||||
* Note: This handler intentionally does not call `next()` even though it
|
||||
* accepts it as an argument; it is expected to be mounted last.
|
||||
*/
|
||||
export const errorHandler: express.ErrorRequestHandler = async (err, req, res, next) => {
|
||||
let statusCode = 500
|
||||
|
||||
@@ -51,7 +57,8 @@ export const errorHandler: express.ErrorRequestHandler = async (err, req, res, n
|
||||
replaceTemplates(req, content)
|
||||
.replace(/{{ERROR_TITLE}}/g, statusCode.toString())
|
||||
.replace(/{{ERROR_HEADER}}/g, statusCode.toString())
|
||||
.replace(/{{ERROR_BODY}}/g, escapeHtml(err.message)),
|
||||
.replace(/{{ERROR_BODY}}/g, escapeHtml(err.message))
|
||||
.replace(/{{APP_NAME}}/g, req.args["app-name"]),
|
||||
)
|
||||
} else {
|
||||
res.json({
|
||||
@@ -61,6 +68,12 @@ export const errorHandler: express.ErrorRequestHandler = async (err, req, res, n
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Final WebSocket error handler.
|
||||
*
|
||||
* Note: This handler intentionally does not call `next()` even though it
|
||||
* accepts it as an argument; it is expected to be mounted last.
|
||||
*/
|
||||
export const wsErrorHandler: express.ErrorRequestHandler = async (err, req, res, next) => {
|
||||
let statusCode = 500
|
||||
if (errorHasStatusCode(err)) {
|
||||
|
||||
@@ -29,11 +29,10 @@ const getRoot = async (req: Request, error?: Error): Promise<string> => {
|
||||
const content = await fs.readFile(path.join(rootPath, "src/browser/pages/login.html"), "utf8")
|
||||
const locale = req.args["locale"] || "en"
|
||||
i18n.changeLanguage(locale)
|
||||
const appName = req.args["app-name"] || "code-server"
|
||||
const welcomeText = req.args["welcome-text"] || (i18n.t("WELCOME", { app: appName }) as string)
|
||||
const welcomeText = req.args["welcome-text"] || (i18n.t("WELCOME", { app: req.args["app-name"] }) as string)
|
||||
|
||||
// Determine password message using i18n
|
||||
let passwordMsg = i18n.t("LOGIN_PASSWORD", { configFile: req.args.config })
|
||||
let passwordMsg = i18n.t("LOGIN_PASSWORD")
|
||||
if (req.args.usingEnvPassword) {
|
||||
passwordMsg = i18n.t("LOGIN_USING_ENV_PASSWORD")
|
||||
} else if (req.args.usingEnvHashedPassword) {
|
||||
@@ -43,7 +42,7 @@ const getRoot = async (req: Request, error?: Error): Promise<string> => {
|
||||
return replaceTemplates(
|
||||
req,
|
||||
content
|
||||
.replace(/{{I18N_LOGIN_TITLE}}/g, i18n.t("LOGIN_TITLE", { app: appName }))
|
||||
.replace(/{{I18N_LOGIN_TITLE}}/g, i18n.t("LOGIN_TITLE", { app: req.args["app-name"] }))
|
||||
.replace(/{{WELCOME_TEXT}}/g, welcomeText)
|
||||
.replace(/{{PASSWORD_MSG}}/g, passwordMsg)
|
||||
.replace(/{{I18N_LOGIN_BELOW}}/g, i18n.t("LOGIN_BELOW"))
|
||||
|
||||
@@ -13,7 +13,8 @@ const getProxyTarget = (
|
||||
): string => {
|
||||
// If there is a base path, strip it out.
|
||||
const base = (req as any).base || ""
|
||||
const port = parseInt(req.params.port, 10)
|
||||
// Cast since we only have one port param.
|
||||
const port = parseInt(req.params.port as string, 10)
|
||||
if (isNaN(port)) {
|
||||
throw new HttpError("Invalid port", HttpCode.BadRequest)
|
||||
}
|
||||
|
||||
@@ -172,7 +172,6 @@ router.get("/", ensureVSCodeLoaded, async (req, res, next) => {
|
||||
})
|
||||
|
||||
router.get("/manifest.json", async (req, res) => {
|
||||
const appName = req.args["app-name"] || "code-server"
|
||||
res.writeHead(200, { "Content-Type": "application/manifest+json" })
|
||||
|
||||
res.end(
|
||||
@@ -180,8 +179,8 @@ router.get("/manifest.json", async (req, res) => {
|
||||
req,
|
||||
JSON.stringify(
|
||||
{
|
||||
name: appName,
|
||||
short_name: appName,
|
||||
name: req.args["app-name"],
|
||||
short_name: req.args["app-name"],
|
||||
start_url: ".",
|
||||
display: "fullscreen",
|
||||
display_override: ["window-controls-overlay"],
|
||||
@@ -211,7 +210,7 @@ router.get("/manifest.json", async (req, res) => {
|
||||
})
|
||||
|
||||
let mintKeyPromise: Promise<Buffer> | undefined
|
||||
router.post("/mint-key", async (req, res) => {
|
||||
router.post("/mint-key", ensureAuthenticated, async (req, res) => {
|
||||
if (!mintKeyPromise) {
|
||||
mintKeyPromise = new Promise(async (resolve) => {
|
||||
const keyPath = path.join(req.args["user-data-dir"], "serve-web-key-half")
|
||||
|
||||
9
test/e2e/appName.test.ts
Normal file
9
test/e2e/appName.test.ts
Normal file
@@ -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 }) => {
|
||||
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 }) => {
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
|
||||
// Action
|
||||
await codeServerPage.openContextMenu("text=unique-file.txt")
|
||||
|
||||
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(true)
|
||||
await expect(codeServerPage.page.locator("text=Download...")).toBeVisible()
|
||||
})
|
||||
|
||||
test("should see the 'Show Local' button on Save As", async ({ codeServerPage }) => {
|
||||
@@ -32,12 +32,11 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
|
||||
await codeServerPage.page.waitForSelector(`text=${fileName}`)
|
||||
|
||||
await codeServerPage.openFile(fileName)
|
||||
await codeServerPage.page.click(".tab")
|
||||
await codeServerPage.navigateMenus(["File", "Auto Save"])
|
||||
await codeServerPage.page.keyboard.type("Making some edits.")
|
||||
await codeServerPage.navigateMenus(["File", "Save As..."])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||
})
|
||||
|
||||
test("should see the 'Show Local' button on Save File", async ({ codeServerPage }) => {
|
||||
@@ -46,14 +45,14 @@ describe("Downloads (enabled)", ["--disable-workspace-trust"], {}, async () => {
|
||||
await codeServerPage.waitForTab("Untitled-1")
|
||||
await codeServerPage.navigateMenus(["File", "Save"])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||
})
|
||||
|
||||
test("should see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
|
||||
// Action
|
||||
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -72,7 +71,7 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
|
||||
// Action
|
||||
await codeServerPage.openContextMenu("text=unique-file.txt")
|
||||
|
||||
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=Download...")).not.toBeVisible()
|
||||
})
|
||||
|
||||
test("should not see the 'Show Local' button on Save as", async ({ codeServerPage }) => {
|
||||
@@ -85,9 +84,9 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
|
||||
// Action
|
||||
await codeServerPage.page.waitForSelector(`text=${fileName}`)
|
||||
await codeServerPage.openFile(fileName)
|
||||
await codeServerPage.page.click(".tab")
|
||||
await codeServerPage.navigateMenus(["File", "Save As..."])
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
||||
await 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 }) => {
|
||||
@@ -96,13 +95,13 @@ describe("Downloads (disabled)", ["--disable-workspace-trust", "--disable-file-d
|
||||
await codeServerPage.waitForTab("Untitled-1")
|
||||
await codeServerPage.navigateMenus(["File", "Save"])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||
})
|
||||
|
||||
test("should not see the 'Show Local' button on Save Workspace As", async ({ codeServerPage }) => {
|
||||
// Action
|
||||
await codeServerPage.navigateMenus(["File", "Save Workspace As..."])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,8 +13,58 @@ function runTestExtensionTests() {
|
||||
|
||||
// Remove end slash in address.
|
||||
const normalizedAddress = address.replace(/\/+$/, "")
|
||||
await codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)
|
||||
await expect(codeServerPage.page.getByText(`Info: proxyUri: ${normalizedAddress}/proxy/{{port}}/`)).toBeVisible()
|
||||
})
|
||||
|
||||
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")]
|
||||
@@ -23,6 +73,17 @@ describe("Extensions", flags, {}, () => {
|
||||
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") {
|
||||
describe("Extensions with --cert", [...flags, "--cert"], {}, () => {
|
||||
runTestExtensionTests()
|
||||
|
||||
@@ -12,7 +12,7 @@ if (process.env.GITHUB_TOKEN) {
|
||||
await codeServerPage.page.click("text=Allow")
|
||||
// It should ask to select an account, one of which will be the one we
|
||||
// pre-injected.
|
||||
expect(await codeServerPage.page.isVisible("text=Select an account")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=Select an account")).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ if (process.env.GITHUB_TOKEN) {
|
||||
await codeServerPage.page.click("text=Allow")
|
||||
// Since there is no account it will ask directly for the token (because
|
||||
// we are on localhost; otherwise it would initiate the oauth flow).
|
||||
expect(await codeServerPage.page.isVisible("text=GitHub Personal Access Token")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=GitHub Personal Access Token")).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -24,8 +24,8 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
|
||||
// Skip entering password
|
||||
// Click the submit button and login
|
||||
await codeServerPage.page.click(".submit")
|
||||
await codeServerPage.page.waitForLoadState("networkidle")
|
||||
expect(await codeServerPage.page.isVisible("text=Missing password"))
|
||||
// The required input blocks empty submits, so the server-side error can't render.
|
||||
await expect(codeServerPage.page.locator("input.password:invalid")).toBeVisible()
|
||||
})
|
||||
|
||||
test("should see an error message for incorrect password", async ({ codeServerPage }) => {
|
||||
@@ -34,28 +34,29 @@ describe("login", ["--disable-workspace-trust", "--auth", "password"], {}, () =>
|
||||
// Click the submit button and login
|
||||
await codeServerPage.page.click(".submit")
|
||||
await codeServerPage.page.waitForLoadState("networkidle")
|
||||
expect(await codeServerPage.page.isVisible("text=Incorrect password"))
|
||||
await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible()
|
||||
})
|
||||
|
||||
test("should hit the rate limiter for too many unsuccessful logins", async ({ codeServerPage }) => {
|
||||
// Type in password
|
||||
await codeServerPage.page.fill(".password", "password123")
|
||||
test.slow()
|
||||
// Click the submit button and login
|
||||
// The current RateLimiter allows 2 logins per minute plus
|
||||
// 12 logins per hour for a total of 14
|
||||
// See: src/node/routes/login.ts
|
||||
for (let i = 1; i <= 14; i++) {
|
||||
await codeServerPage.page.fill(".password", "password123")
|
||||
await codeServerPage.page.click(".submit")
|
||||
await codeServerPage.page.waitForLoadState("networkidle")
|
||||
// We double-check that the correct error message shows
|
||||
// which should be for incorrect password
|
||||
expect(await codeServerPage.page.isVisible("text=Incorrect password"))
|
||||
await expect(codeServerPage.page.locator("text=Incorrect password")).toBeVisible()
|
||||
}
|
||||
|
||||
// The 15th should fail for a different reason:
|
||||
// login rate
|
||||
await codeServerPage.page.fill(".password", "password123")
|
||||
await codeServerPage.page.click(".submit")
|
||||
await codeServerPage.page.waitForLoadState("networkidle")
|
||||
expect(await codeServerPage.page.isVisible("text=Login rate limited!"))
|
||||
await expect(codeServerPage.page.locator("text=Login rate limited!")).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -77,11 +77,14 @@ export class CodeServer {
|
||||
*/
|
||||
private async createWorkspace(): Promise<string> {
|
||||
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(
|
||||
path.join(dir, "Machine/settings.json"),
|
||||
path.join(dir, "User/settings.json"),
|
||||
JSON.stringify({
|
||||
"workbench.startupEditor": "none",
|
||||
// Disable the welcome popup so we can avoid having to click through it
|
||||
// on every test.
|
||||
"workbench.welcomePage.experimentalOnboarding": false,
|
||||
}),
|
||||
"utf8",
|
||||
)
|
||||
@@ -434,6 +437,7 @@ export class CodeServerPage {
|
||||
async executeCommandViaMenus(command: string) {
|
||||
await this.navigateMenus(["View", "Command Palette..."])
|
||||
|
||||
await this.page.waitForSelector(".quick-input-widget:focus-within")
|
||||
await this.page.keyboard.type(command)
|
||||
|
||||
await this.page.hover(`text=${command}`)
|
||||
|
||||
19
test/e2e/settings.test.ts
Normal file
19
test/e2e/settings.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { promises as fs } from "fs"
|
||||
import * as path from "path"
|
||||
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")
|
||||
})
|
||||
})
|
||||
@@ -18,14 +18,14 @@ describe("Uploads (enabled)", ["--disable-workspace-trust"], {}, () => {
|
||||
// Action
|
||||
await codeServerPage.openContextMenu('span:has-text("test-directory")')
|
||||
|
||||
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(true)
|
||||
await expect(codeServerPage.page.locator("text=Upload...")).toBeVisible()
|
||||
})
|
||||
|
||||
test("should see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
|
||||
// Action
|
||||
await codeServerPage.navigateMenus(["File", "Open File..."])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(true)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -44,13 +44,13 @@ describe("Uploads (disabled)", ["--disable-workspace-trust", "--disable-file-upl
|
||||
// Action
|
||||
await codeServerPage.openContextMenu('span:has-text("test-directory")')
|
||||
|
||||
expect(await codeServerPage.page.isVisible("text=Upload...")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=Upload...")).not.toBeVisible()
|
||||
})
|
||||
|
||||
test("should not see the 'Show Local' button on Open File", async ({ codeServerPage }) => {
|
||||
// Action
|
||||
await codeServerPage.navigateMenus(["File", "Open File..."])
|
||||
await codeServerPage.page.waitForSelector(".quick-input-widget")
|
||||
expect(await codeServerPage.page.isVisible("text=Show Local")).toBe(false)
|
||||
await expect(codeServerPage.page.locator("text=Show Local")).not.toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
955
test/package-lock.json
generated
955
test/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user