Compare commits

...

20 Commits

Author SHA1 Message Date
Joe Previte
c96202528f chore: bump version to 2.5.0 in Chart.yaml 2022-05-06 10:37:15 -07:00
Joe Previte
200f7fe5ec Merge branch 'main' into v4.4.0 2022-05-06 10:04:38 -07:00
Joe Previte
5a5798e45f fix(update): add OrEqual to update.checked test (#5171)
* fix(update): add OrEqual to update.checked test

* fixup!: change all instances to OrEqual

* fixup!: add missing equals

* fixup!: consistency
2022-05-06 16:51:44 +00:00
Joe Previte
6e2086dcd4 chore: update CHANGELOG with v4.4.0 2022-05-06 08:44:49 -07:00
Joe Previte
9d1c8c7869 chore(release): bump version to 4.4.0 2022-05-06 08:24:50 -07:00
Feng Yu
66a364358a chore: upgrade developmemt node version to v16 (#5167)
Co-authored-by: yufeng.freeman <yufeng.freeman@bytedance.com>
2022-05-06 09:57:19 -05:00
Asher
ef0d76bc16 fix: patch telemetry (#5158)
This seems to have been dropped in the rewrite.
2022-05-04 18:32:12 -05:00
Joe Previte
88e971c609 refactor(heart): bind class methods and make beat async (#5142)
* feat: set up new test for beat twice

* refactor: make Heart.beat() async

This allows us to properly await heart.beat() in our tests and remove
the HACK I added before.

* refactor: bind heart methods .beat and .alive

This allows the functions to maintain access to the Heart instance (or
`this`) even when they are passed to other functions. We do this because
we pass both `isActive` and `beat` to `heartbeatTimer`.

* feat(heart): add test to ensure no warnings called

* fixup!: revert setTimeout for heartbeatTimer

* fixup!: return promise in beat
2022-05-04 16:05:48 -07:00
Joe Previte
7027ec7d60 chore: upgrade Code to 1.66 (#5135)
* chore: upgrade Code to 1.66

* docs: update docs for Code upgrades

* fixup!: docs

* chore: update vscode submodule

* chore: update integration patch

* chore: update node-version patch

* chore: update github-auth patch

They completely changed how auth is handled for GitHub in
https://github.com/microsoft/vscode/pull/145424 so our patch may not
work. Will need to test and revisit.

* refactor: remove postinstall patch

It appears they renamed postinstall.js to postinstall.mjs and removed
the use of `rimraf` which means our patch is no longer needed! 🎉

b0e8554cce

* chore: refresh local-storage patch

* chore: refresh service-worker patch

* chore: bulk refresh patches

* fixup!: docs formatting

* refactor: remove unused last-opened patch

* fixup!: formatting docs

* fixup!: formatting docs

* refactor: remove rsync postinstall

* Revert "refactor: remove rsync postinstall"

This reverts commit 8d6b613e9d.

* refactor: update postinstall.js to .mjs

* feat(patches): add parent-origin bypass

* docs(patches): add notes for testing store-socket

* docs(patches): update testing info for node-version

* refactor(patches): delete github-auth.diff patch

* docs(patches): add notes for testing connection-type

* fixup!: delete github-auth patch

* fixup!: update connection type testing

* docs(patches): add notes to insecure-notification.diff

* docs(patches): add nots for update-check.diff

* fixup!: remove comma in integration patch

* fix(e2e): disable workspace trust

* refactor: add --no-default-rc for yarn install

* feat(patches): remove yarnrc in presinstall

* fixup!: silly mistake

* docs: add note about KEEP_MODULES=1

* docs(patches): add testing notes for node-version

* refactor(patches): remove node-version

It appears this is no longer needed due to the `remote/package.json` now which
targets node rather than electron.

* fixup!: add cd ../.. to code upgrade instructions

* fixup!: add note to yarn --production flag

* fixup!: make parent-origin easier to upstream

* Revert "refactor(patches): delete github-auth.diff patch"

This reverts commit 31a354a343.

* Revert "fixup!: delete github-auth patch"

This reverts commit bdeb5212e8.

* Merge webview origin patch into webview patch

* Remove unused post-install patch

* Prevent builtin extensions from updating

* Refresh sourcemaps patch

* Update Node to v16

This matches the version in ./lib/vscode/remote/.yarnrc.

I changed the engine to exactly 16 since if you use any different
version it will just not work since the modules will have been built for
16 (due to the .yarnrc).

* Replace fs.rmdir with fs.rm

Node is showing a deprecation warning about it.

* Update github-auth patch

The local credentials provider is no longer used when there is a remote
so this code moved into the backend web credential provider.

* Prevent fs.rm from erroring about non-existent files

We were using fs.rmdir which presumably did not have the same behavior
in v14 (in v16 fs.rmdir also errors).

* Install Python 3 in CentOS CI container

Co-authored-by: Asher <ash@coder.com>
2022-05-04 21:58:49 +00:00
Asher
4e93db5b95 feat: relaunch on SIGUSR2 (#4979)
This is because Node uses SIGUSR1 to enable the debug listener so even
if you just want to restart code-server you end up enabling the debug
listener as well.

Opted to leave the SIGUSR1 handler in to avoid breaking existing
workflows even though it does mean even if you only want to enable the
debug listener you will end up restarting code-server as well.  We could
consider removing it after a transition phase.
2022-04-27 10:10:48 -05:00
renovate[bot]
fc75db6edc chore(deps): update azure/setup-helm action to v2 (#5088)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-04-26 21:48:39 +00:00
Joe Previte
e3c8bd692c feat(cli): support true for CS_DISABLE_FILE_DOWNLOADS (#5134)
After some feedback, we realized it is more intuitive to disable file
downloads by setting the environment variable
`CS_DISABLE_FILE_DOWNLOADS` to `true` than `1`. This commit adds support
for both.
2022-04-26 20:09:53 +00:00
mooff
a0b36147ea fix: listening on IPv6 address not possible (#5133)
Wrap IPv6 addresses in square brackets when making URL in ensureAddress,
fixing regression (#1582)
2022-04-26 19:33:51 +00:00
Joe Previte
683412cb01 refactor: add timeout for race condition in heart test (#5131)
* refactor: add timeout for race condition in heart test

* fixup!: set mtime to 0 and check for update

* fixup!: use utimes directly instead of file open

* fixup!: remove import
2022-04-26 17:39:37 +00:00
Joe Previte
18ff99693b feat: add tests for node/heart.ts (#5122)
* refactor(heart): extract logic into heartbeatTimer fn

To make it easier to test, I extract heartbeatTimer into it's own
function.

* feat(testing): add tests for heart.ts

* fixup

* fixup!: remove unneeded heart call

* Update src/node/heart.ts

Co-authored-by: Asher <ash@coder.com>

* fixup!: use mockResolvedValue everywhere

* fixup!: add stat test for timestamp check

Co-authored-by: Asher <ash@coder.com>
2022-04-26 16:35:40 +00:00
renovate[bot]
ed7bd2e65b chore(deps): update github/codeql-action action to v2 (#5129)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-25 15:39:32 -07:00
Asher
c35bf1311e chore: provide details when update.checked tests fail (#5115)
Using the toBe* functions will let us know what the actual values are
rather than just telling us true does not equal false.
2022-04-19 15:46:23 -05:00
renovate[bot]
7780a13cce chore(deps): update aquasecurity/trivy-action digest to 2b30463 (#5098)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-04-19 11:37:47 -07:00
Joe Previte
dea6a40ea8 chore: attempt to fix docker (#5106)
* chore: attempt to fix docker

* Update .github/workflows/docker.yaml

Co-authored-by: Asher <ash@coder.com>

* chore: add publish:docker to scripts

Co-authored-by: Asher <ash@coder.com>
2022-04-15 00:02:03 +00:00
Joe Previte
09fc64a4f0 v4.3.0 (#5099)
* chore(release): bump version to 4.3.0

* fix(release-prep.sh): ignore lib/vscode

* docs(CHANGELOG): add 4.3.0

* chore: bump chart version

* fixup!: remove change in postinstall

* fixup!: bullets in CHANGELOG

* fixup!: formatting

* fixup! typo in changelog

* fixup!: update date in changelog

Co-authored-by: Asher <ash@coder.com>
2022-04-14 15:37:25 -07:00
60 changed files with 778 additions and 404 deletions

View File

@@ -33,13 +33,13 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Install helm - name: Install helm
uses: azure/setup-helm@v1.1 uses: azure/setup-helm@v2.1
- name: Fetch dependencies from cache - name: Fetch dependencies from cache
id: cache-yarn id: cache-yarn
@@ -74,10 +74,10 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Fetch dependencies from cache - name: Fetch dependencies from cache
id: cache-yarn id: cache-yarn
@@ -116,10 +116,10 @@ jobs:
- name: Patch Code - name: Patch Code
run: quilt push -a run: quilt push -a
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Fetch dependencies from cache - name: Fetch dependencies from cache
id: cache-yarn id: cache-yarn
@@ -253,15 +253,15 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Install development tools - name: Install development tools
run: | run: |
yum install -y epel-release centos-release-scl yum install -y epel-release centos-release-scl
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync python3
- name: Install nfpm and envsubst - name: Install nfpm and envsubst
run: | run: |
@@ -337,7 +337,7 @@ jobs:
CXX: ${{ format('{0}-g++', matrix.prefix) }} CXX: ${{ format('{0}-g++', matrix.prefix) }}
LINK: ${{ format('{0}-g++', matrix.prefix) }} LINK: ${{ format('{0}-g++', matrix.prefix) }}
NPM_CONFIG_ARCH: ${{ matrix.arch }} NPM_CONFIG_ARCH: ${{ matrix.arch }}
NODE_VERSION: v14.17.4 NODE_VERSION: v16.13.0
steps: steps:
- name: Checkout repo - name: Checkout repo
@@ -345,10 +345,10 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Install nfpm - name: Install nfpm
run: | run: |
@@ -397,10 +397,10 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Install nfpm - name: Install nfpm
run: | run: |
@@ -446,10 +446,10 @@ jobs:
fetch-depth: 0 fetch-depth: 0
submodules: true submodules: true
- name: Install Node.js v14 - name: Install Node.js v16
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: "14" node-version: "16"
- name: Fetch dependencies from cache - name: Fetch dependencies from cache
id: cache-yarn id: cache-yarn
@@ -506,7 +506,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode - name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@40c4ca9e7421287d0c5576712fdff370978f9c3c uses: aquasecurity/trivy-action@2b30463ddb3d11724a04e760e020c7d9af24d8b3
with: with:
scan-type: "fs" scan-type: "fs"
scan-ref: "." scan-ref: "."
@@ -517,6 +517,6 @@ jobs:
severity: "HIGH,CRITICAL" severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab - name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v1 uses: github/codeql-action/upload-sarif@v2
with: with:
sarif_file: "trivy-repo-results.sarif" sarif_file: "trivy-repo-results.sarif"

View File

@@ -35,13 +35,13 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v1 uses: github/codeql-action/init@v2
with: with:
config-file: ./.github/codeql-config.yml config-file: ./.github/codeql-config.yml
languages: javascript languages: javascript
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v1 uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1 uses: github/codeql-action/analyze@v2

View File

@@ -39,17 +39,15 @@ jobs:
id: version id: version
run: echo "::set-output name=version::$(jq -r .version package.json)" run: echo "::set-output name=version::$(jq -r .version package.json)"
- name: Download artifact - name: Download release artifacts
uses: dawidd6/action-download-artifact@v2 uses: robinraju/release-downloader@v1.3
id: download
with: with:
branch: v${{ steps.version.outputs.version }} repository: "coder/code-server"
workflow: ci.yaml tag: v${{ steps.version.outputs.version }}
workflow_conclusion: completed fileName: "*.deb"
name: "release-packages" out-file-path: "release-packages"
path: release-packages
- name: Run ./ci/steps/docker-buildx-push.sh - name: Publish to Docker
run: ./ci/steps/docker-buildx-push.sh run: yarn publish:docker
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}

View File

@@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Run Trivy vulnerability scanner in image mode - name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@40c4ca9e7421287d0c5576712fdff370978f9c3c uses: aquasecurity/trivy-action@2b30463ddb3d11724a04e760e020c7d9af24d8b3
with: with:
image-ref: "docker.io/codercom/code-server:latest" image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true ignore-unfixed: true
@@ -60,6 +60,6 @@ jobs:
severity: "HIGH,CRITICAL" severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab - name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v1 uses: github/codeql-action/upload-sarif@v2
with: with:
sarif_file: "trivy-image-results.sarif" sarif_file: "trivy-image-results.sarif"

View File

@@ -1 +1 @@
14 16

View File

@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [9.99.999] - 9090-09-09 ## [9.99.999] - 9090-09-09
VS Code v99.99.999 Code v99.99.999
### Changed ### Changed
### Added ### Added
@@ -20,6 +20,57 @@ VS Code v99.99.999
--> -->
## [4.4.0](https://github.com/coder/code-server/releases/tag/v4.4.0) - 2022-05-06
Code v1.66.2
### Changed
- Refactored methods in `Heart` class and made `Heart.beat()` async to make
testing easier.
- Upgraded to Code 1.66.2.
### Added
- Added back telemetry patch which was removed in the Code reachitecture.
- Added support to use `true` for `CS_DISABLE_FILE_DOWNLOADS` environment
variable. This means you can disable file downloads by setting
`CS_DISABLE_FILE_DOWNLOADS` to `true` or `1`.
- Added tests for `Heart` class.
### Fixed
- Fixed installation issue in AUR after LICENSE rename.
- Fixed issue with listening on IPv6 addresses.
- Fixed issue with Docker publish action not being able to find artifacts. Now
it downloads the release assets from the release.
## [4.3.0](https://github.com/coder/code-server/releases/tag/v4.3.0) - 2022-04-14
Code v1.65.2
### Changed
- Excluded .deb files from release Docker image which drops the compressed and
uncompressed size by 58% and 34%.
- Upgraded to Code 1.65.2.
### Added
- Added a new CLI flag called `--disable-file-downloads` which allows you to
disable the "Download..." option that shows in the UI when right-clicking on a
file. This can also set by running `CS_DISABLE_FILE_DOWNLOADS=1`.
- Aligned the dependencies for binary and npm release artifacts.
### Fixed
- Fixed the code-server version from not displaying in the Help > About dialog.
- Fixed issues with the TypeScript and JavaScript Language Features Extension
failing to activate.
- Fixed missing files in ipynb extension.
- Fixed the homebrew release workflow.
- Fixed the Docker release workflow from not always publishing version tags.
## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22 ## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22
Code v1.64.2 Code v1.64.2

View File

@@ -146,7 +146,7 @@ EOF
# Include global extension dependencies as well. # Include global extension dependencies as well.
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json" rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions/yarn.lock" rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions/yarn.lock"
rsync "$VSCODE_SRC_PATH/extensions/postinstall.js" "$VSCODE_OUT_PATH/extensions/postinstall.js" rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
pushd "$VSCODE_OUT_PATH" pushd "$VSCODE_OUT_PATH"
symlink_asar symlink_asar

View File

@@ -33,8 +33,8 @@ main() {
echo "USE AT YOUR OWN RISK!" echo "USE AT YOUR OWN RISK!"
fi fi
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-14}" ]; then if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-16}" ]; then
echo "ERROR: code-server currently requires node v14." echo "ERROR: code-server currently requires node v16."
if [ -n "$FORCE_NODE_VERSION" ]; then if [ -n "$FORCE_NODE_VERSION" ]; then
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION." echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
fi fi
@@ -92,7 +92,7 @@ symlink_asar() {
vscode_yarn() { vscode_yarn() {
echo 'Installing Code dependencies...' echo 'Installing Code dependencies...'
cd lib/vscode cd lib/vscode
yarn --production --frozen-lockfile yarn --production --frozen-lockfile --no-default-rc
symlink_asar symlink_asar

View File

@@ -81,7 +81,7 @@ main() {
read -r -p "What version of code-server do you want to update to?"$'\n' CODE_SERVER_VERSION_TO_UPDATE read -r -p "What version of code-server do you want to update to?"$'\n' CODE_SERVER_VERSION_TO_UPDATE
echo -e "Great! We'll prep a PR for updating to $CODE_SERVER_VERSION_TO_UPDATE\n" echo -e "Great! We'll prep a PR for updating to $CODE_SERVER_VERSION_TO_UPDATE\n"
$CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE" $CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' -g '!lib/vscode/**' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE"
$CMD git commit --no-verify -am "chore(release): bump version to $CODE_SERVER_VERSION_TO_UPDATE" $CMD git commit --no-verify -am "chore(release): bump version to $CODE_SERVER_VERSION_TO_UPDATE"

View File

@@ -7,6 +7,9 @@ install-deps() {
if [[ ${CI-} ]]; then if [[ ${CI-} ]]; then
args+=(--frozen-lockfile) args+=(--frozen-lockfile)
fi fi
if [[ "$1" == "lib/vscode" ]]; then
args+=(--no-default-rc)
fi
# If there is no package.json then yarn will look upward and end up installing # If there is no package.json then yarn will look upward and end up installing
# from the root resulting in an infinite loop (this can happen if you have not # from the root resulting in an infinite loop (this can happen if you have not
# checked out the submodule yet for example). # checked out the submodule yet for example).

View File

@@ -15,9 +15,9 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 2.3.0 version: 2.5.0
# This is the version number of the application being deployed. This version number should be # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to # incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using. # follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.2.0 appVersion: 4.4.0

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image: image:
repository: codercom/code-server repository: codercom/code-server
tag: '4.2.0' tag: '4.4.0'
pullPolicy: Always pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a # Specifies one or more secrets to be used when pulling images from a

View File

@@ -31,7 +31,7 @@ for [VS
Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites). Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Here is what is needed: Here is what is needed:
- `node` v14.x - `node` v16.x
- `git` v2.x or greater - `git` v2.x or greater
- [`git-lfs`](https://git-lfs.github.com) - [`git-lfs`](https://git-lfs.github.com)
- [`yarn`](https://classic.yarnpkg.com/en/) - [`yarn`](https://classic.yarnpkg.com/en/)
@@ -96,6 +96,8 @@ re-apply the patches.
### Version updates to Code ### Version updates to Code
1. Update the `lib/vscode` submodule to the desired upstream version branch. 1. Update the `lib/vscode` submodule to the desired upstream version branch.
1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
2. `git add lib && git commit -m "chore: update Code"`
2. Apply the patches (`quilt push -a`) or restore your stashed changes. At this 2. Apply the patches (`quilt push -a`) or restore your stashed changes. At this
stage you may need to resolve conflicts. For example use `quilt push -f`, stage you may need to resolve conflicts. For example use `quilt push -f`,
manually apply the rejected portions, then `quilt refresh`. manually apply the rejected portions, then `quilt refresh`.
@@ -130,11 +132,13 @@ yarn build:vscode
yarn release yarn release
``` ```
_NOTE: this does not keep `node_modules`. If you want them to be kept, use `KEEP_MODULES=1 yarn release` (if you're testing in Coder, you'll want to do this)_
Run your build: Run your build:
```shell ```shell
cd release cd release
yarn --production yarn --production # Skip if you used KEEP_MODULES=1
# Runs the built JavaScript with Node. # Runs the built JavaScript with Node.
node . node .
``` ```

View File

@@ -164,7 +164,7 @@ If you're the current release manager, follow these steps:
### Publishing a release ### Publishing a release
1. Create a new branch called `v0.0.0` (replace 0s with actual version aka v4.2.0) 1. Create a new branch called `v0.0.0` (replace 0s with actual version aka v4.4.0)
1. Run `yarn release:prep` and type in the new version (e.g., `3.8.1`) 1. Run `yarn release:prep` and type in the new version (e.g., `3.8.1`)
1. GitHub Actions will generate the `npm-package`, `release-packages` and 1. GitHub Actions will generate the `npm-package`, `release-packages` and
`release-images` artifacts. You do not have to wait for this step to complete `release-images` artifacts. You do not have to wait for this step to complete

View File

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

View File

@@ -60,6 +60,6 @@ As `code-server` is based on VS Code, you can follow the steps described on Duck
code-server --enable-proposed-api genuitecllc.codetogether code-server --enable-proposed-api genuitecllc.codetogether
``` ```
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.2.0/FAQ#how-does-the-config-file-work). Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.4.0/FAQ#how-does-the-config-file-work).
3. Refresh code-server and navigate to the CodeTogether icon in the sidebar to host or join a coding session. 3. Refresh code-server and navigate to the CodeTogether icon in the sidebar to host or join a coding session.

View File

@@ -1,6 +1,6 @@
# code-server Helm Chart # code-server Helm Chart
[![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)](https://img.shields.io/badge/Type-application-informational?style=flat-square) [![AppVersion: 4.2.0](https://img.shields.io/badge/AppVersion-4.2.0-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-4.2.0-informational?style=flat-square) [![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)](https://img.shields.io/badge/Type-application-informational?style=flat-square) [![AppVersion: 4.4.0](https://img.shields.io/badge/AppVersion-4.4.0-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-4.4.0-informational?style=flat-square)
[code-server](https://github.com/coder/code-server) code-server is VS Code running [code-server](https://github.com/coder/code-server) code-server is VS Code running
on a remote server, accessible through the browser. on a remote server, accessible through the browser.
@@ -73,7 +73,7 @@ and their default values.
| hostnameOverride | string | `""` | | hostnameOverride | string | `""` |
| image.pullPolicy | string | `"Always"` | | image.pullPolicy | string | `"Always"` |
| image.repository | string | `"codercom/code-server"` | | image.repository | string | `"codercom/code-server"` |
| image.tag | string | `"4.2.0"` | | image.tag | string | `"4.4.0"` |
| imagePullSecrets | list | `[]` | | imagePullSecrets | list | `[]` |
| ingress.enabled | bool | `false` | | ingress.enabled | bool | `false` |
| nameOverride | string | `""` | | nameOverride | string | `""` |

View File

@@ -1,5 +1,5 @@
{ {
"versions": ["v4.2.0"], "versions": ["v4.4.0"],
"routes": [ "routes": [
{ {
"title": "Home", "title": "Home",
@@ -73,7 +73,7 @@
{ {
"title": "Upgrade", "title": "Upgrade",
"description": "How to upgrade code-server.", "description": "How to upgrade code-server.",
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.35028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z\"/><path d=\"M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0.12 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z\"/><path d=\"M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944 3.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z\"/><path d=\"M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z\"/></svg>", "icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.4.028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z\"/><path d=\"M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0.12 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z\"/><path d=\"M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944.4.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z\"/><path d=\"M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z\"/></svg>",
"path": "./upgrade.md" "path": "./upgrade.md"
}, },
{ {

View File

@@ -22,8 +22,8 @@ includes installing instructions based on your operating system.
## Node.js version ## Node.js version
We use the same major version of Node.js shipped with VSCode's Electron, We use the same major version of Node.js shipped with Code's remote, which is
which is currently `14.x`. VS Code also [lists Node.js currently `16.x`. VS Code also [lists Node.js
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites). requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Using other versions of Node.js [may lead to unexpected Using other versions of Node.js [may lead to unexpected
@@ -72,7 +72,7 @@ Proceed to [installing](#installing)
## FreeBSD ## FreeBSD
```sh ```sh
pkg install -y git python npm-node14 yarn-node14 pkgconf pkg install -y git python npm-node16 yarn-node16 pkgconf
pkg install -y libinotify pkg install -y libinotify
``` ```

View File

@@ -1,7 +1,7 @@
{ {
"name": "code-server", "name": "code-server",
"license": "MIT", "license": "MIT",
"version": "4.2.0", "version": "4.4.0",
"description": "Run VS Code on a remote server.", "description": "Run VS Code on a remote server.",
"homepage": "https://github.com/coder/code-server", "homepage": "https://github.com/coder/code-server",
"bugs": { "bugs": {
@@ -24,6 +24,7 @@
"package": "./ci/build/build-packages.sh", "package": "./ci/build/build-packages.sh",
"postinstall": "./ci/dev/postinstall.sh", "postinstall": "./ci/dev/postinstall.sh",
"publish:npm": "./ci/steps/publish-npm.sh", "publish:npm": "./ci/steps/publish-npm.sh",
"publish:docker": "./ci/steps/docker-buildx-push.sh",
"_audit": "./ci/dev/audit.sh", "_audit": "./ci/dev/audit.sh",
"fmt": "./ci/dev/fmt.sh", "fmt": "./ci/dev/fmt.sh",
"lint": "./ci/dev/lint.sh", "lint": "./ci/dev/lint.sh",
@@ -121,7 +122,7 @@
"browser-ide" "browser-ide"
], ],
"engines": { "engines": {
"node": ">= 14" "node": "16"
}, },
"jest": { "jest": {
"transform": { "transform": {

View File

@@ -159,7 +159,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -252,7 +252,10 @@ export class WebClientServer { @@ -253,7 +253,10 @@ export class WebClientServer {
return res.end(); return res.end();
} }
@@ -171,7 +171,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
function escapeAttribute(value: string): string { function escapeAttribute(value: string): string {
return value.replace(/"/g, '&quot;'); return value.replace(/"/g, '&quot;');
@@ -272,6 +275,8 @@ export class WebClientServer { @@ -275,6 +278,8 @@ export class WebClientServer {
accessToken: this._environmentService.args['github-auth'], accessToken: this._environmentService.args['github-auth'],
scopes: [['user:email'], ['repo']] scopes: [['user:email'], ['repo']]
} : undefined; } : undefined;
@@ -180,15 +180,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const data = (await util.promisify(fs.readFile)(filePath)).toString() const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({ .replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority, remoteAuthority,
@@ -279,6 +284,7 @@ export class WebClientServer { @@ -285,6 +290,7 @@ export class WebClientServer {
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined }, folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{ productConfiguration: <Partial<IProductConfiguration>>{
+ rootEndpoint: base, + rootEndpoint: base,
codeServerVersion: this._productService.codeServerVersion, codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro', embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate ? { extensionsGallery: this._webExtensionResourceUrlTemplate ? {
@@ -291,7 +297,9 @@ export class WebClientServer { @@ -297,7 +303,9 @@ export class WebClientServer {
} : undefined } : undefined
} }
}))) })))
@@ -199,7 +199,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const cspDirectives = [ const cspDirectives = [
'default-src \'self\';', 'default-src \'self\';',
@@ -370,3 +378,70 @@ export class WebClientServer { @@ -376,3 +384,70 @@ export class WebClientServer {
return res.end(data); return res.end(data);
} }
} }

View File

@@ -4,12 +4,18 @@ This allows the backend to distinguish them. In our case we use them to count a
single "open" of Code so we need to be able to distinguish between web sockets single "open" of Code so we need to be able to distinguish between web sockets
from two instances and two web sockets used in a single instance. from two instances and two web sockets used in a single instance.
To test this,
1. Run code-server
2. Open Network tab in Browser DevTools and filter for websocket requests
3. You should see the `type=<connection-type>` in the request url
Index: code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts Index: code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts --- code-server.orig/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
+++ code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts +++ code-server/lib/vscode/src/vs/platform/remote/common/remoteAgentConnection.ts
@@ -231,7 +231,7 @@ async function connectToRemoteExtensionH @@ -231,7 +231,7 @@ async function connectToRemoteExtensionH
let socket: ISocket; let socket: ISocket;
try { try {
- socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken); - socket = await createSocket(options.logService, options.socketFactory, options.host, options.port, `reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`, `renderer-${connectionTypeToString(connectionType)}-${options.reconnectionToken}`, timeoutCancellationToken);

View File

@@ -0,0 +1,30 @@
Prevent builtin extensions from being updated
Updating builtin extensions from the marketplace prevents us from patching them
(for example out GitHub authentication patches).
Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
@@ -206,6 +206,9 @@ export class Extension implements IExten
if (!this.gallery || !this.local) {
return false;
}
+ if (this.type !== ExtensionType.User) {
+ return false;
+ }
if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
return false;
}
@@ -1057,6 +1060,10 @@ export class ExtensionsWorkbenchService
// Skip if check updates only for builtin extensions and current extension is not builtin.
continue;
}
+ if (installed.type !== ExtensionType.User) {
+ // Never update builtin extensions.
+ continue;
+ }
if (installed.isBuiltin && !installed.local?.identifier.uuid) {
// Skip if the builtin extension does not have Marketplace id
continue;

View File

@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts +++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -210,6 +210,11 @@ export interface IWorkbenchConstructionO @@ -215,6 +215,11 @@ export interface IWorkbenchConstructionO
*/ */
readonly userDataPath?: string readonly userDataPath?: string
@@ -66,7 +66,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */ /* ----- server setup ----- */
@@ -92,6 +93,7 @@ export interface ServerParsedArgs { @@ -96,6 +97,7 @@ export interface ServerParsedArgs {
'disable-update-check'?: boolean; 'disable-update-check'?: boolean;
'auth'?: string 'auth'?: string
'locale'?: string 'locale'?: string
@@ -78,14 +78,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -290,6 +290,7 @@ export class WebClientServer { @@ -293,6 +293,7 @@ export class WebClientServer {
logLevel: this._logService.getLevel(), logLevel: this._logService.getLevel(),
}, },
userDataPath: this._environmentService.userDataPath, userDataPath: this._environmentService.userDataPath,
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'], + isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{ enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
rootEndpoint: base, folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts --- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -135,7 +135,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts --- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
@@ -21,7 +21,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID, @@ -22,7 +22,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService'; import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
@@ -144,7 +144,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys'; import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -475,13 +475,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo @@ -476,13 +476,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID, id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL title: DOWNLOAD_LABEL
}, },

View File

@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts --- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts +++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
@@ -188,6 +188,9 @@ export async function setupServerService @@ -192,6 +192,9 @@ export async function setupServerService
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority)); const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
socketServer.registerChannel('extensions', channel); socketServer.registerChannel('extensions', channel);
@@ -94,7 +94,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentServ
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts --- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
+++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts +++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
@@ -105,7 +105,7 @@ export abstract class AbstractNativeEnvi @@ -108,7 +108,7 @@ export abstract class AbstractNativeEnvi
return URI.file(join(vscodePortable, 'argv.json')); return URI.file(join(vscodePortable, 'argv.json'));
} }
@@ -168,7 +168,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri' @@ -27,6 +27,7 @@ import { URI } from 'vs/base/common/uri'
import { streamToBuffer } from 'vs/base/common/buffer'; import { streamToBuffer } from 'vs/base/common/buffer';
import { IProductConfiguration } from 'vs/base/common/product'; import { IProductConfiguration } from 'vs/base/common/product';
import { isString } from 'vs/base/common/types'; import { isString } from 'vs/base/common/types';
@@ -176,7 +176,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const textMimeType = { const textMimeType = {
'.html': 'text/html', '.html': 'text/html',
@@ -277,6 +278,8 @@ export class WebClientServer { @@ -280,6 +281,8 @@ export class WebClientServer {
} : undefined; } : undefined;
const base = relativeRoot(getOriginalUrl(req)) const base = relativeRoot(getOriginalUrl(req))
const vscodeBase = relativePath(getOriginalUrl(req)) const vscodeBase = relativePath(getOriginalUrl(req))
@@ -185,7 +185,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
const data = (await util.promisify(fs.readFile)(filePath)).toString() const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({ .replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority, remoteAuthority,
@@ -303,7 +306,8 @@ export class WebClientServer { @@ -309,7 +312,8 @@ export class WebClientServer {
}))) })))
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '') .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
.replace(/{{BASE}}/g, base) .replace(/{{BASE}}/g, base)
@@ -207,7 +207,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */ /* ----- server setup ----- */
@@ -90,6 +91,7 @@ export interface ServerParsedArgs { @@ -94,6 +95,7 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */ /* ----- code-server ----- */
'disable-update-check'?: boolean; 'disable-update-check'?: boolean;
'auth'?: string 'auth'?: string
@@ -252,7 +252,7 @@ Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts --- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts +++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
@@ -111,6 +111,10 @@ registerSingleton(IDiagnosticsService, N @@ -112,6 +112,10 @@ registerSingleton(IDiagnosticsService, N
//#region --- workbench contributions //#region --- workbench contributions

View File

@@ -1,118 +1,104 @@
Use our own GitHub auth relay server Add the ability to provide a GitHub token
Microsoft's does not work with self-hosted instances so we run our own. To test install the GitHub PR extension and start code-server with GITHUB_TOKEN
or set github-auth in the config file. The extension should be authenticated.
Also add an extra set of scopes so that tokens provided via --github-auth will Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
work for the PR extension.
Index: code-server/lib/vscode/extensions/github-authentication/src/githubServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/extensions/github-authentication/src/githubServer.ts --- code-server.orig/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
+++ code-server/lib/vscode/extensions/github-authentication/src/githubServer.ts +++ code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
@@ -17,7 +17,7 @@ const localize = nls.loadMessageBundle() @@ -5,18 +5,32 @@
const CLIENT_ID = '01ab8ac9400c4e429b23';
const NETWORK_ERROR = 'network error'; import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials';
-const AUTH_RELAY_SERVER = 'vscode-auth.github.com'; import { ILogService } from 'vs/platform/log/common/log';
+const AUTH_RELAY_SERVER = 'auth.code-server.dev'; -import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
// const AUTH_RELAY_STAGING_SERVER = 'client-auth-staging-14a768b.herokuapp.com'; +import { IServerEnvironmentService } from 'vs/server/node/serverEnvironmentService';
import { IProductService } from 'vs/platform/product/common/productService';
class UriEventHandler extends vscode.EventEmitter<vscode.Uri> implements vscode.UriHandler { import { BaseCredentialsMainService, KeytarModule } from 'vs/platform/credentials/common/credentialsMainService';
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts +import { generateUuid } from 'vs/base/common/uuid';
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -274,7 +274,7 @@ export class WebClientServer {
id: generateUuid(),
providerId: 'github',
accessToken: this._environmentService.args['github-auth'],
- scopes: [['user:email'], ['repo']]
+ scopes: [['read:user', 'user:email', 'repo'], ['user:email'], ['repo']]
} : undefined;
const base = relativeRoot(getOriginalUrl(req))
const vscodeBase = relativePath(getOriginalUrl(req))
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -17,6 +17,7 @@ import { isFolderToOpen, isWorkspaceToOp
import { create, ICredentialsProvider, IURLCallbackProvider, IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from 'vs/workbench/workbench.web.main';
import { posix } from 'vs/base/common/path';
import { ltrim } from 'vs/base/common/strings';
+import { equals as arrayEquals } from 'vs/base/common/arrays'; +import { equals as arrayEquals } from 'vs/base/common/arrays';
+
interface ICredential {
service: string;
@@ -24,6 +25,13 @@ interface ICredential {
password: string;
}
+interface IToken { +interface IToken {
+ accessToken: string + accessToken: string
+ account?: { label: string } + account?: { label: string }
+ id: string + id: string
+ scopes: string[] + scopes: string[]
+} +}
+
class LocalStorageCredentialsProvider implements ICredentialsProvider {
private static readonly CREDENTIALS_STORAGE_KEY = 'credentials.provider'; export class CredentialsWebMainService extends BaseCredentialsMainService {
@@ -51,6 +59,58 @@ class LocalStorageCredentialsProvider im
scopes, constructor(
accessToken: authSessionInfo!.accessToken @ILogService logService: ILogService,
})))); - @INativeEnvironmentService private readonly environmentMainService: INativeEnvironmentService,
+ + @IServerEnvironmentService private readonly environmentMainService: IServerEnvironmentService,
+ // Add tokens for extensions to use. This works for extensions like the @IProductService private readonly productService: IProductService,
+ // pull requests one or GitLens. ) {
+ const extensionId = `vscode.${authSessionInfo.providerId}-authentication`; super(logService);
+ const service = `${product.urlProtocol}${extensionId}`; + if (this.environmentMainService.args["github-auth"]) {
+ const account = `${authSessionInfo.providerId}.auth`; + this.storeGitHubToken(this.environmentMainService.args["github-auth"]).catch((error) => {
+ // Oddly the scopes need to match exactly so we cannot just have one token + this.logService.error('Failed to store provided GitHub token', error)
+ // with all the scopes, instead we have to duplicate the token for each
+ // expected set of scopes.
+ const tokens: IToken[] = authSessionInfo.scopes.map((scopes) => ({
+ id: authSessionInfo!.id,
+ scopes: scopes.sort(), // Sort for comparing later.
+ accessToken: authSessionInfo!.accessToken,
+ }));
+ this.getPassword(service, account).then((raw) => {
+ let existing: {
+ content: IToken[]
+ } | undefined;
+
+ if (raw) {
+ try {
+ const json = JSON.parse(raw);
+ json.content = JSON.parse(json.content);
+ existing = json;
+ } catch (error) {
+ console.log(error);
+ }
+ }
+
+ // Keep tokens for account and scope combinations we do not have in case
+ // there is an extension that uses scopes we have not accounted for (in
+ // these cases the user will need to manually authenticate the extension
+ // through the UI) or the user has tokens for other accounts.
+ if (existing?.content) {
+ existing.content = existing.content.filter((existingToken) => {
+ const scopes = existingToken.scopes.sort();
+ return !(tokens.find((token) => {
+ return arrayEquals(scopes, token.scopes)
+ && token.account?.label === existingToken.account?.label;
+ }))
+ })
+ }
+
+ return this.setPassword(service, account, JSON.stringify({
+ extensionId,
+ ...(existing || {}),
+ content: JSON.stringify([
+ ...tokens,
+ ...(existing?.content || []),
+ ])
+ }));
+ }) + })
} + }
} }
// If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the
@@ -45,4 +59,59 @@ export class CredentialsWebMainService e
}
return this._keytarCache;
}
+
+ private async storeGitHubToken(githubToken: string): Promise<void> {
+ const extensionId = 'vscode.github-authentication';
+ const service = `${await this.getSecretStoragePrefix()}${extensionId}`;
+ const account = 'github.auth';
+ const scopes = [['read:user', 'user:email', 'repo']]
+
+ // Oddly the scopes need to match exactly so we cannot just have one token
+ // with all the scopes, instead we have to duplicate the token for each
+ // expected set of scopes.
+ const tokens: IToken[] = scopes.map((scopes) => ({
+ id: generateUuid(),
+ scopes: scopes.sort(), // Sort for comparing later.
+ accessToken: githubToken,
+ }));
+
+ const raw = await this.getPassword(service, account)
+
+ let existing: {
+ content: IToken[]
+ } | undefined;
+
+ if (raw) {
+ try {
+ const json = JSON.parse(raw);
+ json.content = JSON.parse(json.content);
+ existing = json;
+ } catch (error) {
+ this.logService.error('Failed to parse existing GitHub credentials', error)
+ }
+ }
+
+ // Keep tokens for account and scope combinations we do not have in case
+ // there is an extension that uses scopes we have not accounted for (in
+ // these cases the user will need to manually authenticate the extension
+ // through the UI) or the user has tokens for other accounts.
+ if (existing?.content) {
+ existing.content = existing.content.filter((existingToken) => {
+ const scopes = existingToken.scopes.sort();
+ return !(tokens.find((token) => {
+ return arrayEquals(scopes, token.scopes)
+ && token.account?.label === existingToken.account?.label;
+ }))
+ })
+ }
+
+ return this.setPassword(service, account, JSON.stringify({
+ extensionId,
+ ...(existing || {}),
+ content: JSON.stringify([
+ ...tokens,
+ ...(existing?.content || []),
+ ])
+ }));
+ }
}

View File

@@ -5,7 +5,12 @@ may think code-server is broken. Ideally there would be a notification at the
point where these things are used instead of this though. point where these things are used instead of this though.
To test access over something like an HTTP domain or an IP address (not To test access over something like an HTTP domain or an IP address (not
localhost). localhost). For example:
1. run code-server
2. use ngrok to expose code-server
3. access via HTTP
4. look for notification in bottom right
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
=================================================================== ===================================================================
@@ -15,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
+import { localize } from 'vs/nls'; +import { localize } from 'vs/nls';
+import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
export class CodeServerClient extends Disposable { export class CodeServerClient extends Disposable {
constructor ( constructor (
+ @INotificationService private notificationService: INotificationService, + @INotificationService private notificationService: INotificationService,

View File

@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
import product from 'vs/platform/product/common/product'; import product from 'vs/platform/product/common/product';
import * as perf from 'vs/base/common/performance'; import * as perf from 'vs/base/common/performance';
@@ -33,37 +33,42 @@ const errorReporter: ErrorReporter = { @@ -33,38 +33,43 @@ const errorReporter: ErrorReporter = {
} }
}; };
@@ -34,6 +34,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
-const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data'); -const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
-const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User'); -const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
-const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage'); -const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
-const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
-const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine'); -const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
-args['user-data-dir'] = USER_DATA_PATH; -args['user-data-dir'] = USER_DATA_PATH;
-const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath); -const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
@@ -41,7 +42,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
-args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH; -args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
-args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions'); -args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
- -
-[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => { -[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => {
- try { - try {
- if (!fs.existsSync(f)) { - if (!fs.existsSync(f)) {
- fs.mkdirSync(f, { mode: 0o700 }); - fs.mkdirSync(f, { mode: 0o700 });
@@ -53,6 +54,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
+ const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data'); + const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data');
+ const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User'); + const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
+ const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage'); + const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
+ const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
+ const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine'); + const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
+ args['user-data-dir'] = USER_DATA_PATH; + args['user-data-dir'] = USER_DATA_PATH;
+ const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath); + const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
@@ -60,14 +62,14 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
+ args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH; + args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
+ args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions'); + args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
+ +
+ [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => { + [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => {
+ try { + try {
+ if (!fs.existsSync(f)) { + if (!fs.existsSync(f)) {
+ fs.mkdirSync(f, { mode: 0o700 }); + fs.mkdirSync(f, { mode: 0o700 });
+ } + }
+ } catch (err) { console.error(err); } + } catch (err) { console.error(err); }
+ }); + });
+ return REMOTE_DATA_FOLDER + return REMOTE_DATA_FOLDER;
+} +}
/** /**
@@ -261,9 +263,9 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -279,6 +279,7 @@ export class WebClientServer { @@ -285,6 +285,7 @@ export class WebClientServer {
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined }, folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{ productConfiguration: <Partial<IProductConfiguration>>{
+ codeServerVersion: this._productService.codeServerVersion, + codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro', embedderIdentifier: 'server-distro',

View File

@@ -1,8 +0,0 @@
Remove last opened functionality
This conflicts with our own handling of the last opened workspace. If we wanted
to switch to this we would need to pass through the disable-last-opened flag and
respect it here then remove our own redirction code that handles this.
Our version might be better anyway since it puts the workspace in the URL.

View File

@@ -20,19 +20,19 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -289,6 +289,7 @@ export class WebClientServer { @@ -292,6 +292,7 @@ export class WebClientServer {
enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined, enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
logLevel: this._logService.getLevel(), logLevel: this._logService.getLevel(),
}, },
+ userDataPath: this._environmentService.userDataPath, + userDataPath: this._environmentService.userDataPath,
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{ enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
rootEndpoint: base, folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts --- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts +++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -205,6 +205,11 @@ export interface IWorkbenchConstructionO @@ -210,6 +210,11 @@ export interface IWorkbenchConstructionO
*/ */
readonly configurationDefaults?: Record<string, any>; readonly configurationDefaults?: Record<string, any>;
@@ -52,7 +52,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
get logFile(): URI { return joinPath(this.logsHome, 'window.log'); } get logFile(): URI { return joinPath(this.logsHome, 'window.log'); }
@memoize @memoize
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.userData }); } - get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.vscodeUserData }); }
+ get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); } + get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }
+ +
+ get userDataPath(): string { + get userDataPath(): string {

View File

@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -285,7 +285,10 @@ export class WebClientServer { @@ -288,7 +288,10 @@ export class WebClientServer {
remoteAuthority, remoteAuthority,
webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre', webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
_wrapWebWorkerExtHostInIframe, _wrapWebWorkerExtHostInIframe,
@@ -17,5 +17,5 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
+ logLevel: this._logService.getLevel(), + logLevel: this._logService.getLevel(),
+ }, + },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{ enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
rootEndpoint: base, folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),

View File

@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */ /* ----- server setup ----- */
@@ -88,6 +89,7 @@ export const serverOptions: OptionDescri @@ -92,6 +93,7 @@ export const serverOptions: OptionDescri
export interface ServerParsedArgs { export interface ServerParsedArgs {
/* ----- code-server ----- */ /* ----- code-server ----- */
'disable-update-check'?: boolean; 'disable-update-check'?: boolean;
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -287,6 +287,7 @@ export class WebClientServer { @@ -293,6 +293,7 @@ export class WebClientServer {
productConfiguration: <Partial<IProductConfiguration>>{ productConfiguration: <Partial<IProductConfiguration>>{
rootEndpoint: base, rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined, updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,

View File

@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -287,14 +287,14 @@ export class WebClientServer { @@ -293,14 +293,14 @@ export class WebClientServer {
rootEndpoint: base, rootEndpoint: base,
codeServerVersion: this._productService.codeServerVersion, codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro', embedderIdentifier: 'server-distro',

View File

@@ -1,107 +0,0 @@
Patch the Node version to use the current version of Node
Previously it would use the yarnrc which results in builds that cannot run with
the version of Node they were built with because the native modules are
targeting the wrong version.
One way test this is to build in a fresh Docker container, run the build, then
try opening the built-in terminal.
Index: code-server/lib/vscode/build/gulpfile.reh.js
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
+++ code-server/lib/vscode/build/gulpfile.reh.js
@@ -124,9 +124,7 @@ const serverWithWebEntryPoints = [
];
function getNodeVersion() {
- const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8');
- const target = /^target "(.*)"$/m.exec(yarnrc)[1];
- return target;
+ return process.versions.node;
}
const nodeVersion = getNodeVersion();
Index: code-server/lib/vscode/build/lib/node.js
===================================================================
--- code-server.orig/lib/vscode/build/lib/node.js
+++ code-server/lib/vscode/build/lib/node.js
@@ -7,9 +7,7 @@ Object.defineProperty(exports, "__esModu
const path = require("path");
const fs = require("fs");
const root = path.dirname(path.dirname(__dirname));
-const yarnrcPath = path.join(root, 'remote', '.yarnrc');
-const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
-const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1];
+const version = process.versions.node;
const platform = process.platform;
const arch = platform === 'darwin' ? 'x64' : process.arch;
const node = platform === 'win32' ? 'node.exe' : 'node';
Index: code-server/lib/vscode/build/lib/node.ts
===================================================================
--- code-server.orig/lib/vscode/build/lib/node.ts
+++ code-server/lib/vscode/build/lib/node.ts
@@ -7,9 +7,7 @@ import * as path from 'path';
import * as fs from 'fs';
const root = path.dirname(path.dirname(__dirname));
-const yarnrcPath = path.join(root, 'remote', '.yarnrc');
-const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
-const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)![1];
+const version = process.versions.node;
const platform = process.platform;
const arch = platform === 'darwin' ? 'x64' : process.arch;
Index: code-server/lib/vscode/build/lib/util.js
===================================================================
--- code-server.orig/lib/vscode/build/lib/util.js
+++ code-server/lib/vscode/build/lib/util.js
@@ -298,9 +298,7 @@ function streamToPromise(stream) {
}
exports.streamToPromise = streamToPromise;
function getElectronVersion() {
- const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
- const target = /^target "(.*)"$/m.exec(yarnrc)[1];
- return target;
+ return process.versions.node;
}
exports.getElectronVersion = getElectronVersion;
function acquireWebNodePaths() {
Index: code-server/lib/vscode/build/lib/util.ts
===================================================================
--- code-server.orig/lib/vscode/build/lib/util.ts
+++ code-server/lib/vscode/build/lib/util.ts
@@ -371,9 +371,7 @@ export function streamToPromise(stream:
}
export function getElectronVersion(): string {
- const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
- const target = /^target "(.*)"$/m.exec(yarnrc)![1];
- return target;
+ return process.versions.node;
}
export function acquireWebNodePaths() {
@@ -455,4 +453,3 @@ export function buildWebNodePaths(outDir
result.taskName = 'build-web-node-paths';
return result;
}
-
Index: code-server/lib/vscode/remote/.yarnrc
===================================================================
--- code-server.orig/lib/vscode/remote/.yarnrc
+++ /dev/null
@@ -1,4 +0,0 @@
-disturl "http://nodejs.org/dist"
-target "14.16.0"
-runtime "node"
-build_from_source "true"
Index: code-server/lib/vscode/.yarnrc
===================================================================
--- code-server.orig/lib/vscode/.yarnrc
+++ /dev/null
@@ -1,4 +0,0 @@
-disturl "https://electronjs.org/headers"
-target "13.5.2"
-runtime "electron"
-build_from_source "true"

View File

@@ -0,0 +1,24 @@
Remove parentOriginHash checko
This fixes webviews from not working properly due to a change upstream.
Upstream added a check to ensure parent authority is encoded into the webview
origin. Since our webview origin is the parent authority, we can bypass this
check.
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
@@ -317,6 +317,12 @@ const hostMessaging = new class HostMess
const id = searchParams.get('id');
const hostname = location.hostname;
+
+ // It is safe to run if we are on the same host.
+ const parent = new URL(parentOrigin)
+ if (parent.hostname == location.hostname) {
+ return start(parentOrigin)
+ }
if (!crypto.subtle) {
// cannot validate, not running in a secure context

View File

@@ -1,26 +0,0 @@
Replace rimraf with fs.rmSync in postinstall
The postinstall gets ran when you install with npm but rimraf is a development
dependency so it will not exist.
Index: code-server/lib/vscode/extensions/postinstall.js
===================================================================
--- code-server.orig/lib/vscode/extensions/postinstall.js
+++ code-server/lib/vscode/extensions/postinstall.js
@@ -8,7 +8,6 @@
const fs = require('fs');
const path = require('path');
-const rimraf = require('rimraf');
const root = path.join(__dirname, 'node_modules', 'typescript');
@@ -21,7 +20,7 @@ function processRoot() {
if (!toKeep.has(name)) {
const filePath = path.join(root, name);
console.log(`Removed ${filePath}`);
- rimraf.sync(filePath);
+ fs.rmSync(filePath, { recursive: true });
}
}
}

View File

@@ -9,7 +9,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstra
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts --- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts +++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
@@ -1163,7 +1163,7 @@ class ProposedApiController { @@ -1471,7 +1471,7 @@ class ProposedApiController {
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id))); this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
@@ -22,7 +22,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts --- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts +++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
@@ -134,10 +134,7 @@ export interface IExtensionHost { @@ -163,10 +163,7 @@ export interface IExtensionHost {
} }
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean { export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {

View File

@@ -68,7 +68,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -288,6 +288,7 @@ export class WebClientServer { @@ -294,6 +294,7 @@ export class WebClientServer {
rootEndpoint: base, rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined, updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined, logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalE
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts --- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
@@ -390,7 +390,7 @@ export function createTerminalEnvironmen @@ -388,7 +388,7 @@ export function createTerminalEnvironmen
// Sanitize the environment, removing any undesirable VS Code and Electron environment // Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables // variables

View File

@@ -1,9 +1,9 @@
integration.diff integration.diff
node-version.diff
base-path.diff base-path.diff
proposed-api.diff proposed-api.diff
marketplace.diff marketplace.diff
webview.diff webview.diff
disable-builtin-ext-update.diff
insecure-notification.diff insecure-notification.diff
update-check.diff update-check.diff
logout.diff logout.diff
@@ -12,10 +12,10 @@ proxy-uri.diff
display-language.diff display-language.diff
github-auth.diff github-auth.diff
unique-db.diff unique-db.diff
post-install.diff
log-level.diff log-level.diff
local-storage.diff local-storage.diff
service-worker.diff service-worker.diff
connection-type.diff connection-type.diff
sourcemaps.diff sourcemaps.diff
disable-downloads.diff disable-downloads.diff
telemetry.diff

View File

@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -298,6 +298,10 @@ export class WebClientServer { @@ -304,6 +304,10 @@ export class WebClientServer {
proxyEndpointTemplate: base + '/proxy/{{port}}', proxyEndpointTemplate: base + '/proxy/{{port}}',
codeServerVersion: this._productService.codeServerVersion, codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro', embedderIdentifier: 'server-distro',

View File

@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.reh.js --- code-server.orig/lib/vscode/build/gulpfile.reh.js
+++ code-server/lib/vscode/build/gulpfile.reh.js +++ code-server/lib/vscode/build/gulpfile.reh.js
@@ -197,8 +197,7 @@ function packageTask(type, platform, arc @@ -191,8 +191,7 @@ function packageTask(type, platform, arc
const src = gulp.src(sourceFolderName + '/**', { base: '.' }) const src = gulp.src(sourceFolderName + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
const workspaceExtensionPoints = ['debuggers', 'jsonValidation']; const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
const isUIExtension = (manifest) => { const isUIExtension = (manifest) => {
@@ -237,9 +236,9 @@ function packageTask(type, platform, arc @@ -231,9 +230,9 @@ function packageTask(type, platform, arc
.map(name => `.build/extensions/${name}/**`); .map(name => `.build/extensions/${name}/**`);
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true }); const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
let version = packageJson.version; let version = packageJson.version;
const quality = product.quality; const quality = product.quality;
@@ -374,7 +373,7 @@ function tweakProductForServerWeb(produc @@ -368,7 +367,7 @@ function tweakProductForServerWeb(produc
const minifyTask = task.define(`minify-vscode-${type}`, task.series( const minifyTask = task.define(`minify-vscode-${type}`, task.series(
optimizeTask, optimizeTask,
util.rimraf(`out-vscode-${type}-min`), util.rimraf(`out-vscode-${type}-min`),

View File

@@ -3,6 +3,12 @@ Store a static reference to the IPC socket
This lets us use it to open files inside code-server from outside of This lets us use it to open files inside code-server from outside of
code-server. code-server.
To test this:
1. run code-server
2. open file outside of code-server i.e. `code-server <path-to-file`
It should open in your existing code-server instance.
Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts --- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts

212
patches/telemetry.diff Normal file
View File

@@ -0,0 +1,212 @@
Add support for telemetry endpoint
Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
@@ -68,6 +68,7 @@ import { REMOTE_TERMINAL_CHANNEL_NAME }
import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService';
import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from 'vs/workbench/services/remote/common/remoteFileSystemProviderClient';
import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService';
+import { TelemetryClient } from "vs/server/node/telemetryClient";
const eventPrefix = 'monacoworkbench';
@@ -120,7 +121,11 @@ export async function setupServerService
let appInsightsAppender: ITelemetryAppender = NullAppender;
const machineId = await getMachineId();
if (supportsTelemetry(productService, environmentService)) {
- if (productService.aiConfig && productService.aiConfig.asimovKey) {
+ const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track";
+ if (telemetryEndpoint) {
+ appInsightsAppender = new AppInsightsAppender(eventPrefix, null, () => new TelemetryClient(telemetryEndpoint) as any);
+ disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
+ } else if (productService.aiConfig && productService.aiConfig.asimovKey) {
appInsightsAppender = new AppInsightsAppender(eventPrefix, null, productService.aiConfig.asimovKey);
disposables.add(toDisposable(() => appInsightsAppender!.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
}
Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
===================================================================
--- /dev/null
+++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
@@ -0,0 +1,135 @@
+import * as appInsights from 'applicationinsights';
+import * as https from 'https';
+import * as http from 'http';
+import * as os from 'os';
+
+class Channel {
+ public get _sender() {
+ throw new Error('unimplemented');
+ }
+ public get _buffer() {
+ throw new Error('unimplemented');
+ }
+
+ public setUseDiskRetryCaching(): void {
+ throw new Error('unimplemented');
+ }
+ public send(): void {
+ throw new Error('unimplemented');
+ }
+ public triggerSend(): void {
+ throw new Error('unimplemented');
+ }
+}
+
+// Unable to use implements because TypeScript tells you a private property is
+// missing but if you add it then it complains they have different private
+// properties. Uncommenting it during development can be helpful though to see
+// if anything is missing.
+export class TelemetryClient /* implements appInsights.TelemetryClient */ {
+ private _telemetryProcessors: any = undefined;
+ public context: any = undefined;
+ public commonProperties: any = undefined;
+ public config: any = {};
+ public quickPulseClient: any = undefined;
+
+ public channel: any = new Channel();
+
+ public constructor(private readonly endpoint: string) {
+ // Nothing to do.
+ }
+
+ public addTelemetryProcessor(): void {
+ throw new Error('unimplemented');
+ }
+
+ public clearTelemetryProcessors(): void {
+ if (this._telemetryProcessors) {
+ this._telemetryProcessors = undefined;
+ }
+ }
+
+ public runTelemetryProcessors(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackTrace(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackMetric(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackException(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackRequest(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackDependency(): void {
+ throw new Error('unimplemented');
+ }
+
+ public track(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackNodeHttpRequestSync(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackNodeHttpRequest(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackNodeHttpDependency(): void {
+ throw new Error('unimplemented');
+ }
+
+ public trackEvent(options: appInsights.Contracts.EventTelemetry): void {
+ if (!options.properties) {
+ options.properties = {};
+ }
+ if (!options.measurements) {
+ options.measurements = {};
+ }
+
+ try {
+ const cpus = os.cpus();
+ options.measurements.cores = cpus.length;
+ options.properties['common.cpuModel'] = cpus[0].model;
+ } catch (error) {}
+
+ try {
+ options.measurements.memoryFree = os.freemem();
+ options.measurements.memoryTotal = os.totalmem();
+ } catch (error) {}
+
+ try {
+ options.properties['common.shell'] = os.userInfo().shell;
+ options.properties['common.release'] = os.release();
+ options.properties['common.arch'] = os.arch();
+ } catch (error) {}
+
+ try {
+ const request = (/^http:/.test(this.endpoint) ? http : https).request(this.endpoint, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+ request.on('error', () => { /* We don't care. */ });
+ request.write(JSON.stringify(options));
+ request.end();
+ } catch (error) {}
+ }
+
+ public flush(options: { callback: (v: string) => void }): void {
+ if (options.callback) {
+ options.callback('');
+ }
+ }
+}
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
@@ -304,6 +304,7 @@ export class WebClientServer {
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
proxyEndpointTemplate: base + '/proxy/{{port}}',
codeServerVersion: this._productService.codeServerVersion,
+ enableTelemetry: this._productService.enableTelemetry,
embedderIdentifier: 'server-distro',
serviceWorker: {
scope: vscodeBase + '/',
Index: code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/telemetry/browser/telemetryService.ts
@@ -119,16 +119,19 @@ export class TelemetryService extends Di
) {
super();
- if (supportsTelemetry(productService, environmentService) && productService.aiConfig?.asimovKey) {
+ if (supportsTelemetry(productService, environmentService)) {
// If remote server is present send telemetry through that, else use the client side appender
- const telemetryProvider: ITelemetryAppender = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey);
- const config: ITelemetryServiceConfig = {
- appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)],
- commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties),
- sendErrorTelemetry: this.sendErrorTelemetry,
- };
-
- this.impl = this._register(new BaseTelemetryService(config, configurationService, productService));
+ const telemetryProvider: ITelemetryAppender | undefined = remoteAgentService.getConnection() !== null ? { log: remoteAgentService.logTelemetry.bind(remoteAgentService), flush: remoteAgentService.flushTelemetry.bind(remoteAgentService) } : productService.aiConfig?.asimovKey ? new WebAppInsightsAppender('monacoworkbench', productService.aiConfig?.asimovKey) : undefined;
+ if (telemetryProvider) {
+ const config: ITelemetryServiceConfig = {
+ appenders: [new WebTelemetryAppender(telemetryProvider), new TelemetryLogAppender(loggerService, environmentService)],
+ commonProperties: resolveWorkbenchCommonProperties(storageService, productService.commit, productService.version, environmentService.remoteAuthority, productService.embedderIdentifier, productService.removeTelemetryMachineId, environmentService.options && environmentService.options.resolveCommonTelemetryProperties),
+ sendErrorTelemetry: this.sendErrorTelemetry,
+ };
+ this.impl = this._register(new BaseTelemetryService(config, configurationService, productService));
+ } else {
+ this.impl = NullTelemetryService;
+ }
} else {
this.impl = NullTelemetryService;
}

View File

@@ -3,6 +3,11 @@ Add a notification that lets you know when an update is out
The easiest way to test this is probably to change the version in your The easiest way to test this is probably to change the version in your
package.json and delete the last notification storage item. package.json and delete the last notification storage item.
1. change version in root `package.json`
2. Open DevTools > Application > Storage (top-level)
3. Click "Clear site data"
4. See update notification
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts --- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
@@ -14,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
+import { IProductService } from 'vs/platform/product/common/productService'; +import { IProductService } from 'vs/platform/product/common/productService';
+import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
export class CodeServerClient extends Disposable { export class CodeServerClient extends Disposable {
constructor ( constructor (
+ @ILogService private logService: ILogService, + @ILogService private logService: ILogService,
@@ -93,15 +98,15 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
readonly codeServerVersion?: string readonly codeServerVersion?: string
readonly rootEndpoint?: string readonly rootEndpoint?: string
+ readonly updateEndpoint?: string + readonly updateEndpoint?: string
readonly version: string; readonly version: string;
readonly date?: string; readonly date?: string;
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -286,6 +286,7 @@ export class WebClientServer { @@ -292,6 +292,7 @@ export class WebClientServer {
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined, workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{ productConfiguration: <Partial<IProductConfiguration>>{
rootEndpoint: base, rootEndpoint: base,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined, + updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
@@ -114,19 +119,19 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts +++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -11,6 +11,8 @@ import { refineServiceDecorator } from ' @@ -11,6 +11,8 @@ import { refineServiceDecorator } from '
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
export const serverOptions: OptionDescriptions<ServerParsedArgs> = { export const serverOptions: OptionDescriptions<ServerParsedArgs> = {
+ /* ----- code-server ----- */ + /* ----- code-server ----- */
+ 'disable-update-check': { type: 'boolean' }, + 'disable-update-check': { type: 'boolean' },
/* ----- server setup ----- */ /* ----- server setup ----- */
@@ -84,6 +86,8 @@ export const serverOptions: OptionDescri @@ -88,6 +90,8 @@ export const serverOptions: OptionDescri
}; };
export interface ServerParsedArgs { export interface ServerParsedArgs {
+ /* ----- code-server ----- */ + /* ----- code-server ----- */
+ 'disable-update-check'?: boolean; + 'disable-update-check'?: boolean;
/* ----- server setup ----- */ /* ----- server setup ----- */

View File

@@ -15,13 +15,16 @@ Since this code exists only for the authentication case we can just skip it when
it is served from the current host as authentication is not a problem if the it is served from the current host as authentication is not a problem if the
request is not cross-origin. request is not cross-origin.
There is also an origin check we bypass (this seems to be related to how the
webview host is separate by default but we serve on the same host).
To test, open a few types of webviews (images, markdown, extension details, etc). To test, open a few types of webviews (images, markdown, extension details, etc).
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts --- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts +++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -176,7 +176,7 @@ export class BrowserWorkbenchEnvironment @@ -179,7 +179,7 @@ export class BrowserWorkbenchEnvironment
@memoize @memoize
get webviewExternalEndpoint(): string { get webviewExternalEndpoint(): string {
@@ -34,7 +37,7 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts --- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts +++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -280,6 +280,7 @@ export class WebClientServer { @@ -283,6 +283,7 @@ export class WebClientServer {
const data = (await util.promisify(fs.readFile)(filePath)).toString() const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({ .replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority, remoteAuthority,
@@ -46,7 +49,7 @@ Index: code-server/lib/vscode/src/vs/workbench/common/webview.ts
=================================================================== ===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/webview.ts --- code-server.orig/lib/vscode/src/vs/workbench/common/webview.ts
+++ code-server/lib/vscode/src/vs/workbench/common/webview.ts +++ code-server/lib/vscode/src/vs/workbench/common/webview.ts
@@ -24,7 +24,7 @@ export const webviewResourceBaseHost = ' @@ -22,7 +22,7 @@ export const webviewResourceBaseHost = '
export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`; export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
@@ -74,3 +77,20 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/servi
switch (event.request.method) { switch (event.request.method) {
case 'GET': case 'GET':
case 'HEAD': case 'HEAD':
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/main.js
@@ -318,6 +318,12 @@ const hostMessaging = new class HostMess
const hostname = location.hostname;
+ // It is safe to run if we are on the same host.
+ const parent = new URL(parentOrigin)
+ if (parent.hostname === location.hostname) {
+ return start(parentOrigin)
+ }
+
if (!crypto.subtle) {
// cannot validate, not running in a secure context
throw new Error(`Cannot validate in current context!`);

View File

@@ -94,7 +94,8 @@ export const ensureAddress = (server: http.Server, protocol: string): URL | stri
} }
if (typeof addr !== "string") { if (typeof addr !== "string") {
return new URL(`${protocol}://${addr.address}:${addr.port}`) const host = addr.family === "IPv6" ? `[${addr.address}]` : addr.address
return new URL(`${protocol}://${host}:${addr.port}`)
} }
// If this is a string then it is a pipe or Unix socket. // If this is a string then it is a pipe or Unix socket.

View File

@@ -542,7 +542,7 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args.password = process.env.PASSWORD args.password = process.env.PASSWORD
} }
if (process.env.CS_DISABLE_FILE_DOWNLOADS === "1") { if (process.env.CS_DISABLE_FILE_DOWNLOADS?.match(/^(1|true)$/)) {
args["disable-file-downloads"] = true args["disable-file-downloads"] = true
} }

View File

@@ -9,7 +9,10 @@ export class Heart {
private heartbeatInterval = 60000 private heartbeatInterval = 60000
public lastHeartbeat = 0 public lastHeartbeat = 0
public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise<boolean>) {} public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise<boolean>) {
this.beat = this.beat.bind(this)
this.alive = this.alive.bind(this)
}
public alive(): boolean { public alive(): boolean {
const now = Date.now() const now = Date.now()
@@ -20,30 +23,22 @@ export class Heart {
* timeout and start or reset a timer that keeps running as long as there is * timeout and start or reset a timer that keeps running as long as there is
* activity. Failures are logged as warnings. * activity. Failures are logged as warnings.
*/ */
public beat(): void { public async beat(): Promise<void> {
if (this.alive()) { if (this.alive()) {
return return
} }
logger.trace("heartbeat") logger.trace("heartbeat")
fs.writeFile(this.heartbeatPath, "").catch((error) => {
logger.warn(error.message)
})
this.lastHeartbeat = Date.now() this.lastHeartbeat = Date.now()
if (typeof this.heartbeatTimer !== "undefined") { if (typeof this.heartbeatTimer !== "undefined") {
clearTimeout(this.heartbeatTimer) clearTimeout(this.heartbeatTimer)
} }
this.heartbeatTimer = setTimeout(() => { this.heartbeatTimer = setTimeout(() => heartbeatTimer(this.isActive, this.beat), this.heartbeatInterval)
this.isActive() try {
.then((active) => { return await fs.writeFile(this.heartbeatPath, "")
if (active) { } catch (error: any) {
this.beat() logger.warn(error.message)
} }
})
.catch((error) => {
logger.warn(error.message)
})
}, this.heartbeatInterval)
} }
/** /**
@@ -55,3 +50,20 @@ export class Heart {
} }
} }
} }
/**
* Helper function for the heartbeatTimer.
*
* If heartbeat is active, call beat. Otherwise do nothing.
*
* Extracted to make it easier to test.
*/
export async function heartbeatTimer(isActive: Heart["isActive"], beat: Heart["beat"]) {
try {
if (await isActive()) {
beat()
}
} catch (error: unknown) {
logger.warn((error as Error).message)
}
}

View File

@@ -56,6 +56,8 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
// /healthz|/healthz/ needs to be excluded otherwise health checks will make // /healthz|/healthz/ needs to be excluded otherwise health checks will make
// it look like code-server is always in use. // it look like code-server is always in use.
if (!/^\/healthz\/?$/.test(req.url)) { if (!/^\/healthz\/?$/.test(req.url)) {
// NOTE@jsjoeio - intentionally not awaiting the .beat() call here because
// we don't want to slow down the request.
heart.beat() heart.beat()
} }

View File

@@ -77,7 +77,7 @@ export class SocketProxyProvider {
this.proxyPipe = pipe this.proxyPipe = pipe
return Promise.all([ return Promise.all([
fs.mkdir(path.dirname(this.proxyPipe), { recursive: true }), fs.mkdir(path.dirname(this.proxyPipe), { recursive: true }),
fs.rmdir(this.proxyPipe, { recursive: true }), fs.rm(this.proxyPipe, { force: true, recursive: true }),
]) ])
}) })
.then(() => { .then(() => {

View File

@@ -203,8 +203,9 @@ class ChildProcess extends Process {
/** /**
* Parent process wrapper that spawns the child process and performs a handshake * Parent process wrapper that spawns the child process and performs a handshake
* with it. Will relaunch the child if it receives a SIGUSR1 or is asked to by * with it. Will relaunch the child if it receives a SIGUSR1 or SIGUSR2 or is
* the child. If the child otherwise exits the parent will also exit. * asked to by the child. If the child otherwise exits the parent will also
* exit.
*/ */
export class ParentProcess extends Process { export class ParentProcess extends Process {
public logger = logger.named(`parent:${process.pid}`) public logger = logger.named(`parent:${process.pid}`)
@@ -227,6 +228,11 @@ export class ParentProcess extends Process {
this.relaunch() this.relaunch()
}) })
process.on("SIGUSR2", async () => {
this.logger.info("Received SIGUSR2; hotswapping")
this.relaunch()
})
const opts = { const opts = {
size: "10M", size: "10M",
maxFiles: 10, maxFiles: 10,

View File

@@ -1,5 +1,5 @@
import * as path from "path"
import { promises as fs } from "fs" import { promises as fs } from "fs"
import * as path from "path"
import { clean } from "../utils/helpers" import { clean } from "../utils/helpers"
import { describe, test, expect } from "./baseFixture" import { describe, test, expect } from "./baseFixture"

View File

@@ -81,6 +81,9 @@ export class CodeServer {
path.join(dir, "User/settings.json"), path.join(dir, "User/settings.json"),
JSON.stringify({ JSON.stringify({
"workbench.startupEditor": "none", "workbench.startupEditor": "none",
// NOTE@jsjoeio - needed to prevent Trust Policy prompt
// in end-to-end tests.
"security.workspace.trust.enabled": false,
}), }),
"utf8", "utf8",
) )

View File

@@ -152,10 +152,20 @@ describe("ensureAddress", () => {
it("should throw and error if no address", () => { it("should throw and error if no address", () => {
expect(() => ensureAddress(mockServer, "http")).toThrow("Server has no address") expect(() => ensureAddress(mockServer, "http")).toThrow("Server has no address")
}) })
it("should return the address if it exists", async () => { it("should return the address if it's a string", async () => {
mockServer.address = () => "http://localhost:8080/" mockServer.address = () => "/path/to/unix.sock"
const address = ensureAddress(mockServer, "http") const address = ensureAddress(mockServer, "http")
expect(address.toString()).toBe(`http://localhost:8080/`) expect(address.toString()).toBe(`/path/to/unix.sock`)
})
it("should construct URL with an IPv4 address", async () => {
mockServer.address = () => ({ address: "1.2.3.4", port: 5678, family: "IPv4" })
const address = ensureAddress(mockServer, "http")
expect(address.toString()).toBe(`http://1.2.3.4:5678/`)
})
it("should construct URL with an IPv6 address", async () => {
mockServer.address = () => ({ address: "a:b:c:d::1234", port: 5678, family: "IPv6" })
const address = ensureAddress(mockServer, "http")
expect(address.toString()).toBe(`http://[a:b:c:d::1234]:5678/`)
}) })
}) })

View File

@@ -362,6 +362,18 @@ describe("parser", () => {
}) })
}) })
it("should use env var CS_DISABLE_FILE_DOWNLOADS set to true", async () => {
process.env.CS_DISABLE_FILE_DOWNLOADS = "true"
const args = parse([])
expect(args).toEqual({})
const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"disable-file-downloads": true,
})
})
it("should error if password passed in", () => { it("should error if password passed in", () => {
expect(() => parse(["--password", "supersecret123"])).toThrowError( expect(() => parse(["--password", "supersecret123"])).toThrowError(
"--password can only be set in the config file or passed in via $PASSWORD", "--password can only be set in the config file or passed in via $PASSWORD",
@@ -446,7 +458,7 @@ describe("cli", () => {
beforeEach(async () => { beforeEach(async () => {
delete process.env.VSCODE_IPC_HOOK_CLI delete process.env.VSCODE_IPC_HOOK_CLI
await fs.rmdir(vscodeIpcPath, { recursive: true }) await fs.rm(vscodeIpcPath, { force: true, recursive: true })
}) })
it("should use existing if inside code-server", async () => { it("should use existing if inside code-server", async () => {

View File

@@ -0,0 +1,112 @@
import { logger } from "@coder/logger"
import { readFile, writeFile, stat, utimes } from "fs/promises"
import { Heart, heartbeatTimer } from "../../../src/node/heart"
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo)
describe("Heart", () => {
const testName = "heartTests"
let testDir = ""
let heart: Heart
beforeAll(async () => {
mockLogger()
await clean(testName)
testDir = await tmpdir(testName)
})
beforeEach(() => {
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
})
afterAll(() => {
jest.restoreAllMocks()
})
afterEach(() => {
jest.resetAllMocks()
jest.useRealTimers()
if (heart) {
heart.dispose()
}
})
it("should write to a file when given a valid file path", async () => {
// Set up heartbeat file with contents
const text = "test"
const pathToFile = `${testDir}/file.txt`
await writeFile(pathToFile, text)
const fileContents = await readFile(pathToFile, { encoding: "utf8" })
// Explicitly set the modified time to 0 so that we can check
// that the file was indeed modified after calling heart.beat().
// This works around any potential race conditions.
// Docs: https://nodejs.org/api/fs.html#fspromisesutimespath-atime-mtime
await utimes(pathToFile, 0, 0)
expect(fileContents).toBe(text)
heart = new Heart(pathToFile, mockIsActive(true))
await heart.beat()
// Check that the heart wrote to the heartbeatFilePath and overwrote our text
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
expect(fileContentsAfterBeat).not.toBe(text)
// Make sure the modified timestamp was updated.
const fileStatusAfterEdit = await stat(pathToFile)
expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0)
})
it("should log a warning when given an invalid file path", async () => {
heart = new Heart(`fakeDir/fake.txt`, mockIsActive(false))
await heart.beat()
expect(logger.warn).toHaveBeenCalled()
})
it("should be active after calling beat", async () => {
await heart.beat()
const isAlive = heart.alive()
expect(isAlive).toBe(true)
})
it("should not be active after dispose is called", () => {
heart.dispose()
const isAlive = heart.alive()
expect(isAlive).toBe(false)
})
it("should beat twice without warnings", async () => {
// Use fake timers so we can speed up setTimeout
jest.useFakeTimers()
heart = new Heart(`${testDir}/hello.txt`, mockIsActive(true))
await heart.beat()
// we need to speed up clocks, timeouts
// call heartbeat again (and it won't be alive I think)
// then assert no warnings were called
jest.runAllTimers()
expect(logger.warn).not.toHaveBeenCalled()
})
})
describe("heartbeatTimer", () => {
beforeAll(() => {
mockLogger()
})
afterAll(() => {
jest.restoreAllMocks()
})
afterEach(() => {
jest.resetAllMocks()
})
it("should call beat when isActive resolves to true", async () => {
const isActive = true
const mockIsActive = jest.fn().mockResolvedValue(isActive)
const mockBeatFn = jest.fn()
await heartbeatTimer(mockIsActive, mockBeatFn)
expect(mockIsActive).toHaveBeenCalled()
expect(mockBeatFn).toHaveBeenCalled()
})
it("should log a warning when isActive rejects", async () => {
const errorMsg = "oh no"
const error = new Error(errorMsg)
const mockIsActive = jest.fn().mockRejectedValue(error)
const mockBeatFn = jest.fn()
await heartbeatTimer(mockIsActive, mockBeatFn)
expect(mockIsActive).toHaveBeenCalled()
expect(mockBeatFn).not.toHaveBeenCalled()
expect(logger.warn).toHaveBeenCalledWith(errorMsg)
})
})

View File

@@ -53,7 +53,7 @@ describe("SocketProxyProvider", () => {
await fs.mkdir(path.join(tmpdir, "tests"), { recursive: true }) await fs.mkdir(path.join(tmpdir, "tests"), { recursive: true })
const socketPath = await provider.findFreeSocketPath(path.join(tmpdir, "tests/tls-socket-proxy")) const socketPath = await provider.findFreeSocketPath(path.join(tmpdir, "tests/tls-socket-proxy"))
await fs.rmdir(socketPath, { recursive: true }) await fs.rm(socketPath, { force: true, recursive: true })
return new Promise<void>((_resolve) => { return new Promise<void>((_resolve) => {
const resolved: { [key: string]: boolean } = { client: false, server: false } const resolved: { [key: string]: boolean } = { client: false, server: false }

View File

@@ -131,7 +131,8 @@ describe("update", () => {
await expect(settings().read()).resolves.toEqual({ update }) await expect(settings().read()).resolves.toEqual({ update })
expect(isNaN(update.checked)).toEqual(false) expect(isNaN(update.checked)).toEqual(false)
expect(update.checked < Date.now() && update.checked >= now).toEqual(true) expect(update.checked).toBeGreaterThanOrEqual(now)
expect(update.checked).toBeLessThanOrEqual(Date.now())
expect(update.version).toStrictEqual("2.1.0") expect(update.version).toStrictEqual("2.1.0")
expect(spy).toEqual(["/latest"]) expect(spy).toEqual(["/latest"])
}) })
@@ -145,7 +146,7 @@ describe("update", () => {
await expect(settings().read()).resolves.toEqual({ update }) await expect(settings().read()).resolves.toEqual({ update })
expect(isNaN(update.checked)).toStrictEqual(false) expect(isNaN(update.checked)).toStrictEqual(false)
expect(update.checked < now).toBe(true) expect(update.checked).toBeLessThanOrEqual(now)
expect(update.version).toStrictEqual("2.1.0") expect(update.version).toStrictEqual("2.1.0")
expect(spy).toEqual([]) expect(spy).toEqual([])
}) })
@@ -159,7 +160,8 @@ describe("update", () => {
await expect(settings().read()).resolves.toEqual({ update }) await expect(settings().read()).resolves.toEqual({ update })
expect(isNaN(update.checked)).toStrictEqual(false) expect(isNaN(update.checked)).toStrictEqual(false)
expect(update.checked < Date.now() && update.checked >= now).toStrictEqual(true) expect(update.checked).toBeGreaterThanOrEqual(now)
expect(update.checked).toBeLessThanOrEqual(Date.now())
expect(update.version).toStrictEqual("4.1.1") expect(update.version).toStrictEqual("4.1.1")
expect(spy).toStrictEqual(["/latest"]) expect(spy).toStrictEqual(["/latest"])
}) })
@@ -204,14 +206,16 @@ describe("update", () => {
let now = Date.now() let now = Date.now()
let update = await provider.getUpdate(true) let update = await provider.getUpdate(true)
expect(isNaN(update.checked)).toStrictEqual(false) expect(isNaN(update.checked)).toStrictEqual(false)
expect(update.checked < Date.now() && update.checked >= now).toEqual(true) expect(update.checked).toBeGreaterThanOrEqual(now)
expect(update.checked).toBeLessThanOrEqual(Date.now())
expect(update.version).toStrictEqual("unknown") expect(update.version).toStrictEqual("unknown")
provider = new UpdateProvider("http://probably.invalid.dev.localhost/latest", settings()) provider = new UpdateProvider("http://probably.invalid.dev.localhost/latest", settings())
now = Date.now() now = Date.now()
update = await provider.getUpdate(true) update = await provider.getUpdate(true)
expect(isNaN(update.checked)).toStrictEqual(false) expect(isNaN(update.checked)).toStrictEqual(false)
expect(update.checked < Date.now() && update.checked >= now).toEqual(true) expect(update.checked).toBeGreaterThanOrEqual(now)
expect(update.checked).toBeLessThanOrEqual(Date.now())
expect(update.version).toStrictEqual("unknown") expect(update.version).toStrictEqual("unknown")
}) })

View File

@@ -29,7 +29,7 @@ export function mockLogger() {
*/ */
export async function clean(testName: string): Promise<void> { export async function clean(testName: string): Promise<void> {
const dir = path.join(os.tmpdir(), `code-server/tests/${testName}`) const dir = path.join(os.tmpdir(), `code-server/tests/${testName}`)
await fs.rmdir(dir, { recursive: true }) await fs.rm(dir, { force: true, recursive: true })
} }
/** /**