Compare commits

...

90 Commits

Author SHA1 Message Date
Joe Previte
b23c398b7d refactor: remove version check e2e test
I am not sure why this is passing locally and failing CI. I need to
further investigate this since it fails depending on where you test.
2022-07-01 09:46:10 -07:00
Joe Previte
4bc0c75f6a Revert "fix: try setting VSCODE_DEV=1"
This reverts commit 902f5f2f30.
2022-06-30 17:02:34 -07:00
Joe Previte
902f5f2f30 fix: try setting VSCODE_DEV=1 2022-06-30 15:37:19 -07:00
Joe Previte
4dd932a754 Revert "fix: add VSCODE_DEV=1 to e2e script"
This reverts commit 58c4826af8.
2022-06-30 14:59:56 -07:00
Joe Previte
e422c3e5a4 Merge branch 'main' into v4.5.0 2022-06-30 14:09:37 -07:00
Joe Previte
58c4826af8 fix: add VSCODE_DEV=1 to e2e script
I'm not sure what changed in the latest version but without setting
VSCODE_DEV=1, code-server won't load. This fixes that.
2022-06-30 14:01:18 -07:00
renovate[bot]
55cfba8168 chore(deps): update aquasecurity/trivy-action digest to 0105373 (#5310)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-30 10:16:12 -07:00
Joe Previte
21d56f9a29 docs: update MAINTAINING 2022-06-29 21:32:30 +00:00
Joe Previte
e61a294dcc chore: bump chart version 2022-06-29 21:32:17 +00:00
Joe Previte
3fbac01e7d chore: update CHANGELOG 2022-06-29 21:32:06 +00:00
Joe Previte
813e83aa28 chore(release): bump version to 4.5.0 2022-06-29 21:12:18 +00:00
renovate[bot]
4f0d5566c3 chore(deps): update minor dependency updates (#5301)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-29 16:25:52 +00:00
renovate[bot]
79e96a99d3 chore(deps): update codecov/codecov-action action to v3 (#5305)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-29 08:55:44 -07:00
renovate[bot]
c99f4cef25 chore(deps): update azure/setup-helm action to v3 (#5302)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-28 12:57:29 -07:00
Joe Previte
1296848afc refactor: switch to codecov-uploader GitHub Action (#5303)
* refactor: switch to codecov-uploader GitHub Action

codecov deprecated their Node wrapper for uploading coverage reports.

This removes that and uses their new uploaded along with the v2 GitHub
Action they maintain.

* fix: update broken integration test
2022-06-28 10:04:35 -07:00
Joe Previte
c51ff3bce1 refactor: move integration tests to Jest (#5275)
* feat: add installExtension integration test

This adds a new helper function called `runCodeServerCommand` along with
a test for `--install-extension`. We can use this approach for writing
integration tests (i.e. testing a real code-server build, CLI commands,
etc).

* refactor: s/ test:standalone with test:integration

This replaces our integration approach to use Jest instead of a single
bash script. By doing this, we will be able to easily maintain and add
to our integration test suite.

* refactor: filter unit tests

Now that our integration tests also use Jest, we need to update our unit
test script to ignore `test/integration`.

* refactor: add SKIP_SUBMODULE_DEPS to postinstall

* refactor: add SKIP_SUBMODULE_DEPS to postinstall

* fixup!: skip submod deps

* refactor: move runCodeServerCommand into sep. file

When Jest runs a test, it loads all the files and imports for that test.
This means you might be "requiring" code that's unrelated to your tests.

This leads to unexpected errors depending on where the code runs.

Moved this file to avoid GLIBC and other errors relaed to argon2 when
running integration tests in CI.

* fizup: formatting

* fizup: increase timeout

* refactor: use fixture in installExtension test

Instead of relying on a network to install an extension, we use a
fixture - vsix file in the repo. This is also faster.

* feat: add integration test for listExtensions

* chore: ignore integration fixtures

* fixup: formatting

* fixup: remove custom-hacks.css

* fixup: formatting

* Update test/integration/installExtension.test.ts

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

* Update test/integration/listExtensions.test.ts

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

* Update test/integration/installExtension.test.ts

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

* Update test/integration/listExtensions.test.ts

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

* fixup: contributing integration tests section

* fixup: update ci/readme

* fixup: use RELEASE_PATH in test-integration.sh

* refactor: unzip vsix for listExtensions

* refactor: use exec instead of spawn

* Update docs/CONTRIBUTING.md

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

* Update test/integration/listExtensions.test.ts

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

* Update test/integration/listExtensions.test.ts

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

* Update test/integration/listExtensions.test.ts

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

* refactor: use different default binary path

* fixup!: formatting

Co-authored-by: Asher <ash@coder.com>
2022-06-24 16:33:38 +00:00
renovate[bot]
a879844c2d chore(deps): update aquasecurity/trivy-action digest to 7b7aa26 (#5289)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-06-22 20:05:22 +00:00
renovate[bot]
f2693d366c chore(deps): update minor dependency updates (#5276)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-06-22 16:26:20 +00:00
Asher
5ce99f8d1c chore: update Code to 1.68 (#5263)
* chore: update Code to 1.67

Was able to remove our changes to common/webview.ts since they are
upstream now.

Other than that no serious changes, just context diffs.

* chore: update Code to 1.68

- Upstream moved the web socket endpoint so change the Express route
  from / to *.  That will let web sockets work at any endpoint.
- Everything in the workbench config is basically the same but
  de-indented (upstream extracted it into a separate object which
  resulted in a de-indent), the ordering is slightly different, and
  instead of vscodeBase we now need vscodeBase + this._staticRoute since
  everything is served from a sub-path now.
- Move manifest link back to the root since that is where we host our
  manifest.
- Change RemoteAuthoritiesImpl to use the same path building method as
  in other places (+ instead of using URI.parse/join).
- Use existing host/port in RemoteAuthoritiesImpl and
  BrowserSocketFactory instead of patching them to use window.location
  (these are set from window.location to begin with so it should be the
  same result but with less patching).
- Since BrowserSocketFactory includes a sub-path now (endpoints were
  changed upstream to serve from /quality/commit instead of from the
  root) the patch there has changed to prepend the base to that
  path (instead of using the base directly).
- The workbench HTML now natively supports a base URL in the form of
  WORKBENCH_WEB_BASE_URL so no need for VS_BASE patches there anymore.
- Upstream added type="image/x-icon" so I did as well.
- Move the language patch to the end of the series so it is easier to
  eventually remove.
- Remove the existing NLS config in favor of one that supports
  extensions.
- Upstream deleted webview main.js and inlined it into the HTML so move
  that code (the parent origin check) into both those HTML files
  (index.html and index-no-csp.html).
- The remaining diff is from changes to the surrounding context or a
  line was changed slightly by upstream (for example renamed files or
  new arguments like to the remote authority resolver).

* fix: modify product.json before building

Code injects this into the client during the build process so it needs
to be updated before we build.

* fix: update inline script nonces

* Update HTML base path test

* fix: missing commit

Code overrides it with nothing.

The date is also already injected.

* fix: web extensions breaking when the commit changes

By just using the marketplace directly instead of going through the
backend.  I am not sure what the point is when searching extensions
already goes directly to the marketplace anyway.

But also remove the prefix that breaks this as well because otherwise
existing installations will break.
2022-06-21 21:51:46 +00:00
Joe Previte
eb314ff727 chore: only download .deb in docker release (#5277)
* Update docker.yaml

* Update docker.yaml
2022-06-17 08:02:33 -07:00
Joe Previte
61138b4a61 refactor: open function (#5257)
* refactor: fix type annotations in open

There was no clear reason as to why we needed to use type assertions
when initializing both `args` and `options` in `open` so I refactored
them both.

* refactor: create constructOpenOptions

* refactor: add urlSearch and remove options

* feat: add tests for constructOpenOptions
2022-06-15 20:53:07 +00:00
renovate[bot]
113ad85b37 chore(deps): update minor dependency updates (#5244)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-06-15 13:29:52 -07:00
Ben Potter
a2bfcfcc78 chore: update Coder messaging on README (#5268)
* chore: update Coder messaging

* use our shortlink
2022-06-15 09:49:49 -05:00
Joe Previte
a96162d075 feat: add tests for node/util.open (#5256) 2022-06-13 21:16:46 +00:00
Joe Previte
744b301c7a Update bug-report.yml (#5262) 2022-06-13 20:18:51 +00:00
Joe Previte
ba990668a5 chore: update bug report template (#5261)
* chore: update bug report template

Add an additional checkbox to the bug report template

* Update .github/ISSUE_TEMPLATE/bug-report.yml
2022-06-13 12:51:30 -07:00
Joe Previte
2c1cf0259e feat: add tests for isWsl (#5251)
* refactor: add docs to isWsl and make easier to test

* feat: add tests for isWsl

* fixup!: refactor isWsl and tests

* Update test/unit/node/util.test.ts

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

* Update test/unit/node/util.test.ts

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

Co-authored-by: Asher <ash@coder.com>
2022-06-10 20:00:20 +00:00
Joe Previte
d75883bcc6 feat: add additional test for handlePasswordValidation (#5243) 2022-06-06 11:20:22 -07:00
renovate[bot]
792e954937 chore(deps): update aquasecurity/trivy-action digest to df3fb7d (#5239)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-06-06 08:51:15 -07:00
Asher
5d47282ea5 fix: install nfpm straight from GitHub (#5214)
* fix: install nfpm straight from GitHub

install.goreleaser.com appears to no longer be available.

* Add -f to curl commands

This might have made it so we got the right error rather than erroring
on the envsubst step.
2022-05-20 12:39:54 -07:00
Petar Petrov
d3f58f9b7d Fix caddy installation docs (#5209)
Applies Caddy installations documentation fixes and also resolves the following issue when trying to install Caddy:

    W: GPG error: https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY ABA1F9B8875A6661

See:

 - 930109ec33
 - 2e255b1ee3
 - 0f4885e592
2022-05-19 22:36:06 +00:00
Feng Yu
1e304b1e7d chore(deps): upgrade typescript to v4.6 (#5202) 2022-05-13 16:57:50 +00:00
djarbz
5276e41606 Allow user Entrypoint scripts (#5194)
* Allow user Entrypoint scripts

* Variable encapsulation

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

* Check if Entrypoint Dir exists & run all executable

* Don't create entrypoint.d by default

* yarn fmt

* yarn fmt

* Fix for SC2044

* Revert "yarn fmt"

This reverts commit 5ca347f361.

Co-authored-by: Asher <ash@coder.com>
2022-05-11 22:10:04 +00:00
Feng Yu
dedd770a78 docs: rename master to main in all github doc links (#5190)
* docs: correct link master -> main

* fix missing ]
2022-05-11 14:39:57 -07:00
Joe Previte
a02f47714e refactor: remove unused code enumToArray 2022-05-10 23:26:04 +00:00
Joe Previte
b13849ded0 refactor: remove dead code (#5188)
* refactor: delete unused code

* refactor: move onLine to test helpers

* Revert "refactor: move onLine to test helpers"

This reverts commit 32cc27b213.

* fixup! refactor: delete unused code
2022-05-10 22:44:54 +00:00
Devin Buhl
7a8d487729 chore: push code-server image to GHCR (#5187) 2022-05-10 16:11:06 -05:00
renovate[bot]
1788537cce chore(deps): update minor dependency updates (#5181)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-10 21:01:13 +00:00
renovate[bot]
0155a12500 chore(deps): update docker/setup-qemu-action action to v2 (#5166)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-05-10 20:35:25 +00:00
renovate[bot]
53b5d41271 chore(deps): update docker/setup-buildx-action action to v2 (#5164)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-05-10 13:13:45 -07:00
renovate[bot]
55006ccb5a chore(deps): update docker/login-action action to v2 (#5163)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-05-10 12:37:05 -07:00
Joe Previte
cd78f32dc0 refactor(util): remove unused isObject function (#5183) 2022-05-10 00:24:25 +00:00
Joe Previte
3207bfd4ad feat: add test for isFile when error (#5182)
This adds an additional test for the `isFile` utility function to ensure
it returns `false` in the event of an error.
2022-05-09 23:24:40 +00:00
Joe Previte
7c1a45a8d8 chore: update --help for disable-file-downloads (#5176)
* chore: update --help for disable-file-downloads

* fixup: formatting
2022-05-06 23:08:25 +00:00
Joe Previte
60dd8ab374 chore: configure git globally for brew publish (#5173) 2022-05-06 22:31:03 +00:00
Asher
6cf607eab9 fix: Docker push (#5175)
The action actually does not support wildcards but it does support * for
downloading all artifacts.
2022-05-06 16:57:22 -05:00
Joe Previte
f735c87ac7 release: 4.4.0 (#5169)
* chore(release): bump version to 4.4.0

* chore: update CHANGELOG with v4.4.0

* chore: bump version to 2.5.0 in Chart.yaml
2022-05-06 13:45:49 -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
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
Asher
fd42b95164 fix: use current location for web extension resource endpoint (#5104)
This makes it work behind a rewriting proxy as well as make it use the
correct remote authority.
2022-04-14 21:00:10 +00:00
Asher
b62a68ac37 fix: webviews failing to load the iframe HTML (#5103)
Code added in 1.65.0 broke webviews when you are hosting them from the
same domain.
2022-04-14 18:02:52 +00:00
Joe Previte
e7e6c163ed revert(docs): partially revert 326a1d1862 (#5095)
We tried to switch from `yarn` to `npm` because `yarn` ignores lockfiles
but learned that we missed a few key things.

For now, we are reverting docs and a few other changes that suggested
using `npm` instead of `yarn` until we fully remove `yarn` from the
codebase.
t Please enter the commit message for your changes. Lines starting
2022-04-13 17:15:21 +00:00
Joe Previte
0e1f396645 feat: add option for disabling file downloads (#5055)
* feat(cli): add disable-file-downloads to cli

* feat(e2e): add download test

* feat(e2e): add downloads disabled test

* refactor(e2e): explain how to debug unexpected close

* feat(patches): add disable file downloads

* wip: update diff

* Update src/node/cli.ts

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

* fixup! add missing common/contextkeys file to patch

* fixup!: update patch

* fixup!: default disable-file-downloads undefined

* fixup!: combine e2e tests

* fixup!: use different test names

* feat: add CS_DISABLE_FILE_DOWNLOADS

* fixup!: make explicit and cleanup test

* fixup!: use beforeEach

Co-authored-by: Asher <ash@coder.com>
2022-04-13 09:39:05 -07:00
renovate[bot]
c05b727c61 chore(deps): update minor dependency updates (#5060)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-04-12 16:39:58 -07:00
Joseph Reiter
3bf470f19c docs: simplify termux installation process (#5078)
* Update termux.md

1) Updated information to use PRoot (simpler than Andronix and the way supported by Termux) to create and access the Debian distro.
2) Added helpful information on using PRoot with your dev environment.
3) Cleaned up spelling, grammar, and made documentation more consistent between sections.

* docs: Termux correct packages to install

Updated some erroneously missing packages (vim and sudo) necessary for multi-user setup.

* docs: cleaned up verbiage

Co-authored-by: Joe Previte <jjprevite@gmail.com>

* docs: corrected punctuation

Co-authored-by: Joe Previte <jjprevite@gmail.com>

* docs: correct punctuation

Co-authored-by: Joe Previte <jjprevite@gmail.com>

* docs: clarify pkg command shorthand

* Ran yarn fmt on docs

Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-04-12 15:42:22 -07:00
neilnaveen
f4569f0b48 Set permissions for GitHub actions (#5090)
- Included permissions for the action. https://github.com/ossf/scorecard/blob/main/docs/checks.md#token-permissions

https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions

https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs

[Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/)

 Restrict the GitHub token permissions only to the required ones; this way, even if the attackers will succeed in compromising your workflow, they won’t be able to do much.

Signed-off-by: neilnaveen <42328488+neilnaveen@users.noreply.github.com>

Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-04-12 18:59:11 +00:00
Riley Calhoun
fd2a031c21 Update ios.md (#5079) 2022-04-12 11:32:49 -07:00
Asher
3ba3caa8a6 docs: link upstream sync section in MAINTAINING to CONTRIBUTING (#5075)
* Link upstream sync section in MAINTAINING to CONTRIBUTING

* Update MAINTAINING.md table of contents

Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-04-07 13:15:30 -07:00
Joe Previte
f0bfd3b450 chore: remove file ext. from LICENSE (#5070)
* chore: remove file ext. from LICENSE

* fixup!: update LICENSE in missing places

* Revert "fixup!: update LICENSE in missing places"

This reverts commit baa47b68e6.

* fixup!: update LICENSE in build-release
2022-04-07 10:36:33 -07:00
David Wahler
38e57a355b Exclude .deb files from release Docker image (#5068) 2022-04-06 15:45:06 -07:00
Asher
5bc26e90cb fix: version in about dialog (#5057)
* Fix code-server version not appearing in other languages

It needs to be separate from the localize call since the language
version of that string is used and it will not include a spot for the
code-server version.

I also moved the "v" so we do not get "vUnknown".

* Add code-server version to product configuration

Before 1.64 the entire product configuration was sent to the client but
that was removed so we have to add anything we want to use on the
client, like the code-server version (used in the about dialog).

Fixes #5027.

* Refresh patches

* Change version test to look for specific version

This will catch if we are not sending the actual version to the client.
2022-03-31 16:14:03 -05:00
Joe Previte
d796cc20e0 chore(Code): upgrade to 1.65 (#5047)
* docs(CONTRIBUTING): update Code workflow

* chore: update vscode to release/1.65

* chore(quilt): ignore patch backup files

* chore: refresh/update patches for 1.65
2022-03-30 18:33:58 -05:00
Joe Previte
0fceb128f7 fix(npm): write npm package name to file (#5049) 2022-03-30 18:11:11 -05:00
renovate[bot]
d5d7c519e8 chore(deps): update dependency minimist to v2.2.1 (#5013)
Co-authored-by: Renovate Bot <bot@renovateapp.com>
2022-03-30 15:41:26 -07:00
Joe Previte
7f884203f0 chore(ci): disable docs-preview on forks (#5046) 2022-03-30 13:45:35 -07:00
Joe Previte
cd6d740dc3 chore(rennovate): ignore updates for express (#5044) 2022-03-30 13:25:37 -07:00
cjtim
9c4f41d784 docs(helm): add example env required for docker-in-docker (#5045)
Co-authored-by: Joe Previte <jjprevite@gmail.com>
2022-03-30 11:19:58 -07:00
Joe Previte
5341294d2d fix(workflows): docs-preview and npm job (#5042)
* fix(ci): add GITHUB_TOKEN to docs-preview workflow

* feat(ci): comment npm dev build instructions on PR
2022-03-30 10:47:46 -07:00
Asher
06e36b42bb fix: add missing package.json and source maps (#5040)
* Use --exclude to skip node_modules

Instead of copying and then deleting them.  This will also catch some
node_modules directories that were missed.

* Remove per-extension dependency install

Code packages all the dependencies using webpack for each extension so
there are no dependencies to install.

* Include source maps

I also moved this to its own patch because it feels sufficiently
standalone.

Fixes #5026.

* Refresh language patch

The base is slightly different so it needed to be refreshed.

* Add missing package.json

This was caused by switching to Code's package step which does not
include the package.json.

Fixes #5019.

* Include keytar

It seems this actually is used now.
2022-03-30 10:35:22 -05:00
Joe Previte
be0fe10a6a docs(README): point docs to website (#5041)
* docs(README): point docs to website

* Update docs/README.md
2022-03-30 08:26:59 -07:00
Joe Previte
8316a27da4 refactor(brew-bump): fix homebrew bump script (#5025)
* fix: source lib.sh in docker-buildx-push for tagging version

* chore: use ubuntu and update git config homebrew job

* refactor: simplify brew-bump.sh script

* Revert "fix: source lib.sh in docker-buildx-push for tagging version"

This reverts commit 2f7a3610cb.
2022-03-29 16:58:34 -07:00
Asher
18e19d29e6 fix: minor build fixes (#5039)
* Regenerate last opened patch

The lines were a bit off.

* Remove packaged .gitignore files

Fixes #4964.

* Remove extra Node binary

This gets overidden in the standalone but it was getting uselessly
included in the npm package.
2022-03-29 13:13:56 -05:00
Edouard Vincent
326a1d1862 feat: Add a shrinkwrap file to the NPM release (#5010) 2022-03-29 12:33:56 -05:00
Joe Previte
e1c1ba8b36 fix: source lib.sh in docker-buildx-push for tagging version (#5024) 2022-03-24 09:33:39 -07:00
Joe Previte
ba1ddbd181 fix: use -r with jq and add workflow for artifacts (#5016) 2022-03-22 16:45:59 -07:00
Joe Previte
cf7cff0f72 release: 4.2.0 (#5014)
* chore(release): bump version to 4.2.0

* chore: update CHANGELOG

* chore: bump helm chart version
2022-03-22 16:34:29 -07:00
103 changed files with 2320 additions and 1314 deletions

View File

@@ -66,11 +66,13 @@ body:
required: false
- type: checkboxes
attributes:
label: Does this issue happen in VS Code?
description: Please try reproducing this issue in VS Code
label: Does this issue happen in VS Code or GitHub Codespaces?
description: Please try reproducing this issue in VS Code or GitHub Codespaces
options:
- label: I cannot reproduce this in VS Code.
required: true
- label: I cannot reproduce this in GitHub Codespaces.
required: true
- type: checkboxes
attributes:
label: Are you accessing code-server over HTTPS?

View File

@@ -33,13 +33,13 @@ jobs:
fetch-depth: 0
submodules: true
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Install helm
uses: azure/setup-helm@v1.1
uses: azure/setup-helm@v3.0
- name: Fetch dependencies from cache
id: cache-yarn
@@ -74,10 +74,10 @@ jobs:
fetch-depth: 0
submodules: true
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Fetch dependencies from cache
id: cache-yarn
@@ -116,10 +116,10 @@ jobs:
- name: Patch Code
run: quilt push -a
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Fetch dependencies from cache
id: cache-yarn
@@ -164,7 +164,9 @@ jobs:
if: success()
- name: Upload coverage report to Codecov
run: yarn coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
if: success()
# The release package does not contain any native modules
@@ -217,6 +219,26 @@ jobs:
# Instead, itis determined in publish-npm.sh script
# using GITHUB environment variables
- name: Comment npm information
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ github.token }}
header: npm-dev-build
message: |
✨ code-server dev build published to npm for PR #${{ github.event.number }}!
* _Last publish status_: success
* _Commit_: ${{ github.event.pull_request.head.sha }}
To install in a local project, run:
```shell-session
npm install @coder/code-server-pr@${{ github.event.number }}
```
To install globally, run:
```shell-session
npm install -g @coder/code-server-pr@${{ github.event.number }}
```
# TODO: cache building yarn --production
# possibly 2m30s of savings(?)
# this requires refactoring our release scripts
@@ -233,20 +255,21 @@ jobs:
with:
fetch-depth: 0
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Install development tools
run: |
yum install -y epel-release centos-release-scl
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync python3
- name: Install nfpm and envsubst
run: |
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1
curl -L https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst
mkdir -p ~/.local/bin
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
curl -sSfL https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst
chmod +x envsubst
mv envsubst ~/.local/bin
echo "$HOME/.local/bin" >> $GITHUB_PATH
@@ -267,8 +290,11 @@ jobs:
- name: Build standalone release
run: source scl_source enable devtoolset-9 && yarn release:standalone
- name: Sanity test standalone release
run: yarn test:standalone-release
- name: Install test dependencies
run: SKIP_SUBMODULE_DEPS=1 yarn install
- name: Run integration tests on standalone release
run: yarn test:integration
- name: Build packages with nfpm
run: yarn package
@@ -317,7 +343,7 @@ jobs:
CXX: ${{ format('{0}-g++', matrix.prefix) }}
LINK: ${{ format('{0}-g++', matrix.prefix) }}
NPM_CONFIG_ARCH: ${{ matrix.arch }}
NODE_VERSION: v14.17.4
NODE_VERSION: v16.13.0
steps:
- name: Checkout repo
@@ -325,14 +351,15 @@ jobs:
with:
fetch-depth: 0
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Install nfpm
run: |
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1
mkdir -p ~/.local/bin
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install cross-compiler
@@ -377,14 +404,15 @@ jobs:
with:
fetch-depth: 0
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Install nfpm
run: |
curl -sfL https://install.goreleaser.com/github.com/goreleaser/nfpm.sh | sh -s -- -b ~/.local/bin v2.3.1
mkdir -p ~/.local/bin
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Download npm package
@@ -398,8 +426,11 @@ jobs:
- name: Build standalone release
run: yarn release:standalone
- name: Sanity test standalone release
run: yarn test:standalone-release
- name: Install test dependencies
run: SKIP_SUBMODULE_DEPS=1 yarn install
- name: Run integration tests on standalone release
run: yarn test:integration
- name: Build packages with nfpm
run: yarn package
@@ -426,10 +457,10 @@ jobs:
fetch-depth: 0
submodules: true
- name: Install Node.js v14
- name: Install Node.js v16
uses: actions/setup-node@v3
with:
node-version: "14"
node-version: "16"
- name: Fetch dependencies from cache
id: cache-yarn
@@ -475,6 +506,9 @@ jobs:
run: rm -rf ./release-packages ./test/test-results
trivy-scan-repo:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
@@ -483,7 +517,7 @@ jobs:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@296212627a1e693efa09c00adc3e03b2ba8edf18
uses: aquasecurity/trivy-action@0105373003c89c494a3f436bd5efc57f3ac1ca20
with:
scan-type: "fs"
scan-ref: "."
@@ -494,6 +528,6 @@ jobs:
severity: "HIGH,CRITICAL"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v1
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: "trivy-repo-results.sarif"

View File

@@ -17,8 +17,15 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
analyze:
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/autobuild to send a status report
name: Analyze
runs-on: ubuntu-20.04
@@ -28,13 +35,13 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
config-file: ./.github/codeql-config.yml
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

View File

@@ -24,31 +24,37 @@ jobs:
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get version
id: version
run: echo "::set-output name=version::$(jq .version package.json)"
run: echo "::set-output name=version::$(jq -r .version package.json)"
- name: Download artifact
uses: dawidd6/action-download-artifact@v2
id: download
- name: Download release artifacts
uses: robinraju/release-downloader@v1.4
with:
branch: v${{ steps.version.outputs.version }}
workflow_conclusion: completed
name: "release-packages"
path: release-packages
repository: "coder/code-server"
tag: v${{ steps.version.outputs.version }}
fileName: "*.deb"
out-file-path: "release-packages"
- name: Run ./ci/steps/docker-buildx-push.sh
run: ./ci/steps/docker-buildx-push.sh
- name: Publish to Docker
run: yarn publish:docker
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -30,7 +30,11 @@ jobs:
- name: Comment Credentials
uses: marocchino/sticky-pull-request-comment@v2
# Only run if PR comes from base repo
# Reason: forks cannot access secrets and this will always fail
if: github.event.pull_request.head.repo.full_name == github.repository
with:
GITHUB_TOKEN: ${{ github.token }}
header: codercom-preview-docs
message: |
✨ code-server docs for PR #${{ github.event.number }} is ready! It will be updated on every commit.

View File

@@ -19,6 +19,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: read
jobs:
ubuntu:
name: Test installer on Ubuntu
@@ -31,7 +34,7 @@ jobs:
run: ./install.sh
- name: Test code-server
run: yarn test:standalone-release code-server
run: CODE_SERVER_PATH="code-server" yarn test:integration
alpine:
name: Test installer on Alpine
@@ -63,4 +66,4 @@ jobs:
run: ./install.sh
- name: Test code-server
run: yarn test:standalone-release code-server
run: CODE_SERVER_PATH="code-server" yarn test:integration

View File

@@ -25,13 +25,14 @@ jobs:
- name: Get version
id: version
run: echo "::set-output name=version::$(jq .version package.json)"
run: echo "::set-output name=version::$(jq -r .version package.json)"
- name: Download artifact
uses: dawidd6/action-download-artifact@v2
id: download
with:
branch: v${{ steps.version.outputs.version }}
workflow: ci.yaml
workflow_conclusion: completed
name: "npm-package"
path: release-npm-package
@@ -44,10 +45,8 @@ jobs:
NPM_ENVIRONMENT: "production"
homebrew:
# The newest version of code-server needs to be available on npm when this runs
# otherwise, it will 404 and won't open a PR to bump version on homebrew/homebrew-core
needs: npm
runs-on: macos-latest
runs-on: ubuntu-latest
steps:
# Ensure things are up to date
# Suggested by homebrew maintainers
@@ -59,16 +58,10 @@ jobs:
- name: Checkout code-server
uses: actions/checkout@v3
- name: Checkout cdrci/homebrew-core
uses: actions/checkout@v3
with:
repository: cdrci/homebrew-core
path: homebrew-core
- name: Configure git
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git config --global user.name cdrci
git config --global user.email opensource@coder.com
- name: Bump code-server homebrew version
env:

View File

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

1
.gitignore vendored
View File

@@ -22,3 +22,4 @@ test/test-results
# Quilt's internal data.
/.pc
/patches/*.diff~

View File

@@ -1 +1 @@
14
16

View File

@@ -50,7 +50,7 @@
{
"file": "src/node/heart.ts",
"line": 7,
"description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/master/docs/FAQ.md#heartbeat-file)"
"description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file)"
},
{
"file": "src/node/socket.ts",
@@ -80,12 +80,12 @@
{
"file": "src/node/routes/domainProxy.ts",
"line": 18,
"description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
"description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
},
{
"file": "src/node/routes/pathProxy.ts",
"line": 19,
"description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
"description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
},
{
"file": "src/node/proxy.ts",
@@ -95,7 +95,7 @@
{
"file": "src/node/routes/health.ts",
"line": 5,
"description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/master/docs/FAQ.md#healthz-endpoint)"
"description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint)"
},
{
"file": "src/node/routes/login.ts",
@@ -145,7 +145,7 @@
{
"directory": "lib/vscode",
"line": 1,
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
}
]
}

View File

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

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
VS Code v99.99.999
Code v99.99.999
### Changed
### Added
@@ -20,13 +20,109 @@ VS Code v99.99.999
-->
## [Unreleased](https://github.com/coder/code-server/releases)
## [4.5.0](https://github.com/coder/code-server/releases/tag/v4.5.0) - 2022-06-29
Code v0.00.0
Code v1.68.1
### Changed
- Add here
- Updated codecov to use codecov uploader
- Moved integration tests to Jest
- Fixed docker release to only download .deb
- Upgraded to Code 1.68.1
- Install `nfpm` from GitHub
- Upgraded to TypeScript 4.6
### Added
- Added tests for `open`, `isWsl`, `handlePasswordValidation`
- Provided alternate image registry to dockerhub
- Allowed users to have scripts run on container with `ENTRYPOINTD` environment
variable
### Fixed
- Fixed open CLI command to work on macOS
## [4.4.0](https://github.com/coder/code-server/releases/tag/v4.4.0) - 2022-05-06
Code v1.66.2
### Changed
- Refactored methods in `Heart` class and made `Heart.beat()` async to make
testing easier.
- Upgraded to Code 1.66.2.
### Added
- Added back telemetry patch which was removed in the Code reachitecture.
- Added support to use `true` for `CS_DISABLE_FILE_DOWNLOADS` environment
variable. This means you can disable file downloads by setting
`CS_DISABLE_FILE_DOWNLOADS` to `true` or `1`.
- Added tests for `Heart` class.
### Fixed
- Fixed installation issue in AUR after LICENSE rename.
- Fixed issue with listening on IPv6 addresses.
- Fixed issue with Docker publish action not being able to find artifacts. Now
it downloads the release assets from the release.
## [4.3.0](https://github.com/coder/code-server/releases/tag/v4.3.0) - 2022-04-14
Code v1.65.2
### Changed
- Excluded .deb files from release Docker image which drops the compressed and
uncompressed size by 58% and 34%.
- Upgraded to Code 1.65.2.
### Added
- Added a new CLI flag called `--disable-file-downloads` which allows you to
disable the "Download..." option that shows in the UI when right-clicking on a
file. This can also set by running `CS_DISABLE_FILE_DOWNLOADS=1`.
- Aligned the dependencies for binary and npm release artifacts.
### Fixed
- Fixed the code-server version from not displaying in the Help > About dialog.
- Fixed issues with the TypeScript and JavaScript Language Features Extension
failing to activate.
- Fixed missing files in ipynb extension.
- Fixed the homebrew release workflow.
- Fixed the Docker release workflow from not always publishing version tags.
## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22
Code v1.64.2
### Added
- Added tests for `handleArgsSocketCatchError`, `setDefaults` and
`optionDescriptions`.
### Changed
- We switched from using the fork `coder/vscode` to a submodule of
`microsoft/vscode` + patches managed by `quilt` for how Code sits inside the
code-server codebase.
- Upgraded to Code 1.64.2.
### Fixed
- Update popup notification through `--disable-update-check` is now fixed.
- Fixed PWA icons not loading on iPad
- Fixed the homebrew release process. Our `cdrci` bot should now automatically
update the version as part of the release pipeline.
- Fixed titleBar color setting being ignored in PWA.
### Security
- Updated to `minimist-list`.
- Updated `cloud-agent` to `v0.2.4` which uses `nhooyr.io/webscoket` `v1.8.7`.
## [4.1.0](https://github.com/coder/code-server/releases/tag/v4.1.0) - 2022-03-03

View File

@@ -45,9 +45,6 @@ You can disable minification by setting `MINIFY=`.
- Builds vscode into `./lib/vscode/out-vscode`.
- [./ci/build/build-release.sh](./build/build-release.sh) (`yarn release`)
- Bundles the output of the above two scripts into a single node module at `./release`.
- [./ci/build/build-standalone-release.sh](./build/build-standalone-release.sh) (`yarn release:standalone`)
- Requires a node module already built into `./release` with the above script.
- Will build a standalone release with node and node_modules bundled into `./release-standalone`.
- [./ci/build/clean.sh](./build/clean.sh) (`yarn clean`)
- Removes all build artifacts.
- Useful to do a clean build.
@@ -97,6 +94,8 @@ Helps avoid clobbering the CI configuration.
- Runs `yarn lint`.
- [./steps/test-unit.sh](./steps/test-unit.sh)
- Runs `yarn test:unit`.
- [./steps/test-integration.sh](./steps/test-integration.sh)
- Runs `yarn test:integration`.
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
- Runs `yarn test:e2e`.
- [./steps/release.sh](./steps/release.sh)

View File

@@ -24,7 +24,7 @@ main() {
bundle_vscode
rsync ./docs/README.md "$RELEASE_PATH"
rsync LICENSE.txt "$RELEASE_PATH"
rsync LICENSE "$RELEASE_PATH"
rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
}
@@ -55,6 +55,17 @@ bundle_code_server() {
EOF
) > "$RELEASE_PATH/package.json"
rsync yarn.lock "$RELEASE_PATH"
# To ensure deterministic dependency versions (even when code-server is installed with NPM), we seed
# an npm-shrinkwrap file from our yarn lockfile and the current node-modules installed.
synp --source-file yarn.lock
npm shrinkwrap
# HACK@edvincent: The shrinkwrap file will contain the devDependencies, which by default
# are installed if present in a lockfile. To avoid every user having to specify --production
# to skip them, we carefully remove them from the shrinkwrap file.
json -f npm-shrinkwrap.json -I -e "Object.keys(this.dependencies).forEach(dependency => { if (this.dependencies[dependency].dev) { delete this.dependencies[dependency] } } )"
mv npm-shrinkwrap.json "$RELEASE_PATH"
rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"
if [ "$KEEP_MODULES" = 1 ]; then
@@ -66,59 +77,39 @@ EOF
bundle_vscode() {
mkdir -p "$VSCODE_OUT_PATH"
rsync ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"
# Add the commit, date, our name, links, and enable telemetry. This just makes
# telemetry available; telemetry can still be disabled by flag or setting.
jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
cat << EOF
{
"enableTelemetry": true,
"commit": "$(cd "$VSCODE_SRC_PATH" && git rev-parse HEAD)",
"quality": "stable",
"date": $(jq -n 'now | todate'),
"codeServerVersion": "$VERSION",
"nameShort": "code-server",
"nameLong": "code-server",
"applicationName": "code-server",
"dataFolderName": ".code-server",
"win32MutexName": "codeserver",
"licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE.txt",
"win32DirName": "code-server",
"win32NameVersion": "code-server",
"win32AppUserModelId": "coder.code-server",
"win32ShellNameShort": "c&ode-server",
"darwinBundleIdentifier": "com.coder.code.server",
"linuxIconName": "com.coder.code.server",
"reportIssueUrl": "https://github.com/coder/code-server/issues/new",
"documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
"keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
"keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
"keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
"introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
"tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
"newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
"linkProtectionTrustedDomains": [
"https://open-vsx.org"
]
}
EOF
) > "$VSCODE_OUT_PATH/product.json"
local rsync_opts=()
if [[ ${DEBUG-} = 1 ]]; then
rsync_opts+=(-vh)
fi
# Some extensions have a .gitignore which excludes their built source from the
# npm package so exclude any .gitignore files.
rsync_opts+=(--exclude .gitignore)
# Exclude Node as we will add it ourselves for the standalone and will not
# need it for the npm package.
rsync_opts+=(--exclude /node)
# Exclude Node modules.
if [[ $KEEP_MODULES = 0 ]]; then
rsync_opts+=(--exclude node_modules)
fi
rsync "${rsync_opts[@]}" ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"
# Use the package.json for the web/remote server. It does not have the right
# version though so pull that from the main package.json. Also remove keytar
# since the web does not rely on it and that removes the dependency on
# libsecret.
jq --slurp '.[0] * {version: .[1].version} | del(.dependencies.keytar)' \
# version though so pull that from the main package.json.
jq --slurp '.[0] * {version: .[1].version}' \
"$VSCODE_SRC_PATH/remote/package.json" \
"$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
rsync "$VSCODE_SRC_PATH/remote/yarn.lock" "$VSCODE_OUT_PATH/yarn.lock"
if [ "$KEEP_MODULES" = 0 ]; then
rm -Rf "$VSCODE_OUT_PATH/extensions/node_modules"
rm -Rf "$VSCODE_OUT_PATH/node_modules"
fi
# Include global extension dependencies as well.
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions/yarn.lock"
rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
pushd "$VSCODE_OUT_PATH"
symlink_asar

View File

@@ -9,10 +9,62 @@ MINIFY=${MINIFY-true}
main() {
cd "$(dirname "${0}")/../.."
source ./ci/lib.sh
cd lib/vscode
# Set the commit Code will embed into the product.json. We need to do this
# since Code tries to get the commit from the `.git` directory which will fail
# as it is a submodule.
export VSCODE_DISTRO_COMMIT
VSCODE_DISTRO_COMMIT=$(git rev-parse HEAD)
# Add the date, our name, links, and enable telemetry (this just makes
# telemetry available; telemetry can still be disabled by flag or setting).
# This needs to be done before building as Code will read this file and embed
# it into the client-side code.
git checkout product.json # Reset in case the script exited early.
cp product.json product.original.json # Since jq has no inline edit.
jq --slurp '.[0] * .[1]' product.original.json <(
cat << EOF
{
"enableTelemetry": true,
"quality": "stable",
"codeServerVersion": "$VERSION",
"nameShort": "code-server",
"nameLong": "code-server",
"applicationName": "code-server",
"dataFolderName": ".code-server",
"win32MutexName": "codeserver",
"licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
"win32DirName": "code-server",
"win32NameVersion": "code-server",
"win32AppUserModelId": "coder.code-server",
"win32ShellNameShort": "c&ode-server",
"darwinBundleIdentifier": "com.coder.code.server",
"linuxIconName": "com.coder.code.server",
"reportIssueUrl": "https://github.com/coder/code-server/issues/new",
"documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
"keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
"keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
"keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
"introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
"tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
"newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
"linkProtectionTrustedDomains": [
"https://open-vsx.org"
]
}
EOF
) > product.json
# Any platform works since we have our own packaging step (for now).
yarn gulp "vscode-reh-web-linux-x64${MINIFY:+-min}"
# Reset so if you develop after building you will not be stuck with the wrong
# commit (the dev client will use `oss-dev` but the dev server will still use
# product.json which will have `stable-$commit`).
git checkout product.json
}
main "$@"

View File

@@ -33,8 +33,8 @@ main() {
echo "USE AT YOUR OWN RISK!"
fi
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-14}" ]; then
echo "ERROR: code-server currently requires node v14."
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-16}" ]; then
echo "ERROR: code-server currently requires node v16."
if [ -n "$FORCE_NODE_VERSION" ]; then
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
fi
@@ -68,7 +68,7 @@ main() {
if ! vscode_yarn; then
echo "You may not have the required dependencies to build the native modules."
echo "Please see https://github.com/coder/code-server/blob/master/docs/npm.md"
echo "Please see https://github.com/coder/code-server/blob/main/docs/npm.md"
exit 1
fi
@@ -92,20 +92,12 @@ symlink_asar() {
vscode_yarn() {
echo 'Installing Code dependencies...'
cd lib/vscode
yarn --production --frozen-lockfile
yarn --production --frozen-lockfile --no-default-rc
symlink_asar
cd extensions
yarn --production --frozen-lockfile
for ext in */; do
ext="${ext%/}"
echo "extensions/$ext: installing dependencies"
cd "$ext"
yarn --production --frozen-lockfile
cd "$OLDPWD"
done
}
main "$@"

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
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"

View File

@@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Make sure a code-server release works. You can pass in the path otherwise it
# will use release-standalone in the current directory.
#
# This is to make sure we don't have Node version errors or any other
# compilation-related errors.
main() {
cd "$(dirname "${0}")/../.."
local EXTENSIONS_DIR
EXTENSIONS_DIR="$(mktemp -d)"
local path=${1:-./release-standalone/bin/code-server}
echo "Testing standalone release in $path."
# NOTE: using a basic theme extension because it doesn't update often and is more reliable for testing
"$path" --extensions-dir "$EXTENSIONS_DIR" --install-extension wesbos.theme-cobalt2
local installed_extensions
installed_extensions="$("$path" --extensions-dir "$EXTENSIONS_DIR" --list-extensions 2>&1)"
# We use grep as wesbos.theme-cobalt2 may have dependency extensions that change.
if ! echo "$installed_extensions" | grep -q "wesbos.theme-cobalt2"; then
echo "Unexpected output from listing extensions:"
echo "$installed_extensions"
exit 1
fi
echo "Standalone release works correctly."
}
main "$@"

View File

@@ -7,6 +7,9 @@ install-deps() {
if [[ ${CI-} ]]; then
args+=(--frozen-lockfile)
fi
if [[ "$1" == "lib/vscode" ]]; then
args+=(--no-default-rc)
fi
# If there is no package.json then yarn will look upward and end up installing
# from the root resulting in an infinite loop (this can happen if you have not
# checked out the submodule yet for example).
@@ -26,7 +29,11 @@ main() {
install-deps test
install-deps test/e2e/extensions/test-extension
install-deps lib/vscode
# We don't need these when running the integration tests
# so you can pass SKIP_SUBMODULE_DEPS
if [[ ! ${SKIP_SUBMODULE_DEPS-} ]]; then
install-deps lib/vscode
fi
}
main "$@"

39
ci/dev/test-integration.sh Executable file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -euo pipefail
help() {
echo >&2 " You can build the standalone release with 'yarn release:standalone'"
echo >&2 " Or you can pass in a custom path."
echo >&2 " CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' yarn test:integration"
}
# Make sure a code-server release works. You can pass in the path otherwise it
# will look for release-standalone in the current directory.
#
# This is to make sure we don't have Node version errors or any other
# compilation-related errors.
main() {
cd "$(dirname "$0")/../.."
source ./ci/lib.sh
local path="$RELEASE_PATH-standalone/bin/code-server"
if [[ ! ${CODE_SERVER_PATH-} ]]; then
echo "Set CODE_SERVER_PATH to test another build of code-server"
else
path="$CODE_SERVER_PATH"
fi
echo "Running tests with code-server binary: '$path'"
if [[ ! -f $path ]]; then
echo >&2 "No code-server build detected"
echo >&2 "Looked in $path"
help
exit 1
fi
CODE_SERVER_PATH="$path" CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
}
main "$@"

View File

@@ -30,7 +30,7 @@ main() {
# We must keep jest in a sub-directory. See ../../test/package.json for more
# information. We must also run it from the root otherwise coverage will not
# include our source files.
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@"
CS_DISABLE_PLUGINS=true ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts" --testPathIgnorePatterns "./test/unit/node/test-plugin"
}
main "$@"

View File

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

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.1.0'
tag: '4.5.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
@@ -70,6 +70,8 @@ extraArgs: []
extraVars: []
# - name: DISABLE_TELEMETRY
# value: true
# - name: DOCKER_HOST
# value: "tcp://localhost:2375"
##
## Init containers parameters:
@@ -126,6 +128,7 @@ persistence:
## Enable an Specify container in extraContainers.
## This is meant to allow adding code-server dependencies, like docker-dind.
extraContainers: |
# If docker-dind is used, DOCKER_HOST env is mandatory to set in "extraVars"
#- name: docker-dind
# image: docker:19.03-dind
# imagePullPolicy: IfNotPresent

View File

@@ -1,3 +1,8 @@
# syntax=docker/dockerfile:experimental
FROM scratch AS packages
COPY release-packages/code-server*.deb /tmp/
FROM debian:11
RUN apt-get update \
@@ -34,9 +39,12 @@ RUN ARCH="$(dpkg --print-architecture)" && \
mkdir -p /etc/fixuid && \
printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
COPY release-packages/code-server*.deb /tmp/
COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
RUN dpkg -i /tmp/code-server*$(dpkg --print-architecture).deb && rm /tmp/code-server*.deb
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages dpkg -i /tmp/packages/code-server*$(dpkg --print-architecture).deb
# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
ENV ENTRYPOINTD=${HOME}/entrypoint.d
EXPOSE 8080
# This way, if someone sets $DOCKER_USER, docker-exec will still work as

View File

@@ -15,6 +15,8 @@ target "code-server" {
tags = [
"docker.io/codercom/code-server:latest",
notequal("latest",VERSION) ? "docker.io/codercom/code-server:${VERSION}" : "",
"ghcr.io/coder/code-server:latest",
notequal("latest",VERSION) ? "ghcr.io/coder/code-server:${VERSION}" : "",
]
platforms = ["linux/amd64", "linux/arm64"]
}

View File

@@ -18,4 +18,10 @@ if [ "${DOCKER_USER-}" ]; then
fi
fi
# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
if [ -d "${ENTRYPOINTD}" ]; then
find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
fi
exec dumb-init /usr/bin/code-server "$@"

View File

@@ -2,9 +2,6 @@
set -euo pipefail
main() {
REPO="homebrew-core"
GITHUB_USERNAME="cdrci"
UPSTREAM_USERNAME_AND_REPO="Homebrew/$REPO"
# Only sourcing this so we get access to $VERSION
source ./ci/lib.sh
source ./ci/steps/steps-lib.sh
@@ -23,68 +20,6 @@ main() {
exit 1
fi
# Make sure the git clone step is successful
if ! directory_exists "$REPO"; then
echo "git clone failed. Cannot find $REPO directory."
ls -la
exit 1
fi
echo "Changing into $REPO directory"
pushd "$REPO" && pwd
echo "Adding $UPSTREAM_USERNAME_AND_REPO"
git remote add upstream "https://github.com/$UPSTREAM_USERNAME_AND_REPO.git"
# Make sure the git remote step is successful
if ! git config remote.upstream.url > /dev/null; then
echo "git remote add upstream failed."
echo "Could not find upstream in list of remotes."
git remote -v
exit 1
fi
# TODO@jsjoeio - can I somehow check that this succeeded?
echo "Fetching upstream $UPSTREAM_USERNAME_AND_REPO commits"
git fetch upstream master
# TODO@jsjoeio - can I somehow check that this succeeded?
echo "Merging in latest $UPSTREAM_USERNAME_AND_REPO changes branch master"
git merge upstream/master
# GIT_ASKPASS lets us use the password when pushing without revealing it in the process list
# See: https://serverfault.com/a/912788
PATH_TO_GIT_ASKPASS="$HOME/git-askpass.sh"
# Source: https://serverfault.com/a/912788
# shellcheck disable=SC2016,SC2028
echo 'echo $HOMEBREW_GITHUB_API_TOKEN' > "$PATH_TO_GIT_ASKPASS"
# Make sure the git-askpass.sh file creation is successful
if ! file_exists "$PATH_TO_GIT_ASKPASS"; then
echo "git-askpass.sh not found in $HOME."
ls -la "$HOME"
exit 1
fi
# Ensure it's executable since we just created it
chmod +x "$PATH_TO_GIT_ASKPASS"
# Make sure the git-askpass.sh file is executable
if ! is_executable "$PATH_TO_GIT_ASKPASS"; then
echo "$PATH_TO_GIT_ASKPASS is not executable."
ls -la "$PATH_TO_GIT_ASKPASS"
exit 1
fi
# NOTE: we need to make sure our fork is up-to-date
# otherwise, brew bump-formula-pr will use an
# outdated base
echo "Pushing changes to $GITHUB_USERNAME/$REPO fork on GitHub"
# Export the variables so git sees them
export HOMEBREW_GITHUB_API_TOKEN="$HOMEBREW_GITHUB_API_TOKEN"
export GIT_ASKPASS="$PATH_TO_GIT_ASKPASS"
git push "https://$GITHUB_USERNAME@github.com/$GITHUB_USERNAME/$REPO.git" --all
# Find the docs for bump-formula-pr here
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
local output

View File

@@ -3,6 +3,9 @@ set -euo pipefail
main() {
cd "$(dirname "$0")/../.."
# ci/lib.sh sets VERSION so it's available to ci/release-image/docker-bake.hcl
# to push the VERSION tag.
source ./ci/lib.sh
# NOTE@jsjoeio - this script assumes that you've downloaded
# the release-packages artifact to ./release-packages before

View File

@@ -137,7 +137,10 @@ main() {
# Use the development package name
# This is so we don't clutter the code-server versions on npm
# with development versions.
jq ".name |= \"$PACKAGE_NAME\"" package.json
# jq can't edit in place so we must store in memory and echo
local contents
contents="$(jq ".name |= \"$PACKAGE_NAME\"" package.json)"
echo "${contents}" > package.json
popd
fi

View File

@@ -31,7 +31,7 @@ for [VS
Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Here is what is needed:
- `node` v14.x
- `node` v16.x
- `git` v2.x or greater
- [`git-lfs`](https://git-lfs.github.com)
- [`yarn`](https://classic.yarnpkg.com/en/)
@@ -96,10 +96,12 @@ re-apply the patches.
### Version updates to Code
1. Update the `lib/vscode` submodule to the desired upstream version branch.
2. From the code-server **project root**, run `yarn install`.
3. Apply the patches (`quilt push -a`) or restore your stashed changes. At this
1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
2. `git add lib && git commit -m "chore: update Code"`
2. Apply the patches (`quilt push -a`) or restore your stashed changes. At this
stage you may need to resolve conflicts. For example use `quilt push -f`,
manually apply the rejected portions, then `quilt refresh`.
3. From the code-server **project root**, run `yarn install`.
4. Test code-server locally to make sure everything works.
5. Check the Node.js version that's used by Electron (which is shipped with VS
Code. If necessary, update your version of Node.js to match.
@@ -130,11 +132,13 @@ yarn build:vscode
yarn release
```
_NOTE: this does not keep `node_modules`. If you want them to be kept, use `KEEP_MODULES=1 yarn release` (if you're testing in Coder, you'll want to do this)_
Run your build:
```shell
cd release
yarn --production
yarn --production # Skip if you used KEEP_MODULES=1
# Runs the built JavaScript with Node.
node .
```
@@ -143,7 +147,7 @@ Build the release packages (make sure that you run `yarn release` first):
```shell
yarn release:standalone
yarn test:standalone-release
yarn test:integration
yarn package
```
@@ -184,9 +188,8 @@ We use these to test anything related to our scripts (most of which live under `
### Integration tests
These are a work in progress. We build code-server and run a script called
[test-standalone-release.sh](../ci/build/test-standalone-release.sh), which
ensures that code-server's CLI is working.
These are a work in progress. We build code-server and run tests with `yarn test:integration`, which ensures that code-server builds work on their respective
platforms.
Our integration tests look at components that rely on one another. For example,
testing the CLI requires us to build and package code-server.

View File

@@ -19,7 +19,7 @@
- [Docker](#docker)
- [Homebrew](#homebrew)
- [npm](#npm)
- [Syncing with Upstream VS Code](#syncing-with-upstream-vs-code)
- [Syncing with upstream Code](#syncing-with-upstream-code)
- [Testing](#testing)
- [Documentation](#documentation)
- [Troubleshooting](#troubleshooting)
@@ -164,13 +164,14 @@ If you're the current release manager, follow these steps:
### Publishing a release
1. Create a new branch called `v0.0.0` (replace 0s with actual version aka v4.1.0)
1. Create a new branch called `v0.0.0` (replace 0s with actual version aka v4.5.0)
1. Run `yarn release:prep` and type in the new version (e.g., `3.8.1`)
1. GitHub Actions will generate the `npm-package`, `release-packages` and
`release-images` artifacts. You do not have to wait for this step to complete
before proceeding.
1. Run `yarn release:github-draft` to create a GitHub draft release from the
template with the updated version.
template with the updated version. Make sure to update the `CHANGELOG.md`.
1. Bump chart version in `Chart.yaml`.
1. Summarize the major changes in the release notes and link to the relevant
issues.
1. Change the @ to target the version branch. Example: `v3.9.0 @ Target: v3.9.0`
@@ -214,18 +215,9 @@ We publish code-server as a npm package [here](https://www.npmjs.com/package/cod
This is currently automated with the release process.
## Syncing with Upstream VS Code
## Syncing with upstream Code
The VS Code portion of code-server lives under [`coder/vscode`](https://github.com/coder/vscode). To update VS Code for code-server, follow these steps:
1. `git checkout -b vscode-update` - Create a new branch locally based off `main`
2. `git fetch upstream` - Fetch upstream (VS Code)'s latest branches
3. `git merge upstream/release/1.64` - Merge it locally
1. replace `1.64` with the version you're upgrading to
1. If there are merge conflicts, commit first, then fix them locally.
4. Open a PR merging your branch (`vscode-update`) into `main` and add the code-server review team
Ideally, our fork stays as close to upstream as possible. See the differences between our fork and upstream [here](https://github.com/microsoft/vscode/compare/main...coder:main).
Refer to the [contributing docs](https://coder.com/docs/code-server/latest/CONTRIBUTING#version-updates-to-code) for information on how to update Code within code-server.
## Testing

View File

@@ -1,6 +1,6 @@
# code-server
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/coder/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://coder.com/community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/coder/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/coder/code-server) [![See v4.1.0 docs](https://img.shields.io/static/v1?label=Docs&message=see%20v4.1.0%20&color=blue)](https://github.com/coder/code-server/tree/v4.1.0/docs)
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/coder/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://coder.com/community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/coder/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/coder/code-server) [![See latest](https://img.shields.io/static/v1?label=Docs&message=see%20latest&color=blue)](https://coder.com/docs/code-server/latest)
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
access it in the browser.
@@ -14,8 +14,9 @@ access it in the browser.
- Preserve battery life when you're on the go; all intensive tasks run on your
server
| 🔔 code-server is a free browser-based IDE while [Coder](https://coder.com/) is our enterprise developer workspace platform. For more information, visit [Coder.com](https://coder.com/docs/comparison)
| ---
> **Note**
> To manage multiple IDEs, workspaces, and teams, see
> our new project: [coder/coder](http://cdr.co/coder-github)
## Requirements

View File

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

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
```
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.1.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.5.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.

View File

@@ -126,8 +126,8 @@ access code-server on an iPad or do not want to use SSH port forwarding.
```console
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/gpg/gpg.155B6D79CA56EA34.key' | sudo apt-key add -
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/cfg/setup/config.deb.txt?distro=debian&version=any-version' | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add -
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```

View File

@@ -1,6 +1,6 @@
# 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.1.0](https://img.shields.io/badge/AppVersion-4.1.0-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-4.1.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.5.0](https://img.shields.io/badge/AppVersion-4.5.0-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-4.5.0-informational?style=flat-square)
[code-server](https://github.com/coder/code-server) code-server is VS Code running
on a remote server, accessible through the browser.
@@ -73,7 +73,7 @@ and their default values.
| hostnameOverride | string | `""` |
| image.pullPolicy | string | `"Always"` |
| image.repository | string | `"codercom/code-server"` |
| image.tag | string | `"4.1.0"` |
| image.tag | string | `"4.5.0"` |
| imagePullSecrets | list | `[]` |
| ingress.enabled | bool | `false` |
| nameOverride | string | `""` |

View File

@@ -1,7 +1,9 @@
# Using code-server on iOS with iSH
1. Install iSH from the [App Store](https://apps.apple.com/us/app/ish-shell/id1436902243)
2. Install `curl` with `apk add curl`
3. Install code-server with `curl -fsSL https://code-server.dev/install.sh | sh`
4. Run code-server with `code-server`
5. Access on localhost:8080 in your browser
2. Install `curl` and `nano` with `apk add curl nano`
3. Configure iSH to use an earlier version of NodeJS with `nano /etc/apk/repositories` and edit `v3.14` to `v3.12` on both repository links.
4. Install `nodejs` and `npm` with `apk add nodejs npm`
5. Install code-server with `curl -fsSL https://code-server.dev/install.sh | sh`
6. Run code-server with `code-server`
7. Access on localhost:8080 in your browser

View File

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

View File

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

View File

@@ -10,40 +10,45 @@
- [Create a new user](#create-a-new-user)
- [Install Go](#install-go)
- [Install Python](#install-python)
- [Working with PRoot](#working-with-proot)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Install
1. Get [Termux](https://f-droid.org/en/packages/com.termux/) from **F-Droid**.
2. Install Debian by running the following.
2. Install Debian by running the following:
- Run `termux-setup-storage` to allow storage access, or else code-server won't be able to read from `/sdcard`.\
If you used the Andronix command then you may have to edit the `start-debian.sh` script to mount `/sdcard` just as simple as uncommenting the `command+=" -b /sdcard"` line.
> The following command was extracted from [Andronix](https://andronix.app/) you can also use [proot-distro](https://github.com/termux/proot-distro).
> The following command is from [proot-distro](https://github.com/termux/proot-distro), but you can also use [Andronix](https://andronix.app/).
> After Debian is installed the `~ $` will change to `root@localhost`.
```bash
pkg update -y && pkg install wget curl proot tar -y && wget https://raw.githubusercontent.com/AndronixApp/AndronixOrigin/master/Installer/Debian/debian.sh -O debian.sh && chmod +x debian.sh && bash debian.sh
pkg update -y && pkg install proot-distro -y && proot-distro install debian && proot-distro login debian
```
3. Run the following commands to setup Debian.
3. Run the following commands to setup Debian:
```bash
apt update
apt upgrade -y
apt-get install nano vim sudo curl wget git -y
apt update && apt upgrade -y && apt-get install sudo vim git -y
```
4. Install [NVM](https://github.com/nvm-sh/nvm) by following the install guide in the README, just a curl/wget command.
5. Set up NVM for multi-user. After installing NVM it automatically adds the necessary commands for it to work, but it will only work if you are logged in as root;
4. Install [NVM](https://github.com/nvm-sh/nvm#install--update-script) by following the install guide in the README, just a curl/wget command.
5. Set up NVM for multi-user. After installing NVM it automatically adds the necessary commands for it to work, but it will only work if you are logged in as root:
- Copy the lines NVM asks you to run after running the install script.
- Run `nano /root/.bashrc` and comment out those lines by adding a `#` at the start.
- Run `nano /etc/profile` and paste those lines at the end and make sure to replace `$HOME` with `/root`
- Now run `exit` and start Debain again.
- Run `nano /etc/profile` and paste those lines at the end of the file. Make sure to replace `$HOME` with `/root` on the first line.
- Now run `exit`
- Start Debian again `proot-distro login debian`
6. After following the instructions and setting up NVM you can now install the [required node version](https://coder.com/docs/code-server/latest/npm#nodejs-version) using `nvm install version_here`.
7. To install `code-server` run the following.
6. After following the instructions and setting up NVM you can now install the [required node version](https://coder.com/docs/code-server/latest/npm#nodejs-version) by running:
```bash
nvm install v<major_version_here>
```
7. To install `code-server` run the following:
> To check the install process (Will not actually install code-server)
> If it all looks good, you can install code-server by running the second command
@@ -82,11 +87,11 @@ Potential Workaround :
To create a new user follow these simple steps -
1. Create a new user by running `useradd username -m`.
2. Change the password by running `passwd username`.
3. Give your new user sudo access by runnning `visudo`, scroll down to `User privilege specification` and add the following line after root `username ALL=(ALL:ALL) ALL`.
4. Now edit the `/etc/passwd` file with your commadline editor of choice and at the end of the line that specifies your user change `/bin/sh` to `/bin/bash`.
5. Now switch users, by running `su - username`
1. Create a new user by running `useradd <username> -m`.
2. Change the password by running `passwd <username>`.
3. Give your new user sudo access by running `visudo`, scroll down to `User privilege specification` and add the following line after root `username ALL=(ALL:ALL) ALL`.
4. Now edit the `/etc/passwd` file with your command line editor of choice and at the end of the line that specifies your user change `/bin/sh` to `/bin/bash`.
5. Now switch users by running `su - <username>`
- Remember the `-` betweeen `su` and username is required to execute `/etc/profile`,\
since `/etc/profile` may have some necessary things to be executed you should always add a `-`.
@@ -95,7 +100,7 @@ To create a new user follow these simple steps -
> From https://golang.org/doc/install
1. Go to https://golang.org/dl/ and copy the download link for `linux arm` and run the following.
1. Go to https://golang.org/dl/ and copy the download link for `linux arm` and run the following:
```bash
wget download_link
@@ -115,7 +120,7 @@ rm -rf /usr/local/go && tar -C /usr/local -xzf archive_name
> Run these commands as root
1. Run the following command to install required packages to build python.
1. Run the following commands to install required packages to build python:
```bash
sudo apt-get update
@@ -124,13 +129,13 @@ sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
```
2. Install [pyenv](https://github.com/pyenv/pyenv/) from [pyenv-installer](https://github.com/pyenv/pyenv-installer) by running.
2. Install [pyenv](https://github.com/pyenv/pyenv/) from [pyenv-installer](https://github.com/pyenv/pyenv-installer) by running:
```bash
curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
```
3. Run `nano /etc/profile` and add the following
3. Run `nano /etc/profile` and add the following:
```bash
export PYENV_ROOT="/root/.pyenv"
@@ -139,10 +144,42 @@ eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"
```
4. Exit start Debian again.
4. Exit and start Debian again.
5. Run `pyenv versions` to list all installable versions.
6. Run `pyenv install version` to install the desired python version.
> The build process may take some time (an hour or 2 depending on your device).
7. Run `touch /root/.pyenv/version && echo "your_version_here" > /root/.pyenv/version`
8. (You may have to start Debian again) Run `python3 -V` to verify if PATH works or not.
> If `python3` doesn't work but pyenv says that the install was successful in step 6 then try running `$PYENV_ROOT/versions/your_version/bin/python3`.
### Working with PRoot
Debian PRoot Distro Dev Environment
- Since Node and code-server are installed in the Debian PRoot distro, your `~/.ssh/` configuration, `~/.bashrc`, git, npm packages, etc. should be setup in PRoot as well.
- The terminal accessible in code-server will bring up the filesystem and `~/.bashrc` in the Debian PRoot distro.
Accessing files in the Debian PRoot Distro
- The `/data/data/com.termux/files/home` directory in PRoot accesses the termux home directory (`~`)
- The `/sdcard` directory in PRoot accesses the Android storage directory, though there are [known issues with git and files in the `/sdcard` path](#git-wont-work-in-sdcard)
Accessing the Debian PRoot distro/Starting code-server
- Run the following command to access the Debian PRoot distro, from the termux shell:
```bash
proot-distro login debian
```
- Run the following command to start code-server directly in the Debian PRoot distro, from the termux shell:
```bash
proot-distro login debian -- code-server
```
- If you [created a new user](#create-a-new-user), you'll need to insert the `--user <username>` option between `login` and `debian` in the commands above to run as the user instead of root in PRoot.
Additional information on PRoot and Termux
- Additional information on using your Debian PRoot Distro can be [found here](https://github.com/termux/proot-distro#functionality-overview).

View File

@@ -55,7 +55,7 @@ The detection method works as follows:
- Debian, Ubuntu, Raspbian: install the deb package from GitHub.
- Fedora, CentOS, RHEL, openSUSE: install the rpm package from GitHub.
- Arch Linux: install from the AUR (which pulls releases from GitHub).
- FreeBSD, Alpine: install from yarn/npm.
- FreeBSD, Alpine: install from npm.
- macOS: install using Homebrew if installed otherwise install from GitHub.
- All others: install the release from GitHub.
@@ -419,19 +419,9 @@ install_npm() {
echoh "Installing latest from npm."
echoh
YARN_PATH="${YARN_PATH-yarn}"
NPM_PATH="${YARN_PATH-npm}"
if command_exists "$YARN_PATH"; then
sh_c="sh_c"
if [ ! "${DRY_RUN-}" ] && [ ! -w "$($YARN_PATH global bin)" ]; then
sh_c="sudo_sh_c"
fi
echoh "Installing with yarn."
echoh
"$sh_c" "$YARN_PATH" global add code-server --unsafe-perm
NPM_BIN_DIR="\$($YARN_PATH global bin)" echo_npm_postinstall
return
elif command_exists "$NPM_PATH"; then
if command_exists "$NPM_PATH"; then
sh_c="sh_c"
if [ ! "${DRY_RUN-}" ] && [ ! -w "$(NPM_PATH config get prefix)" ]; then
sh_c="sudo_sh_c"
@@ -442,9 +432,9 @@ install_npm() {
NPM_BIN_DIR="\$($NPM_PATH bin -g)" echo_npm_postinstall
return
fi
echoerr "Please install npm or yarn to install code-server!"
echoerr "Please install npm to install code-server!"
echoerr "You will need at least node v12 and a few C dependencies."
echoerr "See the docs https://coder.com/docs/code-server/latest/install#yarn-npm"
echoerr "See the docs https://coder.com/docs/code-server/latest/install#npm"
exit 1
}

View File

@@ -1,7 +1,7 @@
{
"name": "code-server",
"license": "MIT",
"version": "4.1.0",
"version": "4.5.0",
"description": "Run VS Code on a remote server.",
"homepage": "https://github.com/coder/code-server",
"bugs": {
@@ -18,20 +18,20 @@
"release:github-assets": "./ci/build/release-github-assets.sh",
"release:prep": "./ci/build/release-prep.sh",
"test:e2e": "VSCODE_IPC_HOOK_CLI= ./ci/dev/test-e2e.sh",
"test:standalone-release": "./ci/build/test-standalone-release.sh",
"test:unit": "./ci/dev/test-unit.sh --forceExit --detectOpenHandles",
"test:integration": "./ci/dev/test-integration.sh",
"test:scripts": "./ci/dev/test-scripts.sh",
"package": "./ci/build/build-packages.sh",
"postinstall": "./ci/dev/postinstall.sh",
"publish:npm": "./ci/steps/publish-npm.sh",
"publish:docker": "./ci/steps/docker-buildx-push.sh",
"_audit": "./ci/dev/audit.sh",
"fmt": "./ci/dev/fmt.sh",
"lint": "./ci/dev/lint.sh",
"test": "echo 'Run yarn test:unit or yarn test:e2e' && exit 1",
"ci": "./ci/dev/ci.sh",
"watch": "VSCODE_DEV=1 VSCODE_IPC_HOOK_CLI= NODE_OPTIONS='--max_old_space_size=32384 --trace-warnings' ts-node ./ci/dev/watch.ts",
"icons": "./ci/dev/gen_icons.sh",
"coverage": "codecov"
"icons": "./ci/dev/gen_icons.sh"
},
"main": "out/node/entry.js",
"devDependencies": {
@@ -49,23 +49,24 @@
"@types/split2": "^3.2.0",
"@types/trusted-types": "^2.0.2",
"@types/ws": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"@typescript-eslint/eslint-plugin": "^5.23.0",
"@typescript-eslint/parser": "^5.23.0",
"audit-ci": "^6.0.0",
"codecov": "^3.8.3",
"doctoc": "^2.0.0",
"eslint": "^7.7.0",
"eslint-config-prettier": "^8.1.0",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-prettier": "^4.0.0",
"json": "^11.0.0",
"prettier": "^2.2.1",
"prettier-plugin-sh": "^0.8.0",
"prettier-plugin-sh": "^0.12.0",
"shellcheck": "^1.0.0",
"stylelint": "^13.0.0",
"stylelint-config-recommended": "^5.0.0",
"synp": "^1.9.10",
"ts-node": "^10.0.0",
"typescript": "^4.4.0-dev.20210528"
"typescript": "^4.6.2"
},
"resolutions": {
"ansi-regex": "^5.0.1",
@@ -82,7 +83,7 @@
"follow-redirects": "^1.14.8",
"node-fetch": "^2.6.7",
"nanoid": "^3.1.31",
"minimist": "npm:minimist-lite@2.2.0"
"minimist": "npm:minimist-lite@2.2.1"
},
"dependencies": {
"@coder/logger": "1.1.16",
@@ -97,7 +98,7 @@
"limiter": "^1.1.5",
"pem": "^1.14.2",
"proxy-agent": "^5.0.0",
"qs": "6.10.3",
"qs": "6.11.0",
"rotating-file-stream": "^3.0.0",
"safe-buffer": "^5.1.1",
"safe-compare": "^1.1.4",
@@ -119,7 +120,7 @@
"browser-ide"
],
"engines": {
"node": ">= 14"
"node": "16"
},
"jest": {
"transform": {

View File

@@ -10,16 +10,14 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
+++ code-server/lib/vscode/src/vs/base/common/network.ts
@@ -151,8 +151,10 @@ class RemoteAuthoritiesImpl {
}
@@ -157,7 +157,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
- authority: `${host}:${port}`,
- path: `/vscode-remote-resource`,
+ authority: platform.isWeb ? window.location.host : `${host}:${port}`,
authority: `${host}:${port}`,
- path: this._remoteResourcesPath,
+ path: platform.isWeb
+ ? URI.joinPath(URI.parse(window.location.href), `/vscode-remote-resource`).path
+ : `/vscode-remote-resource`,
+ ? (window.location.pathname + "/" + this._remoteResourcesPath).replace(/\/\/+/g, "/")
+ : this._remoteResourcesPath,
query
});
}
@@ -38,40 +36,28 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@@ -27,23 +27,26 @@
@@ -27,9 +27,9 @@
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
<!-- Workbench Icon/Manifest/CSS -->
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
- <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
+ <link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
</head>
<body aria-label="">
</body>
<!-- Startup (do not modify order of script tags!) -->
- <script src="./static/out/vs/loader.js"></script>
- <script src="./static/out/vs/webPackagePaths.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
@@ -39,7 +39,7 @@
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/loader.js"></script>
<script src="{{WORKBENCH_WEB_BASE_URL}}/out/vs/webPackagePaths.js"></script>
<script>
- const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location.origin).toString();
+ const baseUrl = new URL('{{WORKBENCH_WEB_BASE_URL}}', window.location).toString();
Object.keys(self.webPackagePaths).map(function (key, index) {
- self.webPackagePaths[key] = `${window.location.origin}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
+ self.webPackagePaths[key] = new URL(
+ `{{VS_BASE}}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`,
+ window.location,
+ ).toString();
self.webPackagePaths[key] = `${baseUrl}/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`;
});
require.config({
- baseUrl: `${window.location.origin}/static/out`,
+ baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
recordStats: true,
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@@ -87,68 +73,32 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@@ -24,10 +24,10 @@
@@ -24,9 +24,9 @@
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
<!-- Workbench Icon/Manifest/CSS -->
- <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
- <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
- <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
- <link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
+ <link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
+ <link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="{{VS_BASE}}/manifest.json" crossorigin="use-credentials" />
+ <link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.css">
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
</head>
@@ -35,14 +35,17 @@
</body>
<!-- Startup (do not modify order of script tags!) -->
- <script src="./static/out/vs/loader.js"></script>
- <script src="./static/out/vs/webPackagePaths.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
<script>
Object.keys(self.webPackagePaths).map(function (key, index) {
- self.webPackagePaths[key] = `${window.location.origin}/static/node_modules/${key}/${self.webPackagePaths[key]}`;
+ self.webPackagePaths[key] = new URL(
+ `{{VS_BASE}}/static/node_modules/${key}/${self.webPackagePaths[key]}`,
+ window.location,
+ ).toString();
});
require.config({
- baseUrl: `${window.location.origin}/static/out`,
+ baseUrl: new URL(`{{VS_BASE}}/static/out`, window.location).toString(),
recordStats: true,
trustedTypesPolicy: window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {
@@ -55,7 +58,7 @@
<script>
performance.mark('code/willLoadWorkbenchMain');
</script>
- <script src="./static/out/vs/workbench/workbench.web.main.nls.js"></script>
- <script src="./static/out/vs/workbench/workbench.web.main.js"></script>
- <script src="./static/out/vs/code/browser/workbench/workbench.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.nls.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/workbench/workbench.web.main.js"></script>
+ <script src="{{VS_BASE}}/static/out/vs/code/browser/workbench/workbench.js"></script>
</html>
Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
+++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
@@ -274,7 +274,7 @@ export class BrowserSocketFactory implem
@@ -274,6 +274,7 @@ export class BrowserSocketFactory implem
connect(host: string, port: number, query: string, debugLabel: string, callback: IConnectCallback): void {
connect(host: string, port: number, path: string, query: string, debugLabel: string, callback: IConnectCallback): void {
const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
- const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}/?${query}&skipWebSocketFrames=false`, debugLabel);
+ const socket = this._webSocketFactory.create(`${webSocketSchema}://${window.location.host}${window.location.pathname}?${query}&skipWebSocketFrames=false`, debugLabel);
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
const errorListener = socket.onError((err) => callback(err, undefined));
socket.onOpen(() => {
errorListener.dispose();
@@ -282,6 +282,3 @@ export class BrowserSocketFactory implem
@@ -282,6 +283,3 @@ export class BrowserSocketFactory implem
});
}
}
@@ -159,47 +109,56 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -252,7 +252,10 @@ export class WebClientServer {
@@ -267,14 +267,10 @@ export class WebClientServer {
return res.end();
}
- const remoteAuthority = req.headers.host;
- let originalHost = req.headers['x-original-host'];
- if (Array.isArray(originalHost)) {
- originalHost = originalHost[0];
- }
- const remoteAuthority = originalHost || req.headers.host;
- if (!remoteAuthority) {
- return serveError(req, res, 400, `Bad request.`);
- }
+ // It is not possible to reliably detect the remote authority on the server
+ // in all cases. Set this to something invalid to make sure we catch code
+ // that is using this when it should not.
+ const remoteAuthority = 'remote';
function escapeAttribute(value: string): string {
return value.replace(/"/g, '&quot;');
@@ -272,6 +275,8 @@ export class WebClientServer {
accessToken: this._environmentService.args['github-auth'],
function asJSON(value: unknown): string {
return JSON.stringify(value).replace(/"/g, '&quot;');
@@ -297,6 +293,8 @@ export class WebClientServer {
scopes: [['user:email'], ['repo']]
} : undefined;
+ const base = relativeRoot(getOriginalUrl(req))
+ const vscodeBase = relativePath(getOriginalUrl(req))
const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority,
@@ -279,6 +284,7 @@ export class WebClientServer {
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{
+ rootEndpoint: base,
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
@@ -289,7 +295,9 @@ export class WebClientServer {
} : undefined
}
})))
- .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '');
+ .replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
+ .replace(/{{BASE}}/g, base)
+ .replace(/{{VS_BASE}}/g, vscodeBase);
const cspDirectives = [
'default-src \'self\';',
@@ -368,3 +376,70 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
@@ -308,6 +306,7 @@ export class WebClientServer {
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{
codeServerVersion: this._productService.codeServerVersion,
+ rootEndpoint: base,
embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
...this._productService.extensionsGallery,
@@ -328,8 +327,10 @@ export class WebClientServer {
const values: { [key: string]: string } = {
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
- WORKBENCH_WEB_BASE_URL: this._staticRoute,
- WORKBENCH_NLS_BASE_URL: nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : '',
+ WORKBENCH_WEB_BASE_URL: vscodeBase + this._staticRoute,
+ WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : ''),
+ BASE: base,
+ VS_BASE: vscodeBase,
};
@@ -419,3 +420,70 @@ export class WebClientServer {
return res.end(data);
}
}
@@ -286,7 +245,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
@@ -504,6 +504,7 @@ function doCreateUri(path: string, query
@@ -485,6 +485,7 @@ function doCreateUri(path: string, query
});
}
@@ -294,12 +253,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
return URI.parse(window.location.href).with({ path, query });
}
@@ -515,7 +516,7 @@ function doCreateUri(path: string, query
@@ -496,7 +497,7 @@ function doCreateUri(path: string, query
if (!configElement || !configElementAttribute) {
throw new Error('Missing web configuration element');
}
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = JSON.parse(configElementAttribute);
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents, workspaceUri?: UriComponents } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = JSON.parse(configElementAttribute);
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
// Create workbench
create(document.body, {
Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
@@ -16,7 +16,6 @@ import { getServiceMachineId } from 'vs/
import { IStorageService } from 'vs/platform/storage/common/storage';
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
-import { RemoteAuthorities } from 'vs/base/common/network';
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
@@ -75,7 +74,7 @@ export abstract class AbstractExtensionR
public getExtensionGalleryResourceURL(galleryExtension: { publisher: string; name: string; version: string }, path?: string): URI | undefined {
if (this._extensionGalleryResourceUrlTemplate) {
const uri = URI.parse(format2(this._extensionGalleryResourceUrlTemplate, { publisher: galleryExtension.publisher, name: galleryExtension.name, version: galleryExtension.version, path: 'extension' }));
- return this._isWebExtensionResourceEndPoint(uri) ? uri.with({ scheme: RemoteAuthorities.getPreferredWebSchema() }) : uri;
+ return this._isWebExtensionResourceEndPoint(uri) ? URI.joinPath(URI.parse(window.location.href), uri.path) : uri;
}
return undefined;
}

View File

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

View File

@@ -0,0 +1,31 @@
Prevent builtin extensions from being updated
Updating builtin extensions from the marketplace prevents us from patching them
(for example out GitHub authentication patches).
Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
@@ -234,6 +234,10 @@ export class Extension implements IExten
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
return false;
}
+ // Do not update builtin extensions.
+ if (this.type !== ExtensionType.User) {
+ return false;
+ }
if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
return false;
}
@@ -1088,6 +1092,10 @@ export class ExtensionsWorkbenchService
// Skip if check updates only for builtin extensions and current extension is not builtin.
continue;
}
+ if (installed.type !== ExtensionType.User) {
+ // Never update builtin extensions.
+ continue;
+ }
if (installed.isBuiltin && (!installed.local?.identifier.uuid || (!isWeb && this.productService.quality === 'stable'))) {
// Skip checking updates for a builtin extension if it does not has Marketplace identifier or the current product is VS Code Desktop stable.
continue;

View File

@@ -0,0 +1,183 @@
Add option to disable file downloads via CLI
This patch adds support for a new CLI flag called `--disable-file-downloads`
which allows a user to remove the "Download..." option that shows up when you
right-click files in Code. The default value for this is `false`.
To test this, start code-server with `--disable-file-downloads`, open editor,
right-click on a file (not a folder) and you should **not** see the
"Download..." option.
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -250,6 +250,11 @@ export interface IWorkbenchConstructionO
*/
readonly userDataPath?: string
+ /**
+ * Whether the "Download..." option is enabled for files.
+ */
+ readonly isEnabledFileDownloads?: boolean
+
//#endregion
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -31,6 +31,11 @@ export interface IBrowserWorkbenchEnviro
* Options used to configure the workbench.
*/
readonly options?: IWorkbenchConstructionOptions;
+
+ /**
+ * Enable downloading files via menu actions.
+ */
+ readonly isEnabledFileDownloads?: boolean;
}
export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
@@ -62,6 +67,13 @@ export class BrowserWorkbenchEnvironment
return this.options.userDataPath;
}
+ get isEnabledFileDownloads(): boolean {
+ if (typeof this.options.isEnabledFileDownloads === "undefined") {
+ throw new Error('isEnabledFileDownloads was not provided to the browser');
+ }
+ return this.options.isEnabledFileDownloads;
+ }
+
@memoize
get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); }
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
/* ----- code-server ----- */
'disable-update-check': { type: 'boolean' },
'auth': { type: 'string' },
+ 'disable-file-downloads': { type: 'boolean' },
/* ----- server setup ----- */
@@ -94,6 +95,7 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
'auth'?: string
+ 'disable-file-downloads'?: boolean;
/* ----- server setup ----- */
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -300,6 +300,7 @@ export class WebClientServer {
remoteAuthority,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
userDataPath: this._environmentService.userDataPath,
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
_wrapWebWorkerExtHostInIframe,
developmentOptions: {
enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined,
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
@@ -7,12 +7,11 @@ import { Event } from 'vs/base/common/ev
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext } from 'vs/platform/contextkey/common/contextkeys';
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext } from 'vs/workbench/common/contextkeys';
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { WorkbenchState, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
@@ -24,6 +23,7 @@ import { IEditorResolverService } from '
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { Schemas } from 'vs/base/common/network';
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
+import { IBrowserWorkbenchEnvironmentService } from '../services/environment/browser/environmentService';
export class WorkbenchContextKeysHandler extends Disposable {
private inputFocusedContext: IContextKey<boolean>;
@@ -75,7 +75,7 @@ export class WorkbenchContextKeysHandler
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IConfigurationService private readonly configurationService: IConfigurationService,
- @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
+ @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
@IEditorService private readonly editorService: IEditorService,
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@@ -194,6 +194,9 @@ export class WorkbenchContextKeysHandler
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
+ // code-server
+ IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
+
this.registerListeners();
}
Index: code-server/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
@@ -22,7 +22,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
import { Schemas } from 'vs/base/common/network';
-import { DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey } from 'vs/workbench/common/contextkeys';
+import { DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
@@ -477,13 +477,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL
},
- when: ContextKeyExpr.or(
- // native: for any remote resource
- ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
- // web: for any files
- ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
- // web: for any folders if file system API support is provided
- ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
+ when: ContextKeyExpr.and(
+ IsEnabledFileDownloads,
+ ContextKeyExpr.or(
+ // native: for any remote resource
+ ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
+ // web: for any files
+ ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
+ // web: for any folders if file system API support is provided
+ ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
+ )
)
}));
Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
@@ -30,6 +30,8 @@ export const IsFullscreenContext = new R
export const HasWebFileSystemAccess = new RawContextKey<boolean>('hasWebFileSystemAccess', false, true); // Support for FileSystemAccess web APIs (https://wicg.github.io/file-system-access)
+export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
+
//#endregion

View File

@@ -1,17 +1,28 @@
Add display language support
This likely needs tweaking if we want to upstream.
We can remove this once upstream supports all language packs.
1. Proxies language packs to the service on the backend.
2. NLS configuration is embedded into the HTML for the browser to pick up. This
code to generate this configuration is copied from the native portion.
3. Remove navigator.language default since that will prevent the argv file from
being created if you are changing the language to whatever your browser
default happens to be.
4. Move the argv.json file to the server instead of in-browser storage. This is
where the current locale is stored and currently the server needs to be able
to read it.
5. Add the locale flag.
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
@@ -198,6 +198,9 @@ export async function setupServerService
@@ -202,6 +202,9 @@ export async function setupServerService
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
socketServer.registerChannel('extensions', channel);
+ const localizationsChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILocalizationsService));
+ socketServer.registerChannel('localizations', localizationsChannel);
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService));
+ socketServer.registerChannel('languagePacks', languagePackChannel);
+
const encryptionChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(IEncryptionMainService));
socketServer.registerChannel('encryption', encryptionChannel);
@@ -20,9 +31,12 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/platform.ts
+++ code-server/lib/vscode/src/vs/base/common/platform.ts
@@ -83,6 +83,17 @@ if (typeof navigator === 'object' && !is
@@ -80,8 +80,19 @@ if (typeof navigator === 'object' && !is
_isIOS = (_userAgent.indexOf('Macintosh') >= 0 || _userAgent.indexOf('iPad') >= 0 || _userAgent.indexOf('iPhone') >= 0) && !!navigator.maxTouchPoints && navigator.maxTouchPoints > 0;
_isLinux = _userAgent.indexOf('Linux') >= 0;
_isWeb = true;
_locale = navigator.language;
- _locale = navigator.language;
+ _locale = LANGUAGE_DEFAULT;
_language = _locale;
+
+ const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration');
@@ -51,23 +65,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
+
<!-- Workbench Icon/Manifest/CSS -->
<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" />
@@ -38,6 +41,27 @@
<script src="{{VS_BASE}}/static/out/vs/loader.js"></script>
<script src="{{VS_BASE}}/static/out/vs/webPackagePaths.js"></script>
<script>
+ let nlsConfig
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
@@ -43,17 +46,27 @@
self.webPackagePaths[key] = `${baseUrl}/node_modules/${key}/${self.webPackagePaths[key]}`;
});
- // Set up nls if the user is not using the default language (English)
const nlsConfig = {};
- const locale = navigator.language;
- if (!locale.startsWith('en')) {
- nlsConfig['vs/nls'] = {
- availableLanguages: {
- '*': locale
- },
- baseUrl: '{{WORKBENCH_NLS_BASE_URL}}'
- };
- }
+ try {
+ nlsConfig = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
+ if (nlsConfig._resolvedLanguagePackCoreLocation) {
+ nlsConfig['vs/nls'] = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
+ if (nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation) {
+ const bundles = Object.create(null)
+ nlsConfig.loadBundle = (bundle, _language, cb) => {
+ nlsConfig['vs/nls'].loadBundle = (bundle, _language, cb) => {
+ const result = bundles[bundle]
+ if (result) {
+ return cb(undefined, result)
+ }
+ const path = nlsConfig._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
+ fetch(`{{VS_BASE}}/vscode-remote-resource?path=${encodeURIComponent(path)}`)
+ const path = nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation + "/" + bundle.replace(/\//g, "!") + ".nls.json"
+ fetch(`{{WORKBENCH_WEB_BASE_URL}}/vscode-remote-resource?path=${encodeURIComponent(path)}`)
+ .then((response) => response.json())
+ .then((json) => {
+ bundles[bundle] = json
@@ -77,24 +101,14 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
+ }
+ }
+ } catch (error) { /* Probably fine. */ }
Object.keys(self.webPackagePaths).map(function (key, index) {
self.webPackagePaths[key] = new URL(
`{{VS_BASE}}/static/remote/web/node_modules/${key}/${self.webPackagePaths[key]}`,
@@ -52,7 +76,8 @@
return value;
}
}),
- paths: self.webPackagePaths
+ paths: self.webPackagePaths,
+ 'vs/nls': nlsConfig,
});
</script>
<script>
require.config({
baseUrl: `${baseUrl}/out`,
Index: code-server/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
@@ -105,7 +105,7 @@ export abstract class AbstractNativeEnvi
@@ -108,7 +108,7 @@ export abstract class AbstractNativeEnvi
return URI.file(join(vscodePortable, 'argv.json'));
}
@@ -173,93 +187,83 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
import { IProductConfiguration } from 'vs/base/common/product';
import { isString } from 'vs/base/common/types';
+import { getLocaleFromConfig, getNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
import { CharCode } from 'vs/base/common/charCode';
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
@@ -295,6 +296,8 @@ export class WebClientServer {
const textMimeType = {
'.html': 'text/html',
@@ -277,6 +278,8 @@ export class WebClientServer {
} : undefined;
const base = relativeRoot(getOriginalUrl(req))
const vscodeBase = relativePath(getOriginalUrl(req))
+ const locale = this._environmentService.args.locale || await getLocaleFromConfig(this._environmentService.argvResource.fsPath);
+ const nlsConfiguration = await getNLSConfiguration(locale, this._environmentService.userDataPath)
const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority,
@@ -301,7 +304,8 @@ export class WebClientServer {
})))
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
.replace(/{{BASE}}/g, base)
- .replace(/{{VS_BASE}}/g, vscodeBase);
+ .replace(/{{VS_BASE}}/g, vscodeBase)
+ .replace(/{{NLS_CONFIGURATION}}/g, () => escapeAttribute(JSON.stringify(nlsConfiguration)));
const cspDirectives = [
'default-src \'self\';',
const workbenchWebConfiguration = {
remoteAuthority,
@@ -338,6 +341,7 @@ export class WebClientServer {
WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${this._productService.commit}/${this._productService.version}/` : ''),
BASE: base,
VS_BASE: vscodeBase,
+ NLS_CONFIGURATION: asJSON(nlsConfiguration),
};
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
/* ----- code-server ----- */
@@ -15,6 +15,7 @@ export const serverOptions: OptionDescri
'disable-update-check': { type: 'boolean' },
'auth': { type: 'string' },
'disable-file-downloads': { type: 'boolean' },
+ 'locale': { type: 'string' },
/* ----- server setup ----- */
@@ -90,6 +91,7 @@ export interface ServerParsedArgs {
/* ----- code-server ----- */
@@ -96,6 +97,7 @@ export interface ServerParsedArgs {
'disable-update-check'?: boolean;
'auth'?: string
'disable-file-downloads'?: boolean;
+ 'locale'?: string
/* ----- server setup ----- */
Index: code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
@@ -109,6 +109,12 @@ registerSingleton(IDiagnosticsService, N
//#region --- workbench contributions
+// Localization. These do not actually import anything specific to Electron so
+// they should be safe.
+import 'vs/workbench/services/localization/electron-sandbox/localeService';
+import 'vs/workbench/contrib/localization/electron-sandbox/localization.contribution';
+import 'vs/platform/languagePacks/browser/languagePacks';
+
// Output
import 'vs/workbench/contrib/output/common/outputChannelModelService';
Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
===================================================================
--- /dev/null
+++ code-server/lib/vscode/src/vs/workbench/services/localizations/browser/localizationsService.ts
@@ -0,0 +1,28 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Coder Technologies. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+++ code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
@@ -0,0 +1,18 @@
+import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
+import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
+import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
+
+/**
+ * Add localizations service for the browser.
+ * @author coder
+ */
+
+// @ts-ignore: interface is implemented via proxy
+export class LocalizationsService implements ILocalizationsService {
+export class LanguagePackService implements ILanguagePackService {
+
+ declare readonly _serviceBrand: undefined;
+
+ constructor(
+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
+ ) {
+ return ProxyChannel.toService<ILocalizationsService>(remoteAgentService.getConnection()!.getChannel('localizations'));
+ return ProxyChannel.toService<ILanguagePackService>(remoteAgentService.getConnection()!.getChannel('languagePacks'));
+ }
+}
+
+registerSingleton(ILocalizationsService, LocalizationsService, true);
Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
@@ -109,6 +109,10 @@ registerSingleton(ICustomEndpointTelemet
//#region --- workbench contributions
+// Localizations
+import 'vs/workbench/contrib/localizations/browser/localizations.contribution';
+import 'vs/workbench/services/localizations/browser/localizationsService';
+
// Output
import 'vs/workbench/contrib/output/common/outputChannelModelService';
+registerSingleton(ILanguagePackService, LanguagePackService, true);

View File

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

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.
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
===================================================================
@@ -15,7 +20,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
import { Disposable } from 'vs/base/common/lifecycle';
+import { localize } from 'vs/nls';
+import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
export class CodeServerClient extends Disposable {
constructor (
+ @INotificationService private notificationService: INotificationService,

View File

@@ -7,7 +7,7 @@ Prepare Code for integration with code-server
3. Add the code-server version to the help dialog.
4. Add ready events for use in an iframe.
5. Add our icons.
6. Remove sourcemap host since we cannot upload ours there.
6. Use our own manifest.
Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
===================================================================
@@ -22,7 +22,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
import product from 'vs/platform/product/common/product';
import * as perf from 'vs/base/common/performance';
@@ -33,37 +33,42 @@ const errorReporter: ErrorReporter = {
@@ -34,38 +34,43 @@ const errorReporter: ErrorReporter = {
}
};
@@ -35,6 +35,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
-const USER_DATA_PATH = join(REMOTE_DATA_FOLDER, 'data');
-const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
-const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
-const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
-const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
-args['user-data-dir'] = USER_DATA_PATH;
-const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
@@ -42,7 +43,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
-args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
-args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
-
-[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => {
-[REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => {
- try {
- if (!fs.existsSync(f)) {
- fs.mkdirSync(f, { mode: 0o700 });
@@ -54,6 +55,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
+ const USER_DATA_PATH = args['user-data-dir'] || join(REMOTE_DATA_FOLDER, 'data');
+ const APP_SETTINGS_HOME = join(USER_DATA_PATH, 'User');
+ const GLOBAL_STORAGE_HOME = join(APP_SETTINGS_HOME, 'globalStorage');
+ const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
+ const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
+ args['user-data-dir'] = USER_DATA_PATH;
+ const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
@@ -61,14 +63,14 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
+ args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
+ args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
+
+ [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME].forEach(f => {
+ [REMOTE_DATA_FOLDER, args['extensions-dir'], USER_DATA_PATH, APP_SETTINGS_HOME, MACHINE_SETTINGS_HOME, GLOBAL_STORAGE_HOME, LOCAL_HISTORY_HOME].forEach(f => {
+ try {
+ if (!fs.existsSync(f)) {
+ fs.mkdirSync(f, { mode: 0o700 });
+ }
+ } catch (err) { console.error(err); }
+ });
+ return REMOTE_DATA_FOLDER
+ return REMOTE_DATA_FOLDER;
+}
/**
@@ -105,21 +107,20 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
@@ -144,11 +144,12 @@ export class BrowserDialogHandler implem
@@ -143,8 +143,11 @@ export class BrowserDialogHandler implem
async about(): Promise<void> {
const detailString = (useAgo: boolean): string => {
return localize('aboutDetail',
- return localize('aboutDetail',
- "Version: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
+ "code-server: v{4}\nCode: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
+ return localize('aboutCodeServerDetail',
+ "code-server: {0}",
+ this.productService.codeServerVersion ? `v${this.productService.codeServerVersion}` : 'Unknown'
+ ) + '\n' + localize('aboutDetail',
+ "Code: {0}\nCommit: {1}\nDate: {2}\nBrowser: {3}",
this.productService.version || 'Unknown',
this.productService.commit || 'Unknown',
this.productService.date ? `${this.productService.date}${useAgo ? ' (' + fromNow(new Date(this.productService.date), true) + ')' : ''}` : 'Unknown',
- navigator.userAgent
+ navigator.userAgent,
+ this.productService.codeServerVersion || 'Unknown'
);
};
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- /dev/null
@@ -175,15 +176,15 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -69,6 +69,7 @@ import { ICredentialsService } from 'vs/
import { IndexedDB } from 'vs/base/browser/indexedDB';
@@ -69,6 +69,7 @@ import { IndexedDB } from 'vs/base/brows
import { BrowserCredentialsService } from 'vs/workbench/services/credentials/browser/credentialsService';
import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
+import { CodeServerClient } from 'vs/workbench/browser/client';
export class BrowserMain extends Disposable {
@@ -103,6 +104,9 @@ export class BrowserMain extends Disposa
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel';
@@ -109,6 +110,9 @@ export class BrowserMain extends Disposa
// Startup
const instantiationService = workbench.startup();
@@ -214,22 +215,24 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench-dev.html
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Code">
- <link rel="apple-touch-icon" href="/code-192.png" />
- <link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
+ <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
+ <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@@ -26,7 +27,8 @@
@@ -26,8 +27,9 @@
<meta id="vscode-workbench-builtin-extensions" data-settings="{{WORKBENCH_BUILTIN_EXTENSIONS}}">
<!-- Workbench Icon/Manifest/CSS -->
- <link rel="icon" href="/favicon.ico" type="image/x-icon" />
- <link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
- <link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
+ <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
</head>
<body aria-label="">
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
@@ -238,32 +241,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Code">
- <link rel="apple-touch-icon" href="/code-192.png" />
- <link rel="apple-touch-icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/code-192.png" />
+ <link rel="apple-touch-icon" sizes="192x192" href="/_static/src/browser/media/pwa-icon-192.png" />
+ <link rel="apple-touch-icon" sizes="512x512" href="/_static/src/browser/media/pwa-icon-512.png" />
<!-- Disable pinch zooming -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
@@ -23,7 +24,8 @@
@@ -23,8 +24,9 @@
<meta id="vscode-workbench-auth-session" data-settings="{{WORKBENCH_AUTH_SESSION}}">
<!-- Workbench Icon/Manifest/CSS -->
- <link rel="icon" href="/favicon.ico" type="image/x-icon" />
- <link rel="icon" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/favicon.ico" type="image/x-icon" />
- <link rel="manifest" href="{{WORKBENCH_WEB_BASE_URL}}/resources/server/manifest.json" crossorigin="use-credentials" />
+ <link rel="icon" href="/_static/src/browser/media/favicon-dark-support.svg" />
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" />
<link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="./static/out/vs/workbench/workbench.web.main.css">
+ <link rel="alternate icon" href="/_static/src/browser/media/favicon.ico" type="image/x-icon" />
+ <link rel="manifest" href="/manifest.json" crossorigin="use-credentials" />
<link data-name="vs/workbench/workbench.web.main" rel="stylesheet" href="{{WORKBENCH_WEB_BASE_URL}}/out/vs/workbench/workbench.web.main.css">
Index: code-server/lib/vscode/build/gulpfile.reh.js
</head>
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
+++ code-server/lib/vscode/build/gulpfile.reh.js
@@ -365,7 +365,7 @@ function packageTask(type, platform, arc
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
optimizeTask,
util.rimraf(`out-vscode-${type}-min`),
- common.minifyTask(`out-vscode-${type}`, `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`)
+ common.minifyTask(`out-vscode-${type}`, ``)
));
gulp.task(minifyTask);
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -307,6 +307,7 @@ export class WebClientServer {
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
productConfiguration: <Partial<IProductConfiguration>>{
+ codeServerVersion: this._productService.codeServerVersion,
embedderIdentifier: 'server-distro',
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
...this._productService.extensionsGallery,

View File

@@ -1,32 +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.
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
@@ -350,19 +350,6 @@ class WorkspaceProvider implements IWork
workspace = { folderUri: URI.revive(config.folderUri) };
} else if (config.workspaceUri) {
workspace = { workspaceUri: URI.revive(config.workspaceUri) };
- } else {
- workspace = (() => {
- const lastWorkspaceRaw = window.localStorage.getItem(WorkspaceProvider.LAST_WORKSPACE_STORAGE_KEY);
- if (lastWorkspaceRaw) {
- try {
- return parse(lastWorkspaceRaw); // use marshalling#parse() to revive potential URIs
- } catch (error) {
- // Ignore
- }
- }
-
- return undefined;
- })();
}
}

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/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -289,6 +289,7 @@ export class WebClientServer {
enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined,
logLevel: this._logService.getLevel(),
},
+ userDataPath: this._environmentService.userDataPath,
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{
rootEndpoint: base,
@@ -299,6 +299,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
+ userDataPath: this._environmentService.userDataPath,
_wrapWebWorkerExtHostInIframe,
developmentOptions: {
enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined,
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -205,6 +205,11 @@ export interface IWorkbenchConstructionO
@@ -245,6 +245,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, any>;
@@ -48,11 +48,11 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -126,7 +126,14 @@ export class BrowserWorkbenchEnvironment
@@ -53,7 +53,14 @@ export class BrowserWorkbenchEnvironment
get logFile(): URI { return joinPath(this.logsHome, 'window.log'); }
@memoize
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.userData }); }
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.vscodeUserData }); }
+ get userRoamingDataHome(): URI { return joinPath(URI.file(this.userDataPath).with({ scheme: Schemas.vscodeRemote }), 'User'); }
+
+ get userDataPath(): string {

View File

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

View File

@@ -28,7 +28,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -88,6 +89,7 @@ export const serverOptions: OptionDescri
@@ -92,6 +93,7 @@ export const serverOptions: OptionDescri
export interface ServerParsedArgs {
/* ----- code-server ----- */
'disable-update-check'?: boolean;
@@ -40,14 +40,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -287,6 +287,7 @@ export class WebClientServer {
productConfiguration: <Partial<IProductConfiguration>>{
rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
+ logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
extensionsGallery: {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
@@ -309,6 +309,7 @@ export class WebClientServer {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
+ logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
},
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts

View File

@@ -3,6 +3,13 @@ Add Open VSX default and an env var for marketplace, fix old marketplace
Our old marketplace only supports `serviceUrl` but this causes the marketplace
to be disabled entirely so this moves the template var check to fix that.
This also removes serverRootPath from the web extension route because that will
include the commit. When you update code-server (including this update) the web
extension will continue using the old path since it is stored in the browser but
the path will 404 because the commit no longer matches. This change is only to
support current installations though because this patch also removes the
in-between and has web extensions install directly from the marketplace.
This can be tested by setting EXTENSIONS_GALLERY set to:
'{"serviceUrl": "https://extensions.coder.com/api"}'
@@ -32,22 +39,49 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -285,14 +285,14 @@ export class WebClientServer {
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{
rootEndpoint: base,
- extensionsGallery: this._webExtensionResourceUrlTemplate ? {
+ extensionsGallery: {
...this._productService.extensionsGallery,
- 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
+ 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
scheme: 'http',
authority: remoteAuthority,
path: `web-extension-resource/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
- }).toString(true)
- } : undefined
+ }).toString(true) : undefined
+ },
}
})))
.replace('{{WORKBENCH_AUTH_SESSION}}', () => authSessionInfo ? escapeAttribute(JSON.stringify(authSessionInfo)) : '')
@@ -111,7 +111,7 @@ export class WebClientServer {
const serverRootPath = getRemoteServerRootPath(_productService);
this._staticRoute = `${serverRootPath}/static`;
this._callbackRoute = `${serverRootPath}/callback`;
- this._webExtensionRoute = `${serverRootPath}/web-extension-resource`;
+ this._webExtensionRoute = `/web-extension-resource`;
}
/**
@@ -308,14 +308,7 @@ export class WebClientServer {
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: base,
embedderIdentifier: 'server-distro',
- extensionsGallery: this._webExtensionResourceUrlTemplate ? {
- ...this._productService.extensionsGallery,
- 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
- scheme: 'http',
- authority: remoteAuthority,
- path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
- }).toString(true)
- } : undefined
+ extensionsGallery: this._productService.extensionsGallery,
},
callbackRoute: this._callbackRoute
};
Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
@@ -16,7 +16,6 @@ import { getServiceMachineId } from 'vs/
import { IStorageService } from 'vs/platform/storage/common/storage';
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
-import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
@@ -60,7 +59,7 @@ export abstract class AbstractExtensionR
private readonly _environmentService: IEnvironmentService,
private readonly _configurationService: IConfigurationService,
) {
- this._webExtensionResourceEndPoint = `${getRemoteServerRootPath(_productService)}/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
+ this._webExtensionResourceEndPoint = `/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
if (_productService.extensionsGallery) {
this._extensionGalleryResourceUrlTemplate = _productService.extensionsGallery.resourceUrlTemplate;
this._extensionGalleryAuthority = this._extensionGalleryResourceUrlTemplate ? this._getExtensionGalleryAuthority(URI.parse(this._extensionGalleryResourceUrlTemplate)) : undefined;

View File

@@ -1,106 +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
@@ -122,9 +122,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,3 +0,0 @@
-disturl "http://nodejs.org/dist"
-target "14.16.0"
-runtime "node"
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/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
@@ -1134,7 +1134,7 @@ class ProposedApiController {
@@ -1451,7 +1451,7 @@ class ProposedApiController {
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
@@ -22,7 +22,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
@@ -135,10 +135,7 @@ export interface IExtensionHost {
@@ -359,10 +359,7 @@ function extensionDescriptionArrayToMap(
}
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {

View File

@@ -26,25 +26,25 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
+++ code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
@@ -7,7 +7,7 @@ import { Emitter } from 'vs/base/common/
import { Disposable } from 'vs/base/common/lifecycle';
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/comm
import { RemoteAuthorities } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { IProductService } from 'vs/platform/product/common/productService';
-import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
+import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
@@ -20,7 +20,7 @@ export class RemoteAuthorityResolverServ
@@ -22,7 +22,7 @@ export class RemoteAuthorityResolverServ
private readonly _connectionToken: string | undefined;
private readonly _connectionTokens: Map<string, string>;
- constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
+ constructor(connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
- constructor(@IProductService productService: IProductService, connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
+ constructor(@IProductService productService: IProductService, connectionToken: string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
super();
this._cache = new Map<string, ResolverResult>();
this._connectionToken = connectionToken;
@@ -59,12 +59,17 @@ export class RemoteAuthorityResolverServ
@@ -62,12 +62,17 @@ export class RemoteAuthorityResolverServ
private _doResolveAuthority(authority: string): ResolverResult {
const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
@@ -68,24 +68,24 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -288,6 +288,7 @@ export class WebClientServer {
rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
+ proxyEndpointTemplate: base + '/proxy/{{port}}',
extensionsGallery: {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
@@ -310,6 +310,7 @@ export class WebClientServer {
rootEndpoint: base,
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
+ proxyEndpointTemplate: base + '/proxy/{{port}}',
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
},
Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
@@ -179,7 +179,7 @@ export class BrowserMain extends Disposa
@@ -209,7 +209,7 @@ export class BrowserMain extends Disposa
// Remote
const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);
- const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider);
+ const remoteAuthorityResolverService = new RemoteAuthorityResolverService(connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
- const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider);
+ const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
// Signing
@@ -93,7 +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/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
@@ -388,7 +388,7 @@ export function createTerminalEnvironmen
@@ -388,7 +388,7 @@ export async function createTerminalEnvi
// Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables

View File

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

View File

@@ -21,17 +21,17 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -296,6 +296,10 @@ export class WebClientServer {
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
proxyEndpointTemplate: base + '/proxy/{{port}}',
+ serviceWorker: {
+ scope: vscodeBase + '/',
+ path: base + '/_static/out/browser/serviceWorker.js',
+ },
extensionsGallery: {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
@@ -315,6 +315,10 @@ export class WebClientServer {
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
logoutEndpoint: this._environmentService.args['auth'] ? base + '/logout' : undefined,
proxyEndpointTemplate: base + '/proxy/{{port}}',
+ serviceWorker: {
+ scope: vscodeBase + '/',
+ path: base + '/_static/out/browser/serviceWorker.js',
+ },
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
},
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts

43
patches/sourcemaps.diff Normal file
View File

@@ -0,0 +1,43 @@
Make sourcemaps self-hosted
Normally source maps get removed as part of the build process so prevent that
from happening. Also avoid using the windows.net host since obviously we can
not host our source maps there and want them to be self-hosted even if we could.
To test try debugging/browsing the source of a build in a browser.
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
@@ -194,8 +194,7 @@ function packageTask(type, platform, arc
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
- .pipe(util.setExecutableBit(['**/*.sh']))
- .pipe(filter(['**', '!**/*.js.map']));
+ .pipe(util.setExecutableBit(['**/*.sh']));
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
const isUIExtension = (manifest) => {
@@ -234,9 +233,9 @@ function packageTask(type, platform, arc
.map(name => `.build/extensions/${name}/**`);
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
- const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true });
- const sources = es.merge(src, extensions, extensionsCommonDependencies)
+ const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true })
.pipe(filter(['**', '!**/*.js.map'], { dot: true }));
+ const sources = es.merge(src, extensions, extensionsCommonDependencies);
let version = packageJson.version;
const quality = product.quality;
@@ -371,7 +370,7 @@ function tweakProductForServerWeb(produc
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
optimizeTask,
util.rimraf(`out-vscode-${type}-min`),
- common.minifyTask(`out-vscode-${type}`, `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`)
+ common.minifyTask(`out-vscode-${type}`, '')
));
gulp.task(minifyTask);

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
code-server.
To test this:
1. run code-server
2. open file outside of code-server i.e. `code-server <path-to-file`
It should open in your existing code-server instance.
Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts

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
@@ -70,6 +70,7 @@ import { REMOTE_FILE_SYSTEM_CHANNEL_NAME
import { ExtensionHostStatusService, IExtensionHostStatusService } from 'vs/server/node/extensionHostStatusService';
import { IExtensionsScannerService } from 'vs/platform/extensionManagement/common/extensionsScannerService';
import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
+import { TelemetryClient } from "vs/server/node/telemetryClient";
import { NullPolicyService } from 'vs/platform/policy/common/policy';
const eventPrefix = 'monacoworkbench';
@@ -123,7 +124,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/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
@@ -120,16 +120,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;
}
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
@@ -320,6 +320,7 @@ export class WebClientServer {
scope: vscodeBase + '/',
path: base + '/_static/out/browser/serviceWorker.js',
},
+ enableTelemetry: this._productService.enableTelemetry,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
},

View File

@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
@@ -13,6 +13,7 @@ import { InMemoryStorageDatabase, isStor
import { ILogService } from 'vs/platform/log/common/log';
import { AbstractStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
import { IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
+import { hash } from 'vs/base/common/hash';
export class BrowserStorageService extends AbstractStorageService {

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
package.json and delete the last notification storage item.
1. change version in root `package.json`
2. Open DevTools > Application > Storage (top-level)
3. Click "Clear site data"
4. See update notification
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
@@ -100,14 +105,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -286,6 +286,7 @@ export class WebClientServer {
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
productConfiguration: <Partial<IProductConfiguration>>{
rootEndpoint: base,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
extensionsGallery: {
...this._productService.extensionsGallery,
'resourceUrlTemplate': this._webExtensionResourceUrlTemplate ? this._webExtensionResourceUrlTemplate.with({
@@ -308,6 +308,7 @@ export class WebClientServer {
productConfiguration: <Partial<IProductConfiguration>>{
codeServerVersion: this._productService.codeServerVersion,
rootEndpoint: base,
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
embedderIdentifier: 'server-distro',
extensionsGallery: this._productService.extensionsGallery,
},
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
@@ -121,7 +126,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
/* ----- server setup ----- */
@@ -84,6 +86,8 @@ export const serverOptions: OptionDescri
@@ -88,6 +90,8 @@ export const serverOptions: OptionDescri
};
export interface ServerParsedArgs {

View File

@@ -6,41 +6,112 @@ self-hosted.
When doing this CSP will block resources (for example when viewing images) so
add 'self' to the CSP to fix that.
Additionally the service worker defaults to handling *all* requests made to the
current host but when self-hosting the webview this will end up including the
webview HTML itself which means these requests will fail since the communication
channel between the webview and the main thread has not been set up yet as the
webview itself is not ready yet (it has no HTML and therefore no script either).
Since this code exists only for the authentication case we can just skip it when
it is served from the current host as authentication is not a problem if the
request is not cross-origin.
There is also an origin check we bypass (this seems to be related to how the
webview host is separate by default but we serve on the same host).
To test, open a few types of webviews (images, markdown, extension details, etc).
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -240,7 +240,7 @@ export class BrowserWorkbenchEnvironment
@@ -183,7 +183,7 @@ export class BrowserWorkbenchEnvironment
@memoize
get webviewExternalEndpoint(): string {
- const endpoint = this.options.webviewEndpoint
+ const endpoint = (this.options.webviewEndpoint && new URL(this.options.webviewEndpoint, window.location.toString()).toString())
|| this.productService.webviewContentExternalBaseUrlTemplate
|| 'https://{{uuid}}.vscode-webview.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
|| 'https://{{uuid}}.vscode-cdn.net/{{quality}}/{{commit}}/out/vs/workbench/contrib/webview/browser/pre/';
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
@@ -280,6 +280,7 @@ export class WebClientServer {
const data = (await util.promisify(fs.readFile)(filePath)).toString()
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', escapeAttribute(JSON.stringify({
remoteAuthority,
+ webviewEndpoint: vscodeBase + '/static/out/vs/workbench/contrib/webview/browser/pre',
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.driverHandle === 'web' ? true : undefined },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
Index: code-server/lib/vscode/src/vs/workbench/api/common/shared/webview.ts
@@ -298,6 +298,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
+ webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
_wrapWebWorkerExtHostInIframe,
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/api/common/shared/webview.ts
+++ code-server/lib/vscode/src/vs/workbench/api/common/shared/webview.ts
@@ -25,7 +25,7 @@ export const webviewResourceBaseHost = '
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
@@ -5,7 +5,7 @@
<meta charset="UTF-8">
export const webviewRootResourceAuthority = `vscode-resource.${webviewResourceBaseHost}`;
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-xgIcbQmGjpT42GEj54VFSNh6MI15PZ2D1+DdVehfYBI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-aOCIU83V9nV+0ERJudbrKLqgIVOHqU71i4Lv5urjGTI=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
-export const webviewGenericCspSource = `https://*.${webviewResourceBaseHost}`;
+export const webviewGenericCspSource = `'self' https://*.${webviewResourceBaseHost}`;
<!-- Disable pinch zooming -->
<meta name="viewport"
@@ -331,6 +331,12 @@
/**
* Construct a uri that can load resources inside a webview
const hostname = location.hostname;
+ // It is safe to run if we are on the same host.
+ const parent = new URL(parentOrigin)
+ if (parent.hostname === hostname) {
+ return start(parentOrigin)
+ }
+
if (!crypto.subtle) {
// cannot validate, not running in a secure context
throw new Error(`Cannot validate in current context!`);
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
@@ -330,6 +330,12 @@
const hostname = location.hostname;
+ // It is safe to run if we are on the same host.
+ const parent = new URL(parentOrigin)
+ if (parent.hostname === hostname) {
+ return start(parentOrigin)
+ }
+
if (!crypto.subtle) {
// cannot validate, not running in a secure context
throw new Error(`Cannot validate in current context!`);
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
@@ -4,7 +4,7 @@
<meta http-equiv="Content-Security-Policy" content="
default-src 'none';
child-src 'self' data: blob:;
- script-src 'self' 'unsafe-eval' 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' https:;
+ script-src 'self' 'unsafe-eval' 'sha256-yHVIAbzODFRINjoLGID5qWPP45HzMtwhyVRC+7yiuXg=' https:;
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
</head>
<body>
@@ -23,6 +23,13 @@
// validation not requested
return start();
}
+
+ // It is safe to run if we are on the same host.
+ const parent = new URL(parentOrigin)
+ if (parent.hostname === hostname) {
+ return start()
+ }
+
if (!crypto.subtle) {
// cannot validate, not running in a secure context
return sendError(new Error(`Cannot validate in current context!`));

View File

@@ -10,5 +10,6 @@
],
"vulnerabilityAlerts": {
"enabled": "true"
}
},
"ignoreDeps": ["express"]
}

View File

@@ -1,12 +1,3 @@
/**
* Split a string up to the delimiter. If the delimiter doesn't exist the first
* item will have all the text and the second item will be an empty string.
*/
export const split = (str: string, delimiter: string): [string, string] => {
const index = str.indexOf(delimiter)
return index !== -1 ? [str.substring(0, index).trim(), str.substring(index + 1)] : [str, ""]
}
/**
* Appends an 's' to the provided string if count is greater than one;
* otherwise the string is returned
@@ -34,27 +25,6 @@ export const normalize = (url: string, keepTrailing = false): string => {
return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "")
}
/**
* Remove leading and trailing slashes.
*/
export const trimSlashes = (url: string): string => {
return url.replace(/^\/+|\/+$/g, "")
}
/**
* Wrap the value in an array if it's not already an array. If the value is
* undefined return an empty array.
*/
export const arrayify = <T>(value?: T | T[]): T[] => {
if (Array.isArray(value)) {
return value
}
if (typeof value === "undefined") {
return []
}
return [value]
}
// TODO: Might make sense to add Error handling to the logger itself.
export function logError(logger: { error: (msg: string) => void }, prefix: string, err: unknown): void {
if (err instanceof Error) {

View File

@@ -94,36 +94,14 @@ export const ensureAddress = (server: http.Server, protocol: string): URL | stri
}
if (typeof addr !== "string") {
return new URL(`${protocol}://${addr.address}:${addr.port}`)
const host = addr.family === "IPv6" ? `[${addr.address}]` : addr.address
return new URL(`${protocol}://${host}:${addr.port}`)
}
// If this is a string then it is a pipe or Unix socket.
return addr
}
/**
* Handles error events from the server.
*
* If the outlying Promise didn't resolve
* then we reject with the error.
*
* Otherwise, we log the error.
*
* We extracted into a function so that we could
* test this logic more easily.
*/
export const handleServerError = (resolved: boolean, err: Error, reject: (err: Error) => void) => {
// Promise didn't resolve earlier so this means it's an error
// that occurs before the server can successfully listen.
// Possibly triggered by listening on an invalid port or socket.
if (!resolved) {
reject(err)
} else {
// Promise resolved earlier so this is an unrelated error.
util.logError(logger, "http server error", err)
}
}
/**
* Handles the error that occurs in the catch block
* after we try fs.unlink(args.socket).

View File

@@ -49,6 +49,7 @@ export interface UserProvidedCodeArgs {
category?: string
"github-auth"?: string
"disable-update-check"?: boolean
"disable-file-downloads"?: boolean
}
/**
@@ -157,6 +158,11 @@ export const options: Options<Required<UserProvidedArgs>> = {
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
"then notifies you once every week that a new release is available.",
},
"disable-file-downloads": {
type: "boolean",
description:
"Disable file downloads from Code. This can also be set with CS_DISABLE_FILE_DOWNLOADS set to 'true' or '1'.",
},
// --enable can be used to enable experimental features. These features
// provide no guarantees.
enable: { type: "string[]" },
@@ -537,6 +543,10 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args.password = process.env.PASSWORD
}
if (process.env.CS_DISABLE_FILE_DOWNLOADS?.match(/^(1|true)$/)) {
args["disable-file-downloads"] = true
}
const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
if (process.env.HASHED_PASSWORD) {
args["hashed-password"] = process.env.HASHED_PASSWORD

View File

@@ -3,8 +3,6 @@ import type { JSONSchemaForNPMPackageJsonFiles } from "@schemastore/package"
import * as os from "os"
import * as path from "path"
export const WORKBENCH_WEB_CONFIG_ID = "vscode-workbench-web-configuration"
export function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJsonFiles {
let pkg = {}
try {
@@ -21,7 +19,6 @@ export const vsRootPath = path.join(rootPath, "lib/vscode")
const PACKAGE_JSON = "package.json"
const pkg = getPackageJson(`${rootPath}/${PACKAGE_JSON}`)
const codePkg = getPackageJson(`${vsRootPath}/${PACKAGE_JSON}`) || { version: "0.0.0" }
export const pkgName = pkg.name || "code-server"
export const version = pkg.version || "development"
export const commit = pkg.commit || "development"
export const codeVersion = codePkg.version || "development"

View File

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

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
// it look like code-server is always in use.
if (!/^\/healthz\/?$/.test(req.url)) {
// NOTE@jsjoeio - intentionally not awaiting the .beat() call here because
// we don't want to slow down the request.
heart.beat()
}

View File

@@ -172,7 +172,7 @@ export class CodeServerRouteWrapper {
this.router.get("/", this.ensureCodeServerLoaded, this.$root)
this.router.get(/manifest.json$/, this.manifest)
this.router.all("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyRequest)
this._wsRouterWrapper.ws("/", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
this._wsRouterWrapper.ws("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
}
dispose() {

View File

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

View File

@@ -377,11 +377,62 @@ export const getMediaMime = (filePath?: string): string => {
return (filePath && mimeTypes[path.extname(filePath)]) || "text/plain"
}
export const isWsl = async (): Promise<boolean> => {
return (
(process.platform === "linux" && os.release().toLowerCase().indexOf("microsoft") !== -1) ||
(await fs.readFile("/proc/version", "utf8")).toLowerCase().indexOf("microsoft") !== -1
)
/**
* A helper function that checks if the platform is Windows Subsystem for Linux
* (WSL)
*
* @see https://github.com/sindresorhus/is-wsl/blob/main/index.js
* @returns {Boolean} boolean if it is WSL
*/
export const isWsl = async (
platform: NodeJS.Platform,
osRelease: string,
procVersionFilePath: string,
): Promise<boolean> => {
if (platform !== "linux") {
return false
}
if (osRelease.toLowerCase().includes("microsoft")) {
return true
}
try {
return (await fs.readFile(procVersionFilePath, "utf8")).toLowerCase().includes("microsoft")
} catch (_) {
return false
}
}
interface OpenOptions {
args: string[]
command: string
urlSearch: string
}
/**
* A helper function to construct options for `open` function.
*
* Extract to make it easier to test.
*
* @param platform - platform on machine
* @param urlSearch - url.search
* @returns an object with args, command, options and urlSearch
*/
export function constructOpenOptions(platform: NodeJS.Platform | "wsl", urlSearch: string): OpenOptions {
const args: string[] = []
let command = platform === "darwin" ? "open" : "xdg-open"
if (platform === "win32" || platform === "wsl") {
command = platform === "wsl" ? "cmd.exe" : "cmd"
args.push("/c", "start", '""', "/b")
urlSearch = urlSearch.replace(/&/g, "^&")
}
return {
args,
command,
urlSearch,
}
}
/**
@@ -396,16 +447,10 @@ export const open = async (address: URL | string): Promise<void> => {
if (url.hostname === "0.0.0.0") {
url.hostname = "localhost"
}
const args = [] as string[]
const options = {} as cp.SpawnOptions
const platform = (await isWsl()) ? "wsl" : process.platform
let command = platform === "darwin" ? "open" : "xdg-open"
if (platform === "win32" || platform === "wsl") {
command = platform === "wsl" ? "cmd.exe" : "cmd"
args.push("/c", "start", '""', "/b")
url.search = url.search.replace(/&/g, "^&")
}
const proc = cp.spawn(command, [...args, url.toString()], options)
const platform = (await isWsl(process.platform, os.release(), "/proc/version")) ? "wsl" : process.platform
const { command, args, urlSearch } = constructOpenOptions(platform, url.search)
url.search = urlSearch
const proc = cp.spawn(command, [...args, url.toString()], {})
await new Promise<void>((resolve, reject) => {
proc.on("error", reject)
proc.on("close", (code) => {
@@ -414,31 +459,6 @@ export const open = async (address: URL | string): Promise<void> => {
})
}
/**
* For iterating over an enum's values.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const enumToArray = (t: any): string[] => {
const values = [] as string[]
for (const k in t) {
values.push(t[k])
}
return values
}
/**
* For displaying all allowed options in an enum.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const buildAllowedMessage = (t: any): string => {
const values = enumToArray(t)
return `Allowed value${values.length === 1 ? " is" : "s are"} ${values.map((t) => `'${t}'`).join(", ")}`
}
export const isObject = <T extends object>(obj: T): obj is T => {
return !Array.isArray(obj) && typeof obj === "object" && obj !== null
}
/**
* Return a promise that resolves with whether the socket path is active.
*/

View File

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

View File

@@ -0,0 +1,48 @@
import { promises as fs } from "fs"
import * as path from "path"
import { clean } from "../utils/helpers"
import { describe, test, expect } from "./baseFixture"
describe("Downloads (enabled)", true, [], {}, async () => {
const testName = "downloads-enabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should see the 'Download...' option", async ({ codeServerPage }) => {
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const tmpFilePath = path.join(workspaceDir, "unique-file.txt")
await fs.writeFile(tmpFilePath, "hello world")
// Action
const fileInExplorer = await codeServerPage.page.waitForSelector("text=unique-file.txt")
await fileInExplorer.click({
button: "right",
})
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(true)
})
})
describe("Downloads (disabled)", true, ["--disable-file-downloads"], {}, async () => {
const testName = "downloads-disabled"
test.beforeAll(async () => {
await clean(testName)
})
test("should not see the 'Download...' option", async ({ codeServerPage }) => {
// Setup
const workspaceDir = await codeServerPage.workspaceDir
const tmpFilePath = path.join(workspaceDir, "unique-file.txt")
await fs.writeFile(tmpFilePath, "hello world")
// Action
const fileInExplorer = await codeServerPage.page.waitForSelector("text=unique-file.txt")
await fileInExplorer.click({
button: "right",
})
expect(await codeServerPage.page.isVisible("text=Download...")).toBe(false)
})
})

View File

@@ -81,6 +81,9 @@ export class CodeServer {
path.join(dir, "User/settings.json"),
JSON.stringify({
"workbench.startupEditor": "none",
// NOTE@jsjoeio - needed to prevent Trust Policy prompt
// in end-to-end tests.
"security.workspace.trust.enabled": false,
}),
"utf8",
)
@@ -134,7 +137,7 @@ export class CodeServer {
})
proc.on("close", (code) => {
const error = new Error("code-server closed unexpectedly")
const error = new Error("code-server closed unexpectedly. Try running with LOG_LEVEL=debug to see more info.")
if (!this.closed) {
this.logger.error(error.message, field("code", code))
}

View File

@@ -6,7 +6,7 @@ describe("Open Help > About", true, [], {}, () => {
await codeServerPage.navigateMenus(["Help", "About"])
// Look for code-server info div.
const element = await codeServerPage.page.waitForSelector('div[role="dialog"] >> text=code-server')
const element = await codeServerPage.page.waitForSelector(`div[role="dialog"] >> text=code-server`)
expect(element).not.toBeNull()
})
})

View File

@@ -0,0 +1,25 @@
import { stat } from "fs/promises"
import path from "path"
import { clean, tmpdir } from "../utils/helpers"
import { runCodeServerCommand } from "../utils/runCodeServerCommand"
describe("--install-extension", () => {
const testName = "installExtension"
let tempDir: string
let setupFlags: string[]
beforeEach(async () => {
await clean(testName)
tempDir = await tmpdir(testName)
setupFlags = ["--extensions-dir", tempDir]
})
it("should install an extension", async () => {
const extName = `wesbos.theme-cobalt2-2.1.6`
const vsixFileName = "wesbos.theme-cobalt2-2.1.6.vsix"
const extensionFixture = path.resolve(`./test/integration/fixtures/${vsixFileName}`)
await runCodeServerCommand([...setupFlags, "--install-extension", extensionFixture])
const pathToExtFolder = path.join(tempDir, extName)
const statInfo = await stat(pathToExtFolder)
expect(statInfo.isDirectory()).toBe(true)
}, 20000)
})

View File

@@ -0,0 +1,30 @@
import extract from "extract-zip"
import { rename } from "fs/promises"
import path from "path"
import { clean, tmpdir } from "../utils/helpers"
import { runCodeServerCommand } from "../utils/runCodeServerCommand"
describe("--list-extensions", () => {
const testName = "listExtensions"
const extName = `wesbos.theme-cobalt2`
const extVersion = "2.1.6"
const vsixFileName = `${extName}-${extVersion}.vsix`
let tempDir: string
let setupFlags: string[]
beforeEach(async () => {
await clean(testName)
tempDir = await tmpdir(testName)
setupFlags = ["--extensions-dir", tempDir]
const extensionFixture = path.resolve(`./test/integration/fixtures/${vsixFileName}`)
// Make folder because this is where we'll move the extension
const pathToUnpackedExtension = path.join(tempDir, `${extName}-${extVersion}`)
const tempPathToUnpackedExtension = path.join(tempDir, `${extName}-temp`)
await extract(extensionFixture, { dir: tempPathToUnpackedExtension })
await rename(path.join(tempPathToUnpackedExtension, "extension"), pathToUnpackedExtension)
})
it("should list installed extensions", async () => {
const { stdout } = await runCodeServerCommand([...setupFlags, "--list-extensions"])
expect(stdout).toMatch(extName)
}, 20000)
})

View File

@@ -10,6 +10,7 @@
"@types/supertest": "^2.0.11",
"@types/wtfnode": "^0.7.0",
"argon2": "^0.28.0",
"extract-zip": "^2.0.1",
"jest": "^27.3.1",
"jest-fetch-mock": "^3.0.3",
"jsdom": "^16.4.0",

View File

@@ -24,16 +24,6 @@ describe("util", () => {
})
})
describe("split", () => {
it("should split at a comma", () => {
expect(util.split("Hello,world", ",")).toStrictEqual(["Hello", "world"])
})
it("shouldn't split if the delimiter doesn't exist", () => {
expect(util.split("Hello world", ",")).toStrictEqual(["Hello world", ""])
})
})
describe("plural", () => {
it("should add an s if count is greater than 1", () => {
expect(util.plural(2, "dog")).toBe("dogs")
@@ -57,43 +47,6 @@ describe("util", () => {
})
})
describe("trimSlashes", () => {
it("should remove leading slashes", () => {
expect(util.trimSlashes("/hello-world")).toBe("hello-world")
})
it("should remove trailing slashes", () => {
expect(util.trimSlashes("hello-world/")).toBe("hello-world")
})
it("should remove both leading and trailing slashes", () => {
expect(util.trimSlashes("/hello-world/")).toBe("hello-world")
})
it("should remove multiple leading and trailing slashes", () => {
expect(util.trimSlashes("///hello-world////")).toBe("hello-world")
})
})
describe("arrayify", () => {
it("should return value it's already an array", () => {
expect(util.arrayify(["hello", "world"])).toStrictEqual(["hello", "world"])
})
it("should wrap the value in an array if not an array", () => {
expect(
util.arrayify({
name: "Coder",
version: "3.8",
}),
).toStrictEqual([{ name: "Coder", version: "3.8" }])
})
it("should return an empty array if the value is undefined", () => {
expect(util.arrayify(undefined)).toStrictEqual([])
})
})
describe("logError", () => {
beforeAll(() => {
mockLogger()

View File

@@ -3,7 +3,7 @@ import { promises } from "fs"
import * as http from "http"
import * as https from "https"
import * as path from "path"
import { createApp, ensureAddress, handleArgsSocketCatchError, handleServerError, listen } from "../../../src/node/app"
import { createApp, ensureAddress, handleArgsSocketCatchError, listen } from "../../../src/node/app"
import { OptionalString, setDefaults } from "../../../src/node/cli"
import { generateCertificate } from "../../../src/node/util"
import { clean, mockLogger, getAvailablePort, tmpdir } from "../../utils/helpers"
@@ -152,42 +152,20 @@ describe("ensureAddress", () => {
it("should throw and error if no address", () => {
expect(() => ensureAddress(mockServer, "http")).toThrow("Server has no address")
})
it("should return the address if it exists", async () => {
mockServer.address = () => "http://localhost:8080/"
it("should return the address if it's a string", async () => {
mockServer.address = () => "/path/to/unix.sock"
const address = ensureAddress(mockServer, "http")
expect(address.toString()).toBe(`http://localhost:8080/`)
expect(address.toString()).toBe(`/path/to/unix.sock`)
})
})
describe("handleServerError", () => {
beforeAll(() => {
mockLogger()
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/`)
})
afterEach(() => {
jest.clearAllMocks()
})
it("should call reject if resolved is false", async () => {
const resolved = false
const reject = jest.fn((err: Error) => undefined)
const error = new Error("handleServerError Error")
handleServerError(resolved, error, reject)
expect(reject).toHaveBeenCalledTimes(1)
expect(reject).toHaveBeenCalledWith(error)
})
it("should log an error if resolved is true", async () => {
const resolved = true
const reject = jest.fn((err: Error) => undefined)
const error = new Error("handleServerError Error")
handleServerError(resolved, error, reject)
expect(logger.error).toHaveBeenCalledTimes(1)
expect(logger.error).toHaveBeenCalledWith(`http server error: ${error.message} ${error.stack}`)
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

@@ -42,6 +42,7 @@ describe("parser", () => {
beforeEach(() => {
delete process.env.LOG_LEVEL
delete process.env.PASSWORD
delete process.env.CS_DISABLE_FILE_DOWNLOADS
console.log = jest.fn()
})
@@ -92,6 +93,8 @@ describe("parser", () => {
"--port=8081",
"--disable-file-downloads",
["--host", "0.0.0.0"],
"4",
"--",
@@ -108,6 +111,7 @@ describe("parser", () => {
cert: {
value: path.resolve("path/to/cert"),
},
"disable-file-downloads": true,
enable: ["feature1", "feature2"],
help: true,
host: "0.0.0.0",
@@ -346,6 +350,30 @@ describe("parser", () => {
expect(process.env.GITHUB_TOKEN).toBe(undefined)
})
it("should use env var CS_DISABLE_FILE_DOWNLOADS", async () => {
process.env.CS_DISABLE_FILE_DOWNLOADS = "1"
const args = parse([])
expect(args).toEqual({})
const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
"disable-file-downloads": true,
})
})
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", () => {
expect(() => parse(["--password", "supersecret123"])).toThrowError(
"--password can only be set in the config file or passed in via $PASSWORD",
@@ -430,7 +458,7 @@ describe("cli", () => {
beforeEach(async () => {
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 () => {

View File

@@ -34,10 +34,6 @@ describe("constants", () => {
jest.resetModules()
})
it("should provide the package name", () => {
expect(constants.pkgName).toBe(mockPackageJson.name)
})
it("should provide the commit", () => {
expect(constants.commit).toBe(mockPackageJson.commit)
})

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

@@ -38,6 +38,7 @@ describe("plugin", () => {
"proxy-domain": [],
config: "~/.config/code-server/config.yaml",
verbose: false,
"disable-file-downloads": false,
usingEnvPassword: false,
usingEnvHashedPassword: false,
"extensions-dir": "",

View File

@@ -33,10 +33,10 @@ describe("vscode", () => {
switch (route) {
case "/":
case "/vscode/":
expect(html).toContain(`src="./static/`)
expect(html).toMatch(/src="\.\/[a-z]+-[0-9a-z]+\/static\//)
break
case "/vscode":
expect(html).toContain(`src="./vscode/static/`)
expect(html).toMatch(/src="\.\/vscode\/[a-z]+-[0-9a-z]+\/static\//)
break
}
}

View File

@@ -53,7 +53,7 @@ describe("SocketProxyProvider", () => {
await fs.mkdir(path.join(tmpdir, "tests"), { recursive: true })
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) => {
const resolved: { [key: string]: boolean } = { client: false, server: false }

View File

@@ -131,7 +131,8 @@ describe("update", () => {
await expect(settings().read()).resolves.toEqual({ update })
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(spy).toEqual(["/latest"])
})
@@ -145,7 +146,7 @@ describe("update", () => {
await expect(settings().read()).resolves.toEqual({ update })
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(spy).toEqual([])
})
@@ -159,7 +160,8 @@ describe("update", () => {
await expect(settings().read()).resolves.toEqual({ update })
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(spy).toStrictEqual(["/latest"])
})
@@ -204,14 +206,16 @@ describe("update", () => {
let now = Date.now()
let update = await provider.getUpdate(true)
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")
provider = new UpdateProvider("http://probably.invalid.dev.localhost/latest", settings())
now = Date.now()
update = await provider.getUpdate(true)
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")
})

View File

@@ -4,6 +4,7 @@ import * as path from "path"
import { generateUuid } from "../../../src/common/util"
import { tmpdir } from "../../../src/node/constants"
import * as util from "../../../src/node/util"
import { clean, tmpdir as tempDirHelper } from "../../utils/helpers"
describe("getEnvPaths", () => {
describe("on darwin", () => {
@@ -349,6 +350,22 @@ describe("isCookieValid", () => {
})
expect(isValid).toBe(false)
})
it("should return false and empty string as hashedPassword when passwordMethod is invalid", async () => {
const p = "password1"
const passwordValidation = await util.handlePasswordValidation({
// @ts-expect-error although this shouldn't ever happen, it ensures the default case in this function
// works as expected.
passwordMethod: "INVALID",
passwordFromRequestBody: p,
passwordFromArgs: undefined,
hashedPasswordFromArgs: undefined,
})
const matchesHash = await util.isHashMatch(p, passwordValidation.hashedPassword)
expect(passwordValidation.isPasswordValid).toBe(false)
expect(matchesHash).toBe(false)
})
})
describe("sanitizeString", () => {
@@ -446,6 +463,9 @@ describe("isFile", () => {
it("should return true if is file", async () => {
expect(await util.isFile(pathToFile)).toBe(true)
})
it("should return false if error", async () => {
expect(await util.isFile("fakefile.txt")).toBe(false)
})
})
describe("humanPath", () => {
@@ -463,3 +483,98 @@ describe("humanPath", () => {
expect(actual).toBe(expected)
})
})
describe("isWsl", () => {
const testName = "wsl"
beforeAll(async () => {
await clean(testName)
})
describe("on Linux (microsoft)", () => {
it("should return true", async () => {
const fileName = "proc-version"
const osRelease = "5.4.0-1066-gke"
const pathToFile = path.join(await tempDirHelper(testName), fileName)
await fs.writeFile(
pathToFile,
"Linux version 3.4.0-Microsoft (Microsoft@Microsoft.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Wed Dec 31 14:42:53 PST 2014",
)
expect(await util.isWsl("linux", osRelease, pathToFile)).toBe(true)
})
})
describe("on Linux (non-microsoft)", () => {
it("should return false", async () => {
const fileName = "proc-version2"
const osRelease = "Linux"
const pathToFile = path.join(await tempDirHelper(testName), fileName)
await fs.writeFile(
pathToFile,
"Linux version 5.4.0-1066-gke (buildd@lcy02-amd64-039) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04)) #69-Ubuntu SMP Fri Mar 11 13:52:45 UTC 202",
)
expect(await util.isWsl("linux", osRelease, pathToFile)).toBe(false)
})
})
describe("on Win32 with microsoft in /proc/version", () => {
it("should return false", async () => {
const fileName = "proc-version3"
const osRelease = "3.4.0-Microsoft"
const pathToFile = path.join(await tempDirHelper(testName), fileName)
await fs.writeFile(
pathToFile,
"Linux version 3.4.0-Microsoft (Microsoft@Microsoft.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Wed Dec 31 14:42:53 PST 2014",
)
expect(await util.isWsl("win32", osRelease, pathToFile)).toBe(false)
})
})
describe("on Darwin", () => {
it("should return false", async () => {
const fileName = "proc-version4"
const osRelease =
"Darwin Roadrunner.local 10.3.0 Darwin Kernel Version 10.3.0: Fri Feb 26 11:58:09 PST 2010; root:xnu-1504.3.12~1/RELEASE_I386 i386"
const pathToFile = path.join(await tempDirHelper(testName), fileName)
expect(await util.isWsl("darwin", osRelease, pathToFile)).toBe(false)
})
})
})
describe("open", () => {
it("should throw an error if address is a string", async () => {
const address = "localhost:3000"
await expect(util.open(address)).rejects.toThrow("Cannot open socket paths")
})
})
describe("constructOpenOptions", () => {
it("should return options for darwin", () => {
const platform: NodeJS.Platform | "wsl" = "darwin"
const url = new URL("localhost:8080")
const { args, command, urlSearch } = util.constructOpenOptions(platform, url.search)
expect(args).toStrictEqual([])
expect(command).toBe("open")
expect(urlSearch).toBe("")
})
it("should return options for linux", () => {
const platform: NodeJS.Platform | "wsl" = "linux"
const url = new URL("localhost:8080")
const { args, command, urlSearch } = util.constructOpenOptions(platform, url.search)
expect(args).toStrictEqual([])
expect(command).toBe("xdg-open")
expect(urlSearch).toBe("")
})
it("should return options for win32", () => {
const platform: NodeJS.Platform | "wsl" = "win32"
const url = new URL("localhost:8080?q=&test")
const { args, command, urlSearch } = util.constructOpenOptions(platform, url.search)
expect(args).toStrictEqual(["/c", "start", '""', "/b"])
expect(command).toBe("cmd")
expect(urlSearch).toBe("?q=^&test")
})
it("should return options for wsl", () => {
const platform: NodeJS.Platform | "wsl" = "wsl"
const url = new URL("localhost:8080?q=&test")
const { args, command, urlSearch } = util.constructOpenOptions(platform, url.search)
expect(args).toStrictEqual(["/c", "start", '""', "/b"])
expect(command).toBe("cmd.exe")
expect(urlSearch).toBe("?q=^&test")
})
})

View File

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

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