Compare commits

..

34 Commits

Author SHA1 Message Date
Asher
ac1fba8bde Remove deprecated --link (#6018) 2023-02-13 16:52:48 -06:00
Blue
6d8ed77fb0 feat(helm-chart): Add support for extraSecretMounts subPath in helm-chart (#5961) 2023-02-13 13:01:32 -06:00
Samuel Walker
4fb87f920f feature: add ability to attach ports to code server (#6015) 2023-02-13 12:56:05 -06:00
Asher
36daac3031 Update to 1.75.1 2023-02-13 07:45:24 -09:00
Asher
45aef719d3 Make sure heartbeat isActive resolves
This does not seem to actually cause an issue (not resolving ends up
with the same behavior as resolving with false) but I am not sure if the
hanging promises would be a memory leak so seems best to fix.
2023-02-08 11:43:40 -09:00
Asher
6d6c5e18d1 Fix watch script ignoring stdout
This was lost due to the change from fork to spawn.
2023-02-08 11:42:28 -09:00
Asher
17bca521af Update changelog 2023-02-07 13:57:53 -09:00
Asher
82073743b1 Update release guide 2023-02-07 13:57:52 -09:00
Asher
71ff747c48 Update Code to 1.75.0 (#6004)
* Update Code to 1.75.0

- getting-started.diff: The way to get an icon's class changed
- proxy-uri.diff: The product service is passed in so we can get the
  proxy URI from that now instead of passing it in separately.

* Remove workspace trust test

Something in how/when Code displays the trust dialog appears to have
changed, failing the test.  I am not sure it makes sense for us to be
testing upstream code anyway.

* Use regular Node for watch

Since we spawn the watch script with ts-node it was using ts-node for
the web server spawn as well.  With latest Code there are for some
reason type errors (it cannot find @types/node) but this is already
compiled code which already passed type checks; any type errors here are
useless.  To fix spawn with regular Node.

* Fix some workers not loading
2023-02-07 16:22:06 -06:00
dependabot[bot]
e5a2537aee chore: bump limiter from 1.1.5 to 2.1.0 (#6001)
* chore: bump limiter from 1.1.5 to 2.1.0

Bumps [limiter](https://github.com/jhurliman/node-rate-limiter) from 1.1.5 to 2.1.0.
- [Release notes](https://github.com/jhurliman/node-rate-limiter/releases)
- [Commits](https://github.com/jhurliman/node-rate-limiter/commits)

---
updated-dependencies:
- dependency-name: limiter
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update limiter usage

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Asher <ash@coder.com>
2023-02-06 13:12:57 -06:00
dependabot[bot]
bce6239801 chore: bump @typescript-eslint/eslint-plugin from 5.41.0 to 5.51.0 (#6002)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.41.0 to 5.51.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.51.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 18:59:24 +00:00
dependabot[bot]
93589edb61 chore: bump eslint-config-prettier from 8.5.0 to 8.6.0 (#6003)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.5.0 to 8.6.0.
- [Release notes](https://github.com/prettier/eslint-config-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.5.0...v8.6.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 12:41:05 -06:00
Asher
bfcca5fcc0 Remove docs preview
This is failing CI on Dependabot PRs.  Opted to just remove it since
most (all?) PRs will be from forks and this workflow will not run
anyway.  If we figure out the secret situation we can add it back.
2023-02-06 09:07:34 -09:00
Asher
a76c0c5742 Remove PR npm package
It is causing CI to fail for Dependabot (no access to the token) and it
does not work with forks and currently there is no one who pushes
straight to the repo so this will never be used.

Can always add it back if we figure out how to make the secrets work.
2023-02-06 08:56:47 -09:00
renovate[bot]
6e1b9131e9 chore(deps): update aquasecurity/trivy-action digest to cff3e9a (#5994)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-06 11:36:05 -06:00
Dean Sheather
776d57b12b chore: enable dependabot (#5997) 2023-02-06 11:32:52 -06:00
Asher
026879b78c Update Code to 1.74.3 (#5989) 2023-02-06 10:24:37 -06:00
Joe Previte
401d423dfd docs: add usage in Coder (#5975)
* docs: add difference between Coder

Add a short block explaining the difference between code-server and
Coder.

* docs: add new doc coder.md under Install

This adds a new doc explaining how to install code-server in a Coder
workspace using Terraform.
2023-01-27 17:14:54 +00:00
Joe Previte
96d9c5eb0f docs: add port-forwarding (#5979) 2023-01-27 16:41:27 +00:00
Kyle Carberry
134e9b40b7 chore: fix requirements so it navigates to docs (#5973)
This was navigating to the relative markdown file,
which is confusing when some links go to the docs.
2023-01-17 17:09:24 +00:00
zhaozhiming
7c2aa8c417 feat: add i18n in login page (#5947)
* feat: add i18n in login page

* fix: add word space and put the app name into the title

* fix: remove duplicate replace title

* fix: prettier format code

* fix: fix typescript check warning

* fix: add zh-cn locale file code owner

* fix: use existing flag locale to the login page

Co-authored-by: Joe Previte <jjprevite@gmail.com>
2023-01-13 17:42:49 +00:00
Joe Previte
d40a9742c0 feat(ci): add lint-actions step to build.yaml (#5957)
* feat(ci): add lint-actions step to build.yaml

This adds a new job to the Build CI pipeline to lint our GitHub Actions.

By doing this, we can prevent typos from slipping in.

Fixes #5776

* fix: disable shellcheck in actionlint

I don't think we want to enable this for now.

* fix: ignore set-output warnings for now

It's deprecated but there isn't a reason to move away from using it yet.
2023-01-13 17:21:56 +00:00
renovate[bot]
67416b7b79 fix(deps): update dependency argon2 to v0.30.3 (#5937)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-05 08:27:11 -07:00
Joe Previte
9e266db379 chore: use matchUpdateTypes (#5942) 2023-01-04 23:08:39 +00:00
Joe Previte
834d16df2a docs(CONTRIBUTING): add standalone release section (#5946)
* docs: update section in troubleshooting

* docs: add section on standalone release
2023-01-04 15:47:34 -07:00
Joe Previte
d835cb9865 docs: add new termux installation method (#5938)
* docs: add new termux installation method

* fixup: formatting
2023-01-04 17:16:23 +00:00
Joe Previte
9e9cbd846d chore: update renovate to include peer deps (#5940) 2023-01-03 15:14:21 -07:00
Joe Previte
077a8f6a6b chore: pin json5 to 1.0.2 (#5936)
* chore: pin json5 to 1.0.2

* fixup: formatting
2023-01-03 20:57:16 +00:00
Joe Previte
4e280811f9 chore: update renovate and deps (#5914)
* chore: update renovate.json ignoreDeps

ansi-regex, env-paths and limiter all switch to ESM which we can't
support at the moment so ignore updates for now.

* chore: update actions/cache@v3

* chore: update minor deps

* chore: add pretteir to renovate.json
2023-01-03 17:28:58 +00:00
Joe Previte
3eb35979f0 chore: update aur job in publish.yaml (#5915)
This uses the `env.VERSION` which should fix the issue with version being blank.
2022-12-22 13:58:20 -06:00
Joe Previte
8377bd23df chore: upgrade Code to 1.74.1 (#5909)
* chore: upgrade Code to 1.74.1

* chore: remove require in integration.diff

I don't know what the impact of this is but in 192c67db71
they removed the usage of `require` in `server.main.ts`.

More details in PR: https://github.com/microsoft/vscode/pull/165831

* chore: update marketplace.diff

* chore: update sha hash in webview.diff

* chore: update disable-builtin-ext-update.diff

If my logic is right, then this patch is now simplified thanks to this:
https://github.com/microsoft/vscode/blob/1.74.1/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts#L1238

* chore: refresh proxy-uri patch

* chore: refresh local-storage.diff

* chore: refresh sourcemaps.diff

* chore: refresh disable-downloads.diff

* chore: refresh display-language.diff

* chore: refresh getting-started.diff

* docs: update testing notes for cli-window-open

* docs: update telemetry testing instructions

* fix: add GITHUB_TOKEN to build code-server job

Downloading @vscode/ripgrep is failing only in CI so adding this
environment variable to see if it increases the rate limit.

Ref: https://github.com/microsoft/vscode-ripgrep#github-api-limit-note

* refactor: use own cache key build code-server job

* temp: disable vscode test

* refactor: delete wrapper test

* Revert "refactor: delete wrapper test"

This reverts commit 3999279b73.

* refactor: move vscode tests to e2e (#5911)

* wip: migrate vscode tests to e2e

* feat: add codeWorkspace to global setup

* refactor: only use dir in spawn when we should

* wip: migrate more tests

* refactor: move all vscode tests to e2e

* refactor(ci): move unit to own job

* fixup: add codecov to unit test step

* Update test/e2e/models/CodeServer.ts

* Update test/e2e/models/CodeServer.ts

* docs: add note about intercept requests

* refactor: rm unused clean() calls

* refactor: delete duplicate test

* refactor: update 'should not redirect' test

* refactor: rm unused imports

* refactor: rm unnecessary navigate call in test

* fixup: formatting

* wip: update test

* refactor: modify assertion for proxy

* fixup: use REVERSE_PROXY_BASE_PATH

* refactor: add helper fn getMaybeProxiedPathname

* fixup: formatting

* fixup: rm unused import

* chore: increase playwright timeout

* Revert "chore: increase playwright timeout"

This reverts commit a059129252.

* chore: rm timeout
2022-12-22 10:25:28 -07:00
Toby Cm
930791d249 Added how to disable file downloads in faq (#5907) 2022-12-19 16:00:42 +00:00
Joe Previte
5c21015dbe release: v4.9.1 (#5893)
* chore: add 4.9.1 to changelog

* chore: bump Helm to 4.9.1
2022-12-16 12:07:36 -07:00
Joe Previte
fa39d4761a fix: dst path in nfpm (#5875)
* fix: dst path in nfpm

* trigger ci

* Update ci/README.md
2022-12-16 11:35:13 -07:00
64 changed files with 737 additions and 730 deletions

2
.github/CODEOWNERS vendored
View File

@@ -3,3 +3,5 @@
ci/helm-chart/ @Matthew-Beckett @alexgorbatchev
docs/install.md @GNUxeava
src/node/i18n/locales/zh-cn.json @zhaozhiming

31
.github/dependabot.yaml vendored Normal file
View File

@@ -0,0 +1,31 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
time: "06:00"
timezone: "America/Chicago"
labels: []
commit-message:
prefix: "chore"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "monthly"
time: "06:00"
timezone: "America/Chicago"
commit-message:
prefix: "chore"
labels: []
ignore:
# Ignore patch updates for all dependencies
- dependency-name: "*"
update-types:
- version-update:semver-patch
# Ignore major updates to Node.js types, because they need to
# correspond to the Node.js engine version
- dependency-name: "@types/node"
update-types:
- version-update:semver-major

View File

@@ -83,7 +83,7 @@ jobs:
- name: Install helm
if: steps.changed-files.outputs.any_changed == 'true'
uses: azure/setup-helm@v3.4
uses: azure/setup-helm@v3.5
with:
token: ${{ secrets.GITHUB_TOKEN }}
@@ -139,6 +139,67 @@ jobs:
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn lint:ts
lint-actions:
name: Lint GitHub Actions
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Check workflow files
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/7fdc9630cc360ea1a469eed64ac6d78caeda1234/scripts/download-actionlint.bash)
./actionlint -color -shellcheck= -ignore "set-output"
shell: bash
test-unit:
name: Run unit tests
runs-on: ubuntu-20.04
timeout-minutes: 5
steps:
- name: Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v26.1
with:
files: |
**/*.ts
files_ignore: |
lib/vscode/**
- name: Install Node.js v16
if: steps.changed-files.outputs.any_changed == 'true'
uses: actions/setup-node@v3
with:
node-version: "16"
- name: Fetch dependencies from cache
if: steps.changed-files.outputs.any_changed == 'true'
id: cache-node-modules
uses: actions/cache@v3
with:
path: "**/node_modules"
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-
- name: Install dependencies
if: steps.changed-files.outputs.any_changed == 'true' && steps.cache-node-modules.outputs.cache-hit != 'true'
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
- name: Run unit tests
if: steps.changed-files.outputs.any_changed == 'true'
run: yarn test:unit
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
if: success()
build:
name: Build code-server
runs-on: ubuntu-20.04
@@ -170,15 +231,17 @@ jobs:
uses: actions/cache@v3
with:
path: "**/node_modules"
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
key: yarn-build-code-server-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-build-
yarn-build-code-server-
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: yarn --frozen-lockfile
- name: Build code-server
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: yarn build
# Get Code's git hash. When this changes it means the content is
@@ -204,19 +267,6 @@ jobs:
if: steps.cache-vscode.outputs.cache-hit != 'true'
run: yarn build:vscode
# Our code imports code from VS Code's `out` directory meaning VS Code
# must be built before running these tests.
# TODO: Move to its own step?
- name: Run code-server unit tests
run: yarn test:unit
if: success()
- name: Upload coverage report to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
if: success()
# The release package does not contain any native modules
# and is neutral to architecture/os/libc version.
- name: Create release package
@@ -233,65 +283,6 @@ jobs:
name: npm-package
path: ./package.tar.gz
npm:
name: Publish npm package
# the npm-package gets uploaded as an artifact in Build
# so we need that to complete before this runs
needs: build
# This environment "npm" requires someone from
# coder/code-server-reviewers to approve the PR before this job runs.
environment: npm
# Only run if PR comes from base repo or event is not a PR
# Reason: forks cannot access secrets and this will always fail
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
runs-on: ubuntu-20.04
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Download artifact
uses: actions/download-artifact@v3
id: download
with:
name: "npm-package"
path: release-npm-package
- name: Run ./ci/steps/publish-npm.sh
run: yarn publish:npm
env:
# NOTE@jsjoeio
# This is because npm enforces semantic versioning
# so it has to be a valid version. We only use this
# to publish dev versions from prs
# and beta versions from main.
VERSION: "0.0.0"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# NOTE@jsjoeio
# NPM_ENVIRONMENT intentionally not set here.
# 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 }}
```
test-e2e:
name: Run e2e tests
needs: build
@@ -336,7 +327,7 @@ jobs:
./test/node_modules/.bin/playwright install
- name: Run end-to-end tests
run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e --global-timeout 840000
run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e
- name: Upload test artifacts
if: always()
@@ -392,7 +383,7 @@ jobs:
./test/node_modules/.bin/playwright install
- name: Cache Caddy
uses: actions/cache@v2
uses: actions/cache@v3
id: caddy-cache
with:
path: |
@@ -405,7 +396,7 @@ jobs:
if: steps.caddy-cache.outputs.cache-hit != 'true'
run: |
gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
mkdir -p ~/.cache/caddy
mkdir -p ~/.cache/caddy
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
- name: Start Caddy

View File

@@ -1,46 +0,0 @@
name: Docs preview
on:
pull_request:
branches:
- main
paths:
- "docs/**"
permissions:
actions: none
checks: none
contents: read
deployments: none
issues: none
packages: none
pull-requests: write
repository-projects: none
security-events: none
statuses: none
jobs:
preview:
name: Docs preview
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Set outputs
id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- 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.
* _Host_: https://coder.com/docs/code-server/${{ steps.vars.outputs.sha_short }}
* _Last deploy status_: success
* _Commit_: ${{ github.event.pull_request.head.sha }}
* _Workflow status_: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}

View File

@@ -30,7 +30,7 @@ jobs:
uses: actions/checkout@v3
- name: Download npm package from release artifacts
uses: robinraju/release-downloader@v1.6
uses: robinraju/release-downloader@v1.7
with:
repository: "coder/code-server"
tag: ${{ github.event.inputs.version || github.ref_name }}
@@ -137,12 +137,14 @@ jobs:
- name: Open PR
# We need to git push -u otherwise gh will prompt
# asking where to push the branch.
env:
VERSION: ${{ env.VERSION }}
run: |
git checkout -b update-version-${{ steps.version.outputs.version }}
git checkout -b update-version-${{ env.VERSION }}
git add .
git commit -m "chore: updating version to ${{ steps.version.outputs.version }}"
git commit -m "chore: updating version to ${{ env.VERSION }}"
git push -u origin $(git branch --show)
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ steps.version.outputs.version }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
docker:
runs-on: ubuntu-20.04
steps:
@@ -176,7 +178,7 @@ jobs:
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
- name: Download release artifacts
uses: robinraju/release-downloader@v1.6
uses: robinraju/release-downloader@v1.7
with:
repository: "coder/code-server"
tag: v${{ env.VERSION }}

View File

@@ -65,7 +65,7 @@ jobs:
fetch-depth: 0
- name: Run Trivy vulnerability scanner in repo mode
uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5
uses: aquasecurity/trivy-action@cff3e9a7f62c41dd51975266d0ae235709e39c41
with:
scan-type: "fs"
scan-ref: "."

View File

@@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@v3
- name: Run Trivy vulnerability scanner in image mode
uses: aquasecurity/trivy-action@9ab158e8597f3b310480b9a69402b419bc03dbd5
uses: aquasecurity/trivy-action@cff3e9a7f62c41dd51975266d0ae235709e39c41
with:
image-ref: "docker.io/codercom/code-server:latest"
ignore-unfixed: true

View File

@@ -20,6 +20,32 @@ Code v99.99.999
-->
## [4.10.0](https://github.com/coder/code-server/releases/tag/v4.10.0) - TBD
Code v1.75.1
### Changed
- Updated to Code 1.75.1
### Removed
- Removed `--link` (was deprecated in 4.0.1).
## [4.9.1](https://github.com/coder/code-server/releases/tag/v4.9.1) - 2022-12-15
Code v1.73.1
### Changed
- Updated a couple steps in the build and release process to ensure we're using
`npm` and `yarn` consistently depending on the step.
### Fixed
- Fixed an issue with code-server version not displaying in the Help > About window.
- Fixed terminal not loading on macOS clients.
## [4.9.0](https://github.com/coder/code-server/releases/tag/v4.9.0) - 2022-12-06
Code v1.73.1

View File

@@ -14,22 +14,6 @@ main() {
sed -i.bak "1s;^;#!/usr/bin/env node\n;" out/node/entry.js && rm out/node/entry.js.bak
chmod +x out/node/entry.js
fi
# for arch; we do not use OS from lib.sh and get our own.
# lib.sh normalizes macos to darwin - but cloud-agent's binaries do not
source ./ci/lib.sh
OS="$(uname | tr '[:upper:]' '[:lower:]')"
mkdir -p ./lib
if ! [ -f ./lib/coder-cloud-agent ]; then
echo "Downloading the cloud agent..."
set +e
curl -fsSL "https://github.com/coder/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent
chmod +x ./lib/coder-cloud-agent
set -e
fi
}
main "$@"

View File

@@ -63,8 +63,6 @@ EOF
if [ "$KEEP_MODULES" = 1 ]; then
rsync node_modules/ "$RELEASE_PATH/node_modules"
mkdir -p "$RELEASE_PATH/lib"
rsync ./lib/coder-cloud-agent "$RELEASE_PATH/lib"
fi
}

View File

@@ -1,18 +1,8 @@
#!/usr/bin/env sh
set -eu
# Copied from ../lib.sh.
arch() {
cpu="$(uname -m)"
case "$cpu" in
aarch64) cpu=arm64 ;;
x86_64) cpu=amd64 ;;
esac
echo "$cpu"
}
# Copied from ../lib.sh except we do not rename Darwin since the cloud agent
# uses "darwin" in the release names and we do not need to detect Alpine.
# Copied from ../lib.sh except we do not rename Darwin and we do not need to
# detect Alpine.
os() {
osname=$(uname | tr '[:upper:]' '[:lower:]')
case $osname in
@@ -61,7 +51,6 @@ symlink_bin_script() {
cd "$oldpwd"
}
ARCH="${NPM_CONFIG_ARCH:-$(arch)}"
OS="$(os)"
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
@@ -102,14 +91,6 @@ main() {
;;
esac
mkdir -p ./lib
if curl -fsSL "https://github.com/coder/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent; then
chmod +x ./lib/coder-cloud-agent
else
echo "Failed to download cloud agent; --link will not work"
fi
if ! vscode_install; then
echo "You may not have the required dependencies to build the native modules."
echo "Please see https://github.com/coder/code-server/blob/main/docs/npm.md"

View File

@@ -11,22 +11,6 @@ main() {
make -s out/index.js
popd
# Our code imports from `out` in order to work during development but if you
# have only built for production you will have not have this directory. In
# that case symlink `out` to a production build directory.
if [[ ! -e lib/vscode/out ]]; then
pushd lib
local out=(vscode-reh-web-*)
if [[ -d "${out[0]}" ]]; then
ln -s "../${out[0]}/out" ./vscode/out
else
echo "Could not find lib/vscode/out or lib/vscode-reh-web-*"
echo "Code must be built before running unit tests"
exit 1
fi
popd
fi
# 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.

View File

@@ -1,4 +1,4 @@
import { spawn, fork, ChildProcess } from "child_process"
import { spawn, ChildProcess } from "child_process"
import * as path from "path"
import { onLine, OnLineCallback } from "../../src/node/util"
@@ -30,12 +30,13 @@ class Watcher {
// Pass CLI args, save for `node` and the initial script name.
const args = process.argv.slice(2)
this.webServer = fork(path.join(this.rootPath, "out/node/entry.js"), args)
this.webServer = spawn("node", [path.join(this.rootPath, "out/node/entry.js"), ...args])
onLine(this.webServer, (line) => console.log("[code-server]", line))
const { pid } = this.webServer
this.webServer.on("exit", () => console.log("[Code Server]", `Web process ${pid} exited`))
this.webServer.on("exit", () => console.log("[code-server]", `Web process ${pid} exited`))
console.log("\n[Code Server]", `Spawned web server process ${pid}`)
console.log("\n[code-server]", `Spawned web server process ${pid}`)
}
//#endregion
@@ -82,10 +83,10 @@ class Watcher {
private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
if (!strippedLine.length) return
console.log("[VS Code]", originalLine)
console.log("[Code OSS]", originalLine)
if (strippedLine.includes("Finished compilation with")) {
console.log("[VS Code] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
console.log("[Code OSS] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
this.reloadWebServer()
}
}
@@ -93,10 +94,10 @@ class Watcher {
private parseCodeServerLine: OnLineCallback = (strippedLine, originalLine) => {
if (!strippedLine.length) return
console.log("[Compiler][Code Server]", originalLine)
console.log("[Compiler][code-server]", originalLine)
if (strippedLine.includes("Watching for file changes")) {
console.log("[Compiler][Code Server]", "Finished compiling!", "(Refresh your web browser ♻️)")
console.log("[Compiler][code-server]", "Finished compiling!", "(Refresh your web browser ♻️)")
this.reloadWebServer()
}
}

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: 3.4.0
version: 3.5.1
# 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.9.0
appVersion: 4.9.1

View File

@@ -102,6 +102,7 @@ spec:
{{- range .Values.extraSecretMounts }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
subPath: {{ .subPath | default "" }}
readOnly: {{ .readOnly }}
{{- end }}
{{- range .Values.extraVolumeMounts }}
@@ -114,6 +115,11 @@ spec:
- name: http
containerPort: 8080
protocol: TCP
{{- range .Values.extraPorts }}
- name: {{ .name }}
containerPort: {{ .port }}
protocol: {{ .protocol }}
{{- end }}
livenessProbe:
httpGet:
path: /

View File

@@ -14,6 +14,12 @@ spec:
targetPort: http
protocol: TCP
name: http
{{- range .Values.extraPorts }}
- port: {{ .port }}
targetPort: {{ .port }}
protocol: {{ .protocol }}
name: {{ .name }}
{{- end }}
selector:
app.kubernetes.io/name: {{ include "code-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.9.0'
tag: '4.9.1'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a
@@ -179,6 +179,7 @@ extraInitContainers: |
extraSecretMounts: []
# - name: secret-files
# mountPath: /etc/secrets
# subPath: private.key # (optional)
# secretName: code-server-secret-files
# readOnly: true
@@ -196,3 +197,8 @@ extraConfigmapMounts: []
# subPath: certificates.crt # (optional)
# configMap: certs-configmap
# readOnly: true
extraPorts: []
# - name: minecraft
# port: 25565
# protocol: tcp

View File

@@ -11,9 +11,10 @@
- [Version updates to Code](#version-updates-to-code)
- [Patching Code](#patching-code)
- [Build](#build)
- [Creating a Standalone Release](#creating-a-standalone-release)
- [Troubleshooting](#troubleshooting)
- [I see "Forbidden access" when I load code-server in the browser](#i-see-forbidden-access-when-i-load-code-server-in-the-browser)
- ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
- ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
- [Help](#help)
- [Test](#test)
- [Unit tests](#unit-tests)
@@ -170,6 +171,22 @@ yarn package
> If you need your builds to support older distros, run the build commands
> inside a Docker container with all the build requirements installed.
#### Creating a Standalone Release
Part of the build process involves creating standalone releases. At the time of
writing, we do this for the following platforms/architectures:
- Linux amd64 (.tar.gz, .deb, and .rpm)
- Linux arm64 (.tar.gz, .deb, and .rpm)
- Linux arm7l (.tar.gz)
- Linux armhf.deb
- Linux armhf.rpm
- macOS amd64 (Intel-based)
Currently, these are compiled in CI using the `yarn release-standalone` command
in the `release.yaml` workflow. We then upload them to the draft release and
distribute via GitHub Releases.
### Troubleshooting
#### I see "Forbidden access" when I load code-server in the browser
@@ -178,7 +195,7 @@ This means your patches didn't apply correctly. We have a patch to remove the au
Try popping off the patches with `quilt pop -a` and reapplying with `quilt push -a`.
### "Can only have one anonymous define call per script"
#### "Can only have one anonymous define call per script"
Code might be trying to use a dev or prod HTML in the wrong context. You can try re-running code-server and setting `VSCODE_DEV=1`.

View File

@@ -26,6 +26,7 @@
- [Is multi-tenancy possible?](#is-multi-tenancy-possible)
- [Can I use Docker in a code-server container?](#can-i-use-docker-in-a-code-server-container)
- [How do I disable telemetry?](#how-do-i-disable-telemetry)
- [What's the difference between code-server and Coder?](#whats-the-difference-between-code-server-and-coder)
- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
- [What's the difference between code-server and OpenVSCode-Server?](#whats-the-difference-between-code-server-and-openvscode-server)
- [What's the difference between code-server and GitHub Codespaces?](#whats-the-difference-between-code-server-and-github-codespaces)
@@ -33,6 +34,7 @@
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
- [How do I change the port?](#how-do-i-change-the-port)
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
- [How do I disable file download?](#how-do-i-disable-file-download)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->
@@ -362,6 +364,15 @@ Use the `--disable-telemetry` flag to disable telemetry.
> We use the data collected only to improve code-server.
## What's the difference between code-server and Coder?
code-server and Coder are both applications that can be installed on any
machine. The main difference is who they serve. Out of the box, code-server is
simply VS Code in the browser while Coder is a tool for provisioning remote
development environments via Terraform.
code-server was built for individuals while Coder was built for teams. In Coder, you create Workspaces which can have applications like code-server. If you're looking for a team solution, you should reach for [Coder](https://github.com/coder/coder).
## What's the difference between code-server and Theia?
At a high level, code-server is a patched fork of VS Code that runs in the
@@ -425,3 +436,7 @@ There are two ways to change the port on which code-server runs:
You can pass the flag `--disable-getting-started-override` to `code-server` or
you can set the environment variable `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
`CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
## How do I disable file download?
You can pass the flag `--disable-file-downloads` to `code-server`

View File

@@ -142,24 +142,28 @@ changelog](https://github.com/emacs-mirror/emacs/blob/master/etc/NEWS).
### Publishing a release
1. Go to GitHub Actions > Draft release > Run workflow off commit you want to
release. CI will automatically upload the artifacts to the release. Make sure CI
has finished on that commit.
1. CI will automatically grab the
artifacts, publish the NPM package from `npm-package`, and publish the Docker
Hub image from `release-images`.
1. Publish release.
1. After, create a new branch called `release/v0.0.0` (replace 0s with actual version aka v4.5.0)
1. Summarize the major changes in the `CHANGELOG.md`
1. Bump chart version in `Chart.yaml`.
1. Go to GitHub Actions > Draft release > Run workflow on the commit you want to
release. Make sure CI has finished the build workflow on that commit or this
will fail.
2. CI will automatically grab the build artifact on that commit, inject the
version into the `package.json`, put together platform-specific packages, and
upload those packages to a draft release.
3. Summarize the major changes in the `CHANGELOG.md`.
4. Copy the relevant changelog section to the release then publish it.
5. CI will automatically publish the NPM package, Docker image, and update
Homebrew using the published release assets.
6. Bump the chart version in `Chart.yaml` and merge in the changelog updates.
#### Release Candidates
We prefer to do release candidates so the community can test things before a full-blown release. To do this follow the same steps as above but:
We prefer to do release candidates so the community can test things before a
full-blown release. To do this follow the same steps as above but:
1. Only bump version in `package.json`
1. use `0.0.0-rc.0`
1. When you publish the release, select "pre-release"
1. Add a `-rc.<number>` suffix to the version.
2. When you publish the release select "pre-release". CI will not automatically
publish pre-releases.
3. Do not update the chart version or merge in the changelog until the final
release.
#### AUR

View File

@@ -16,7 +16,7 @@ access it in the browser.
## Requirements
See [requirements](requirements.md) for minimum specs, as well as instructions
See [requirements](https://coder.com/docs/code-server/latest/requirements) for minimum specs, as well as instructions
on how to set up a Google VM on which you can install code-server.
**TL;DR:** Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs

37
docs/coder.md Normal file
View File

@@ -0,0 +1,37 @@
# Coder
To install and run code-server in a Coder workspace, we suggest using the `install.sh`
script in your template like so:
```terraform
resource "coder_agent" "dev" {
arch = "amd64"
os = "linux"
startup_script = <<EOF
#!/bin/sh
set -x
# install and start code-server
curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3
code-server --auth none --port 13337 &
EOF
}
resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
slug = "code-server"
display_name = "code-server"
url = "http://localhost:13337/"
icon = "/icon/code.svg"
subdomain = false
share = "owner"
healthcheck {
url = "http://localhost:13337/healthz"
interval = 3
threshold = 10
}
}
```
If you run into issues, ask for help on the `coder/coder` [Discussions
here](https://github.com/coder/coder/discussions).

View File

@@ -14,6 +14,7 @@
- [Accessing web services](#accessing-web-services)
- [Using a subdomain](#using-a-subdomain)
- [Using a subpath](#using-a-subpath)
- [Using your own proxy](#using-your-own-proxy)
- [Stripping `/proxy/<port>` from the request path](#stripping-proxyport-from-the-request-path)
- [Proxying to create a React app](#proxying-to-create-a-react-app)
- [Proxying to a Vue app](#proxying-to-a-vue-app)
@@ -316,12 +317,32 @@ To set your domain, start code-server with the `--proxy-domain` flag:
code-server --proxy-domain <domain>
```
Now you can browse to `<port>.<domain>`. Note that this uses the host header, so
ensure your reverse proxy (if you're using one) forwards that information.
For instance, if you have code-server exposed on `domain.tld` and a Python
server running on port 8080 of the same machine code-server is running on, you
could run code-server with `--proxy-domain domain.tld` and access the Python
server via `8080.domain.tld`.
Note that this uses the host header, so ensure your reverse proxy (if you're
using one) forwards that information.
### Using a subpath
Simply browse to `/proxy/<port>/`.
Simply browse to `/proxy/<port>/`. For instance, if you have code-server
exposed on `domain.tld` and a Python server running on port 8080 of the same
machine code-server is running on, you could access the Python server via
`domain.tld/proxy/8000`.
### Using your own proxy
You can make extensions and the ports panel use your own proxy by setting
`VSCODE_PROXY_URI`. For example if you set
`VSCODE_PROXY_URI=https://{{port}}.kyle.dev` when an application is detected
running on port 3000 of the same machine code-server is running on the ports
panel will create a link to https://3000.kyle.dev instead of pointing to the
built-in subpath-based proxy.
Note: relative paths are also supported i.e.
`VSCODE_PROXY_URI=./proxy/{{port}}`
### Stripping `/proxy/<port>` from the request path

View File

@@ -297,9 +297,9 @@ You can install code-server using the [Helm package manager](https://coder.com/d
## Windows
We currently [do not publish Windows releases](https://github.com/coder/code-server/issues/1397). We recommend installing code-server onto Windows with [`npm`](#npm).
> Note: You will also need to [build coder/cloud-agent manually](https://github.com/coder/cloud-agent/issues/17) if you would like to use `code-server --link` on Windows.
We currently [do not publish Windows
releases](https://github.com/coder/code-server/issues/1397). We recommend
installing code-server onto Windows with [`npm`](#npm).
## Raspberry Pi

View File

@@ -1,11 +0,0 @@
# code-server --link
> Note: This feature is no longer recommended due to instability. Stay tuned for a revised version.
Run code-server with the flag `--link` and you'll get TLS, authentication, and a dedicated URL
for accessing your IDE out of the box.
```console
$ code-server --link
Proxying code-server, you can access your IDE at https://example.coder.co
```

View File

@@ -38,9 +38,9 @@
"path": "./guide.md",
"children": [
{
"title": "--link",
"description": "How to run code-server --link",
"path": "./link.md"
"title": "Coder",
"description": "How to run code-server in Coder",
"path": "./coder.md"
},
{
"title": "iPad",

View File

@@ -12,7 +12,6 @@
- [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 -->
<!-- prettier-ignore-end -->
@@ -20,53 +19,9 @@
## Install
1. Get [Termux](https://f-droid.org/en/packages/com.termux/) from **F-Droid**.
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`.\
> 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 proot-distro -y && proot-distro install debian && proot-distro login debian
```
3. Run the following commands to setup Debian:
```bash
apt update && apt upgrade -y && apt-get install sudo vim git -y
```
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 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) 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
```bash
curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
```
```bash
curl -fsSL https://code-server.dev/install.sh | sh
```
8. You can now start code server by simply running `code-server`.
> Consider using a new user instead of root, read [here](https://www.howtogeek.com/124950/htg-explains-why-you-shouldnt-log-into-your-linux-system-as-root/) why using root is not recommended.\
> Learn how to add a user [here](#create-a-new-user).
2. Run `pkg install tur-repo`
3. Run `pkg install code-server`
4. You can now start code server by simply running `code-server`.
## NPM Installation
@@ -202,35 +157,3 @@ eval "$(pyenv virtualenv-init -)"
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

@@ -88,15 +88,16 @@
},
"dependencies": {
"@coder/logger": "^3.0.0",
"argon2": "0.30.2",
"argon2": "0.30.3",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
"env-paths": "^2.2.0",
"express": "5.0.0-alpha.8",
"http-proxy": "^1.18.0",
"httpolyglot": "^0.1.2",
"i18next": "^22.4.6",
"js-yaml": "^4.0.0",
"limiter": "^1.1.5",
"limiter": "^2.1.0",
"pem": "^1.14.2",
"proxy-agent": "^5.0.0",
"qs": "6.11.0",

View File

@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
+++ code-server/lib/vscode/src/vs/base/common/network.ts
@@ -162,7 +162,9 @@ class RemoteAuthoritiesImpl {
@@ -166,7 +166,9 @@ class RemoteAuthoritiesImpl {
return URI.from({
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
authority: `${host}:${port}`,

View File

@@ -8,7 +8,7 @@ To test:
2. Open code-server
3. Open terminal
4. Open another code-server window
5. Run code-server with a file or directory argument
5. Run node ./out/node/entry.js with a file or directory argument
The file or directory should only open from the instance attached to that
terminal.

View File

@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
@@ -237,6 +237,10 @@ export class Extension implements IExten
@@ -243,6 +243,10 @@ export class Extension implements IExten
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
return false;
}
@@ -18,14 +18,3 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
return false;
}
@@ -1237,6 +1241,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

@@ -12,7 +12,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -271,6 +271,11 @@ export interface IWorkbenchConstructionO
@@ -266,6 +266,11 @@ export interface IWorkbenchConstructionO
*/
readonly userDataPath?: string
@@ -23,7 +23,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
+
//#endregion
//#region Profile options
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
@@ -40,7 +40,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
}
export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
@@ -87,6 +92,13 @@ export class BrowserWorkbenchEnvironment
@@ -104,6 +109,13 @@ export class BrowserWorkbenchEnvironment
return this.options.userDataPath;
}
@@ -143,8 +143,8 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions
+import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, 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';
@@ -483,13 +483,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
import { ThemeIcon } from 'vs/base/common/themables';
@@ -484,13 +484,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
id: DOWNLOAD_COMMAND_ID,
title: DOWNLOAD_LABEL
},

View File

@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
@@ -216,6 +216,9 @@ export async function setupServerService
@@ -220,6 +220,9 @@ export async function setupServerService
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
socketServer.registerChannel('extensions', channel);
@@ -42,7 +42,7 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
export const LANGUAGE_DEFAULT = 'en';
let _isWindows = false;
@@ -83,17 +81,19 @@ if (typeof navigator === 'object' && !is
@@ -86,17 +84,19 @@ if (typeof navigator === 'object' && !is
_isMobile = _userAgent?.indexOf('Mobi') >= 0;
_isWeb = true;
@@ -125,7 +125,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentServ
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
+++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
@@ -110,7 +110,7 @@ export abstract class AbstractNativeEnvi
@@ -107,7 +107,7 @@ export abstract class AbstractNativeEnvi
return URI.file(join(vscodePortable, 'argv.json'));
}

View File

@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
@@ -62,7 +62,7 @@ import { GettingStartedIndexList } from
@@ -60,7 +60,7 @@ import { GettingStartedIndexList } from
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
import { OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
import { Toggle } from 'vs/base/browser/ui/toggle/toggle';
@@ -758,6 +758,72 @@ export class GettingStartedPage extends
@@ -759,6 +759,72 @@ export class GettingStartedPage extends
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
);
@@ -72,7 +72,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
+ 'align-items: center',
+ ].join(';'),
+ }, 'Get started ', $('span', {
+ class: Codicon.arrowRight.classNames,
+ class: ThemeIcon.asClassName(Codicon.arrowRight),
+ style: [
+ 'color: white',
+ 'margin-left: 8px',
@@ -92,7 +92,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
const leftColumn = $('.categories-column.categories-column-left', {},);
const rightColumn = $('.categories-column.categories-column-right', {},);
@@ -775,13 +841,23 @@ export class GettingStartedPage extends
@@ -776,13 +842,23 @@ export class GettingStartedPage extends
const layoutLists = () => {
if (gettingStartedList.itemCount) {
this.container.classList.remove('noWalkthroughs');
@@ -143,7 +143,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -276,6 +276,11 @@ export interface IWorkbenchConstructionO
@@ -271,6 +271,11 @@ export interface IWorkbenchConstructionO
*/
readonly isEnabledFileDownloads?: boolean
@@ -154,7 +154,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
+
//#endregion
//#region Profile options
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
@@ -171,7 +171,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
}
export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
@@ -99,6 +104,13 @@ export class BrowserWorkbenchEnvironment
@@ -116,6 +121,13 @@ export class BrowserWorkbenchEnvironment
return this.options.isEnabledFileDownloads;
}

View File

@@ -38,7 +38,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
-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);
-const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath);
-const BUILTIN_EXTENSIONS_FOLDER_PATH = join(APP_ROOT, 'extensions');
-args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
-args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
@@ -58,7 +58,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
+ 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);
+ const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath);
+ const BUILTIN_EXTENSIONS_FOLDER_PATH = args['builtin-extensions-dir'] || join(APP_ROOT, 'extensions');
+ args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
+ args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
@@ -95,7 +95,7 @@ Index: code-server/lib/vscode/src/vs/base/common/processes.ts
--- code-server.orig/lib/vscode/src/vs/base/common/processes.ts
+++ code-server/lib/vscode/src/vs/base/common/processes.ts
@@ -111,6 +111,8 @@ export function sanitizeProcessEnvironme
/^VSCODE_(?!SHELL_LOGIN).+$/,
/^VSCODE_(?!(PORTABLE|SHELL_LOGIN)).+$/,
/^SNAP(|_.*)$/,
/^GDK_PIXBUF_.+$/,
+ /^CODE_SERVER_.+$/,
@@ -107,7 +107,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
@@ -143,8 +143,11 @@ export class BrowserDialogHandler implem
@@ -145,8 +145,11 @@ export class BrowserDialogHandler implem
async about(): Promise<void> {
const detailString = (useAgo: boolean): string => {
@@ -184,7 +184,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
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';
@@ -117,6 +118,9 @@ export class BrowserMain extends Disposa
@@ -119,6 +120,9 @@ export class BrowserMain extends Disposa
// Startup
const instantiationService = workbench.startup();

View File

@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
@@ -266,6 +266,11 @@ export interface IWorkbenchConstructionO
@@ -261,6 +261,11 @@ export interface IWorkbenchConstructionO
*/
readonly configurationDefaults?: Record<string, any>;
@@ -43,12 +43,12 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
+
//#endregion
//#region Profile options
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
@@ -78,7 +78,14 @@ export class BrowserWorkbenchEnvironment
@@ -95,7 +95,14 @@ export class BrowserWorkbenchEnvironment
get logFile(): URI { return joinPath(this.windowLogsPath, 'window.log'); }
@memoize

View File

@@ -19,7 +19,7 @@ Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
@@ -53,6 +53,16 @@ else if (typeof require?.__$__nodeRequir
@@ -47,6 +47,16 @@ else if (globalThis._VSCODE_PRODUCT_JSON
version: pkg.version
});
}

View File

@@ -10,7 +10,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
@@ -1482,7 +1482,7 @@ class ProposedApiController {
@@ -1486,7 +1486,7 @@ class ProposedApiController {
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));

View File

@@ -42,31 +42,31 @@ 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
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/comm
import { RemoteAuthorities } from 'vs/base/common/network';
@@ -11,7 +11,7 @@ import { StopWatch } from 'vs/base/commo
import { URI } from 'vs/base/common/uri';
import { ILogService } from 'vs/platform/log/common/log';
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 { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult, getRemoteAuthorityPrefix } from 'vs/platform/remote/common/remoteAuthorityResolver';
+import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult, getRemoteAuthorityPrefix } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { getRemoteServerRootPath, parseAuthorityWithOptionalPort } from 'vs/platform/remote/common/remoteHosts';
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
@@ -23,7 +23,7 @@ export class RemoteAuthorityResolverServ
private readonly _connectionToken: Promise<string> | string | undefined;
private readonly _connectionTokens: Map<string, string>;
- constructor(@IProductService productService: IProductService, connectionToken: Promise<string> | string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
+ constructor(@IProductService productService: IProductService, connectionToken: Promise<string> | string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
@@ -29,7 +29,7 @@ export class RemoteAuthorityResolverServ
constructor(
connectionToken: Promise<string> | string | undefined,
resourceUriProvider: ((uri: URI) => URI) | undefined,
- @IProductService productService: IProductService,
+ @IProductService private readonly productService: IProductService,
@ILogService private readonly _logService: ILogService,
) {
super();
this._connectionToken = connectionToken;
this._connectionTokens = new Map<string, string>();
@@ -61,9 +61,14 @@ export class RemoteAuthorityResolverServ
private async _doResolveAuthority(authority: string): Promise<ResolverResult> {
@@ -75,9 +75,14 @@ export class RemoteAuthorityResolverServ
const connectionToken = await Promise.resolve(this._connectionTokens.get(authority) || this._connectionToken);
performance.mark(`code/didResolveConnectionToken/${authorityPrefix}`);
this._logService.info(`Resolved connection token (${authorityPrefix}) after ${sw.elapsed()} ms`);
+ let options: ResolvedOptions | undefined;
+ if (this.proxyEndpointTemplate) {
+ const proxyUrl = new URL(this.proxyEndpointTemplate, window.location.href);
+ if (this.productService.proxyEndpointTemplate) {
+ const proxyUrl = new URL(this.productService.proxyEndpointTemplate, window.location.href);
+ options = { extensionHostEnv: { VSCODE_PROXY_URI: decodeURIComponent(proxyUrl.toString()) }}
+ }
const defaultPort = (/^https:/.test(window.location.href) ? 443 : 80);
@@ -88,24 +88,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
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
@@ -248,7 +248,7 @@ export class BrowserMain extends Disposa
// Remote
const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);
- 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
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
@@ -381,7 +381,7 @@ export async function createTerminalEnvi
@@ -383,7 +383,7 @@ export async function createTerminalEnvi
// Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables
@@ -170,7 +157,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExpl
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
@@ -73,7 +73,7 @@ export class ForwardedPortsView extends
@@ -73,7 +73,7 @@ export class ForwardedPortsView extends
this.contextKeyListener = undefined;
}

View File

@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
let version = packageJson.version;
const quality = product.quality;
@@ -388,7 +387,7 @@ function tweakProductForServerWeb(produc
@@ -389,7 +388,7 @@ function tweakProductForServerWeb(produc
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
optimizeTask,
util.rimraf(`out-vscode-${type}-min`),

View File

@@ -1,7 +1,7 @@
Add support for telemetry endpoint
To test:
1. Create a RequestBin - https://requestbin.io/
1. Create a mock API using [RequestBin](https://requestbin.io/) or [Beeceptor](https://beeceptor.com/)
2. Run code-server with `CS_TELEMETRY_URL` set:
i.e. `CS_TELEMETRY_URL="https://requestbin.io/1ebub9z1" ./code-server-<version>-macos-amd64/bin/code-server`
NOTE: it has to be a production build.
@@ -12,15 +12,15 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
===================================================================
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
@@ -71,6 +71,7 @@ import { IExtensionsScannerService } fro
@@ -70,6 +70,7 @@ import { IExtensionsScannerService } fro
import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
import { ExtensionsProfileScannerService, IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
import { IUserDataProfilesService, UserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
+import { TelemetryClient } from "vs/server/node/telemetryClient";
import { NullPolicyService } from 'vs/platform/policy/common/policy';
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
import { LoggerService } from 'vs/platform/log/node/loggerService';
@@ -139,10 +140,13 @@ export async function setupServerService
@@ -142,10 +143,13 @@ export async function setupServerService
const machineId = await getMachineId();
const isInternal = isInternalTelemetry(productService, configurationService);
if (supportsTelemetry(productService, environmentService)) {

View File

@@ -41,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
@@ -210,7 +210,7 @@ export class BrowserWorkbenchEnvironment
@@ -224,7 +224,7 @@ export class BrowserWorkbenchEnvironment
@memoize
get webviewExternalEndpoint(): string {
@@ -62,6 +62,15 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
_wrapWebWorkerExtHostInIframe,
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,
@@ -344,7 +345,7 @@ export class WebClientServer {
`script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=';`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
'child-src \'self\';',
`frame-src 'self' https://*.vscode-cdn.net data:;`,
- 'worker-src \'self\' data:;',
+ 'worker-src \'self\' data: blob:;',
'style-src \'self\' \'unsafe-inline\';',
'connect-src \'self\' ws: wss: https:;',
'font-src \'self\' blob:;',
Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index.html
@@ -70,12 +79,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
- content="default-src 'none'; script-src 'sha256-lC8sxUeeYqUtmkCpPt/OX/HQdE0JbHG1Z3dzrilsRU0=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-/9/YQU12wvTeVXCsIGB4shLwdWrMceCpKojfkloNjPU=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
- content="default-src 'none'; script-src 'sha256-RaCvj6SRgHm+2C3LKzSAamDwa3Bp4u4iQ1Y2Sm+97tE=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+ content="default-src 'none'; script-src 'sha256-mi72idjvdhsPSBMKFqU82FG/kZVJjKR0TfHLE13gB+w=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
<!-- Disable pinch zooming -->
<meta name="viewport"
@@ -331,6 +331,12 @@
@@ -325,6 +325,12 @@
const hostname = location.hostname;
@@ -92,7 +101,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
===================================================================
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
@@ -330,6 +330,12 @@
@@ -324,6 +324,12 @@
const hostname = location.hostname;

View File

@@ -6,10 +6,16 @@
"matchUpdateTypes": ["minor", "patch", "digest"],
"automerge": true,
"groupName": "Minor dependency updates"
},
{
"matchDepTypes": ["peerDependencies"],
"matchUpdateTypes": ["minor", "patch", "digest"],
"automerge": true,
"groupName": "Peer dependency updates"
}
],
"vulnerabilityAlerts": {
"enabled": "true"
},
"ignoreDeps": ["express"]
"ignoreDeps": ["express", "ansi-regex", "env-paths", "limiter", "node", "prettier"]
}

View File

@@ -10,7 +10,7 @@
http-equiv="Content-Security-Policy"
content="style-src 'self'; script-src 'self' 'unsafe-inline'; manifest-src 'self'; img-src 'self' data:; font-src 'self' data:;"
/>
<title>{{APP_NAME}} login</title>
<title>{{I18N_LOGIN_TITLE}}</title>
<link rel="icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon-dark-support.svg" />
<link rel="alternate icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon.ico" />
<link rel="manifest" href="{{BASE}}/manifest.json" crossorigin="use-credentials" />
@@ -25,7 +25,7 @@
<div class="card-box">
<div class="header">
<h1 class="main">{{WELCOME_TEXT}}</h1>
<div class="sub">Please log in below. {{PASSWORD_MSG}}</div>
<div class="sub">{{I18N_LOGIN_BELOW}} {{PASSWORD_MSG}}</div>
</div>
<div class="content">
<form class="login-form" method="post">
@@ -38,11 +38,11 @@
autofocus
class="password"
type="password"
placeholder="PASSWORD"
placeholder="{{I18N_PASSWORD_PLACEHOLDER}}"
name="password"
autocomplete="current-password"
/>
<input class="submit -button" value="SUBMIT" type="submit" />
<input class="submit -button" value="{{I18N_SUBMIT}}" type="submit" />
</div>
{{ERROR}}
</form>

View File

@@ -84,7 +84,6 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
"reuse-window"?: boolean
"new-window"?: boolean
"ignore-last-opened"?: boolean
link?: OptionalString
verbose?: boolean
"app-name"?: string
"welcome-text"?: string
@@ -180,7 +179,14 @@ export const options: Options<Required<UserProvidedArgs>> = {
enable: { type: "string[]" },
help: { type: "boolean", short: "h", description: "Show this output." },
json: { type: "boolean" },
locale: { type: "string" }, // The preferred way to set the locale is via the UI.
locale: {
// The preferred way to set the locale is via the UI.
type: "string",
description: `
Set vscode display language and language to show on the login page, more info see
https://en.wikipedia.org/wiki/IETF_language_tag
`,
},
open: { type: "boolean", description: "Open in browser on startup. Does not work remotely." },
"bind-addr": {
@@ -255,15 +261,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
short: "w",
description: "Text to show on login page",
},
link: {
type: OptionalString,
description: `
Securely bind code-server via our cloud service with the passed name. You'll get a URL like
https://hostname-username.coder.co at which you can easily access your code-server instance.
Authorization is done via GitHub.
`,
deprecated: true,
},
}
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
@@ -540,17 +537,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
args.host = addr.host
args.port = addr.port
// If we're being exposed to the cloud, we listen on a random address and
// disable auth.
if (args.link) {
args.host = "localhost"
args.port = 0
args.socket = undefined
args["socket-mode"] = undefined
args.cert = undefined
args.auth = AuthType.None
}
if (args.cert && !args.cert.value) {
const { cert, certKey } = await generateCertificate(args["cert-host"] || "localhost")
args.cert = {

View File

@@ -1,43 +0,0 @@
import { logger } from "@coder/logger"
import { spawn } from "child_process"
import path from "path"
import split2 from "split2"
// https://github.com/coder/coder-cloud
const coderCloudAgent = path.resolve(__dirname, "../../lib/coder-cloud-agent")
function runAgent(...args: string[]): Promise<void> {
logger.debug(`running agent with ${args}`)
const agent = spawn(coderCloudAgent, args, {
stdio: ["inherit", "inherit", "pipe"],
})
agent.stderr.pipe(split2()).on("data", (line) => {
line = line.replace(/^[0-9-]+ [0-9:]+ [^ ]+\t/, "")
logger.info(line)
})
return new Promise((res, rej) => {
agent.on("error", rej)
agent.on("close", (code) => {
if (code !== 0) {
rej({
message: `--link agent exited with ${code}`,
})
return
}
res()
})
})
}
export function coderCloudBind(address: URL | string, serverName = ""): Promise<void> {
if (typeof address === "string") {
throw new Error("Cannot link socket paths")
}
// Address needs to be in hostname:port format without the protocol.
return runAgent("bind", `--code-server-addr=${address.host}`, serverName)
}

21
src/node/i18n/index.ts Normal file
View File

@@ -0,0 +1,21 @@
import i18next, { init } from "i18next"
import * as en from "./locales/en.json"
import * as zhCn from "./locales/zh-cn.json"
init({
lng: "en",
fallbackLng: "en", // language to use if translations in user language are not available.
returnNull: false,
lowerCaseLng: true,
debug: process.env.NODE_ENV === "development",
resources: {
en: {
translation: en,
},
"zh-cn": {
translation: zhCn,
},
},
})
export default i18next

View File

@@ -0,0 +1,13 @@
{
"LOGIN_TITLE": "{{app}} login",
"LOGIN_BELOW": "Please log in below.",
"WELCOME": "Welcome to {{app}}",
"LOGIN_PASSWORD": "Check the config file at {{configFile}} for the password.",
"LOGIN_USING_ENV_PASSWORD": "Password was set from $PASSWORD.",
"LOGIN_USING_HASHED_PASSWORD": "Password was set from $HASHED_PASSWORD.",
"SUBMIT": "SUBMIT",
"PASSWORD_PLACEHOLDER": "PASSWORD",
"LOGIN_RATE_LIMIT": "Login rate limited!",
"MISS_PASSWORD": "Missing password",
"INCORRECT_PASSWORD": "Incorrect password"
}

View File

@@ -0,0 +1,13 @@
{
"LOGIN_TITLE": "{{app}} 登录",
"LOGIN_BELOW": "请在下面登录。",
"WELCOME": "欢迎来到 {{app}}",
"LOGIN_PASSWORD": "查看配置文件 {{configFile}} 中的密码。",
"LOGIN_USING_ENV_PASSWORD": "密码在 $PASSWORD 中设置。",
"LOGIN_USING_HASHED_PASSWORD": "密码在 $HASHED_PASSWORD 中设置。",
"SUBMIT": "提交",
"PASSWORD_PLACEHOLDER": "密码",
"LOGIN_RATE_LIMIT": "登录速率限制!",
"MISS_PASSWORD": "缺少密码",
"INCORRECT_PASSWORD": "密码不正确"
}

View File

@@ -6,7 +6,6 @@ import { Disposable } from "../common/emitter"
import { plural } from "../common/util"
import { createApp, ensureAddress } from "./app"
import { AuthType, DefaultedArgs, Feature, SpawnCodeCli, toCodeArgs, UserProvidedArgs } from "./cli"
import { coderCloudBind } from "./coder_cloud"
import { commit, version } from "./constants"
import { register } from "./routes"
import { humanPath, isDirectory, loadAMDModule, open } from "./util"
@@ -127,11 +126,7 @@ export const runCodeServer = async (
const disposeRoutes = await register(app, args)
logger.info(`Using config file ${humanPath(os.homedir(), args.config)}`)
logger.info(
`${protocol.toUpperCase()} server listening on ${serverAddress.toString()} ${
args.link ? "(randomized by --link)" : ""
}`,
)
logger.info(`${protocol.toUpperCase()} server listening on ${serverAddress.toString()}`)
if (args.auth === AuthType.Password) {
logger.info(" - Authentication is enabled")
@@ -143,13 +138,13 @@ export const runCodeServer = async (
logger.info(` - Using password from ${humanPath(os.homedir(), args.config)}`)
}
} else {
logger.info(` - Authentication is disabled ${args.link ? "(disabled by --link)" : ""}`)
logger.info(" - Authentication is disabled")
}
if (args.cert) {
logger.info(` - Using certificate for HTTPS: ${humanPath(os.homedir(), args.cert.value)}`)
} else {
logger.info(` - Not serving HTTPS ${args.link ? "(disabled by --link)" : ""}`)
logger.info(" - Not serving HTTPS")
}
if (args["proxy-domain"].length > 0) {
@@ -157,11 +152,6 @@ export const runCodeServer = async (
args["proxy-domain"].forEach((domain) => logger.info(` - *.${domain}`))
}
if (args.link) {
await coderCloudBind(serverAddress, args.link.value)
logger.info(" - Connected to cloud agent")
}
if (args.enable && args.enable.length > 0) {
logger.info("Enabling the following experimental features:")
args.enable.forEach((feature) => {

View File

@@ -33,7 +33,15 @@ import { CodeServerRouteWrapper } from "./vscode"
export const register = async (app: App, args: DefaultedArgs): Promise<Disposable["dispose"]> => {
const heart = new Heart(path.join(paths.data, "heartbeat"), async () => {
return new Promise((resolve, reject) => {
// getConnections appears to not call the callback when there are no more
// connections. Feels like it must be a bug? For now add a timer to make
// sure we eventually resolve.
const timer = setTimeout(() => {
logger.debug("Node failed to respond with connections; assuming zero")
resolve(false)
}, 5000)
app.server.getConnections((error, count) => {
clearTimeout(timer)
if (error) {
return reject(error)
}

View File

@@ -7,12 +7,13 @@ import { CookieKeys } from "../../common/http"
import { rootPath } from "../constants"
import { authenticated, getCookieOptions, redirect, replaceTemplates } from "../http"
import { getPasswordMethod, handlePasswordValidation, humanPath, sanitizeString, escapeHtml } from "../util"
import i18n from "../i18n"
// RateLimiter wraps around the limiter library for logins.
// It allows 2 logins every minute plus 12 logins every hour.
export class RateLimiter {
private readonly minuteLimiter = new Limiter(2, "minute")
private readonly hourLimiter = new Limiter(12, "hour")
private readonly minuteLimiter = new Limiter({ tokensPerInterval: 2, interval: "minute" })
private readonly hourLimiter = new Limiter({ tokensPerInterval: 12, interval: "hour" })
public canTry(): boolean {
// Note: we must check using >= 1 because technically when there are no tokens left
@@ -28,21 +29,26 @@ export class RateLimiter {
const getRoot = async (req: Request, error?: Error): Promise<string> => {
const content = await fs.readFile(path.join(rootPath, "src/browser/pages/login.html"), "utf8")
const locale = req.args["locale"] || "en"
i18n.changeLanguage(locale)
const appName = req.args["app-name"] || "code-server"
const welcomeText = req.args["welcome-text"] || `Welcome to ${appName}`
let passwordMsg = `Check the config file at ${humanPath(os.homedir(), req.args.config)} for the password.`
const welcomeText = req.args["welcome-text"] || (i18n.t("WELCOME", { app: appName }) as string)
let passwordMsg = i18n.t("LOGIN_PASSWORD", { configFile: humanPath(os.homedir(), req.args.config) })
if (req.args.usingEnvPassword) {
passwordMsg = "Password was set from $PASSWORD."
passwordMsg = i18n.t("LOGIN_USING_ENV_PASSWORD")
} else if (req.args.usingEnvHashedPassword) {
passwordMsg = "Password was set from $HASHED_PASSWORD."
passwordMsg = i18n.t("LOGIN_USING_HASHED_PASSWORD")
}
return replaceTemplates(
req,
content
.replace(/{{APP_NAME}}/g, appName)
.replace(/{{I18N_LOGIN_TITLE}}/g, i18n.t("LOGIN_TITLE", { app: appName }))
.replace(/{{WELCOME_TEXT}}/g, welcomeText)
.replace(/{{PASSWORD_MSG}}/g, passwordMsg)
.replace(/{{I18N_LOGIN_BELOW}}/g, i18n.t("LOGIN_BELOW"))
.replace(/{{I18N_PASSWORD_PLACEHOLDER}}/g, i18n.t("PASSWORD_PLACEHOLDER"))
.replace(/{{I18N_SUBMIT}}/g, i18n.t("SUBMIT"))
.replace(/{{ERROR}}/, error ? `<div class="error">${escapeHtml(error.message)}</div>` : ""),
)
}
@@ -70,11 +76,11 @@ router.post<{}, string, { password: string; base?: string }, { to?: string }>("/
try {
// Check to see if they exceeded their login attempts
if (!limiter.canTry()) {
throw new Error("Login rate limited!")
throw new Error(i18n.t("LOGIN_RATE_LIMIT") as string)
}
if (!password) {
throw new Error("Missing password")
throw new Error(i18n.t("MISS_PASSWORD") as string)
}
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
@@ -108,7 +114,7 @@ router.post<{}, string, { password: string; base?: string }, { to?: string }>("/
}),
)
throw new Error("Incorrect password")
throw new Error(i18n.t("INCORRECT_PASSWORD") as string)
} catch (error: any) {
const renderedHtml = await getRoot(req, error)
res.send(renderedHtml)

View File

@@ -128,6 +128,8 @@ export class CodeServer {
path.join(dir, "extensions"),
"--auth",
"none",
// The workspace to open.
...(this.args.includes("--ignore-last-opened") ? [] : [dir]),
...this.args,
// Using port zero will spawn on a random port.
"--bind-addr",
@@ -139,8 +141,6 @@ export class CodeServer {
path.join(dir, "config.yaml"),
"--user-data-dir",
dir,
// The last argument is the workspace to open.
dir,
]
this.logger.debug("spawning `node " + args.join(" ") + "`")
const proc = cp.spawn("node", args, {

111
test/e2e/routes.test.ts Normal file
View File

@@ -0,0 +1,111 @@
import { describe, test, expect } from "./baseFixture"
import { clean, getMaybeProxiedPathname } from "../utils/helpers"
const routes = ["/", "/vscode", "/vscode/"]
describe("VS Code Routes", ["--disable-workspace-trust"], {}, async () => {
const testName = "vscode-routes-default"
test.beforeAll(async () => {
await clean(testName)
})
test("should load all route variations", async ({ codeServerPage }) => {
for (const route of routes) {
await codeServerPage.navigate(route)
// Check there were no redirections
const url = new URL(codeServerPage.page.url())
const pathname = getMaybeProxiedPathname(url)
expect(pathname).toBe(route)
// TODO@jsjoeio
// now that we are in a proper browser instead of scraping the HTML we
// could possibly intercept requests to make sure assets are loading from
// the right spot.
//
// Check that page loaded from correct route
const html = await codeServerPage.page.innerHTML("html")
switch (route) {
case "/":
case "/vscode/":
expect(html).toMatch(/src="\.\/[a-z]+-[0-9a-z]+\/static\//)
break
case "/vscode":
expect(html).toMatch(/src="\.\/vscode\/[a-z]+-[0-9a-z]+\/static\//)
break
}
}
})
})
const CODE_WORKSPACE_DIR = process.env.CODE_WORKSPACE_DIR || ""
describe("VS Code Routes with code-workspace", ["--disable-workspace-trust", CODE_WORKSPACE_DIR], {}, async () => {
test("should redirect to the passed in workspace using human-readable query", async ({ codeServerPage }) => {
const url = new URL(codeServerPage.page.url())
const pathname = getMaybeProxiedPathname(url)
expect(pathname).toBe("/")
expect(url.search).toBe(`?workspace=${CODE_WORKSPACE_DIR}`)
})
})
const CODE_FOLDER_DIR = process.env.CODE_FOLDER_DIR || ""
describe("VS Code Routes with code-workspace", ["--disable-workspace-trust", CODE_FOLDER_DIR], {}, async () => {
test("should redirect to the passed in folder using human-readable query", async ({ codeServerPage }) => {
const url = new URL(codeServerPage.page.url())
const pathname = getMaybeProxiedPathname(url)
expect(pathname).toBe("/")
expect(url.search).toBe(`?folder=${CODE_FOLDER_DIR}`)
})
})
describe(
"VS Code Routes with ignore-last-opened",
["--disable-workspace-trust", "--ignore-last-opened"],
{},
async () => {
test("should not redirect", async ({ codeServerPage }) => {
const folder = process.env.CODE_FOLDER_DIR
await codeServerPage.navigate(`/?folder=${folder}`)
await codeServerPage.navigate(`/`)
const url = new URL(codeServerPage.page.url())
const pathname = getMaybeProxiedPathname(url)
expect(pathname).toBe("/")
expect(url.search).toBe("")
})
},
)
describe("VS Code Routes with no workspace or folder", ["--disable-workspace-trust"], {}, async () => {
test("should redirect to last query folder/workspace", async ({ codeServerPage }) => {
const folder = process.env.CODE_FOLDER_DIR
const workspace = process.env.CODE_WORKSPACE_DIR
await codeServerPage.navigate(`/?folder=${folder}&workspace=${workspace}`)
// If you visit again without query parameters it will re-attach them by
// redirecting. It should always redirect to the same route.
for (const route of routes) {
await codeServerPage.navigate(route)
const url = new URL(codeServerPage.page.url())
const pathname = getMaybeProxiedPathname(url)
expect(pathname).toBe(route)
expect(url.search).toBe(`?folder=${folder}&workspace=${workspace}`)
}
})
})
describe("VS Code Routes with no workspace or folder", ["--disable-workspace-trust"], {}, async () => {
test("should not redirect if ew passed in", async ({ codeServerPage }) => {
const folder = process.env.CODE_FOLDER_DIR
const workspace = process.env.CODE_WORKSPACE_DIR
await codeServerPage.navigate(`/?folder=${folder}&workspace=${workspace}`)
// Closing the folder should stop the redirecting.
await codeServerPage.navigate("/?ew=true")
let url = new URL(codeServerPage.page.url())
const pathname = getMaybeProxiedPathname(url)
expect(pathname).toBe("/")
expect(url.search).toBe("?ew=true")
})
})

View File

@@ -1,13 +0,0 @@
import { describe, test, expect } from "./baseFixture"
describe("Workspace trust (enabled)", [], {}, async () => {
test("should see the 'I Trust...' option", async ({ codeServerPage }) => {
expect(await codeServerPage.page.isVisible("text=Yes, I trust")).toBe(true)
})
})
describe("Workspace trust (disabled)", ["--disable-workspace-trust"], {}, async () => {
test("should not see the 'I Trust...' option", async ({ codeServerPage }) => {
expect(await codeServerPage.page.isVisible("text=Yes, I trust")).toBe(false)
})
})

View File

@@ -1,5 +1,6 @@
import { promises as fs } from "fs"
import { clean, getAvailablePort, tmpdir, useEnv } from "../../test/utils/helpers"
import { clean, getAvailablePort, getMaybeProxiedPathname, tmpdir, useEnv } from "../../test/utils/helpers"
import { REVERSE_PROXY_BASE_PATH } from "../utils/constants"
/**
* This file is for testing test helpers (not core code).
@@ -56,3 +57,22 @@ describe("getAvailablePort", () => {
expect(portOne).not.toEqual(portTwo)
})
})
describe("getMaybeProxiedPathname", () => {
it("should return the route", () => {
const route = "/vscode"
const url = new URL(`http://localhost:3000${route}`)
const actual = getMaybeProxiedPathname(url)
expect(actual).toBe(route)
})
it("should strip proxy if env var set", () => {
const envKey = "USE_PROXY"
const [setValue, resetValue] = useEnv(envKey)
setValue("1")
const route = "/vscode"
const url = new URL(`http://localhost:3000/8000/${REVERSE_PROXY_BASE_PATH}${route}`)
const actual = getMaybeProxiedPathname(url)
expect(actual).toBe(route)
resetValue()
})
})

View File

@@ -297,26 +297,6 @@ describe("parser", () => {
})
})
it("should override with --link", async () => {
const args = parse(
"--cert test --cert-key test --socket test --socket-mode 777 --host 0.0.0.0 --port 8888 --link test".split(" "),
)
const defaultArgs = await setDefaults(args)
expect(defaultArgs).toEqual({
...defaults,
auth: "none",
host: "localhost",
link: {
value: "test",
},
port: 0,
cert: undefined,
"cert-key": path.resolve("test"),
socket: undefined,
"socket-mode": undefined,
})
})
it("should use env var password", async () => {
process.env.PASSWORD = "test"
const args = parse([])
@@ -881,21 +861,13 @@ describe("optionDescriptions", () => {
it("should show if an option is deprecated", () => {
const opts: Partial<Options<Required<UserProvidedArgs>>> = {
link: {
cert: {
type: OptionalString,
description: `
Securely bind code-server via our cloud service with the passed name. You'll get a URL like
https://hostname-username.coder.co at which you can easily access your code-server instance.
Authorization is done via GitHub.
`,
description: "foo",
deprecated: true,
},
}
expect(optionDescriptions(opts)).toStrictEqual([
` --link (deprecated) Securely bind code-server via our cloud service with the passed name. You'll get a URL like
https://hostname-username.coder.co at which you can easily access your code-server instance.
Authorization is done via GitHub.`,
])
expect(optionDescriptions(opts)).toStrictEqual([" --cert (deprecated) foo"])
})
it("should show newlines in description", () => {

View File

@@ -138,5 +138,16 @@ describe("login", () => {
expect(resp.status).toBe(200)
expect(htmlContent).toContain(`Welcome to ${appName}`)
})
it("should return correct welcome text when locale is set to non-English", async () => {
process.env.PASSWORD = previousEnvPassword
const locale = "zh-cn"
const codeServer = await integration.setup([`--locale=${locale}`], "")
const resp = await codeServer.fetch("/login", { method: "GET" })
const htmlContent = await resp.text()
expect(resp.status).toBe(200)
expect(htmlContent).toContain(`欢迎来到 code-server`)
})
})
})

View File

@@ -1,137 +0,0 @@
import { promises as fs } from "fs"
import * as path from "path"
import { clean, tmpdir } from "../../../utils/helpers"
import * as httpserver from "../../../utils/httpserver"
import * as integration from "../../../utils/integration"
// TODO@jsjoeio - move these to integration tests since they rely on Code
// to be built
describe("vscode", () => {
let codeServer: httpserver.HttpServer | undefined
const testName = "vscode"
beforeAll(async () => {
await clean(testName)
})
afterEach(async () => {
if (codeServer) {
await codeServer.dispose()
codeServer = undefined
}
})
const routes = ["/", "/vscode", "/vscode/"]
it("should load all route variations", async () => {
codeServer = await integration.setup(["--auth=none"], "")
for (const route of routes) {
const resp = await codeServer.fetch(route)
expect(resp.status).toBe(200)
const html = await resp.text()
const url = new URL(resp.url) // Check there were no redirections.
expect(url.pathname + url.search).toBe(route)
switch (route) {
case "/":
case "/vscode/":
expect(html).toMatch(/src="\.\/[a-z]+-[0-9a-z]+\/static\//)
break
case "/vscode":
expect(html).toMatch(/src="\.\/vscode\/[a-z]+-[0-9a-z]+\/static\//)
break
}
}
})
it("should redirect to the passed in workspace using human-readable query", async () => {
const workspace = path.join(await tmpdir(testName), "test.code-workspace")
await fs.writeFile(workspace, "")
codeServer = await integration.setup(["--auth=none", workspace], "")
const resp = await codeServer.fetch("/")
const url = new URL(resp.url)
expect(url.pathname).toBe("/")
expect(url.search).toBe(`?workspace=${workspace}`)
})
it("should redirect to the passed in folder using human-readable query", async () => {
const folder = await tmpdir(testName)
codeServer = await integration.setup(["--auth=none", folder], "")
const resp = await codeServer.fetch("/")
const url = new URL(resp.url)
expect(url.pathname).toBe("/")
expect(url.search).toBe(`?folder=${folder}`)
})
it("should redirect to last query folder/workspace", async () => {
codeServer = await integration.setup(["--auth=none"], "")
const folder = await tmpdir(testName)
const workspace = path.join(await tmpdir(testName), "test.code-workspace")
await fs.writeFile(workspace, "")
let resp = await codeServer.fetch("/", undefined, {
folder,
workspace,
})
expect(resp.status).toBe(200)
await resp.text()
// If you visit again without query parameters it will re-attach them by
// redirecting. It should always redirect to the same route.
for (const route of routes) {
resp = await codeServer.fetch(route)
const url = new URL(resp.url)
expect(url.pathname).toBe(route)
expect(url.search).toBe(`?folder=${folder}&workspace=${workspace}`)
await resp.text()
}
// Closing the folder should stop the redirecting.
resp = await codeServer.fetch("/", undefined, { ew: "true" })
let url = new URL(resp.url)
expect(url.pathname).toBe("/")
expect(url.search).toBe("?ew=true")
await resp.text()
resp = await codeServer.fetch("/")
url = new URL(resp.url)
expect(url.pathname).toBe("/")
expect(url.search).toBe("")
await resp.text()
})
it("should do nothing when nothing is passed in", async () => {
codeServer = await integration.setup(["--auth=none"], "")
const resp = await codeServer.fetch("/", undefined)
expect(resp.status).toBe(200)
const url = new URL(resp.url)
expect(url.search).toBe("")
await resp.text()
})
it("should not redirect when last opened is ignored", async () => {
codeServer = await integration.setup(["--auth=none", "--ignore-last-opened"], "")
const folder = await tmpdir(testName)
const workspace = path.join(await tmpdir(testName), "test.code-workspace")
await fs.writeFile(workspace, "")
let resp = await codeServer.fetch("/", undefined, {
folder,
workspace,
})
expect(resp.status).toBe(200)
await resp.text()
// No redirections.
resp = await codeServer.fetch("/")
const url = new URL(resp.url)
expect(url.pathname).toBe("/")
expect(url.search).toBe("")
await resp.text()
})
})

View File

@@ -1,6 +1,8 @@
import { workspaceDir } from "./constants"
import { clean } from "./helpers"
import { clean, tmpdir } from "./helpers"
import * as wtfnode from "./wtfnode"
import * as path from "path"
import { promises as fs } from "fs"
/**
* Perform workspace cleanup and authenticate. This should be ran before e2e
@@ -17,5 +19,14 @@ export default async function () {
wtfnode.setup()
}
// Create dummy code-workspace for routes.test.ts
const codeWorkspace = path.join(await tmpdir(workspaceDir), "test.code-workspace")
await fs.writeFile(codeWorkspace, "")
process.env.CODE_WORKSPACE_DIR = codeWorkspace
// Create dummy folder for routes.test.ts
const folder = await tmpdir(workspaceDir)
process.env.CODE_FOLDER_DIR = folder
console.log("✅ Global Setup for Playwright End-to-End Tests is now complete.")
}

View File

@@ -136,3 +136,17 @@ export async function getMaybeProxiedCodeServer(codeServer: CodeServerPage | Cod
return address
}
/**
* Stripes proxy base from url.pathname
* i.e. /<port>/ide + route returns just route
*/
export function getMaybeProxiedPathname(url: URL): string {
if (process.env.USE_PROXY === "1") {
// Behind proxy, path will be /<port>/ide + route
const pathWithoutProxy = url.pathname.split(`/${REVERSE_PROXY_BASE_PATH}`)[1]
return pathWithoutProxy
}
return url.pathname
}

View File

@@ -22,7 +22,8 @@
"./test/node_modules/@types",
"./lib/vscode/src/vs/server/@types"
],
"downlevelIteration": true
"downlevelIteration": true,
"resolveJsonModule": true
},
"include": ["./src/**/*"],
"exclude": ["/test", "/lib", "/ci", "/doc"]

157
yarn.lock
View File

@@ -2,6 +2,13 @@
# yarn lockfile v1
"@babel/runtime@^7.20.6":
version "7.20.7"
resolved "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd"
integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==
dependencies:
regenerator-runtime "^0.13.11"
"@coder/logger@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-3.0.0.tgz#fd4d2332ca375412c75cb5ba7767d3290b106dec"
@@ -329,15 +336,17 @@
"@types/node" "*"
"@typescript-eslint/eslint-plugin@^5.41.0":
version "5.41.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.41.0.tgz#f8eeb1c6bb2549f795f3ba71aec3b38d1ab6b1e1"
integrity sha512-DXUS22Y57/LAFSg3x7Vi6RNAuLpTXwxB9S2nIA7msBb/Zt8p7XqMwdpdc1IU7CkOQUPgAqR5fWvxuKCbneKGmA==
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.51.0.tgz#da3f2819633061ced84bb82c53bba45a6fe9963a"
integrity sha512-wcAwhEWm1RgNd7dxD/o+nnLW8oH+6RK1OGnmbmkj/GGoDPV1WWMVP0FXYQBivKHdwM1pwii3bt//RC62EriIUQ==
dependencies:
"@typescript-eslint/scope-manager" "5.41.0"
"@typescript-eslint/type-utils" "5.41.0"
"@typescript-eslint/utils" "5.41.0"
"@typescript-eslint/scope-manager" "5.51.0"
"@typescript-eslint/type-utils" "5.51.0"
"@typescript-eslint/utils" "5.51.0"
debug "^4.3.4"
grapheme-splitter "^1.0.4"
ignore "^5.2.0"
natural-compare-lite "^1.4.0"
regexpp "^3.2.0"
semver "^7.3.7"
tsutils "^3.21.0"
@@ -360,13 +369,21 @@
"@typescript-eslint/types" "5.41.0"
"@typescript-eslint/visitor-keys" "5.41.0"
"@typescript-eslint/type-utils@5.41.0":
version "5.41.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.41.0.tgz#2371601171e9f26a4e6da918a7913f7266890cdf"
integrity sha512-L30HNvIG6A1Q0R58e4hu4h+fZqaO909UcnnPbwKiN6Rc3BUEx6ez2wgN7aC0cBfcAjZfwkzE+E2PQQ9nEuoqfA==
"@typescript-eslint/scope-manager@5.51.0":
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.51.0.tgz#ad3e3c2ecf762d9a4196c0fbfe19b142ac498990"
integrity sha512-gNpxRdlx5qw3yaHA0SFuTjW4rxeYhpHxt491PEcKF8Z6zpq0kMhe0Tolxt0qjlojS+/wArSDlj/LtE69xUJphQ==
dependencies:
"@typescript-eslint/typescript-estree" "5.41.0"
"@typescript-eslint/utils" "5.41.0"
"@typescript-eslint/types" "5.51.0"
"@typescript-eslint/visitor-keys" "5.51.0"
"@typescript-eslint/type-utils@5.51.0":
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.51.0.tgz#7af48005531700b62a20963501d47dfb27095988"
integrity sha512-QHC5KKyfV8sNSyHqfNa0UbTbJ6caB8uhcx2hYcWVvJAZYJRBo5HyyZfzMdRx8nvS+GyMg56fugMzzWnojREuQQ==
dependencies:
"@typescript-eslint/typescript-estree" "5.51.0"
"@typescript-eslint/utils" "5.51.0"
debug "^4.3.4"
tsutils "^3.21.0"
@@ -375,6 +392,11 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.41.0.tgz#6800abebc4e6abaf24cdf220fb4ce28f4ab09a85"
integrity sha512-5BejraMXMC+2UjefDvrH0Fo/eLwZRV6859SXRg+FgbhA0R0l6lDqDGAQYhKbXhPN2ofk2kY5sgGyLNL907UXpA==
"@typescript-eslint/types@5.51.0":
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.51.0.tgz#e7c1622f46c7eea7e12bbf1edfb496d4dec37c90"
integrity sha512-SqOn0ANn/v6hFn0kjvLwiDi4AzR++CBZz0NV5AnusT2/3y32jdc0G4woXPWHCumWtUXZKPAS27/9vziSsC9jnw==
"@typescript-eslint/typescript-estree@5.41.0":
version "5.41.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.41.0.tgz#bf5c6b3138adbdc73ba4871d060ae12c59366c61"
@@ -388,16 +410,29 @@
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.41.0":
version "5.41.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.41.0.tgz#f41ae5883994a249d00b2ce69f4188f3a23fa0f9"
integrity sha512-QlvfwaN9jaMga9EBazQ+5DDx/4sAdqDkcs05AsQHMaopluVCUyu1bTRUVKzXbgjDlrRAQrYVoi/sXJ9fmG+KLQ==
"@typescript-eslint/typescript-estree@5.51.0":
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.51.0.tgz#0ec8170d7247a892c2b21845b06c11eb0718f8de"
integrity sha512-TSkNupHvNRkoH9FMA3w7TazVFcBPveAAmb7Sz+kArY6sLT86PA5Vx80cKlYmd8m3Ha2SwofM1KwraF24lM9FvA==
dependencies:
"@typescript-eslint/types" "5.51.0"
"@typescript-eslint/visitor-keys" "5.51.0"
debug "^4.3.4"
globby "^11.1.0"
is-glob "^4.0.3"
semver "^7.3.7"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.51.0":
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.51.0.tgz#074f4fabd5b12afe9c8aa6fdee881c050f8b4d47"
integrity sha512-76qs+5KWcaatmwtwsDJvBk4H76RJQBFe+Gext0EfJdC3Vd2kpY2Pf//OHHzHp84Ciw0/rYoGTDnIAr3uWhhJYw==
dependencies:
"@types/json-schema" "^7.0.9"
"@types/semver" "^7.3.12"
"@typescript-eslint/scope-manager" "5.41.0"
"@typescript-eslint/types" "5.41.0"
"@typescript-eslint/typescript-estree" "5.41.0"
"@typescript-eslint/scope-manager" "5.51.0"
"@typescript-eslint/types" "5.51.0"
"@typescript-eslint/typescript-estree" "5.51.0"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
semver "^7.3.7"
@@ -410,6 +445,14 @@
"@typescript-eslint/types" "5.41.0"
eslint-visitor-keys "^3.3.0"
"@typescript-eslint/visitor-keys@5.51.0":
version "5.51.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.51.0.tgz#c0147dd9a36c0de758aaebd5b48cae1ec59eba87"
integrity sha512-Oh2+eTdjHjOFjKA27sxESlA87YPSOJafGCR0md5oeMdh1ZcCfAGCIOL216uTBAkAIptvLIfKQhl7lHxMJet4GQ==
dependencies:
"@typescript-eslint/types" "5.51.0"
eslint-visitor-keys "^3.3.0"
JSONStream@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
@@ -505,10 +548,10 @@ arg@^4.1.0:
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
argon2@0.30.2:
version "0.30.2"
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.30.2.tgz#b308a039d6d0cda5a3c47cbddd12685f033c33fa"
integrity sha512-RBbXTUsrJUQH259/72CCJxQa0hV961pV4PyZ7R1czGkArSsQP4DToCS2axmNfHywXaBNEMPWMW6rM82EArulYA==
argon2@0.30.3:
version "0.30.3"
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.30.3.tgz#795ca57acad76fc67dd5695732662a03018b84ed"
integrity sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.10"
"@phc/format" "^1.0.0"
@@ -851,10 +894,10 @@ debug@3.1.0:
dependencies:
ms "2.0.0"
debug@4, debug@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
debug@4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
@@ -865,13 +908,6 @@ debug@^3.2.7:
dependencies:
ms "^2.1.1"
debug@^4.0.0, debug@^4.1.1, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
@@ -1134,9 +1170,9 @@ escodegen@^1.8.1:
source-map "~0.6.1"
eslint-config-prettier@^8.5.0:
version "8.5.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
version "8.6.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207"
integrity sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==
eslint-import-resolver-node@^0.3.6:
version "0.3.6"
@@ -1814,6 +1850,13 @@ https-proxy-agent@5, https-proxy-agent@^5.0.0:
agent-base "6"
debug "4"
i18next@^22.4.6:
version "22.4.6"
resolved "https://registry.npmmirror.com/i18next/-/i18next-22.4.6.tgz#876352c3ba81bdfedc38eeda124e2bbd05f46988"
integrity sha512-9Tm1ezxWyzV+306CIDMBbYBitC1jedQyYuuLtIv7oxjp2ohh8eyxP9xytIf+2bbQfhH784IQKPSYp+Zq9+YSbw==
dependencies:
"@babel/runtime" "^7.20.6"
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -2090,9 +2133,9 @@ json-stable-stringify-without-jsonify@^1.0.1:
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
version "1.0.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
dependencies:
minimist "^1.2.0"
@@ -2108,6 +2151,11 @@ jsonparse@^1.2.0:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
just-performance@4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/just-performance/-/just-performance-4.3.0.tgz#cc2bc8c9227f09e97b6b1df4cd0de2df7ae16db1"
integrity sha512-L7RjvtJsL0QO8xFs5wEoDDzzJwoiowRw6Rn/GnvldlchS2JQr9wFYPiwZcDfrbbujEKqKN0tvENdbjXdYhDp5Q==
levn@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
@@ -2124,10 +2172,12 @@ levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
limiter@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2"
integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==
limiter@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/limiter/-/limiter-2.1.0.tgz#d38d7c5b63729bb84fb0c4d8594b7e955a5182a2"
integrity sha512-361TYz6iay6n+9KvUUImqdLuFigK+K79qrUtBsXhJTLdH4rIt/r1y8r1iozwh8KbZNpujbFTSh74mJ7bwbAMOw==
dependencies:
just-performance "4.3.0"
locate-path@^6.0.0:
version "6.0.0"
@@ -2466,6 +2516,11 @@ nanoid@^3.1.23, nanoid@^3.1.31:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
natural-compare-lite@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -2873,6 +2928,11 @@ readline-transform@1.0.0:
resolved "https://registry.yarnpkg.com/readline-transform/-/readline-transform-1.0.0.tgz#3157f97428acaec0f05a5c1ff2c3120f4e6d904b"
integrity sha512-7KA6+N9IGat52d83dvxnApAWN+MtVb1MiVuMR/cf1O4kYsJG+g/Aav0AHcHKsb6StinayfPLne0+fMX2sOzAKg==
regenerator-runtime@^0.13.11:
version "0.13.11"
resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
regexp.prototype.flags@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
@@ -3023,14 +3083,7 @@ semver@^6.0.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.0.0, semver@^7.1.3, semver@^7.3.5:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
semver@^7.3.7:
semver@^7.0.0, semver@^7.1.3, semver@^7.3.5, semver@^7.3.7:
version "7.3.8"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==