Compare commits
1 Commits
main
...
watcher-im
Author | SHA1 | Date |
---|---|---|
Teffen Ellis | f47abdfd27 |
|
@ -3,4 +3,9 @@ root = true
|
||||||
[*]
|
[*]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# The indent size used in the `package.json` file cannot be changed
|
||||||
|
# https://github.com/npm/npm/pull/3180#issuecomment-16336516
|
||||||
|
[{*.yml,*.yaml,package.json}]
|
||||||
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
|
@ -36,8 +36,11 @@ rules:
|
||||||
import/order:
|
import/order:
|
||||||
[error, { alphabetize: { order: "asc" }, groups: [["builtin", "external", "internal"], "parent", "sibling"] }]
|
[error, { alphabetize: { order: "asc" }, groups: [["builtin", "external", "internal"], "parent", "sibling"] }]
|
||||||
no-async-promise-executor: off
|
no-async-promise-executor: off
|
||||||
|
# This isn't a real module, just types, which apparently doesn't resolve.
|
||||||
|
import/no-unresolved: [error, { ignore: ["express-serve-static-core"] }]
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
import/resolver:
|
# Does not work with CommonJS unfortunately.
|
||||||
typescript:
|
import/ignore:
|
||||||
alwaysTryTypes: true
|
- env-paths
|
||||||
|
- xdg-basedir
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
* @coder/code-server-reviewers
|
* @cdr/code-server-reviewers
|
||||||
|
|
||||||
ci/helm-chart/ @Matthew-Beckett @alexgorbatchev
|
ci/helm-chart/ @Matthew-Beckett @alexgorbatchev
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Report a bug and help us improve
|
||||||
|
title: ""
|
||||||
|
labels: ""
|
||||||
|
assignees: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Hi there! 👋
|
||||||
|
|
||||||
|
Thanks for reporting a bug.
|
||||||
|
|
||||||
|
Please search for existing issues before filing, as they may contain additional
|
||||||
|
information about the problem and descriptions of workarounds. Provide as much
|
||||||
|
information as you can, so that we can reproduce the issue. Otherwise, we may
|
||||||
|
not be able to help diagnose the problem, and may close the issue as
|
||||||
|
unreproducible or incomplete. For visual defects, please include screenshots to
|
||||||
|
help us understand the issue.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## OS/Web Information
|
||||||
|
|
||||||
|
- Web Browser:
|
||||||
|
- Local OS:
|
||||||
|
- Remote OS:
|
||||||
|
- Remote Architecture:
|
||||||
|
- `code-server --version`:
|
||||||
|
|
||||||
|
## Steps to Reproduce
|
||||||
|
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
## Expected
|
||||||
|
|
||||||
|
<!-- What should happen? -->
|
||||||
|
|
||||||
|
## Actual
|
||||||
|
|
||||||
|
<!-- What actually happens? -->
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
|
||||||
|
<!--
|
||||||
|
First run code-server with at least debug logging (or trace to be really
|
||||||
|
thorough) by setting the --log flag or the LOG_LEVEL environment variable. -vvv
|
||||||
|
and --verbose are aliases for --log trace. For example:
|
||||||
|
|
||||||
|
code-server --log debug
|
||||||
|
|
||||||
|
Once this is done, replicate the issue you're having then collect logging
|
||||||
|
information from the following places:
|
||||||
|
|
||||||
|
1. The most recent files from ~/.local/share/code-server/coder-logs.
|
||||||
|
2. The browser console.
|
||||||
|
3. The browser network tab.
|
||||||
|
|
||||||
|
Additionally, collecting core dumps (you may need to enable them first) if
|
||||||
|
code-server crashes can be helpful.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If you're having issues with installation please include the installation logs
|
||||||
|
i.e. the output of `yarn global add code-server` if you installed with `yarn`
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Screenshot
|
||||||
|
|
||||||
|
<!-- Ideally provide a screenshot, gif, video or screen recording. -->
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
<!-- If you can reproduce the issue on vanilla VS Code,
|
||||||
|
please file the issue at the VS Code repository instead. -->
|
||||||
|
|
||||||
|
This issue can be reproduced in VS Code: Yes/No
|
|
@ -1,86 +0,0 @@
|
||||||
name: Bug report
|
|
||||||
description: File a bug report
|
|
||||||
title: "[Bug]: "
|
|
||||||
labels: ["bug", "triage"]
|
|
||||||
body:
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Is there an existing issue for this?
|
|
||||||
description: Please search to see if an issue already exists for the bug you encountered.
|
|
||||||
options:
|
|
||||||
- label: I have searched the existing issues
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: OS/Web Information
|
|
||||||
description: |
|
|
||||||
examples:
|
|
||||||
- **Web Browser**: Chrome
|
|
||||||
- **Local OS**: macOS
|
|
||||||
- **Remote OS**: Ubuntu
|
|
||||||
- **Remote Architecture**: amd64
|
|
||||||
- **`code-server --version`**: 4.0.1
|
|
||||||
value: |
|
|
||||||
- Web Browser:
|
|
||||||
- Local OS:
|
|
||||||
- Remote OS:
|
|
||||||
- Remote Architecture:
|
|
||||||
- `code-server --version`:
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Steps to Reproduce
|
|
||||||
description: |
|
|
||||||
1. open code-server
|
|
||||||
2. install extension
|
|
||||||
3. run command
|
|
||||||
value: |
|
|
||||||
1.
|
|
||||||
2.
|
|
||||||
3.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Expected
|
|
||||||
description: What should happen?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Actual
|
|
||||||
description: What actually happens?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Logs
|
|
||||||
description: Run code-server with the --verbose flag and then paste any relevant logs from the server, from the browser console and/or the browser network tab. For issues with installation, include installation logs (i.e. output of `yarn global add code-server`).
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Screenshot/Video
|
|
||||||
description: Please include a screenshot, gif or screen recording of your issue.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Does this issue happen in VS Code?
|
|
||||||
description: Please try reproducing this issue in VS Code
|
|
||||||
options:
|
|
||||||
- label: I cannot reproduce this in VS Code.
|
|
||||||
required: true
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Are you accessing code-server over HTTPS?
|
|
||||||
description: code-server relies on service workers for many features. Double-check that you are using HTTPS.
|
|
||||||
options:
|
|
||||||
- label: I am using HTTPS.
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Notes
|
|
||||||
description: Please include any addition notes that will help us resolve this issue.
|
|
||||||
validations:
|
|
||||||
required: false
|
|
|
@ -1,8 +1,8 @@
|
||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Question?
|
- name: Question
|
||||||
url: https://github.com/coder/code-server/discussions/new?category_id=22503114
|
url: https://github.com/cdr/code-server/discussions/new?category_id=22503114
|
||||||
about: Ask the community for help on our GitHub Discussions board
|
about: Ask the community for help on our GitHub Discussions board
|
||||||
- name: code-server Slack Community
|
- name: Chat
|
||||||
about: Need immediate help or just want to talk? Hop in our Slack. Note - this Slack is not actively monitored by code-server maintainers.
|
about: Need immediate help or just want to talk? Hop in our Slack
|
||||||
url: https://cdr.co/join-community
|
url: https://cdr.co/join-community
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
---
|
---
|
||||||
name: Documentation improvement
|
name: Documentation improvement
|
||||||
about: Suggest a documentation improvement
|
about: Suggest a documentation improvement
|
||||||
title: "[Docs]: "
|
title: ""
|
||||||
labels: "docs"
|
labels: "docs"
|
||||||
assignees: "@jsjoeio"
|
assignees: ""
|
||||||
---
|
---
|
||||||
|
|
||||||
## What is your suggestion?
|
|
||||||
|
|
||||||
## How will this improve the docs?
|
|
||||||
|
|
||||||
## Are you interested in submitting a PR for this?
|
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
---
|
---
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Suggest an idea to improve code-server
|
about: Suggest an idea
|
||||||
title: "[Feat]: "
|
title: ""
|
||||||
labels: enhancement
|
labels: feature
|
||||||
assignees: ""
|
assignees: ""
|
||||||
---
|
---
|
||||||
|
|
||||||
## What is your suggestion?
|
<!--
|
||||||
|
Please search for existing issues before filing.
|
||||||
|
|
||||||
## Why do you want this feature?
|
Please describe the feature as clearly as possible!
|
||||||
|
-->
|
||||||
## Are there any workarounds to get this functionality today?
|
|
||||||
|
|
||||||
## Are you interested in submitting a PR for this?
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
name: Release
|
||||||
|
about: "*For maintainers only*"
|
||||||
|
title: "release: 0.0.0"
|
||||||
|
labels: ""
|
||||||
|
assignees: "@cdr/code-server-reviewers"
|
||||||
|
---
|
||||||
|
|
||||||
|
<!-- Maintainer: fill out the checklist -->
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Assign to next release manager
|
||||||
|
- [ ] Close previous release milestone
|
||||||
|
- [ ] Create next release milestone
|
||||||
|
- [ ] Associate issue with next release milestone
|
|
@ -8,14 +8,6 @@ coverage:
|
||||||
range: "40...70"
|
range: "40...70"
|
||||||
status:
|
status:
|
||||||
patch: off
|
patch: off
|
||||||
notify:
|
|
||||||
slack:
|
|
||||||
default:
|
|
||||||
url: secret:v1::tXC7VwEIKYjNU8HRgRv2GdKOSCt5UzpykKZb+o1eCDqBgb2PEqwE3A26QUPYMLo4BO2qtrJhFIvwhUvlPwyzDCNGoNiuZfXr0UeZZ0y1TcZu672R/NBNMwEPO/e1Ye0pHxjzKHnuH7HqbjFucox/RBQLtiL3J56SWGE3JtbkC6o=
|
|
||||||
threshold: 1%
|
|
||||||
only_pulls: false
|
|
||||||
branches:
|
|
||||||
- "main"
|
|
||||||
|
|
||||||
parsers:
|
parsers:
|
||||||
gcov:
|
gcov:
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
###############################################################################
|
|
||||||
# This file configures "Semantic Pull Requests", which is documented here:
|
|
||||||
# https://github.com/zeke/semantic-pull-requests
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
# Scopes are optionally supplied after a 'type'. For example, in
|
|
||||||
#
|
|
||||||
# feat(docs): autostart ui
|
|
||||||
#
|
|
||||||
# '(docs)' is the scope. Scopes are used to signify where the change occurred.
|
|
||||||
scopes:
|
|
||||||
# docs: changes to the code-server documentation.
|
|
||||||
- docs
|
|
||||||
|
|
||||||
# vendor: changes to vendored dependencies.
|
|
||||||
- vendor
|
|
||||||
|
|
||||||
# deps: changes to code-server's dependencies.
|
|
||||||
- deps
|
|
||||||
|
|
||||||
# cs: changes to code specific to code-server.
|
|
||||||
- cs
|
|
||||||
|
|
||||||
# cli: changes to the command-line interface.
|
|
||||||
- cli
|
|
||||||
|
|
||||||
# We only check that the PR title is semantic. The PR title is automatically
|
|
||||||
# applied to the "Squash & Merge" flow as the suggested commit message, so this
|
|
||||||
# should suffice unless someone drastically alters the message in that flow.
|
|
||||||
titleOnly: true
|
|
||||||
|
|
||||||
# Types are the 'tag' types in a commit or PR title. For example, in
|
|
||||||
#
|
|
||||||
# chore: fix thing
|
|
||||||
#
|
|
||||||
# 'chore' is the type.
|
|
||||||
types:
|
|
||||||
# A build of any kind.
|
|
||||||
- build
|
|
||||||
|
|
||||||
# A user-facing change that corrects a defect in code-server.
|
|
||||||
- fix
|
|
||||||
|
|
||||||
# Any code task that is ignored for changelog purposes. Examples include
|
|
||||||
# devbin scripts and internal-only configurations.
|
|
||||||
- chore
|
|
||||||
|
|
||||||
# Any work performed on CI.
|
|
||||||
- ci
|
|
||||||
|
|
||||||
# Work that directly implements or supports the implementation of a feature.
|
|
||||||
- feat
|
|
||||||
|
|
||||||
# A refactor changes code structure without any behavioral change.
|
|
||||||
- refactor
|
|
||||||
|
|
||||||
# A git revert for any style of commit.
|
|
||||||
- revert
|
|
||||||
|
|
||||||
# Adding tests of any kind. Should be separate from feature or fix
|
|
||||||
# implementations. For example, if a commit adds a fix + test, it's a fix
|
|
||||||
# commit. If a commit is simply bumping coverage, it's a test commit.
|
|
||||||
- test
|
|
|
@ -34,7 +34,7 @@ jobs:
|
||||||
# NOTE@jsjoeio
|
# NOTE@jsjoeio
|
||||||
# disabling this until we can audit the build process
|
# disabling this until we can audit the build process
|
||||||
# and the usefulness of this step
|
# and the usefulness of this step
|
||||||
# See: https://github.com/coder/code-server/issues/4287
|
# See: https://github.com/cdr/code-server/issues/4287
|
||||||
# - name: Fetch dependencies from cache
|
# - name: Fetch dependencies from cache
|
||||||
# id: cache-yarn
|
# id: cache-yarn
|
||||||
# uses: actions/cache@v2
|
# uses: actions/cache@v2
|
||||||
|
@ -177,33 +177,6 @@ jobs:
|
||||||
name: npm-package
|
name: npm-package
|
||||||
path: ./package.tar.gz
|
path: ./package.tar.gz
|
||||||
|
|
||||||
npm:
|
|
||||||
# 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
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v2
|
|
||||||
id: download
|
|
||||||
with:
|
|
||||||
name: "npm-package"
|
|
||||||
path: release-npm-package
|
|
||||||
|
|
||||||
- name: Run ./ci/steps/publish-npm.sh
|
|
||||||
run: yarn publish:npm
|
|
||||||
env:
|
|
||||||
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
|
|
||||||
|
|
||||||
# TODO: cache building yarn --production
|
# TODO: cache building yarn --production
|
||||||
# possibly 2m30s of savings(?)
|
# possibly 2m30s of savings(?)
|
||||||
# this requires refactoring our release scripts
|
# this requires refactoring our release scripts
|
||||||
|
@ -455,7 +428,7 @@ jobs:
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Run Trivy vulnerability scanner in repo mode
|
- name: Run Trivy vulnerability scanner in repo mode
|
||||||
#Commit SHA for v0.0.17
|
#Commit SHA for v0.0.17
|
||||||
uses: aquasecurity/trivy-action@a7a829a4345428ddd92ca57b18257440f6a18c90
|
uses: aquasecurity/trivy-action@1ccef265f594a7555a720f623a461a3d69b45bf7
|
||||||
with:
|
with:
|
||||||
scan-type: "fs"
|
scan-type: "fs"
|
||||||
scan-ref: "."
|
scan-ref: "."
|
||||||
|
|
|
@ -6,15 +6,13 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
release:
|
release:
|
||||||
types:
|
types: [released]
|
||||||
- released
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker-images:
|
docker-images:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v2
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
|
@ -22,13 +20,9 @@ jobs:
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Run ./ci/steps/docker-buildx-push.sh
|
- name: Run ./ci/steps/docker-buildx-push.sh
|
||||||
run: ./ci/steps/docker-buildx-push.sh
|
run: ./ci/steps/docker-buildx-push.sh
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
|
@ -21,7 +21,6 @@ jobs:
|
||||||
preview:
|
preview:
|
||||||
name: Docs preview
|
name: Docs preview
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
environment: CI
|
|
||||||
steps:
|
steps:
|
||||||
- name: Cancel Previous Runs
|
- name: Cancel Previous Runs
|
||||||
uses: styfle/cancel-workflow-action@0.9.1
|
uses: styfle/cancel-workflow-action@0.9.1
|
||||||
|
@ -29,9 +28,9 @@ jobs:
|
||||||
- name: Checkout m
|
- name: Checkout m
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
repository: coder/m
|
repository: cdr/m
|
||||||
ref: refs/heads/master
|
ref: refs/heads/master
|
||||||
ssh-key: ${{ secrets.READONLY_M_DEPLOY_KEY }}
|
token: ${{ secrets.GH_ACCESS_TOKEN }}
|
||||||
submodules: true
|
submodules: true
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|
|
@ -16,18 +16,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
- uses: actions/download-artifact@v2
|
- name: Run ./ci/steps/publish-npm.sh
|
||||||
id: download
|
run: ./ci/steps/publish-npm.sh
|
||||||
with:
|
|
||||||
name: "npm-package"
|
|
||||||
path: release-npm-package
|
|
||||||
|
|
||||||
- name: Publish npm package and tag with "latest"
|
|
||||||
run: yarn publish:npm
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
NPM_ENVIRONMENT: "production"
|
|
||||||
|
|
||||||
homebrew:
|
homebrew:
|
||||||
# The newest version of code-server needs to be available on npm when this runs
|
# The newest version of code-server needs to be available on npm when this runs
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
{
|
{
|
||||||
"file": "src/node/heart.ts",
|
"file": "src/node/heart.ts",
|
||||||
"line": 7,
|
"line": 7,
|
||||||
"description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/master/docs/FAQ.md#heartbeat-file)"
|
"description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/cdr/code-server/blob/master/docs/FAQ.md#heartbeat-file](https://github.com/cdr/code-server/blob/master/docs/FAQ.md#heartbeat-file)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/node/socket.ts",
|
"file": "src/node/socket.ts",
|
||||||
|
@ -80,12 +80,12 @@
|
||||||
{
|
{
|
||||||
"file": "src/node/routes/domainProxy.ts",
|
"file": "src/node/routes/domainProxy.ts",
|
||||||
"line": 18,
|
"line": 18,
|
||||||
"description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
"description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/cdr/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/cdr/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/node/routes/pathProxy.ts",
|
"file": "src/node/routes/pathProxy.ts",
|
||||||
"line": 19,
|
"line": 19,
|
||||||
"description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
"description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/cdr/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/cdr/code-server/blob/master/docs/FAQ.md#how-do-i-securely-access-web-services)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/node/proxy.ts",
|
"file": "src/node/proxy.ts",
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
{
|
{
|
||||||
"file": "src/node/routes/health.ts",
|
"file": "src/node/routes/health.ts",
|
||||||
"line": 5,
|
"line": 5,
|
||||||
"description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/master/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/master/docs/FAQ.md#healthz-endpoint)"
|
"description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/cdr/code-server/blob/master/docs/FAQ.md#healthz-endpoint](https://github.com/cdr/code-server/blob/master/docs/FAQ.md#healthz-endpoint)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"file": "src/node/routes/login.ts",
|
"file": "src/node/routes/login.ts",
|
||||||
|
@ -145,7 +145,7 @@
|
||||||
{
|
{
|
||||||
"directory": "vendor/modules/code-oss-dev",
|
"directory": "vendor/modules/code-oss-dev",
|
||||||
"line": 1,
|
"line": 1,
|
||||||
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
|
"description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/cdr/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/cdr/code-server/blob/master/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
{
|
{
|
||||||
"file": "src/node/app.ts",
|
"file": "src/node/app.ts",
|
||||||
"line": 62,
|
"line": 62,
|
||||||
"description": "## That's it!\n\n\nThat's all there is to it! When this tour ends, your terminal session may stop, but just use `yarn watch` to start developing from here on out!\n\n\nIf you haven't already, be sure to check out these resources:\n- [Tour: Contributing](command:codetour.startTourByTitle?[\"Contributing\")\n- [Docs: FAQ.md](https://github.com/coder/code-server/blob/master/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/coder/code-server/blob/master/docs/CONTRIBUTING.md)\n- [Community: GitHub Discussions](https://github.com/coder/code-server/discussions)\n- [Community: Slack](https://community.coder.com)"
|
"description": "## That's it!\n\n\nThat's all there is to it! When this tour ends, your terminal session may stop, but just use `yarn watch` to start developing from here on out!\n\n\nIf you haven't already, be sure to check out these resources:\n- [Tour: Contributing](command:codetour.startTourByTitle?[\"Contributing\")\n- [Docs: FAQ.md](https://github.com/cdr/code-server/blob/master/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/cdr/code-server/blob/master/docs/CONTRIBUTING.md)\n- [Community: GitHub Discussions](https://github.com/cdr/code-server/discussions)\n- [Community: Slack](https://community.coder.com)"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
64
CHANGELOG.md
64
CHANGELOG.md
|
@ -20,26 +20,7 @@ VS Code v99.99.999
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## [Unreleased](https://github.com/coder/code-server/releases)
|
## [Unreleased](https://github.com/cdr/code-server/releases)
|
||||||
|
|
||||||
VS Code v0.00.0
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Add here
|
|
||||||
|
|
||||||
## [4.0.2](https://github.com/coder/code-server/releases/tag/v4.0.2) - 2022-01-27
|
|
||||||
|
|
||||||
VS Code v1.63.0
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Unset the `BROWSER` environment variable. This fixes applications that hard
|
|
||||||
exit when trying to spawn the helper script `BROWSER` points to because the
|
|
||||||
file is missing. While we do include the script now we are leaving the
|
|
||||||
variable omitted because the script does not work yet.
|
|
||||||
|
|
||||||
## [4.0.1](https://github.com/coder/code-server/releases/tag/v4.0.1) - 2022-01-04
|
|
||||||
|
|
||||||
VS Code v1.63.0
|
VS Code v1.63.0
|
||||||
|
|
||||||
|
@ -50,34 +31,15 @@ implementation (#4414).
|
||||||
|
|
||||||
- Web socket compression has been made the default (when supported). This means
|
- Web socket compression has been made the default (when supported). This means
|
||||||
the `--enable` flag will no longer take `permessage-deflate` as an option.
|
the `--enable` flag will no longer take `permessage-deflate` as an option.
|
||||||
|
- Extra extension directories have been removed. The `--extra-extensions-dir`
|
||||||
|
and `--extra-builtin-extensions-dir` will no longer be accepted.
|
||||||
|
- The `--install-source` and `--locale` flags have been removed.
|
||||||
- The static endpoint can no longer reach outside code-server. However the
|
- The static endpoint can no longer reach outside code-server. However the
|
||||||
vscode-remote-resource endpoint still can.
|
vscode-remote-resource endpoint still can.
|
||||||
- OpenVSX has been made the default marketplace.
|
- OpenVSX has been made the default marketplace. However this means web
|
||||||
- The last opened folder/workspace is no longer stored separately in the
|
extensions like Vim are now broken.
|
||||||
settings file (we rely on the already-existing query object instead).
|
|
||||||
- The marketplace override environment variables `SERVICE_URL` and `ITEM_URL`
|
|
||||||
have been replaced with a single `EXTENSIONS_GALLERY` variable that
|
|
||||||
corresponds to `extensionsGallery` in VS Code's `product.json`.
|
|
||||||
|
|
||||||
### Added
|
## [3.12.0](https://github.com/cdr/code-server/releases/tag/v3.12.0) - 2021-09-15
|
||||||
|
|
||||||
- `VSCODE_PROXY_URI` env var for use in the terminal and extensions.
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- Extra extension directories have been removed. The `--extra-extensions-dir`
|
|
||||||
and `--extra-builtin-extensions-dir` flags will no longer be accepted.
|
|
||||||
- The `--install-source` flag has been removed.
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
- `--link` is now deprecated (#4562).
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
- We fixed a XSS vulnerability by escaping HTML from messages in the error page (#4430).
|
|
||||||
|
|
||||||
## [3.12.0](https://github.com/coder/code-server/releases/tag/v3.12.0) - 2021-09-15
|
|
||||||
|
|
||||||
VS Code v1.60.0
|
VS Code v1.60.0
|
||||||
|
|
||||||
|
@ -89,15 +51,15 @@ VS Code v1.60.0
|
||||||
|
|
||||||
- Fix logout when using a base path (#3608).
|
- Fix logout when using a base path (#3608).
|
||||||
|
|
||||||
## [3.11.1](https://github.com/coder/code-server/releases/tag/v3.11.1) - 2021-08-06
|
## [3.11.1](https://github.com/cdr/code-server/releases/tag/v3.11.1) - 2021-08-06
|
||||||
|
|
||||||
Undocumented (see releases page).
|
Undocumented (see releases page).
|
||||||
|
|
||||||
## [3.11.0](https://github.com/coder/code-server/releases/tag/v3.11.0) - 2021-06-14
|
## [3.11.0](https://github.com/cdr/code-server/releases/tag/v3.11.0) - 2021-06-14
|
||||||
|
|
||||||
Undocumented (see releases page).
|
Undocumented (see releases page).
|
||||||
|
|
||||||
## [3.10.2](https://github.com/coder/code-server/releases/tag/v3.10.2) - 2021-05-21
|
## [3.10.2](https://github.com/cdr/code-server/releases/tag/v3.10.2) - 2021-05-21
|
||||||
|
|
||||||
VS Code v1.56.1
|
VS Code v1.56.1
|
||||||
|
|
||||||
|
@ -113,7 +75,7 @@ VS Code v1.56.1
|
||||||
|
|
||||||
- Fix "Open Folder" on welcome page (#3437).
|
- Fix "Open Folder" on welcome page (#3437).
|
||||||
|
|
||||||
## [3.10.1](https://github.com/coder/code-server/releases/tag/v3.10.1) - 2021-05-17
|
## [3.10.1](https://github.com/cdr/code-server/releases/tag/v3.10.1) - 2021-05-17
|
||||||
|
|
||||||
VS Code v1.56.1
|
VS Code v1.56.1
|
||||||
|
|
||||||
|
@ -127,7 +89,7 @@ VS Code v1.56.1
|
||||||
|
|
||||||
- Use xdgBasedir.runtime instead of tmp (#3304).
|
- Use xdgBasedir.runtime instead of tmp (#3304).
|
||||||
|
|
||||||
## [3.10.0](https://github.com/coder/code-server/releases/tag/v3.10.0) - 2021-05-10
|
## [3.10.0](https://github.com/cdr/code-server/releases/tag/v3.10.0) - 2021-05-10
|
||||||
|
|
||||||
VS Code v1.56.0
|
VS Code v1.56.0
|
||||||
|
|
||||||
|
@ -158,4 +120,4 @@ VS Code v1.56.0
|
||||||
This was added with `3.10.0`, which means any previous versions are not
|
This was added with `3.10.0`, which means any previous versions are not
|
||||||
documented in the changelog.
|
documented in the changelog.
|
||||||
|
|
||||||
To see those, please visit the [Releases page](https://github.com/coder/code-server/releases).
|
To see those, please visit the [Releases page](https://github.com/cdr/code-server/releases).
|
||||||
|
|
|
@ -26,7 +26,7 @@ main() {
|
||||||
echo "Downloading the cloud agent..."
|
echo "Downloading the cloud agent..."
|
||||||
|
|
||||||
set +e
|
set +e
|
||||||
curl -fsSL "https://github.com/coder/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent
|
curl -fsSL "https://github.com/cdr/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent
|
||||||
chmod +x ./lib/coder-cloud-agent
|
chmod +x ./lib/coder-cloud-agent
|
||||||
set -e
|
set -e
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -82,13 +82,6 @@ bundle_vscode() {
|
||||||
mkdir -p "$VSCODE_OUT_PATH/resources/"
|
mkdir -p "$VSCODE_OUT_PATH/resources/"
|
||||||
rsync "$VSCODE_SRC_PATH/resources/" "$VSCODE_OUT_PATH/resources/"
|
rsync "$VSCODE_SRC_PATH/resources/" "$VSCODE_OUT_PATH/resources/"
|
||||||
|
|
||||||
# TODO: We should look into using VS Code's packaging task (see
|
|
||||||
# gulpfile.reh.js). For now copy this directory into the right spot (for some
|
|
||||||
# reason VS Code uses a different path in production).
|
|
||||||
mkdir -p "$VSCODE_OUT_PATH/bin/helpers"
|
|
||||||
rsync "$VSCODE_SRC_PATH/resources/server/bin/helpers/" "$VSCODE_OUT_PATH/bin/helpers"
|
|
||||||
chmod +x "$VSCODE_OUT_PATH/bin/helpers/browser.sh"
|
|
||||||
|
|
||||||
# Add the commit and date and enable telemetry. This just makes telemetry
|
# Add the commit and date and enable telemetry. This just makes telemetry
|
||||||
# available; telemetry can still be disabled by flag or setting.
|
# available; telemetry can still be disabled by flag or setting.
|
||||||
jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
|
jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
|
||||||
|
@ -97,8 +90,7 @@ bundle_vscode() {
|
||||||
"enableTelemetry": true,
|
"enableTelemetry": true,
|
||||||
"commit": "$(cd "$VSCODE_SRC_PATH" && git rev-parse HEAD)",
|
"commit": "$(cd "$VSCODE_SRC_PATH" && git rev-parse HEAD)",
|
||||||
"quality": "stable",
|
"quality": "stable",
|
||||||
"date": $(jq -n 'now | todate'),
|
"date": $(jq -n 'now | todate')
|
||||||
"codeServerVersion": "$VERSION"
|
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
) > "$VSCODE_OUT_PATH/product.json"
|
) > "$VSCODE_OUT_PATH/product.json"
|
||||||
|
|
|
@ -5,7 +5,7 @@ set -eu
|
||||||
# Runs code-server with the bundled node binary.
|
# Runs code-server with the bundled node binary.
|
||||||
|
|
||||||
_realpath() {
|
_realpath() {
|
||||||
# See https://github.com/coder/code-server/issues/1537 on why no realpath or readlink -f.
|
# See https://github.com/cdr/code-server/issues/1537 on why no realpath or readlink -f.
|
||||||
|
|
||||||
script="$1"
|
script="$1"
|
||||||
cd "$(dirname "$script")"
|
cd "$(dirname "$script")"
|
||||||
|
@ -16,7 +16,7 @@ _realpath() {
|
||||||
&& cat package.json | grep -q '^ "name": "code-server",$'; then
|
&& cat package.json | grep -q '^ "name": "code-server",$'; then
|
||||||
echo "***** Please use the script in bin/code-server instead!" >&2
|
echo "***** Please use the script in bin/code-server instead!" >&2
|
||||||
echo "***** This script will soon be removed!" >&2
|
echo "***** This script will soon be removed!" >&2
|
||||||
echo "***** See the release notes at https://github.com/coder/code-server/releases/tag/v3.4.0" >&2
|
echo "***** See the release notes at https://github.com/cdr/code-server/releases/tag/v3.4.0" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
script="$(readlink "$(basename "$script")")"
|
script="$(readlink "$(basename "$script")")"
|
||||||
|
|
|
@ -8,7 +8,7 @@ maintainer: "Anmol Sethi <hi@nhooyr.io>"
|
||||||
description: |
|
description: |
|
||||||
Run VS Code in the browser.
|
Run VS Code in the browser.
|
||||||
vendor: "Coder"
|
vendor: "Coder"
|
||||||
homepage: "https://github.com/coder/code-server"
|
homepage: "https://github.com/cdr/code-server"
|
||||||
license: "MIT"
|
license: "MIT"
|
||||||
|
|
||||||
contents:
|
contents:
|
||||||
|
|
|
@ -60,7 +60,7 @@ main() {
|
||||||
|
|
||||||
mkdir -p ./lib
|
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
|
if curl -fsSL "https://github.com/cdr/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent; then
|
||||||
chmod +x ./lib/coder-cloud-agent
|
chmod +x ./lib/coder-cloud-agent
|
||||||
else
|
else
|
||||||
echo "Failed to download cloud agent; --link will not work"
|
echo "Failed to download cloud agent; --link will not work"
|
||||||
|
@ -68,7 +68,7 @@ main() {
|
||||||
|
|
||||||
if ! vscode_yarn; then
|
if ! vscode_yarn; then
|
||||||
echo "You may not have the required dependencies to build the native modules."
|
echo "You may not have the required dependencies to build the native modules."
|
||||||
echo "Please see https://github.com/coder/code-server/blob/master/docs/npm.md"
|
echo "Please see https://github.com/cdr/code-server/blob/master/docs/npm.md"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ main() {
|
||||||
download_artifact release-packages ./release-packages
|
download_artifact release-packages ./release-packages
|
||||||
local assets=(./release-packages/code-server*"$VERSION"*{.tar.gz,.deb,.rpm})
|
local assets=(./release-packages/code-server*"$VERSION"*{.tar.gz,.deb,.rpm})
|
||||||
|
|
||||||
EDITOR=true gh release upload "v$VERSION" "${assets[@]}" --clobber
|
EDITOR=true gh release upload "v$VERSION" "${assets[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
@ -83,14 +83,14 @@ main() {
|
||||||
echo -e "Great! We'll prep a PR for updating to $CODE_SERVER_VERSION_TO_UPDATE\n"
|
echo -e "Great! We'll prep a PR for updating to $CODE_SERVER_VERSION_TO_UPDATE\n"
|
||||||
$CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE"
|
$CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE"
|
||||||
|
|
||||||
$CMD git commit --no-verify -am "chore(release): bump version to $CODE_SERVER_VERSION_TO_UPDATE"
|
$CMD git commit -am "chore(release): bump version to $CODE_SERVER_VERSION_TO_UPDATE"
|
||||||
|
|
||||||
# This runs from the root so that's why we use this path vs. ../../
|
# This runs from the root so that's why we use this path vs. ../../
|
||||||
RELEASE_TEMPLATE_STRING=$(cat ./.github/PULL_REQUEST_TEMPLATE/release_template.md)
|
RELEASE_TEMPLATE_STRING=$(cat ./.github/PULL_REQUEST_TEMPLATE/release_template.md)
|
||||||
|
|
||||||
echo -e "\nOpening a draft PR on GitHub"
|
echo -e "\nOpening a draft PR on GitHub"
|
||||||
# To read about these flags, visit the docs: https://cli.github.com/manual/gh_pr_create
|
# To read about these flags, visit the docs: https://cli.github.com/manual/gh_pr_create
|
||||||
$CMD gh pr create --base main --title "release: $CODE_SERVER_VERSION_TO_UPDATE" --body "$RELEASE_TEMPLATE_STRING" --reviewer @coder/code-server-reviewers --repo coder/code-server --draft --assignee "@me"
|
$CMD gh pr create --base main --title "release: $CODE_SERVER_VERSION_TO_UPDATE" --body "$RELEASE_TEMPLATE_STRING" --reviewer @cdr/code-server-reviewers --repo cdr/code-server --draft --assignee "@me"
|
||||||
|
|
||||||
# Open PR in browser
|
# Open PR in browser
|
||||||
$CMD gh pr view --web
|
$CMD gh pr view --web
|
||||||
|
|
|
@ -3,30 +3,20 @@ set -euo pipefail
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/../.."
|
cd "$(dirname "$0")/../.."
|
||||||
source ./ci/lib.sh
|
|
||||||
|
|
||||||
pushd test
|
echo "Installing code-server test dependencies..."
|
||||||
echo "Installing dependencies for $PWD"
|
|
||||||
yarn install
|
|
||||||
popd
|
|
||||||
|
|
||||||
local args=(install)
|
local args=(install)
|
||||||
if [[ ${CI-} ]]; then
|
if [[ ${CI-} ]]; then
|
||||||
args+=(--frozen-lockfile)
|
args+=(--frozen-lockfile)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pushd test
|
cd test
|
||||||
echo "Installing dependencies for $PWD"
|
|
||||||
yarn "${args[@]}"
|
yarn "${args[@]}"
|
||||||
popd
|
cd ..
|
||||||
|
|
||||||
pushd test/e2e/extensions/test-extension
|
cd vendor
|
||||||
echo "Installing dependencies for $PWD"
|
echo "Installing vendor dependencies..."
|
||||||
yarn "${args[@]}"
|
|
||||||
popd
|
|
||||||
|
|
||||||
pushd vendor
|
|
||||||
echo "Installing dependencies for $PWD"
|
|
||||||
|
|
||||||
# We install in 'modules' instead of 'node_modules' because VS Code's
|
# We install in 'modules' instead of 'node_modules' because VS Code's
|
||||||
# extensions use a webpack config which cannot differentiate between its own
|
# extensions use a webpack config which cannot differentiate between its own
|
||||||
|
@ -43,8 +33,6 @@ main() {
|
||||||
|
|
||||||
# Finally, run the vendor `postinstall`
|
# Finally, run the vendor `postinstall`
|
||||||
yarn run postinstall
|
yarn run postinstall
|
||||||
|
|
||||||
popd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
@ -13,11 +13,6 @@ main() {
|
||||||
|
|
||||||
source ./ci/lib.sh
|
source ./ci/lib.sh
|
||||||
|
|
||||||
pushd test/e2e/extensions/test-extension
|
|
||||||
echo "Building test extension"
|
|
||||||
yarn build
|
|
||||||
popd
|
|
||||||
|
|
||||||
local dir="$PWD"
|
local dir="$PWD"
|
||||||
if [[ ! ${CODE_SERVER_TEST_ENTRY-} ]]; then
|
if [[ ! ${CODE_SERVER_TEST_ENTRY-} ]]; then
|
||||||
echo "Set CODE_SERVER_TEST_ENTRY to test another build of code-server"
|
echo "Set CODE_SERVER_TEST_ENTRY to test another build of code-server"
|
||||||
|
|
|
@ -6,7 +6,6 @@ main() {
|
||||||
|
|
||||||
source ./ci/lib.sh
|
source ./ci/lib.sh
|
||||||
|
|
||||||
echo "Building test plugin"
|
|
||||||
pushd test/unit/node/test-plugin
|
pushd test/unit/node/test-plugin
|
||||||
make -s out/index.js
|
make -s out/index.js
|
||||||
popd
|
popd
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { spawn, fork, ChildProcess } from "child_process"
|
import { spawn, fork, ChildProcess } from "child_process"
|
||||||
|
import del from "del"
|
||||||
|
import { promises as fs } from "fs"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { onLine, OnLineCallback } from "../../src/node/util"
|
import { CompilationStats, onLine, OnLineCallback, VSCodeCompileStatus } from "../../src/node/util"
|
||||||
|
|
||||||
interface DevelopmentCompilers {
|
interface DevelopmentCompilers {
|
||||||
[key: string]: ChildProcess | undefined
|
[key: string]: ChildProcess | undefined
|
||||||
|
@ -15,6 +17,7 @@ class Watcher {
|
||||||
private readonly paths = {
|
private readonly paths = {
|
||||||
/** Path to uncompiled VS Code source. */
|
/** Path to uncompiled VS Code source. */
|
||||||
vscodeDir: path.join(this.rootPath, "vendor", "modules", "code-oss-dev"),
|
vscodeDir: path.join(this.rootPath, "vendor", "modules", "code-oss-dev"),
|
||||||
|
compilationStatsFile: path.join(this.rootPath, "out", "watcher.json"),
|
||||||
pluginDir: process.env.PLUGIN_DIR,
|
pluginDir: process.env.PLUGIN_DIR,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,16 +52,24 @@ class Watcher {
|
||||||
plugins: this.paths.pluginDir ? spawn("yarn", ["build", "--watch"], { cwd: this.paths.pluginDir }) : undefined,
|
plugins: this.paths.pluginDir ? spawn("yarn", ["build", "--watch"], { cwd: this.paths.pluginDir }) : undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private vscodeCompileStatus = VSCodeCompileStatus.Loading
|
||||||
|
|
||||||
public async initialize(): Promise<void> {
|
public async initialize(): Promise<void> {
|
||||||
for (const event of ["SIGINT", "SIGTERM"]) {
|
for (const event of ["SIGINT", "SIGTERM"]) {
|
||||||
process.on(event, () => this.dispose(0))
|
process.on(event, () => this.dispose(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.hasVerboseLogging) {
|
||||||
|
console.log("\n[Watcher]", "Compiler logs will be minimal. Pass --log to show all output.")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cleanFiles()
|
||||||
|
|
||||||
for (const [processName, devProcess] of Object.entries(this.compilers)) {
|
for (const [processName, devProcess] of Object.entries(this.compilers)) {
|
||||||
if (!devProcess) continue
|
if (!devProcess) continue
|
||||||
|
|
||||||
devProcess.on("exit", (code) => {
|
devProcess.on("exit", (code) => {
|
||||||
console.log(`[${processName}]`, "Terminated unexpectedly")
|
this.log(`[${processName}]`, "Terminated unexpectedly")
|
||||||
this.dispose(code)
|
this.dispose(code)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -80,13 +91,33 @@ class Watcher {
|
||||||
//#region Line Parsers
|
//#region Line Parsers
|
||||||
|
|
||||||
private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
|
private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
|
||||||
if (!strippedLine.length) return
|
if (!strippedLine.includes("watch-extensions") || this.hasVerboseLogging) {
|
||||||
|
console.log("[VS Code]", originalLine)
|
||||||
|
}
|
||||||
|
|
||||||
console.log("[VS Code]", originalLine)
|
switch (this.vscodeCompileStatus) {
|
||||||
|
case VSCodeCompileStatus.Loading:
|
||||||
|
// Wait for watch-client since "Finished compilation" will appear multiple
|
||||||
|
// times before the client starts building.
|
||||||
|
if (strippedLine.includes("Starting 'watch-client'")) {
|
||||||
|
console.log("[VS Code] 🚧 Compiling 🚧", "(This may take a moment!)")
|
||||||
|
this.vscodeCompileStatus = VSCodeCompileStatus.Compiling
|
||||||
|
}
|
||||||
|
break
|
||||||
|
case VSCodeCompileStatus.Compiling:
|
||||||
|
if (strippedLine.includes("Finished compilation")) {
|
||||||
|
console.log("[VS Code] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
|
||||||
|
this.vscodeCompileStatus = VSCodeCompileStatus.Compiled
|
||||||
|
|
||||||
if (strippedLine.includes("Finished compilation with")) {
|
this.emitCompilationStats()
|
||||||
console.log("[VS Code] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
|
this.reloadWebServer()
|
||||||
this.reloadWebServer()
|
}
|
||||||
|
break
|
||||||
|
case VSCodeCompileStatus.Compiled:
|
||||||
|
console.log("[VS Code] 🔔 Finished recompiling! 🔔", "(Refresh your web browser ♻️)")
|
||||||
|
this.emitCompilationStats()
|
||||||
|
this.reloadWebServer()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +128,7 @@ class Watcher {
|
||||||
|
|
||||||
if (strippedLine.includes("Watching for file changes")) {
|
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()
|
this.reloadWebServer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,15 +147,50 @@ class Watcher {
|
||||||
|
|
||||||
//#region Utilities
|
//#region Utilities
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans files from previous builds.
|
||||||
|
*/
|
||||||
|
private cleanFiles(): Promise<string[]> {
|
||||||
|
console.log("[Watcher]", "Cleaning files from previous builds...")
|
||||||
|
|
||||||
|
return del([
|
||||||
|
"out/**/*",
|
||||||
|
// Included because the cache can sometimes enter bad state when debugging compiled files.
|
||||||
|
".cache/**/*",
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits a file containing compilation data.
|
||||||
|
* This is especially useful when Express needs to determine if VS Code is still compiling.
|
||||||
|
*/
|
||||||
|
private emitCompilationStats(): Promise<void> {
|
||||||
|
const stats: CompilationStats = {
|
||||||
|
status: this.vscodeCompileStatus,
|
||||||
|
lastCompiledAt: new Date(),
|
||||||
|
}
|
||||||
|
|
||||||
|
this.log("Writing watcher stats...")
|
||||||
|
return fs.writeFile(this.paths.compilationStatsFile, JSON.stringify(stats, null, 2))
|
||||||
|
}
|
||||||
|
|
||||||
|
private log(...entries: string[]) {
|
||||||
|
process.stdout.write(entries.join(" "))
|
||||||
|
}
|
||||||
|
|
||||||
private dispose(code: number | null): void {
|
private dispose(code: number | null): void {
|
||||||
for (const [processName, devProcess] of Object.entries(this.compilers)) {
|
for (const [processName, devProcess] of Object.entries(this.compilers)) {
|
||||||
console.log(`[${processName}]`, "Killing...\n")
|
this.log(`[${processName}]`, "Killing...\n")
|
||||||
devProcess?.removeAllListeners()
|
devProcess?.removeAllListeners()
|
||||||
devProcess?.kill()
|
devProcess?.kill()
|
||||||
}
|
}
|
||||||
process.exit(typeof code === "number" ? code : 0)
|
process.exit(typeof code === "number" ? code : 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get hasVerboseLogging() {
|
||||||
|
return process.argv.includes("--log")
|
||||||
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: code-server
|
name: code-server
|
||||||
description: A Helm chart for coder/code-server
|
description: A Helm chart for cdr/code-server
|
||||||
|
|
||||||
# A chart can be either an 'application' or a 'library' chart.
|
# A chart can be either an 'application' or a 'library' chart.
|
||||||
#
|
#
|
||||||
|
@ -15,9 +15,9 @@ type: application
|
||||||
# This is the chart version. This version number should be incremented each time you make changes
|
# This is the chart version. This version number should be incremented each time you make changes
|
||||||
# to the chart and its templates, including the app version.
|
# to the chart and its templates, including the app version.
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||||
version: 2.1.0
|
version: 1.0.5
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
# This is the version number of the application being deployed. This version number should be
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
# incremented each time you make changes to the application. Versions are not expected to
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||||
appVersion: 4.0.2
|
appVersion: 3.12.0
|
||||||
|
|
|
@ -21,7 +21,6 @@ spec:
|
||||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
spec:
|
spec:
|
||||||
imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }}
|
|
||||||
{{- if .Values.hostnameOverride }}
|
{{- if .Values.hostnameOverride }}
|
||||||
hostname: {{ .Values.hostnameOverride }}
|
hostname: {{ .Values.hostnameOverride }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -18,9 +18,6 @@ metadata:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
{{- if .Values.ingress.ingressClassName }}
|
|
||||||
ingressClassName: {{ .Values.ingress.ingressClassName }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.ingress.tls }}
|
{{- if .Values.ingress.tls }}
|
||||||
tls:
|
tls:
|
||||||
{{- range .Values.ingress.tls }}
|
{{- range .Values.ingress.tls }}
|
||||||
|
|
|
@ -6,15 +6,10 @@ replicaCount: 1
|
||||||
|
|
||||||
image:
|
image:
|
||||||
repository: codercom/code-server
|
repository: codercom/code-server
|
||||||
tag: '4.0.2'
|
tag: '3.12.0'
|
||||||
pullPolicy: Always
|
pullPolicy: Always
|
||||||
|
|
||||||
# Specifies one or more secrets to be used when pulling images from a
|
|
||||||
# private container repository
|
|
||||||
# https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry
|
|
||||||
imagePullSecrets: []
|
imagePullSecrets: []
|
||||||
# - name: registry-creds
|
|
||||||
|
|
||||||
nameOverride: ""
|
nameOverride: ""
|
||||||
fullnameOverride: ""
|
fullnameOverride: ""
|
||||||
hostnameOverride: ""
|
hostnameOverride: ""
|
||||||
|
@ -40,12 +35,13 @@ service:
|
||||||
ingress:
|
ingress:
|
||||||
enabled: false
|
enabled: false
|
||||||
#annotations:
|
#annotations:
|
||||||
|
# kubernetes.io/ingress.class: nginx
|
||||||
# kubernetes.io/tls-acme: "true"
|
# kubernetes.io/tls-acme: "true"
|
||||||
#hosts:
|
#hosts:
|
||||||
# - host: code-server.example.loc
|
# - host: code-server.example.loc
|
||||||
# paths:
|
# paths:
|
||||||
# - /
|
# - /
|
||||||
ingressClassName: ""
|
|
||||||
#tls:
|
#tls:
|
||||||
# - secretName: code-server
|
# - secretName: code-server
|
||||||
# hosts:
|
# hosts:
|
||||||
|
|
|
@ -10,13 +10,11 @@ RUN apt-get update \
|
||||||
man \
|
man \
|
||||||
nano \
|
nano \
|
||||||
git \
|
git \
|
||||||
git-lfs \
|
|
||||||
procps \
|
procps \
|
||||||
openssh-client \
|
openssh-client \
|
||||||
sudo \
|
sudo \
|
||||||
vim.tiny \
|
vim.tiny \
|
||||||
lsb-release \
|
lsb-release \
|
||||||
&& git lfs install \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# https://wiki.debian.org/Locale#Manually
|
# https://wiki.debian.org/Locale#Manually
|
||||||
|
|
|
@ -18,4 +18,4 @@ if [ "${DOCKER_USER-}" ]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec dumb-init /usr/bin/code-server "$@"
|
dumb-init /usr/bin/code-server "$@"
|
||||||
|
|
|
@ -10,23 +10,23 @@ main() {
|
||||||
echo "Checking environment variables"
|
echo "Checking environment variables"
|
||||||
|
|
||||||
# We need VERSION to bump the brew formula
|
# We need VERSION to bump the brew formula
|
||||||
if ! is_env_var_set "VERSION"; then
|
if is_env_var_set "VERSION"; then
|
||||||
echo "VERSION is not set"
|
echo "VERSION is not set"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We need HOMEBREW_GITHUB_API_TOKEN to push up commits
|
# We need HOMEBREW_GITHUB_API_TOKEN to push up commits
|
||||||
if ! is_env_var_set "HOMEBREW_GITHUB_API_TOKEN"; then
|
if is_env_var_set "HOMEBREW_GITHUB_API_TOKEN"; then
|
||||||
echo "HOMEBREW_GITHUB_API_TOKEN is not set"
|
echo "HOMEBREW_GITHUB_API_TOKEN is not set"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# NOTE: we need to make sure coderci/homebrew-core
|
# NOTE: we need to make sure cdrci/homebrew-core
|
||||||
# is up-to-date
|
# is up-to-date
|
||||||
# otherwise, brew bump-formula-pr will use an
|
# otherwise, brew bump-formula-pr will use an
|
||||||
# outdated base
|
# outdated base
|
||||||
echo "Cloning coderci/homebrew-core"
|
echo "Cloning cdrci/homebrew-core"
|
||||||
git clone https://github.com/coderci/homebrew-core.git
|
git clone https://github.com/cdrci/homebrew-core.git
|
||||||
|
|
||||||
# Make sure the git clone step is successful
|
# Make sure the git clone step is successful
|
||||||
if directory_exists "homebrew-core"; then
|
if directory_exists "homebrew-core"; then
|
||||||
|
@ -57,7 +57,7 @@ main() {
|
||||||
echo "Merging in latest Homebrew/homebrew-core changes"
|
echo "Merging in latest Homebrew/homebrew-core changes"
|
||||||
git merge upstream/master
|
git merge upstream/master
|
||||||
|
|
||||||
echo "Pushing changes to coderci/homebrew-core fork on GitHub"
|
echo "Pushing changes to cdrci/homebrew-core fork on GitHub"
|
||||||
|
|
||||||
# GIT_ASKPASS lets us use the password when pushing without revealing it in the process list
|
# GIT_ASKPASS lets us use the password when pushing without revealing it in the process list
|
||||||
# See: https://serverfault.com/a/912788
|
# See: https://serverfault.com/a/912788
|
||||||
|
@ -86,7 +86,7 @@ main() {
|
||||||
# Export the variables so git sees them
|
# Export the variables so git sees them
|
||||||
export HOMEBREW_GITHUB_API_TOKEN="$HOMEBREW_GITHUB_API_TOKEN"
|
export HOMEBREW_GITHUB_API_TOKEN="$HOMEBREW_GITHUB_API_TOKEN"
|
||||||
export GIT_ASKPASS="$PATH_TO_ASKPASS"
|
export GIT_ASKPASS="$PATH_TO_ASKPASS"
|
||||||
git push https://coder-oss@github.com/coder-oss/homebrew-core.git --all
|
git push https://cdr-oss@github.com/cdr-oss/homebrew-core.git --all
|
||||||
|
|
||||||
# Find the docs for bump-formula-pr here
|
# Find the docs for bump-formula-pr here
|
||||||
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
|
# https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
|
||||||
|
|
|
@ -1,15 +1,36 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# See if this version already exists on Docker Hub.
|
||||||
|
function version_exists() {
|
||||||
|
local output
|
||||||
|
output=$(curl --silent "https://index.docker.io/v1/repositories/codercom/code-server/tags/$VERSION")
|
||||||
|
if [[ $output == "Tag not found" ]]; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/../.."
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
# ci/lib.sh sets VERSION and provides download_artifact here
|
# ci/lib.sh sets VERSION and provides download_artifact here
|
||||||
source ./ci/lib.sh
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
if version_exists; then
|
||||||
|
echo "$VERSION is already pushed"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
# Download the release-packages artifact
|
# Download the release-packages artifact
|
||||||
download_artifact release-packages ./release-packages
|
download_artifact release-packages ./release-packages
|
||||||
|
|
||||||
|
# Login to Docker
|
||||||
|
if [[ ${CI-} ]]; then
|
||||||
|
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||||
|
fi
|
||||||
|
|
||||||
docker buildx bake -f ci/release-image/docker-bake.hcl --push
|
docker buildx bake -f ci/release-image/docker-bake.hcl --push
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,144 +4,27 @@ set -euo pipefail
|
||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/../.."
|
cd "$(dirname "$0")/../.."
|
||||||
source ./ci/lib.sh
|
source ./ci/lib.sh
|
||||||
source ./ci/steps/steps-lib.sh
|
|
||||||
|
|
||||||
## Authentication tokens
|
# npm view won't exit with non-zero so we have to check the output.
|
||||||
# Needed to publish on NPM
|
local hasVersion
|
||||||
if ! is_env_var_set "NPM_TOKEN"; then
|
hasVersion=$(npm view "code-server@$VERSION" version)
|
||||||
echo "NPM_TOKEN is not set. Cannot publish to npm without credentials."
|
if [[ $hasVersion == "$VERSION" ]]; then
|
||||||
exit 1
|
echo "$VERSION is already published"
|
||||||
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# NOTE@jsjoeio - only needed if we use the download_artifact
|
|
||||||
# because we talk to the GitHub API.
|
|
||||||
# Needed to use GitHub API
|
|
||||||
if ! is_env_var_set "GITHUB_TOKEN"; then
|
|
||||||
echo "GITHUB_TOKEN is not set. Cannot download npm release artifact without GitHub credentials."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
## Publishing Information
|
|
||||||
# All the variables below are used to determine how we should publish
|
|
||||||
# the npm package. We also use this information for bumping the version.
|
|
||||||
# This is because npm won't publish your package unless it's a new version.
|
|
||||||
# i.e. for development, we bump the version to <current version>-<pr number>-<commit sha>
|
|
||||||
# example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
|
||||||
# We need the current package.json VERSION
|
|
||||||
if ! is_env_var_set "VERSION"; then
|
|
||||||
echo "VERSION is not set. Cannot publish to npm without VERSION."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We use this to grab the PR_NUMBER
|
|
||||||
if ! is_env_var_set "GITHUB_REF"; then
|
|
||||||
echo "GITHUB_REF is not set. Are you running this locally? We rely on values provided by GitHub."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We use this when setting NPM_VERSION
|
|
||||||
if ! is_env_var_set "GITHUB_SHA"; then
|
|
||||||
echo "GITHUB_SHA is not set. Are you running this locally? We rely on values provided by GitHub."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We use this to determine the NPM_ENVIRONMENT
|
|
||||||
if ! is_env_var_set "GITHUB_EVENT_NAME"; then
|
|
||||||
echo "GITHUB_EVENT_NAME is not set. Are you running this locally? We rely on values provided by GitHub."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# This allows us to publish to npm in CI workflows
|
|
||||||
if [[ ${CI-} ]]; then
|
if [[ ${CI-} ]]; then
|
||||||
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
## Environment
|
download_artifact npm-package ./release-npm-package
|
||||||
# This string is used to determine how we should tag the npm release.
|
|
||||||
# Environment can be one of three choices:
|
|
||||||
# "development" - this means we tag with the PR number, allowing
|
|
||||||
# a developer to install this version with `yarn add code-server@<pr-number>`
|
|
||||||
# "staging" - this means we tag with `beta`, allowing
|
|
||||||
# a developer to install this version with `yarn add code-server@beta`
|
|
||||||
# "production" - this means we tag with `latest` (default), allowing
|
|
||||||
# a developer to install this version with `yarn add code-server@latest`
|
|
||||||
if ! is_env_var_set "NPM_ENVIRONMENT"; then
|
|
||||||
echo "NPM_ENVIRONMENT is not set. Determining in script based on GITHUB environment variables."
|
|
||||||
|
|
||||||
if [[ "$GITHUB_EVENT_NAME" == 'push' && "$GITHUB_REF" == 'refs/heads/main' ]]; then
|
|
||||||
NPM_ENVIRONMENT="staging"
|
|
||||||
else
|
|
||||||
NPM_ENVIRONMENT="development"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Using npm environment: $NPM_ENVIRONMENT"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# NOTE@jsjoeio - this script assumes we have the artifact downloaded on disk
|
|
||||||
# That happens in CI as a step before we run this.
|
|
||||||
# https://github.com/actions/upload-artifact/issues/38
|
# https://github.com/actions/upload-artifact/issues/38
|
||||||
tar -xzf release-npm-package/package.tar.gz
|
tar -xzf release-npm-package/package.tar.gz
|
||||||
|
|
||||||
# Ignore symlink when publishing npm package
|
# Ignore symlink when publishing npm package
|
||||||
# See: https://github.com/coder/code-server/pull/3935
|
# See: https://github.com/cdr/code-server/pull/3935
|
||||||
echo "node_modules.asar" > release/.npmignore
|
echo "node_modules.asar" > release/.npmignore
|
||||||
|
yarn publish --non-interactive release
|
||||||
# NOTES:@jsjoeio
|
|
||||||
# We only need to run npm version for "development" and "staging".
|
|
||||||
# This is because our release:prep script automatically bumps the version
|
|
||||||
# in the package.json and we commit it as part of the release PR.
|
|
||||||
if [[ "$NPM_ENVIRONMENT" == "production" ]]; then
|
|
||||||
NPM_VERSION="$VERSION"
|
|
||||||
# This means the npm version will be published as "stable"
|
|
||||||
# and installed when a user runs `yarn install code-server`
|
|
||||||
NPM_TAG="latest"
|
|
||||||
else
|
|
||||||
COMMIT_SHA="$GITHUB_SHA"
|
|
||||||
echo "Not a production environment"
|
|
||||||
echo "Found environment: $NPM_ENVIRONMENT"
|
|
||||||
echo "Manually bumping npm version..."
|
|
||||||
|
|
||||||
if [[ "$NPM_ENVIRONMENT" == "staging" ]]; then
|
|
||||||
NPM_VERSION="$VERSION-beta-$COMMIT_SHA"
|
|
||||||
# This means the npm version will be tagged with "beta"
|
|
||||||
# and installed when a user runs `yarn install code-server@beta`
|
|
||||||
NPM_TAG="beta"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$NPM_ENVIRONMENT" == "development" ]]; then
|
|
||||||
# Source: https://github.com/actions/checkout/issues/58#issuecomment-614041550
|
|
||||||
PR_NUMBER=$(echo "$GITHUB_REF" | awk 'BEGIN { FS = "/" } ; { print $3 }')
|
|
||||||
NPM_VERSION="$VERSION-$PR_NUMBER-$COMMIT_SHA"
|
|
||||||
# This means the npm version will be tagged with "<pr number>"
|
|
||||||
# and installed when a user runs `yarn install code-server@<pr number>`
|
|
||||||
NPM_TAG="$PR_NUMBER"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "using tag: $NPM_TAG"
|
|
||||||
|
|
||||||
# We modify the version in the package.json
|
|
||||||
# to be the current version + the PR number + commit SHA
|
|
||||||
# or we use current version + beta + commit SHA
|
|
||||||
# Example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
|
||||||
# Example: "version": "4.0.1-beta-ad7b23cfe6ffd72914e34781ef7721b129a23040"
|
|
||||||
pushd release
|
|
||||||
# NOTE:@jsjoeio
|
|
||||||
# I originally tried to use `yarn version` but ran into issues and abandoned it.
|
|
||||||
npm version "$NPM_VERSION"
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We need to make sure we haven't already published the version.
|
|
||||||
# This is because npm view won't exit with non-zero so we have
|
|
||||||
# to check the output.
|
|
||||||
local hasVersion
|
|
||||||
hasVersion=$(npm view "code-server@$NPM_VERSION" version)
|
|
||||||
if [[ $hasVersion == "$NPM_VERSION" ]]; then
|
|
||||||
echo "$NPM_VERSION is already published"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
yarn publish --non-interactive release --tag "$NPM_TAG"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
@ -61,7 +61,7 @@ These are required by VS Code. See [their Wiki](https://github.com/microsoft/vsc
|
||||||
|
|
||||||
## Creating pull requests
|
## Creating pull requests
|
||||||
|
|
||||||
Please create a [GitHub Issue](https://github.com/coder/code-server/issues) that
|
Please create a [GitHub Issue](https://github.com/cdr/code-server/issues) that
|
||||||
includes context for issues that you see. You can skip this if the proposed fix
|
includes context for issues that you see. You can skip this if the proposed fix
|
||||||
is minor.
|
is minor.
|
||||||
|
|
||||||
|
@ -78,37 +78,38 @@ we'll guide you.
|
||||||
|
|
||||||
## Development workflow
|
## Development workflow
|
||||||
|
|
||||||
The current development workflow is a bit tricky because we have this repo and we use our `coder/vscode` fork inside it with [`yarn link`](https://classic.yarnpkg.com/lang/en/docs/cli/link/).
|
The current development workflow is a bit tricky because we have this repo and we use our `cdr/vscode` fork inside it with [`yarn link`](https://classic.yarnpkg.com/lang/en/docs/cli/link/).
|
||||||
|
|
||||||
Here are these steps you should follow to get your dev environment setup:
|
Here are these steps you should follow to get your dev environment setup:
|
||||||
|
|
||||||
1. `git clone https://github.com/coder/code-server.git` - Clone `code-server`
|
1. `git clone https://github.com/cdr/code-server.git` - Clone `code-server`
|
||||||
2. `git clone https://github.com/coder/vscode.git` - Clone `vscode`
|
2. `git clone https://github.com/cdr/vscode.git` - Clone `vscode`
|
||||||
3. `cd vscode && yarn install` - install the dependencies in the `vscode` repo
|
3. `cd vscode && git checkout code-server-v2` - checkout the branch we use (not the default)
|
||||||
4. `cd code-server && yarn install` - install the dependencies in the `code-server` repo
|
4. `cd vscode && yarn install` - install the dependencies in the `vscode` repo
|
||||||
5. `cd vscode && yarn link` - use `yarn` to create a symlink to the `vscode` repo (`code-oss-dev` package)
|
5. `cd code-server && yarn install` - install the dependencies in the `code-server` repo
|
||||||
6. `cd code-server && yarn link code-oss-dev --modules-folder vendor/modules` - links your local `vscode` repo (`code-oss-dev` package) inside your local version of code-server
|
6. `cd vscode && yarn link` - use `yarn` to create a symlink to the `vscode` repo (`code-oss-dev` package)
|
||||||
7. `cd code-server && yarn watch` - this will spin up code-server on localhost:8080 which you can start developing. It will live reload changes to the source.
|
7. `cd code-server && yarn link code-oss-dev --modules-folder vendor/modules` - links your local `vscode` repo (`code-oss-dev` package) inside your local version of code-server
|
||||||
|
8. `cd code-server && yarn watch` - this will spin up code-server on localhost:8080 which you can start developing. It will live reload changes to the source.
|
||||||
|
|
||||||
### Updates to VS Code
|
### Updates to VS Code
|
||||||
|
|
||||||
If changes are made and merged into `main` in the [`coder/vscode`](https://github.com/coder/vscode) repo, then you'll need to update the version in the `code-server` repo by following these steps:
|
If changes are made and merged into `code-server-v2` in the `cdr/vscode` repo, then you'll need to update the version in the `code-server` repo by following these steps:
|
||||||
|
|
||||||
1. Update the package tag listed in `vendor/package.json`:
|
1. Update the package tag listed in `vendor/package.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vscode": "coder/vscode#<latest-commit-sha>"
|
"vscode": "cdr/vscode#X.XX.X-code-server"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
2. From the code-server **project root**, run `yarn install`.
|
1. From the code-server **project root**, run `yarn install`.
|
||||||
Then, test code-server locally to make sure everything works.
|
Then, test code-server locally to make sure everything works.
|
||||||
3. Check the Node.js version that's used by Electron (which is shipped with VS
|
1. Check the Node.js version that's used by Electron (which is shipped with VS
|
||||||
Code. If necessary, update your version of Node.js to match.
|
Code. If necessary, update your version of Node.js to match.
|
||||||
4. Open a PR
|
1. Open a PR
|
||||||
|
|
||||||
> Watch for updates to
|
> Watch for updates to
|
||||||
> `vendor/modules/code-oss-dev/src/vs/code/browser/workbench/workbench.html`. You may need to
|
> `vendor/modules/code-oss-dev/src/vs/code/browser/workbench/workbench.html`. You may need to
|
||||||
|
@ -148,7 +149,7 @@ yarn package
|
||||||
|
|
||||||
### Help
|
### Help
|
||||||
|
|
||||||
If you get stuck or need help, you can always start a new GitHub Discussion [here](https://github.com/coder/code-server/discussions). One of the maintainers will respond and help you out.
|
If you get stuck or need help, you can always start a new GitHub Discussion [here](https://github.com/cdr/code-server/discussions). One of the maintainers will respond and help you out.
|
||||||
|
|
||||||
## Test
|
## Test
|
||||||
|
|
||||||
|
|
16
docs/FAQ.md
16
docs/FAQ.md
|
@ -37,7 +37,7 @@
|
||||||
## Questions?
|
## Questions?
|
||||||
|
|
||||||
Please file all questions and support requests at
|
Please file all questions and support requests at
|
||||||
<https://github.com/coder/code-server/discussions>.
|
<https://github.com/cdr/code-server/discussions>.
|
||||||
|
|
||||||
## How should I expose code-server to the internet?
|
## How should I expose code-server to the internet?
|
||||||
|
|
||||||
|
@ -111,11 +111,11 @@ These are the closed-source extensions that are presently unavailable:
|
||||||
|
|
||||||
1. [Live Share](https://visualstudio.microsoft.com/services/live-share). We may
|
1. [Live Share](https://visualstudio.microsoft.com/services/live-share). We may
|
||||||
implement something similar (see
|
implement something similar (see
|
||||||
[#33](https://github.com/coder/code-server/issues/33))
|
[#33](https://github.com/cdr/code-server/issues/33))
|
||||||
1. [Remote Extensions (SSH, Containers,
|
1. [Remote Extensions (SSH, Containers,
|
||||||
WSL)](https://github.com/microsoft/vscode-remote-release). We may implement
|
WSL)](https://github.com/microsoft/vscode-remote-release). We may implement
|
||||||
these again at some point, see
|
these again at some point, see
|
||||||
([#1315](https://github.com/coder/code-server/issues/1315)).
|
([#1315](https://github.com/cdr/code-server/issues/1315)).
|
||||||
|
|
||||||
For more about the closed source portions of VS Code, see [vscodium/vscodium](https://github.com/VSCodium/vscodium#why-does-this-exist).
|
For more about the closed source portions of VS Code, see [vscodium/vscodium](https://github.com/VSCodium/vscodium#why-does-this-exist).
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ You may have to give Node.js full disk access, since it doesn't implement any of
|
||||||
Privacy** > **Privacy** > **Full Disk Access**. Then, click the 🔒 to unlock,
|
Privacy** > **Privacy** > **Full Disk Access**. Then, click the 🔒 to unlock,
|
||||||
click **+**, and select the Node.js binary you located in the previous step.
|
click **+**, and select the Node.js binary you located in the previous step.
|
||||||
|
|
||||||
See [#2794](https://github.com/coder/code-server/issues/2794) for additional context.
|
See [#2794](https://github.com/cdr/code-server/issues/2794) for additional context.
|
||||||
|
|
||||||
## How do I direct server-side requests through a proxy?
|
## How do I direct server-side requests through a proxy?
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ after a predetermined amount of time, you can do so by checking continuously for
|
||||||
the last modified time on the heartbeat file. If it is older than X minutes (or
|
the last modified time on the heartbeat file. If it is older than X minutes (or
|
||||||
whatever amount of time you'd like), you can kill code-server.
|
whatever amount of time you'd like), you can kill code-server.
|
||||||
|
|
||||||
Eventually, [#1636](https://github.com/coder/code-server/issues/1636) will make
|
Eventually, [#1636](https://github.com/cdr/code-server/issues/1636) will make
|
||||||
this process better.
|
this process better.
|
||||||
|
|
||||||
## How do I change the password?
|
## How do I change the password?
|
||||||
|
@ -376,7 +376,7 @@ Theia doesn't allow you to reuse your existing VS Code config.
|
||||||
## What's the difference between code-server and OpenVSCode-Server?
|
## What's the difference between code-server and OpenVSCode-Server?
|
||||||
|
|
||||||
code-server and OpenVSCode-Server both allow you to access VS Code via a
|
code-server and OpenVSCode-Server both allow you to access VS Code via a
|
||||||
browser. The two projects also use their own [forks of VS Code](https://github.com/coder/vscode) to
|
browser. The two projects also use their own [forks of VS Code](https://github.com/cdr/vscode) to
|
||||||
leverage modern VS Code APIs and stay up to date with the upsteam version.
|
leverage modern VS Code APIs and stay up to date with the upsteam version.
|
||||||
|
|
||||||
However, OpenVSCode-Server is scoped at only making VS Code available in the web browser.
|
However, OpenVSCode-Server is scoped at only making VS Code available in the web browser.
|
||||||
|
@ -388,7 +388,7 @@ code-server includes some other features:
|
||||||
- plugin API
|
- plugin API
|
||||||
- settings sync (coming soon)
|
- settings sync (coming soon)
|
||||||
|
|
||||||
For more details, see [this discussion post](https://github.com/coder/code-server/discussions/4267#discussioncomment-1411583).
|
For more details, see [this discussion post](https://github.com/cdr/code-server/discussions/4267#discussioncomment-1411583).
|
||||||
|
|
||||||
## What's the difference between code-server and GitHub Codespaces?
|
## What's the difference between code-server and GitHub Codespaces?
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ minute plus an additional twelve per hour.
|
||||||
|
|
||||||
## Are there community projects involving code-server?
|
## Are there community projects involving code-server?
|
||||||
|
|
||||||
Visit the [awesome-code-server](https://github.com/coder/awesome-code-server)
|
Visit the [awesome-code-server](https://github.com/cdr/awesome-code-server)
|
||||||
repository to view community projects and guides with code-server! Feel free to
|
repository to view community projects and guides with code-server! Feel free to
|
||||||
add your own!
|
add your own!
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
- [Docker](#docker)
|
- [Docker](#docker)
|
||||||
- [Homebrew](#homebrew)
|
- [Homebrew](#homebrew)
|
||||||
- [npm](#npm)
|
- [npm](#npm)
|
||||||
- [Syncing with Upstream VS Code](#syncing-with-upstream-vs-code)
|
|
||||||
- [Testing](#testing)
|
- [Testing](#testing)
|
||||||
- [Documentation](#documentation)
|
- [Documentation](#documentation)
|
||||||
- [Troubleshooting](#troubleshooting)
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
@ -37,23 +36,23 @@ Current maintainers:
|
||||||
- @TeffenEllis
|
- @TeffenEllis
|
||||||
- @jsjoeio
|
- @jsjoeio
|
||||||
|
|
||||||
Occasionally, other Coder employees may step in time to time to assist with code-server.
|
Occassionally, other Coder employees may step in time to time to assist with code-server.
|
||||||
|
|
||||||
### Onboarding
|
### Onboarding
|
||||||
|
|
||||||
To onboard a new maintainer to the project, please make sure to do the following:
|
To onboard a new maintainer to the project, please make sure to do the following:
|
||||||
|
|
||||||
- [ ] Add to [coder/code-server-reviewers](https://github.com/orgs/coder/teams/code-server-reviewers)
|
- [ ] Add to [cdr/code-server-reviewers](https://github.com/orgs/cdr/teams/code-server-reviewers)
|
||||||
- [ ] Add as Admin under [Repository Settings > Access](https://github.com/coder/code-server/settings/access)
|
- [ ] Add as Admin under [Repository Settings > Access](https://github.com/cdr/code-server/settings/access)
|
||||||
- [ ] Add to [npm Coder org](https://www.npmjs.com/org/coder)
|
- [ ] Add to [npm Coder org](https://www.npmjs.com/org/coder)
|
||||||
- [ ] Add as [AUR maintainer](https://aur.archlinux.org/packages/code-server/) (talk to Colin)
|
- [ ] Add as [AUR maintainer](https://aur.archlinux.org/packages/code-server/) (talk to Colin)
|
||||||
- [ ] Introduce to community via Discussion (see [example](https://github.com/coder/code-server/discussions/3955))
|
- [ ] Introduce to community via Discussion (see [example](https://github.com/cdr/code-server/discussions/3955))
|
||||||
|
|
||||||
### Offboarding
|
### Offboarding
|
||||||
|
|
||||||
Very similar to Onboarding but Remove maintainer from all teams and revoke access. Please also do the following:
|
Very similar to Onboarding but Remove maintainer from all teams and revoke access. Please also do the following:
|
||||||
|
|
||||||
- [ ] Write farewell post via Discussion (see [example](https://github.com/coder/code-server/discussions/3933))
|
- [ ] Write farewell post via Discussion (see [example](https://github.com/cdr/code-server/discussions/3933))
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ contributing on day one.
|
||||||
### Milestones
|
### Milestones
|
||||||
|
|
||||||
We operate mainly using
|
We operate mainly using
|
||||||
[milestones](https://github.com/coder/code-server/milestones). This was heavily
|
[milestones](https://github.com/cdr/code-server/milestones). This was heavily
|
||||||
inspired by our friends over at [vscode](https://github.com/microsoft/vscode).
|
inspired by our friends over at [vscode](https://github.com/microsoft/vscode).
|
||||||
|
|
||||||
Here are the milestones we use and how we use them:
|
Here are the milestones we use and how we use them:
|
||||||
|
@ -127,7 +126,8 @@ the issue.
|
||||||
|
|
||||||
### Merge strategies
|
### Merge strategies
|
||||||
|
|
||||||
For most things, we recommend the **squash and merge** strategy. There
|
For most things, we recommend the **squash and merge** strategy. If you're
|
||||||
|
updating `lib/vscode`, we suggest using the **rebase and merge** strategy. There
|
||||||
may be times where **creating a merge commit** makes sense as well. Use your
|
may be times where **creating a merge commit** makes sense as well. Use your
|
||||||
best judgment. If you're unsure, you can always discuss in the PR with the team.
|
best judgment. If you're unsure, you can always discuss in the PR with the team.
|
||||||
|
|
||||||
|
@ -185,12 +185,12 @@ If you're the current release manager, follow these steps:
|
||||||
artifacts, publish the NPM package from `npm-package`, and publish the Docker
|
artifacts, publish the NPM package from `npm-package`, and publish the Docker
|
||||||
Hub image from `release-images`.
|
Hub image from `release-images`.
|
||||||
1. Update the AUR package. Instructions for updating the AUR package are at
|
1. Update the AUR package. Instructions for updating the AUR package are at
|
||||||
[coder/code-server-aur](https://github.com/coder/code-server-aur).
|
[cdr/code-server-aur](https://github.com/cdr/code-server-aur).
|
||||||
1. Wait for the npm package to be published.
|
1. Wait for the npm package to be published.
|
||||||
|
|
||||||
#### AUR
|
#### AUR
|
||||||
|
|
||||||
We publish to AUR as a package [here](https://aur.archlinux.org/packages/code-server/). This process is manual and can be done by following the steps in [this repo](https://github.com/coder/code-server-aur).
|
We publish to AUR as a package [here](https://aur.archlinux.org/packages/code-server/). This process is manual and can be done by following the steps in [this repo](https://github.com/cdr/code-server-aur).
|
||||||
|
|
||||||
#### Docker
|
#### Docker
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ This is currently automated with the release process.
|
||||||
|
|
||||||
We publish code-server on Homebrew [here](https://github.com/Homebrew/homebrew-core/blob/master/Formula/code-server.rb).
|
We publish code-server on Homebrew [here](https://github.com/Homebrew/homebrew-core/blob/master/Formula/code-server.rb).
|
||||||
|
|
||||||
This is currently automated with the release process (but may fail occasionally). If it does, run this locally:
|
This is currently automated with the release process (but may fail occassionally). If it does, run this locally:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Replace VERSION with version
|
# Replace VERSION with version
|
||||||
|
@ -215,24 +215,11 @@ We publish code-server as a npm package [here](https://www.npmjs.com/package/cod
|
||||||
|
|
||||||
This is currently automated with the release process.
|
This is currently automated with the release process.
|
||||||
|
|
||||||
## Syncing with Upstream VS Code
|
|
||||||
|
|
||||||
The VS Code portion of code-server lives under [`coder/vscode`](https://github.com/coder/vscode). To update VS Code for code-server, follow these steps:
|
|
||||||
|
|
||||||
1. `git checkout -b vscode-update` - Create a new branch locally based off `main`
|
|
||||||
2. `git fetch upstream` - Fetch upstream (VS Code)'s latest branches
|
|
||||||
3. `git merge upstream/release/1.64` - Merge it locally
|
|
||||||
1. replace `1.64` with the version you're upgrading to
|
|
||||||
1. If there are merge conflicts, commit first, then fix them locally.
|
|
||||||
4. Open a PR merging your branch (`vscode-update`) into `main` and add the code-server review team
|
|
||||||
|
|
||||||
Ideally, our fork stays as close to upstream as possible. See the differences between our fork and upstream [here](https://github.com/microsoft/vscode/compare/main...coder:main).
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Our testing structure is laid out under our [Contributing docs](https://coder.com/docs/code-server/latest/CONTRIBUTING#test).
|
Our testing structure is laid out under our [Contributing docs](https://coder.com/docs/code-server/latest/CONTRIBUTING#test).
|
||||||
|
|
||||||
We hope to eventually hit 100% test coverage with our unit tests, and maybe one day our scripts (coverage not tracked currently).
|
We hope to eventually hit 100% test converage with our unit tests, and maybe one day our scripts (coverage not tracked currently).
|
||||||
|
|
||||||
If you're ever looking to add more tests, here are a few ways to get started:
|
If you're ever looking to add more tests, here are a few ways to get started:
|
||||||
|
|
||||||
|
@ -248,7 +235,7 @@ Otherwise, talk to a current maintainer and ask which part of the codebase is la
|
||||||
|
|
||||||
Our docs are hosted on [Vercel](https://vercel.com/). Vercel only shows logs in realtime, which means you need to have the logs open in one tab and reproduce your error in another tab. Since our logs are private to Coder the organization, you can only follow these steps if you're a Coder employee. Ask a maintainer for help if you need it.
|
Our docs are hosted on [Vercel](https://vercel.com/). Vercel only shows logs in realtime, which means you need to have the logs open in one tab and reproduce your error in another tab. Since our logs are private to Coder the organization, you can only follow these steps if you're a Coder employee. Ask a maintainer for help if you need it.
|
||||||
|
|
||||||
Taking a real scenario, let's say you wanted to troubleshoot [this docs change](https://github.com/coder/code-server/pull/4042). Here is how you would do it:
|
Taking a real scenario, let's say you wanted to troubleshoot [this docs change](https://github.com/cdr/code-server/pull/4042). Here is how you would do it:
|
||||||
|
|
||||||
1. Go to https://vercel.com/codercom/codercom
|
1. Go to https://vercel.com/codercom/codercom
|
||||||
2. Click "View Function Logs"
|
2. Click "View Function Logs"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# code-server
|
# code-server
|
||||||
|
|
||||||
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/coder/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://coder.com/community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/coder/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/coder/code-server) [![See v4.0.2 docs](https://img.shields.io/static/v1?label=Docs&message=see%20v4.0.2%20&color=blue)](https://github.com/coder/code-server/tree/v4.0.2/docs)
|
[!["GitHub Discussions"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&logo=github&colorB=purple)](https://github.com/cdr/code-server/discussions) [!["Join us on Slack"](https://img.shields.io/badge/join-us%20on%20slack-gray.svg?longCache=true&logo=slack&colorB=brightgreen)](https://cdr.co/join-community) [![Twitter Follow](https://img.shields.io/twitter/follow/CoderHQ?label=%40CoderHQ&style=social)](https://twitter.com/coderhq) [![codecov](https://codecov.io/gh/cdr/code-server/branch/main/graph/badge.svg?token=5iM9farjnC)](https://codecov.io/gh/cdr/code-server) [![See v3.12.0 docs](https://img.shields.io/static/v1?label=Docs&message=see%20v3.12.0%20&color=blue)](https://github.com/cdr/code-server/tree/v3.12.0/docs)
|
||||||
|
|
||||||
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
|
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
|
||||||
access it in the browser.
|
access it in the browser.
|
||||||
|
@ -14,7 +14,7 @@ access it in the browser.
|
||||||
- Preserve battery life when you're on the go; all intensive tasks run on your
|
- Preserve battery life when you're on the go; all intensive tasks run on your
|
||||||
server
|
server
|
||||||
|
|
||||||
| 🔔 code-server is a free browser-based IDE while [Coder](https://coder.com/) is our enterprise developer workspace platform. For more information, visit [Coder.com](https://coder.com/docs/comparison)
|
| 🔔 code-server is a free browser-based IDE while [Coder](https://coder.com/), is our enterprise developer workspace platform. For more information, visit [Coder.com](https://coder.com/docs/comparison)
|
||||||
| ---
|
| ---
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
@ -29,13 +29,13 @@ on how to set up a Google VM on which you can install code-server.
|
||||||
There are three ways to get started:
|
There are three ways to get started:
|
||||||
|
|
||||||
1. Using the [install
|
1. Using the [install
|
||||||
script](https://github.com/coder/code-server/blob/main/install.sh), which
|
script](https://github.com/cdr/code-server/blob/main/install.sh), which
|
||||||
automates most of the process. The script uses the system package manager if
|
automates most of the process. The script uses the system package manager if
|
||||||
possible.
|
possible.
|
||||||
2. Manually [installing
|
2. Manually [installing
|
||||||
code-server](https://coder.com/docs/code-server/latest/install)
|
code-server](https://coder.com/docs/code-server/latest/install)
|
||||||
3. Using our one-click buttons and guides to [deploy code-server to a cloud
|
3. Using our one-click buttons and guides to [deploy code-server to a cloud
|
||||||
provider](https://github.com/coder/deploy-code-server) ⚡
|
provider](https://github.com/cdr/deploy-code-server) ⚡
|
||||||
|
|
||||||
If you use the install script, you can preview what occurs during the install
|
If you use the install script, you can preview what occurs during the install
|
||||||
process:
|
process:
|
||||||
|
@ -56,6 +56,10 @@ code-server.
|
||||||
We also have an in-depth [setup and
|
We also have an in-depth [setup and
|
||||||
configuration](https://coder.com/docs/code-server/latest/guide) guide.
|
configuration](https://coder.com/docs/code-server/latest/guide) guide.
|
||||||
|
|
||||||
|
## TLS and authentication (beta)
|
||||||
|
|
||||||
|
To add TLS and authentication out of the box, use [code-server --link](https://coder.com/docs/code-server/latest/link).
|
||||||
|
|
||||||
## Questions?
|
## Questions?
|
||||||
|
|
||||||
See answers to [frequently asked
|
See answers to [frequently asked
|
||||||
|
|
|
@ -26,9 +26,9 @@ We use the following tools to help us stay on top of vulnerability mitigation.
|
||||||
|
|
||||||
Coder sponsors the development and maintenance of the code-server project. We will fix security issues within 90 days of receiving a report and publish the fix in a subsequent release. The code-server project does not provide backports or patch releases for security issues at this time.
|
Coder sponsors the development and maintenance of the code-server project. We will fix security issues within 90 days of receiving a report and publish the fix in a subsequent release. The code-server project does not provide backports or patch releases for security issues at this time.
|
||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------------------------------------------------------- | ------------------ |
|
| ----------------------------------------------------- | ------------------ |
|
||||||
| [Latest](https://github.com/coder/code-server/releases) | :white_check_mark: |
|
| [Latest](https://github.com/cdr/code-server/releases) | :white_check_mark: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Running code-server using UserLAnd
|
|
||||||
|
|
||||||
1. Install UserLAnd from [Google Play](https://play.google.com/store/apps/details?id=tech.ula&hl=en_US&gl=US)
|
|
||||||
2. Install an Ubuntu VM
|
|
||||||
3. Start app
|
|
||||||
4. Install Node.js, `curl` and `yarn` using `sudo apt install nodejs npm yarn curl -y`
|
|
||||||
5. Install `nvm`:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Exit the terminal using `exit` and then reopen the terminal
|
|
||||||
7. Install and use Node.js 14:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
nvm install 14
|
|
||||||
nvm use 14
|
|
||||||
```
|
|
||||||
|
|
||||||
8. Install code-server globally on device with: `npm i -g code-server`
|
|
||||||
9. Run code-server with `code-server`
|
|
||||||
10. Access on localhost:8080 in your browser
|
|
|
@ -60,6 +60,6 @@ As `code-server` is based on VS Code, you can follow the steps described on Duck
|
||||||
code-server --enable-proposed-api genuitecllc.codetogether
|
code-server --enable-proposed-api genuitecllc.codetogether
|
||||||
```
|
```
|
||||||
|
|
||||||
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v4.0.2/FAQ#how-does-the-config-file-work).
|
Another option would be to add a value in code-server's [config file](https://coder.com/docs/code-server/v3.12.0/FAQ#how-does-the-config-file-work).
|
||||||
|
|
||||||
3. Refresh code-server and navigate to the CodeTogether icon in the sidebar to host or join a coding session.
|
3. Refresh code-server and navigate to the CodeTogether icon in the sidebar to host or join a coding session.
|
||||||
|
|
|
@ -115,7 +115,7 @@ we recommend using another method, such as [Let's Encrypt](#let-encrypt) instead
|
||||||
Using [Let's Encrypt](https://letsencrypt.org) is an option if you want to
|
Using [Let's Encrypt](https://letsencrypt.org) is an option if you want to
|
||||||
access code-server on an iPad or do not want to use SSH port forwarding.
|
access code-server on an iPad or do not want to use SSH port forwarding.
|
||||||
|
|
||||||
1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic.
|
1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTP traffic.
|
||||||
|
|
||||||
1. You'll need a domain name (if you don't have one, you can purchase one from
|
1. You'll need a domain name (if you don't have one, you can purchase one from
|
||||||
[Google Domains](https://domains.google.com) or the domain service of your
|
[Google Domains](https://domains.google.com) or the domain service of your
|
||||||
|
@ -162,7 +162,7 @@ At this point, you should be able to access code-server via
|
||||||
|
|
||||||
### Using Let's Encrypt with NGINX
|
### Using Let's Encrypt with NGINX
|
||||||
|
|
||||||
1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTPS traffic.
|
1. This option requires that the remote machine be exposed to the internet. Make sure that your instance allows HTTP/HTTP traffic.
|
||||||
|
|
||||||
1. You'll need a domain name (if you don't have one, you can purchase one from
|
1. You'll need a domain name (if you don't have one, you can purchase one from
|
||||||
[Google Domains](https://domains.google.com) or the domain service of your
|
[Google Domains](https://domains.google.com) or the domain service of your
|
||||||
|
@ -229,7 +229,7 @@ code-server. You should only proceed with this option if:
|
||||||
To use a self-signed certificate:
|
To use a self-signed certificate:
|
||||||
|
|
||||||
1. This option requires that the remote machine be exposed to the internet. Make
|
1. This option requires that the remote machine be exposed to the internet. Make
|
||||||
sure that your instance allows HTTP/HTTPS traffic.
|
sure that your instance allows HTTP/HTTP traffic.
|
||||||
|
|
||||||
1. SSH into your instance and edit your code-server config file to use a
|
1. SSH into your instance and edit your code-server config file to use a
|
||||||
randomly generated self-signed certificate:
|
randomly generated self-signed certificate:
|
||||||
|
@ -294,7 +294,7 @@ Note: if you set `proxy_set_header Host $host;` in your reverse proxy config, it
|
||||||
|
|
||||||
## Accessing web services
|
## Accessing web services
|
||||||
|
|
||||||
If you're working on web services and want to access them locally, code-server
|
If you're working on web services and want to access it locally, code-server
|
||||||
can proxy to any port using either a subdomain or a subpath, allowing you to
|
can proxy to any port using either a subdomain or a subpath, allowing you to
|
||||||
securely access these services using code-server's built-in authentication.
|
securely access these services using code-server's built-in authentication.
|
||||||
|
|
||||||
|
@ -345,8 +345,8 @@ instead and the path will be passed as is (e.g., `/absproxy/3000/my-app-path`).
|
||||||
### Proxying to create a React app
|
### Proxying to create a React app
|
||||||
|
|
||||||
You must use `/absproxy/<port>` with `create-react-app` (see
|
You must use `/absproxy/<port>` with `create-react-app` (see
|
||||||
[#2565](https://github.com/coder/code-server/issues/2565) and
|
[#2565](https://github.com/cdr/code-server/issues/2565) and
|
||||||
[#2222](https://github.com/coder/code-server/issues/2222) for more information).
|
[#2222](https://github.com/cdr/code-server/issues/2222) for more information).
|
||||||
You will need to inform `create-react-app` of the path at which you are serving
|
You will need to inform `create-react-app` of the path at which you are serving
|
||||||
via `$PUBLIC_URL` and webpack via `$WDS_SOCKET_PATH`:
|
via `$PUBLIC_URL` and webpack via `$WDS_SOCKET_PATH`:
|
||||||
|
|
||||||
|
@ -396,7 +396,7 @@ sudo apt update
|
||||||
sudo apt install wget unzip openssh-server
|
sudo apt install wget unzip openssh-server
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Start the SSH server and set the password for your user, if you haven't already. If you use [deploy-code-server](https://github.com/coder/deploy-code-server),
|
2. Start the SSH server and set the password for your user, if you haven't already. If you use [deploy-code-server](https://github.com/cdr/deploy-code-server),
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo service ssh start
|
sudo service ssh start
|
||||||
|
|
10
docs/helm.md
10
docs/helm.md
|
@ -1,8 +1,8 @@
|
||||||
# code-server Helm Chart
|
# code-server Helm Chart
|
||||||
|
|
||||||
[![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)](https://img.shields.io/badge/Type-application-informational?style=flat-square) [![AppVersion: 4.0.2](https://img.shields.io/badge/AppVersion-4.0.2-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-4.0.2-informational?style=flat-square)
|
[![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square) [![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)](https://img.shields.io/badge/Type-application-informational?style=flat-square) [![AppVersion: 3.12.0](https://img.shields.io/badge/AppVersion-3.12.0-informational?style=flat-square)](https://img.shields.io/badge/AppVersion-3.12.0-informational?style=flat-square)
|
||||||
|
|
||||||
[code-server](https://github.com/coder/code-server) code-server is VS Code running
|
[code-server](https://github.com/cdr/code-server) code-server is VS Code running
|
||||||
on a remote server, accessible through the browser.
|
on a remote server, accessible through the browser.
|
||||||
|
|
||||||
This chart is community maintained by [@Matthew-Beckett](https://github.com/Matthew-Beckett) and [@alexgorbatchev](https://github.com/alexgorbatchev)
|
This chart is community maintained by [@Matthew-Beckett](https://github.com/Matthew-Beckett) and [@alexgorbatchev](https://github.com/alexgorbatchev)
|
||||||
|
@ -10,7 +10,7 @@ This chart is community maintained by [@Matthew-Beckett](https://github.com/Matt
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ git clone https://github.com/coder/code-server
|
$ git clone https://github.com/cdr/code-server
|
||||||
$ cd code-server
|
$ cd code-server
|
||||||
$ helm upgrade --install code-server ci/helm-chart
|
$ helm upgrade --install code-server ci/helm-chart
|
||||||
```
|
```
|
||||||
|
@ -30,7 +30,7 @@ package manager.
|
||||||
To install the chart with the release name `code-server`:
|
To install the chart with the release name `code-server`:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ git clone https://github.com/coder/code-server
|
$ git clone https://github.com/cdr/code-server
|
||||||
$ cd code-server
|
$ cd code-server
|
||||||
$ helm upgrade --install code-server ci/helm-chart
|
$ helm upgrade --install code-server ci/helm-chart
|
||||||
```
|
```
|
||||||
|
@ -73,7 +73,7 @@ and their default values.
|
||||||
| hostnameOverride | string | `""` |
|
| hostnameOverride | string | `""` |
|
||||||
| image.pullPolicy | string | `"Always"` |
|
| image.pullPolicy | string | `"Always"` |
|
||||||
| image.repository | string | `"codercom/code-server"` |
|
| image.repository | string | `"codercom/code-server"` |
|
||||||
| image.tag | string | `"4.0.2"` |
|
| image.tag | string | `"3.12.0"` |
|
||||||
| imagePullSecrets | list | `[]` |
|
| imagePullSecrets | list | `[]` |
|
||||||
| ingress.enabled | bool | `false` |
|
| ingress.enabled | bool | `false` |
|
||||||
| nameOverride | string | `""` |
|
| nameOverride | string | `""` |
|
||||||
|
|
|
@ -30,7 +30,7 @@ operating systems.
|
||||||
## install.sh
|
## install.sh
|
||||||
|
|
||||||
The easiest way to install code-server is to use our [install
|
The easiest way to install code-server is to use our [install
|
||||||
script](https://github.com/coder/code-server/blob/main/install.sh) for Linux, macOS and FreeBSD. The install script
|
script](../install.sh) for Linux, macOS and FreeBSD. The install script
|
||||||
[attempts to use the system package manager](#detection-reference) if possible.
|
[attempts to use the system package manager](#detection-reference) if possible.
|
||||||
|
|
||||||
You can preview what occurs during the install process:
|
You can preview what occurs during the install process:
|
||||||
|
@ -67,7 +67,7 @@ code-server.
|
||||||
|
|
||||||
If you prefer to install code-server manually, despite the [detection
|
If you prefer to install code-server manually, despite the [detection
|
||||||
references](#detection-reference) and `--dry-run` feature, then continue on for
|
references](#detection-reference) and `--dry-run` feature, then continue on for
|
||||||
information on how to do this. The [`install.sh`](https://github.com/coder/code-server/blob/main/install.sh) script runs the
|
information on how to do this. The [`install.sh`](../install.sh) script runs the
|
||||||
_exact_ same commands presented in the rest of this document.
|
_exact_ same commands presented in the rest of this document.
|
||||||
|
|
||||||
### Detection reference
|
### Detection reference
|
||||||
|
@ -104,7 +104,7 @@ We recommend installing with `yarn` or `npm` when:
|
||||||
1. You're on Linux with `glibc` < v2.17, `glibcxx` < v3.4.18 on `amd64`, `glibc`
|
1. You're on Linux with `glibc` < v2.17, `glibcxx` < v3.4.18 on `amd64`, `glibc`
|
||||||
< v2.23, or `glibcxx` < v3.4.21 on `arm64`.
|
< v2.23, or `glibcxx` < v3.4.21 on `arm64`.
|
||||||
1. You're running Alpine Linux or are using a non-glibc libc. See
|
1. You're running Alpine Linux or are using a non-glibc libc. See
|
||||||
[#1430](https://github.com/coder/code-server/issues/1430#issuecomment-629883198)
|
[#1430](https://github.com/cdr/code-server/issues/1430#issuecomment-629883198)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
Installing code-server with `yarn` or `npm` builds native modules on install.
|
Installing code-server with `yarn` or `npm` builds native modules on install.
|
||||||
|
@ -114,7 +114,7 @@ This process requires C dependencies; see our guide on [installing with yarn and
|
||||||
## Standalone releases
|
## Standalone releases
|
||||||
|
|
||||||
We publish self-contained `.tar.gz` archives for every release on
|
We publish self-contained `.tar.gz` archives for every release on
|
||||||
[GitHub](https://github.com/coder/code-server/releases). The archives bundle the
|
[GitHub](https://github.com/cdr/code-server/releases). The archives bundle the
|
||||||
node binary and node modules.
|
node binary and node modules.
|
||||||
|
|
||||||
We create the standalone releases using the [npm package](#yarn-npm), and we
|
We create the standalone releases using the [npm package](#yarn-npm), and we
|
||||||
|
@ -127,7 +127,7 @@ requirement).
|
||||||
To use a standalone release:
|
To use a standalone release:
|
||||||
|
|
||||||
1. Download the latest release archive for your system from
|
1. Download the latest release archive for your system from
|
||||||
[GitHub](https://github.com/coder/code-server/releases).
|
[GitHub](https://github.com/cdr/code-server/releases).
|
||||||
2. Unpack the release.
|
2. Unpack the release.
|
||||||
3. Run code-server by executing `./bin/code-server`.
|
3. Run code-server by executing `./bin/code-server`.
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ release on Linux:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mkdir -p ~/.local/lib ~/.local/bin
|
mkdir -p ~/.local/lib ~/.local/bin
|
||||||
curl -fL https://github.com/coder/code-server/releases/download/v$VERSION/code-server-$VERSION-linux-amd64.tar.gz \
|
curl -fL https://github.com/cdr/code-server/releases/download/v$VERSION/code-server-$VERSION-linux-amd64.tar.gz \
|
||||||
| tar -C ~/.local/lib -xz
|
| tar -C ~/.local/lib -xz
|
||||||
mv ~/.local/lib/code-server-$VERSION-linux-amd64 ~/.local/lib/code-server-$VERSION
|
mv ~/.local/lib/code-server-$VERSION-linux-amd64 ~/.local/lib/code-server-$VERSION
|
||||||
ln -s ~/.local/lib/code-server-$VERSION/bin/code-server ~/.local/bin/code-server
|
ln -s ~/.local/lib/code-server-$VERSION/bin/code-server ~/.local/bin/code-server
|
||||||
|
@ -154,7 +154,7 @@ code-server
|
||||||
> upgrade or [build with yarn](#yarn-npm).
|
> upgrade or [build with yarn](#yarn-npm).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fOL https://github.com/coder/code-server/releases/download/v$VERSION/code-server_$VERSION_amd64.deb
|
curl -fOL https://github.com/cdr/code-server/releases/download/v$VERSION/code-server_$VERSION_amd64.deb
|
||||||
sudo dpkg -i code-server_$VERSION_amd64.deb
|
sudo dpkg -i code-server_$VERSION_amd64.deb
|
||||||
sudo systemctl enable --now code-server@$USER
|
sudo systemctl enable --now code-server@$USER
|
||||||
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
||||||
|
@ -166,7 +166,7 @@ sudo systemctl enable --now code-server@$USER
|
||||||
> with yarn](#yarn-npm).
|
> with yarn](#yarn-npm).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fOL https://github.com/coder/code-server/releases/download/v$VERSION/code-server-$VERSION-amd64.rpm
|
curl -fOL https://github.com/cdr/code-server/releases/download/v$VERSION/code-server-$VERSION-amd64.rpm
|
||||||
sudo rpm -i code-server-$VERSION-amd64.rpm
|
sudo rpm -i code-server-$VERSION-amd64.rpm
|
||||||
sudo systemctl enable --now code-server@$USER
|
sudo systemctl enable --now code-server@$USER
|
||||||
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
||||||
|
@ -228,9 +228,9 @@ You can install code-server using the [Helm package manager](https://coder.com/d
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
We currently [do not publish Windows releases](https://github.com/coder/code-server/issues/1397). We recommend installing code-server onto Windows with [`yarn` or `npm`](#yarn-npm).
|
We currently [do not publish Windows releases](https://github.com/cdr/code-server/issues/1397). We recommend installing code-server onto Windows with [`yarn` or `npm`](#yarn-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.
|
> Note: You will also need to [build cdr/cloud-agent manually](https://github.com/cdr/cloud-agent/issues/17) if you would like to use `code-server --link` on Windows.
|
||||||
|
|
||||||
## Raspberry Pi
|
## Raspberry Pi
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ information.
|
||||||
## Cloud providers
|
## Cloud providers
|
||||||
|
|
||||||
We maintain [one-click apps and install scripts for cloud
|
We maintain [one-click apps and install scripts for cloud
|
||||||
providers](https://github.com/coder/deploy-code-server) such as DigitalOcean,
|
providers](https://github.com/cdr/deploy-code-server) such as DigitalOcean,
|
||||||
Railway, Heroku, and Azure.
|
Railway, Heroku, and Azure.
|
||||||
|
|
||||||
## Uninstall
|
## Uninstall
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
# Using code-server on iOS with iSH
|
|
||||||
|
|
||||||
1. Install iSH from the [App Store](https://apps.apple.com/us/app/ish-shell/id1436902243)
|
|
||||||
2. Install `curl` with `apk add curl`
|
|
||||||
3. Install code-server with `curl -fsSL https://code-server.dev/install.sh | sh`
|
|
||||||
4. Run code-server with `code-server`
|
|
||||||
5. Access on localhost:8080 in your browser
|
|
14
docs/ipad.md
14
docs/ipad.md
|
@ -104,7 +104,7 @@ and tricks helpful:
|
||||||
process](#access-code-server-with-a-self-signed-certificate-on-an-ipad)
|
process](#access-code-server-with-a-self-signed-certificate-on-an-ipad)
|
||||||
- Keyboard issues:
|
- Keyboard issues:
|
||||||
- The keyboard disappear sometimes
|
- The keyboard disappear sometimes
|
||||||
[#979](https://github.com/coder/code-server/issues/979)
|
[#979](https://github.com/cdr/code-server/issues/979)
|
||||||
- Some expectations regarding shortcuts may not be met:
|
- Some expectations regarding shortcuts may not be met:
|
||||||
- `cmd + n` opens new browser window instead of new file, and it's difficult
|
- `cmd + n` opens new browser window instead of new file, and it's difficult
|
||||||
to set alternative as a workaround
|
to set alternative as a workaround
|
||||||
|
@ -112,18 +112,18 @@ and tricks helpful:
|
||||||
- There's no escape key by default on the Magic Keyboard, so most users set
|
- There's no escape key by default on the Magic Keyboard, so most users set
|
||||||
the globe key to be an escape key
|
the globe key to be an escape key
|
||||||
- Trackpad scrolling does not work on iPadOS < 14.5
|
- Trackpad scrolling does not work on iPadOS < 14.5
|
||||||
([#1455](https://github.com/coder/code-server/issues/1455))
|
([#1455](https://github.com/cdr/code-server/issues/1455))
|
||||||
- [WebKit fix](https://bugs.webkit.org/show_bug.cgi?id=210071#c13)
|
- [WebKit fix](https://bugs.webkit.org/show_bug.cgi?id=210071#c13)
|
||||||
- Keyboard may lose focus in Safari / split view [#4182](https://github.com/coder/code-server/issues/4182)
|
- Keyboard may lose focus in Safari / split view [#4182](https://github.com/cdr/code-server/issues/4182)
|
||||||
- Terminal text does not appear by default [#3824](https://github.com/coder/code-server/issues/3824)
|
- Terminal text does not appear by default [#3824](https://github.com/cdr/code-server/issues/3824)
|
||||||
- Copy & paste in terminal does not work well with keyboard shortcuts [#3491](https://github.com/coder/code-server/issues/3491)
|
- Copy & paste in terminal does not work well with keyboard shortcuts [#3491](https://github.com/cdr/code-server/issues/3491)
|
||||||
- `ctrl+c` does not stop a long-running process in the browser
|
- `ctrl+c` does not stop a long-running process in the browser
|
||||||
- Tracking upstream issue here:
|
- Tracking upstream issue here:
|
||||||
[#114009](https://github.com/microsoft/vscode/issues/114009)
|
[#114009](https://github.com/microsoft/vscode/issues/114009)
|
||||||
- See [workaround](#ctrl-c-workaround)
|
- See [workaround](#ctrl-c-workaround)
|
||||||
|
|
||||||
Additionally, see [issues in the code-server repo that are tagged with the `os-ios`
|
Additionally, see [issues in the code-server repo that are tagged with the iPad
|
||||||
label](https://github.com/coder/code-server/issues?q=is%3Aopen+is%3Aissue+label%3Aos-ios)
|
label](https://github.com/cdr/code-server/issues?q=is%3Aopen+is%3Aissue+label%3AiPad)
|
||||||
for more information.
|
for more information.
|
||||||
|
|
||||||
### Workaround for issue with `ctrl+c` not stopping a running process in the terminal
|
### Workaround for issue with `ctrl+c` not stopping a running process in the terminal
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
# code-server --link
|
# code-server --link
|
||||||
|
|
||||||
> Note: This feature is no longer recommended due to instability. Stay tuned for a revised version.
|
Run code-server with the beta flag `--link` and you'll get TLS, authentication, and a dedicated URL
|
||||||
|
|
||||||
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.
|
for accessing your IDE out of the box.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ code-server --link
|
$ code-server --link
|
||||||
Proxying code-server, you can access your IDE at https://example.coder.co
|
Proxying code-server, you can access your IDE at https://example.cdr.co
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"versions": ["v4.0.2"],
|
"versions": ["v3.12.0"],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"title": "Home",
|
"title": "Home",
|
||||||
|
@ -51,16 +51,6 @@
|
||||||
"title": "Termux",
|
"title": "Termux",
|
||||||
"description": "How to install Termux to run code-server on an Android device.",
|
"description": "How to install Termux to run code-server on an Android device.",
|
||||||
"path": "./termux.md"
|
"path": "./termux.md"
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "iOS",
|
|
||||||
"description": "How to use code-server on iOS with iSH.",
|
|
||||||
"path": "./ios.md"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"title": "Android",
|
|
||||||
"description": "How to run code-server on an Android device using UserLAnd.",
|
|
||||||
"path": "./android.md"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -73,7 +63,7 @@
|
||||||
{
|
{
|
||||||
"title": "Upgrade",
|
"title": "Upgrade",
|
||||||
"description": "How to upgrade code-server.",
|
"description": "How to upgrade code-server.",
|
||||||
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.35028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z\"/><path d=\"M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0.12 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z\"/><path d=\"M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944 3.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z\"/><path d=\"M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z\"/></svg>",
|
"icon": "<svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M17.8049 2.19795C17.7385 2.1311 17.6587 2.07899 17.5708 2.04504C17.4829 2.01108 17.3889 1.99604 17.2948 2.00089C7.89216 2.49153 4.4188 10.8673 4.38528 10.9517C4.33624 11.0736 4.32406 11.2071 4.35028 11.3358C4.3765 11.4645 4.43995 11.5827 4.53274 11.6756L8.32449 15.4674C8.41787 15.5606 8.53669 15.6242 8.66606 15.6502C8.79543 15.6762 8.92959 15.6634 9.05174 15.6135C9.13552 15.5793 17.4664 12.0671 17.9986 2.7087C18.0039 2.61474 17.9895 2.5207 17.9561 2.4327C17.9227 2.3447 17.8712 2.26471 17.8049 2.19795ZM12.3314 9.56427C12.1439 9.75179 11.9051 9.87951 11.645 9.93126C11.385 9.98302 11.1154 9.9565 10.8704 9.85505C10.6254 9.7536 10.4161 9.58178 10.2687 9.36131C10.1214 9.14085 10.0428 8.88166 10.0428 8.6165C10.0428 8.35135 10.1214 8.09215 10.2687 7.87169C10.4161 7.65123 10.6254 7.47941 10.8704 7.37796C11.1154 7.27651 11.385 7.24998 11.645 7.30174C11.9051 7.3535 12.1439 7.48121 12.3314 7.66873C12.5827 7.92012 12.7239 8.26104 12.7239 8.6165C12.7239 8.97197 12.5827 9.31288 12.3314 9.56427Z\"/><path d=\"M2.74602 14.5444C2.92281 14.3664 3.133 14.2251 3.36454 14.1285C3.59608 14.0319 3.8444 13.9819 4.09529 13.9815C4.34617 13.9811 4.59466 14.0302 4.82653 14.126C5.05839 14.2218 5.26907 14.3624 5.44647 14.5398C5.62386 14.7172 5.7645 14.9279 5.86031 15.1598C5.95612 15.3916 6.00522 15.6401 6.00479 15.891C6.00437 16.1419 5.95442 16.3902 5.85782 16.6218C5.76122 16.8533 5.61987 17.0635 5.44186 17.2403C4.69719 17.985 2 18.0004 2 18.0004C2 18.0004 2 15.2884 2.74602 14.5444Z\"/><path d=\"M8.9416 3.48269C7.99688 3.31826 7.02645 3.38371 6.11237 3.67352C5.19828 3.96332 4.36741 4.46894 3.68999 5.14765C3.33153 5.50944 3.01988 5.91477 2.76233 6.35415C2.68692 6.4822 2.6562 6.63169 2.67501 6.77911C2.69381 6.92652 2.76108 7.06351 2.86623 7.16853L4.1994 8.50238C5.43822 6.53634 7.04911 4.83119 8.9416 3.48269Z\"/><path d=\"M16.5181 11.0585C16.6825 12.0033 16.6171 12.9737 16.3273 13.8878C16.0375 14.8019 15.5318 15.6327 14.8531 16.3101C14.4914 16.6686 14.086 16.9803 13.6466 17.2378C13.5186 17.3132 13.3691 17.3439 13.2217 17.3251C13.0743 17.3063 12.9373 17.2391 12.8323 17.1339L11.4984 15.8007C13.4645 14.5619 15.1696 12.951 16.5181 11.0585Z\"/></svg>",
|
||||||
"path": "./upgrade.md"
|
"path": "./upgrade.md"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ which is currently `14.x`. VS Code also [lists Node.js
|
||||||
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||||
|
|
||||||
Using other versions of Node.js [may lead to unexpected
|
Using other versions of Node.js [may lead to unexpected
|
||||||
behavior](https://github.com/coder/code-server/issues/1633).
|
behavior](https://github.com/cdr/code-server/issues/1633).
|
||||||
|
|
||||||
## Ubuntu, Debian
|
## Ubuntu, Debian
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ yarn global bin
|
||||||
# Or: npm config get prefix
|
# Or: npm config get prefix
|
||||||
```
|
```
|
||||||
|
|
||||||
For help and additional troubleshooting, see [#1397](https://github.com/coder/code-server/issues/1397).
|
For help and additional troubleshooting, see [#1397](https://github.com/cdr/code-server/issues/1397).
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ code-server
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
If you need further assistance, post on our [GitHub Discussions
|
If you need further assistance, post on our [GitHub Discussions
|
||||||
page](https://github.com/coder/code-server/discussions).
|
page](https://github.com/cdr/code-server/discussions).
|
||||||
|
|
||||||
### Issues with Node.js after version upgrades
|
### Issues with Node.js after version upgrades
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ new Compute Engine VM instance:
|
||||||
4. Choose the **region** that's closest to you based on [GCP
|
4. Choose the **region** that's closest to you based on [GCP
|
||||||
ping](https://gcping.com/).
|
ping](https://gcping.com/).
|
||||||
5. Choose a **zone** (any option is fine).
|
5. Choose a **zone** (any option is fine).
|
||||||
6. We recommend choosing an **E2 series instance** from the [general-purpose
|
6. We recommend choose an **E2 series instance** from the [general-purpose
|
||||||
family](https://cloud.google.com/compute/docs/machine-types#general_purpose).
|
family](https://cloud.google.com/compute/docs/machine-types#general_purpose).
|
||||||
7. Change the instance type to **custom** and set at least **2 cores** and **2
|
7. Change the instance type to **custom** and set at least **2 cores** and **2
|
||||||
GB of RAM**. You can add more resources if desired, though you can also edit
|
GB of RAM**. You can add more resources if desired, though you can also edit
|
||||||
|
|
|
@ -28,8 +28,8 @@ This will show issues that:
|
||||||
1. If more information is required, please ask the submitter and tag as
|
1. If more information is required, please ask the submitter and tag as
|
||||||
`waiting-for-info` and wait.
|
`waiting-for-info` and wait.
|
||||||
1. Finally, the issue should be moved into the
|
1. Finally, the issue should be moved into the
|
||||||
[code-server](https://github.com/coder/code-server/projects/1) project where we
|
[code-server](https://github.com/cdr/code-server/projects/1) project where we
|
||||||
pick out issues to fix and track their progress.
|
pick out issues to fix and track their progress.
|
||||||
|
|
||||||
We also use [milestones](https://github.com/coder/code-server/milestones) to track
|
We also use [milestones](https://github.com/cdr/code-server/milestones) to track
|
||||||
what issues are planned/or were closed for what release.
|
what issues are planned/or were closed for what release.
|
||||||
|
|
25
install.sh
25
install.sh
|
@ -23,7 +23,7 @@ The remote host must have internet access.
|
||||||
${not_curl_usage-}
|
${not_curl_usage-}
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
$arg0 [--dry-run] [--version X.X.X] [--edge] [--method detect] \
|
$arg0 [--dry-run] [--version X.X.X] [--method detect] \
|
||||||
[--prefix ~/.local] [--rsh ssh] [user@host]
|
[--prefix ~/.local] [--rsh ssh] [user@host]
|
||||||
|
|
||||||
--dry-run
|
--dry-run
|
||||||
|
@ -32,9 +32,6 @@ Usage:
|
||||||
--version X.X.X
|
--version X.X.X
|
||||||
Install a specific version instead of the latest.
|
Install a specific version instead of the latest.
|
||||||
|
|
||||||
--edge
|
|
||||||
Install the latest edge version instead of the latest stable version.
|
|
||||||
|
|
||||||
--method [detect | standalone]
|
--method [detect | standalone]
|
||||||
Choose the installation method. Defaults to detect.
|
Choose the installation method. Defaults to detect.
|
||||||
- detect detects the system package manager and tries to use it.
|
- detect detects the system package manager and tries to use it.
|
||||||
|
@ -74,13 +71,9 @@ EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
echo_latest_version() {
|
echo_latest_version() {
|
||||||
if [ "${EDGE-}" ]; then
|
# https://gist.github.com/lukechilds/a83e1d7127b78fef38c2914c4ececc3c#gistcomment-2758860
|
||||||
version="$(curl -fsSL https://api.github.com/repos/coder/code-server/releases | awk 'match($0,/.*"html_url": "(.*\/releases\/tag\/.*)".*/)' | head -n 1 | awk -F '"' '{print $4}')"
|
version="$(curl -fsSLI -o /dev/null -w "%{url_effective}" https://github.com/cdr/code-server/releases/latest)"
|
||||||
else
|
version="${version#https://github.com/cdr/code-server/releases/tag/}"
|
||||||
# https://gist.github.com/lukechilds/a83e1d7127b78fef38c2914c4ececc3c#gistcomment-2758860
|
|
||||||
version="$(curl -fsSLI -o /dev/null -w "%{url_effective}" https://github.com/coder/code-server/releases/latest)"
|
|
||||||
fi
|
|
||||||
version="${version#https://github.com/coder/code-server/releases/tag/}"
|
|
||||||
version="${version#v}"
|
version="${version#v}"
|
||||||
echo "$version"
|
echo "$version"
|
||||||
}
|
}
|
||||||
|
@ -142,7 +135,6 @@ main() {
|
||||||
OPTIONAL \
|
OPTIONAL \
|
||||||
ALL_FLAGS \
|
ALL_FLAGS \
|
||||||
RSH_ARGS \
|
RSH_ARGS \
|
||||||
EDGE \
|
|
||||||
RSH
|
RSH
|
||||||
|
|
||||||
ALL_FLAGS=""
|
ALL_FLAGS=""
|
||||||
|
@ -178,9 +170,6 @@ main() {
|
||||||
--version=*)
|
--version=*)
|
||||||
VERSION="$(parse_arg "$@")"
|
VERSION="$(parse_arg "$@")"
|
||||||
;;
|
;;
|
||||||
--edge)
|
|
||||||
EDGE=1
|
|
||||||
;;
|
|
||||||
--rsh)
|
--rsh)
|
||||||
RSH="$(parse_arg "$@")"
|
RSH="$(parse_arg "$@")"
|
||||||
shift
|
shift
|
||||||
|
@ -351,7 +340,7 @@ install_deb() {
|
||||||
echoh "Installing v$VERSION of the $ARCH deb package from GitHub."
|
echoh "Installing v$VERSION of the $ARCH deb package from GitHub."
|
||||||
echoh
|
echoh
|
||||||
|
|
||||||
fetch "https://github.com/coder/code-server/releases/download/v$VERSION/code-server_${VERSION}_$ARCH.deb" \
|
fetch "https://github.com/cdr/code-server/releases/download/v$VERSION/code-server_${VERSION}_$ARCH.deb" \
|
||||||
"$CACHE_DIR/code-server_${VERSION}_$ARCH.deb"
|
"$CACHE_DIR/code-server_${VERSION}_$ARCH.deb"
|
||||||
sudo_sh_c dpkg -i "$CACHE_DIR/code-server_${VERSION}_$ARCH.deb"
|
sudo_sh_c dpkg -i "$CACHE_DIR/code-server_${VERSION}_$ARCH.deb"
|
||||||
|
|
||||||
|
@ -362,7 +351,7 @@ install_rpm() {
|
||||||
echoh "Installing v$VERSION of the $ARCH rpm package from GitHub."
|
echoh "Installing v$VERSION of the $ARCH rpm package from GitHub."
|
||||||
echoh
|
echoh
|
||||||
|
|
||||||
fetch "https://github.com/coder/code-server/releases/download/v$VERSION/code-server-$VERSION-$ARCH.rpm" \
|
fetch "https://github.com/cdr/code-server/releases/download/v$VERSION/code-server-$VERSION-$ARCH.rpm" \
|
||||||
"$CACHE_DIR/code-server-$VERSION-$ARCH.rpm"
|
"$CACHE_DIR/code-server-$VERSION-$ARCH.rpm"
|
||||||
sudo_sh_c rpm -i "$CACHE_DIR/code-server-$VERSION-$ARCH.rpm"
|
sudo_sh_c rpm -i "$CACHE_DIR/code-server-$VERSION-$ARCH.rpm"
|
||||||
|
|
||||||
|
@ -388,7 +377,7 @@ install_standalone() {
|
||||||
echoh "Installing v$VERSION of the $ARCH release from GitHub."
|
echoh "Installing v$VERSION of the $ARCH release from GitHub."
|
||||||
echoh
|
echoh
|
||||||
|
|
||||||
fetch "https://github.com/coder/code-server/releases/download/v$VERSION/code-server-$VERSION-$OS-$ARCH.tar.gz" \
|
fetch "https://github.com/cdr/code-server/releases/download/v$VERSION/code-server-$VERSION-$OS-$ARCH.tar.gz" \
|
||||||
"$CACHE_DIR/code-server-$VERSION-$OS-$ARCH.tar.gz"
|
"$CACHE_DIR/code-server-$VERSION-$OS-$ARCH.tar.gz"
|
||||||
|
|
||||||
# -w only works if the directory exists so try creating it first. If this
|
# -w only works if the directory exists so try creating it first. If this
|
||||||
|
|
30
package.json
30
package.json
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "code-server",
|
"name": "code-server",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "4.0.2",
|
"version": "3.12.0",
|
||||||
"description": "Run VS Code on a remote server.",
|
"description": "Run VS Code on a remote server.",
|
||||||
"homepage": "https://github.com/coder/code-server",
|
"homepage": "https://github.com/cdr/code-server",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/coder/code-server/issues"
|
"url": "https://github.com/cdr/code-server/issues"
|
||||||
},
|
},
|
||||||
"repository": "https://github.com/coder/code-server",
|
"repository": "https://github.com/cdr/code-server",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "./ci/build/clean.sh",
|
"clean": "./ci/build/clean.sh",
|
||||||
"build": "./ci/build/build-code-server.sh",
|
"build": "./ci/build/build-code-server.sh",
|
||||||
|
@ -17,13 +17,12 @@
|
||||||
"release:github-draft": "./ci/build/release-github-draft.sh",
|
"release:github-draft": "./ci/build/release-github-draft.sh",
|
||||||
"release:github-assets": "./ci/build/release-github-assets.sh",
|
"release:github-assets": "./ci/build/release-github-assets.sh",
|
||||||
"release:prep": "./ci/build/release-prep.sh",
|
"release:prep": "./ci/build/release-prep.sh",
|
||||||
"test:e2e": "VSCODE_IPC_HOOK_CLI= ./ci/dev/test-e2e.sh",
|
"test:e2e": "./ci/dev/test-e2e.sh",
|
||||||
"test:standalone-release": "./ci/build/test-standalone-release.sh",
|
"test:standalone-release": "./ci/build/test-standalone-release.sh",
|
||||||
"test:unit": "./ci/dev/test-unit.sh --forceExit --detectOpenHandles",
|
"test:unit": "./ci/dev/test-unit.sh --forceExit --detectOpenHandles",
|
||||||
"test:scripts": "./ci/dev/test-scripts.sh",
|
"test:scripts": "./ci/dev/test-scripts.sh",
|
||||||
"package": "./ci/build/build-packages.sh",
|
"package": "./ci/build/build-packages.sh",
|
||||||
"postinstall": "./ci/dev/postinstall.sh",
|
"postinstall": "./ci/dev/postinstall.sh",
|
||||||
"publish:npm": "./ci/steps/publish-npm.sh",
|
|
||||||
"_audit": "./ci/dev/audit.sh",
|
"_audit": "./ci/dev/audit.sh",
|
||||||
"fmt": "./ci/dev/fmt.sh",
|
"fmt": "./ci/dev/fmt.sh",
|
||||||
"lint": "./ci/dev/lint.sh",
|
"lint": "./ci/dev/lint.sh",
|
||||||
|
@ -53,14 +52,15 @@
|
||||||
"@typescript-eslint/parser": "^5.0.0",
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
"audit-ci": "^5.0.0",
|
"audit-ci": "^5.0.0",
|
||||||
"codecov": "^3.8.3",
|
"codecov": "^3.8.3",
|
||||||
|
"del": "^6.0.0",
|
||||||
"doctoc": "^2.0.0",
|
"doctoc": "^2.0.0",
|
||||||
"eslint": "^7.7.0",
|
"eslint": "^7.7.0",
|
||||||
"eslint-config-prettier": "^8.1.0",
|
"eslint-config-prettier": "^8.1.0",
|
||||||
"eslint-import-resolver-typescript": "^2.5.0",
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
"eslint-plugin-import": "^2.18.2",
|
"eslint-plugin-import": "^2.18.2",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
"prettier-plugin-sh": "^0.8.0",
|
"prettier-plugin-sh": "^0.7.1",
|
||||||
"shellcheck": "^1.0.0",
|
"shellcheck": "^1.0.0",
|
||||||
"stylelint": "^13.0.0",
|
"stylelint": "^13.0.0",
|
||||||
"stylelint-config-recommended": "^5.0.0",
|
"stylelint-config-recommended": "^5.0.0",
|
||||||
|
@ -78,10 +78,7 @@
|
||||||
"vfile-message": "^2.0.2",
|
"vfile-message": "^2.0.2",
|
||||||
"tar": "^6.1.9",
|
"tar": "^6.1.9",
|
||||||
"path-parse": "^1.0.7",
|
"path-parse": "^1.0.7",
|
||||||
"vm2": "^3.9.6",
|
"vm2": "^3.9.4"
|
||||||
"follow-redirects": "^1.14.8",
|
|
||||||
"node-fetch": "^2.6.7",
|
|
||||||
"nanoid": "^3.1.31"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coder/logger": "1.1.16",
|
"@coder/logger": "1.1.16",
|
||||||
|
@ -96,7 +93,8 @@
|
||||||
"limiter": "^1.1.5",
|
"limiter": "^1.1.5",
|
||||||
"pem": "^1.14.2",
|
"pem": "^1.14.2",
|
||||||
"proxy-agent": "^5.0.0",
|
"proxy-agent": "^5.0.0",
|
||||||
"qs": "6.10.3",
|
"proxy-from-env": "^1.1.0",
|
||||||
|
"qs": "6.10.1",
|
||||||
"rotating-file-stream": "^3.0.0",
|
"rotating-file-stream": "^3.0.0",
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"safe-compare": "^1.1.4",
|
"safe-compare": "^1.1.4",
|
||||||
|
@ -157,12 +155,10 @@
|
||||||
"<rootDir>/release-standalone",
|
"<rootDir>/release-standalone",
|
||||||
"<rootDir>/release-npm-package",
|
"<rootDir>/release-npm-package",
|
||||||
"<rootDir>/release-gcp",
|
"<rootDir>/release-gcp",
|
||||||
"<rootDir>/release-images",
|
"<rootDir>/release-images"
|
||||||
"<rootDir>/vendor"
|
|
||||||
],
|
],
|
||||||
"moduleNameMapper": {
|
"moduleNameMapper": {
|
||||||
"^.+\\.(css|less)$": "<rootDir>/test/utils/cssStub.ts"
|
"^.+\\.(css|less)$": "<rootDir>/test/utils/cssStub.ts"
|
||||||
},
|
}
|
||||||
"globalSetup": "<rootDir>/test/utils/globalUnitSetup.ts"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<form class="login-form" method="post">
|
<form class="login-form" method="post">
|
||||||
<input class="user" type="text" autocomplete="username" />
|
<input class="user" type="text" autocomplete="username" />
|
||||||
<input id="base" type="hidden" name="base" value="{{BASE}}" />
|
<input id="base" type="hidden" name="base" value="/" />
|
||||||
<input id="href" type="hidden" name="href" value="" />
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<input
|
<input
|
||||||
required
|
required
|
||||||
|
@ -52,9 +51,9 @@
|
||||||
<script>
|
<script>
|
||||||
// Inform the backend about the path since the proxy might have rewritten
|
// Inform the backend about the path since the proxy might have rewritten
|
||||||
// it out of the headers and cookies must be set with absolute paths.
|
// it out of the headers and cookies must be set with absolute paths.
|
||||||
const el = document.getElementById("href")
|
const el = document.getElementById("base")
|
||||||
if (el) {
|
if (el) {
|
||||||
el.value = location.href
|
el.value = window.location.pathname
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -13,12 +13,8 @@ export enum HttpCode {
|
||||||
* used in the HTTP response.
|
* used in the HTTP response.
|
||||||
*/
|
*/
|
||||||
export class HttpError extends Error {
|
export class HttpError extends Error {
|
||||||
public constructor(message: string, public readonly statusCode: HttpCode, public readonly details?: object) {
|
public constructor(message: string, public readonly status: HttpCode, public readonly details?: object) {
|
||||||
super(message)
|
super(message)
|
||||||
this.name = this.constructor.name
|
this.name = this.constructor.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CookieKeys {
|
|
||||||
Session = "code-server-session",
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,12 +23,6 @@ export const generateUuid = (length = 24): string => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove extra slashes in a URL.
|
* Remove extra slashes in a URL.
|
||||||
*
|
|
||||||
* This is meant to fill the job of `path.join` so you can concatenate paths and
|
|
||||||
* then normalize out any extra slashes.
|
|
||||||
*
|
|
||||||
* If you are using `path.join` you do not need this but note that `path` is for
|
|
||||||
* file system paths, not URLs.
|
|
||||||
*/
|
*/
|
||||||
export const normalize = (url: string, keepTrailing = false): string => {
|
export const normalize = (url: string, keepTrailing = false): string => {
|
||||||
return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "")
|
return url.replace(/\/\/+/g, "/").replace(/\/+$/, keepTrailing ? "/" : "")
|
||||||
|
@ -41,6 +35,21 @@ export const trimSlashes = (url: string): string => {
|
||||||
return url.replace(/^\/+|\/+$/g, "")
|
return url.replace(/^\/+|\/+$/g, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a relative base against the window location. This is used for
|
||||||
|
* anything that doesn't work with a relative path.
|
||||||
|
*/
|
||||||
|
export const resolveBase = (base?: string): string => {
|
||||||
|
// After resolving the base will either start with / or be an empty string.
|
||||||
|
if (!base || base.startsWith("/")) {
|
||||||
|
return base ?? ""
|
||||||
|
}
|
||||||
|
const parts = location.pathname.split("/")
|
||||||
|
parts[parts.length - 1] = base
|
||||||
|
const url = new URL(location.origin + "/" + parts.join("/"))
|
||||||
|
return normalize(url.pathname)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap the value in an array if it's not already an array. If the value is
|
* Wrap the value in an array if it's not already an array. If the value is
|
||||||
* undefined return an empty array.
|
* undefined return an empty array.
|
||||||
|
|
|
@ -57,7 +57,6 @@ export interface UserProvidedArgs {
|
||||||
enable?: string[]
|
enable?: string[]
|
||||||
help?: boolean
|
help?: boolean
|
||||||
host?: string
|
host?: string
|
||||||
locale?: string
|
|
||||||
port?: number
|
port?: number
|
||||||
json?: boolean
|
json?: boolean
|
||||||
log?: LogLevel
|
log?: LogLevel
|
||||||
|
@ -105,9 +104,9 @@ interface Option<T> {
|
||||||
description?: string
|
description?: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If marked as deprecated, the option is marked as deprecated in help.
|
* If marked as beta, the option is marked as beta in help.
|
||||||
*/
|
*/
|
||||||
deprecated?: boolean
|
beta?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type OptionType<T> = T extends boolean
|
type OptionType<T> = T extends boolean
|
||||||
|
@ -164,7 +163,6 @@ const options: Options<Required<UserProvidedArgs>> = {
|
||||||
enable: { type: "string[]" },
|
enable: { type: "string[]" },
|
||||||
help: { type: "boolean", short: "h", description: "Show this output." },
|
help: { type: "boolean", short: "h", description: "Show this output." },
|
||||||
json: { type: "boolean" },
|
json: { type: "boolean" },
|
||||||
locale: { type: "string" }, // The preferred way to set the locale is via the UI.
|
|
||||||
open: { type: "boolean", description: "Open in browser on startup. Does not work remotely." },
|
open: { type: "boolean", description: "Open in browser on startup. Does not work remotely." },
|
||||||
|
|
||||||
"bind-addr": {
|
"bind-addr": {
|
||||||
|
@ -229,10 +227,10 @@ const options: Options<Required<UserProvidedArgs>> = {
|
||||||
type: OptionalString,
|
type: OptionalString,
|
||||||
description: `
|
description: `
|
||||||
Securely bind code-server via our cloud service with the passed name. You'll get a URL like
|
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.
|
https://hostname-username.cdr.co at which you can easily access your code-server instance.
|
||||||
Authorization is done via GitHub.
|
Authorization is done via GitHub.
|
||||||
`,
|
`,
|
||||||
deprecated: true,
|
beta: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +253,7 @@ export const optionDescriptions = (): string[] => {
|
||||||
.map((line, i) => {
|
.map((line, i) => {
|
||||||
line = line.trim()
|
line = line.trim()
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
return " ".repeat(widths.long - k.length) + (v.deprecated ? "(deprecated) " : "") + line
|
return " ".repeat(widths.long - k.length) + (v.beta ? "(beta) " : "") + line
|
||||||
}
|
}
|
||||||
return " ".repeat(widths.long + widths.short + 6) + line
|
return " ".repeat(widths.long + widths.short + 6) + line
|
||||||
})
|
})
|
||||||
|
@ -407,10 +405,7 @@ export const parse = (
|
||||||
throw new Error("--cert-key is missing")
|
throw new Error("--cert-key is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug(() => [
|
logger.debug(() => ["parsed command line", field("args", { ...args, password: undefined })])
|
||||||
`parsed ${opts?.configFile ? "config" : "command line"}`,
|
|
||||||
field("args", { ...args, password: undefined }),
|
|
||||||
])
|
|
||||||
|
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
@ -435,6 +430,8 @@ export interface DefaultedArgs extends ConfigArgs {
|
||||||
"user-data-dir": string
|
"user-data-dir": string
|
||||||
/* Positional arguments. */
|
/* Positional arguments. */
|
||||||
_: []
|
_: []
|
||||||
|
folder: string
|
||||||
|
workspace: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -542,8 +539,25 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||||
args._ = []
|
args._ = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let workspace = ""
|
||||||
|
let folder = ""
|
||||||
|
if (args._.length) {
|
||||||
|
const lastEntry = path.resolve(process.cwd(), args._[args._.length - 1])
|
||||||
|
const entryIsFile = await isFile(lastEntry)
|
||||||
|
|
||||||
|
if (entryIsFile && path.extname(lastEntry) === ".code-workspace") {
|
||||||
|
workspace = lastEntry
|
||||||
|
args._.pop()
|
||||||
|
} else if (!entryIsFile) {
|
||||||
|
folder = lastEntry
|
||||||
|
args._.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...args,
|
...args,
|
||||||
|
workspace,
|
||||||
|
folder,
|
||||||
usingEnvPassword,
|
usingEnvPassword,
|
||||||
usingEnvHashedPassword,
|
usingEnvHashedPassword,
|
||||||
} as DefaultedArgs // TODO: Technically no guarantee this is fulfilled.
|
} as DefaultedArgs // TODO: Technically no guarantee this is fulfilled.
|
||||||
|
@ -746,34 +760,3 @@ export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Prom
|
||||||
|
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert our arguments to VS Code server arguments.
|
|
||||||
*/
|
|
||||||
export const toVsCodeArgs = async (args: DefaultedArgs): Promise<CodeServerLib.ServerParsedArgs> => {
|
|
||||||
let workspace = ""
|
|
||||||
let folder = ""
|
|
||||||
if (args._.length) {
|
|
||||||
const lastEntry = path.resolve(args._[args._.length - 1])
|
|
||||||
const entryIsFile = await isFile(lastEntry)
|
|
||||||
if (entryIsFile && path.extname(lastEntry) === ".code-workspace") {
|
|
||||||
workspace = lastEntry
|
|
||||||
} else if (!entryIsFile) {
|
|
||||||
folder = lastEntry
|
|
||||||
}
|
|
||||||
// Otherwise it is a regular file. Spawning VS Code with a file is not yet
|
|
||||||
// supported but it can be done separately after code-server spawns.
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"connection-token": "0000",
|
|
||||||
...args,
|
|
||||||
workspace,
|
|
||||||
folder,
|
|
||||||
"accept-server-license-terms": true,
|
|
||||||
/** Type casting. */
|
|
||||||
help: !!args.help,
|
|
||||||
version: !!args.version,
|
|
||||||
port: args.port?.toString(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { spawn } from "child_process"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import split2 from "split2"
|
import split2 from "split2"
|
||||||
|
|
||||||
// https://github.com/coder/coder-cloud
|
// https://github.com/cdr/coder-cloud
|
||||||
const coderCloudAgent = path.resolve(__dirname, "../../lib/coder-cloud-agent")
|
const coderCloudAgent = path.resolve(__dirname, "../../lib/coder-cloud-agent")
|
||||||
|
|
||||||
function runAgent(...args: string[]): Promise<void> {
|
function runAgent(...args: string[]): Promise<void> {
|
||||||
|
|
|
@ -25,5 +25,3 @@ export const rootPath = path.resolve(__dirname, "../..")
|
||||||
export const vsRootPath = path.join(rootPath, "vendor/modules/code-oss-dev")
|
export const vsRootPath = path.join(rootPath, "vendor/modules/code-oss-dev")
|
||||||
export const tmpdir = path.join(os.tmpdir(), "code-server")
|
export const tmpdir = path.join(os.tmpdir(), "code-server")
|
||||||
export const isDevMode = commit === "development"
|
export const isDevMode = commit === "development"
|
||||||
export const httpProxyUri =
|
|
||||||
process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy
|
|
||||||
|
|
|
@ -1,10 +1,32 @@
|
||||||
import { logger } from "@coder/logger"
|
import { logger } from "@coder/logger"
|
||||||
import { optionDescriptions, parse, readConfigFile, setDefaults, shouldOpenInExistingInstance } from "./cli"
|
import { optionDescriptions, parse, readConfigFile, setDefaults, shouldOpenInExistingInstance } from "./cli"
|
||||||
import { commit, version } from "./constants"
|
import { commit, pkgName, version } from "./constants"
|
||||||
import { openInExistingInstance, runCodeServer, runVsCodeCli, shouldSpawnCliProcess } from "./main"
|
import { openInExistingInstance, runCodeServer, runVsCodeCli, shouldSpawnCliProcess } from "./main"
|
||||||
|
import { monkeyPatchProxyProtocols } from "./proxy_agent"
|
||||||
|
import { loadAMDModule } from "./util"
|
||||||
import { isChild, wrapper } from "./wrapper"
|
import { isChild, wrapper } from "./wrapper"
|
||||||
|
|
||||||
|
const cliPipe = process.env["VSCODE_IPC_HOOK_CLI"] as string
|
||||||
|
const cliCommand = process.env["VSCODE_CLIENT_COMMAND"] as string
|
||||||
|
|
||||||
async function entry(): Promise<void> {
|
async function entry(): Promise<void> {
|
||||||
|
monkeyPatchProxyProtocols()
|
||||||
|
|
||||||
|
if (cliPipe || cliCommand) {
|
||||||
|
const remoteAgentMain = await loadAMDModule<CodeServerLib.RemoteCLIMain>("vs/server/remoteCli", "main")
|
||||||
|
|
||||||
|
remoteAgentMain(
|
||||||
|
{
|
||||||
|
productName: pkgName,
|
||||||
|
version,
|
||||||
|
commit,
|
||||||
|
executableName: pkgName,
|
||||||
|
},
|
||||||
|
process.argv.slice(2),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// There's no need to check flags like --help or to spawn in an existing
|
// There's no need to check flags like --help or to spawn in an existing
|
||||||
// instance for the child process because these would have already happened in
|
// instance for the child process because these would have already happened in
|
||||||
// the parent and the child wouldn't have been spawned. We also get the
|
// the parent and the child wouldn't have been spawned. We also get the
|
||||||
|
|
|
@ -3,15 +3,14 @@ import * as express from "express"
|
||||||
import * as expressCore from "express-serve-static-core"
|
import * as expressCore from "express-serve-static-core"
|
||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
import * as net from "net"
|
import * as net from "net"
|
||||||
import * as qs from "qs"
|
import path from "path"
|
||||||
|
import qs from "qs"
|
||||||
import { Disposable } from "../common/emitter"
|
import { Disposable } from "../common/emitter"
|
||||||
import { CookieKeys, HttpCode, HttpError } from "../common/http"
|
import { HttpCode, HttpError } from "../common/http"
|
||||||
import { normalize } from "../common/util"
|
import { normalize } from "../common/util"
|
||||||
import { AuthType, DefaultedArgs } from "./cli"
|
import { AuthType, DefaultedArgs } from "./cli"
|
||||||
import { version as codeServerVersion } from "./constants"
|
import { version as codeServerVersion } from "./constants"
|
||||||
import { Heart } from "./heart"
|
import { Heart } from "./heart"
|
||||||
import { CoderSettings, SettingsProvider } from "./settings"
|
|
||||||
import { UpdateProvider } from "./update"
|
|
||||||
import { getPasswordMethod, IsCookieValidArgs, isCookieValid, sanitizeString, escapeHtml, escapeJSON } from "./util"
|
import { getPasswordMethod, IsCookieValidArgs, isCookieValid, sanitizeString, escapeHtml, escapeJSON } from "./util"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,9 +18,7 @@ import { getPasswordMethod, IsCookieValidArgs, isCookieValid, sanitizeString, es
|
||||||
*/
|
*/
|
||||||
export interface ClientConfiguration {
|
export interface ClientConfiguration {
|
||||||
codeServerVersion: string
|
codeServerVersion: string
|
||||||
/** Relative path from this page to the root. No trailing slash. */
|
|
||||||
base: string
|
base: string
|
||||||
/** Relative path from this page to the static root. No trailing slash. */
|
|
||||||
csStaticBase: string
|
csStaticBase: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,18 +28,16 @@ declare global {
|
||||||
export interface Request {
|
export interface Request {
|
||||||
args: DefaultedArgs
|
args: DefaultedArgs
|
||||||
heart: Heart
|
heart: Heart
|
||||||
settings: SettingsProvider<CoderSettings>
|
|
||||||
updater: UpdateProvider
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createClientConfiguration = (req: express.Request): ClientConfiguration => {
|
export const createClientConfiguration = (req: express.Request): ClientConfiguration => {
|
||||||
const base = relativeRoot(req.originalUrl)
|
const base = relativeRoot(req)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
base,
|
base,
|
||||||
csStaticBase: base + "/_static",
|
csStaticBase: normalize(path.posix.join(base, "_static/")),
|
||||||
codeServerVersion,
|
codeServerVersion,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +93,7 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {
|
||||||
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
|
const passwordMethod = getPasswordMethod(hashedPasswordFromArgs)
|
||||||
const isCookieValidArgs: IsCookieValidArgs = {
|
const isCookieValidArgs: IsCookieValidArgs = {
|
||||||
passwordMethod,
|
passwordMethod,
|
||||||
cookieKey: sanitizeString(req.cookies[CookieKeys.Session]),
|
cookieKey: sanitizeString(req.cookies.key),
|
||||||
passwordFromArgs: req.args.password || "",
|
passwordFromArgs: req.args.password || "",
|
||||||
hashedPasswordFromArgs: req.args["hashed-password"],
|
hashedPasswordFromArgs: req.args["hashed-password"],
|
||||||
}
|
}
|
||||||
|
@ -113,34 +108,21 @@ export const authenticated = async (req: express.Request): Promise<boolean> => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the relative path that will get us to the root of the page. For each
|
* Get the relative path that will get us to the root of the page. For each
|
||||||
* slash we need to go up a directory. Will not have a trailing slash.
|
* slash we need to go up a directory. For example:
|
||||||
*
|
|
||||||
* For example:
|
|
||||||
*
|
|
||||||
* / => .
|
* / => .
|
||||||
* /foo => .
|
* /foo => .
|
||||||
* /foo/ => ./..
|
* /foo/ => ./..
|
||||||
* /foo/bar => ./..
|
* /foo/bar => ./..
|
||||||
* /foo/bar/ => ./../..
|
* /foo/bar/ => ./../..
|
||||||
*
|
|
||||||
* All paths must be relative in order to work behind a reverse proxy since we
|
|
||||||
* we do not know the base path. Anything that needs to be absolute (for
|
|
||||||
* example cookies) must get the base path from the frontend.
|
|
||||||
*
|
|
||||||
* All relative paths must be prefixed with the relative root to ensure they
|
|
||||||
* work no matter the depth at which they happen to appear.
|
|
||||||
*
|
|
||||||
* For Express `req.originalUrl` should be used as they remove the base from the
|
|
||||||
* standard `url` property making it impossible to get the true depth.
|
|
||||||
*/
|
*/
|
||||||
export const relativeRoot = (originalUrl: string): string => {
|
export const relativeRoot = (req: express.Request): string => {
|
||||||
const depth = (originalUrl.split("?", 1)[0].match(/\//g) || []).length
|
const depth = (req.originalUrl.split("?", 1)[0].match(/\//g) || []).length
|
||||||
return normalize("./" + (depth > 1 ? "../".repeat(depth - 1) : ""))
|
return normalize("./" + (depth > 1 ? "../".repeat(depth - 1) : ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirect relatively to `/${to}`. Query variables on the current URI will be
|
* Redirect relatively to `/${to}`. Query variables on the current URI will be preserved.
|
||||||
* preserved. `to` should be a simple path without any query parameters
|
* `to` should be a simple path without any query parameters
|
||||||
* `override` will merge with the existing query (use `undefined` to unset).
|
* `override` will merge with the existing query (use `undefined` to unset).
|
||||||
*/
|
*/
|
||||||
export const redirect = (
|
export const redirect = (
|
||||||
|
@ -156,7 +138,7 @@ export const redirect = (
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const relativePath = normalize(`${relativeRoot(req.originalUrl)}/${to}`, true)
|
const relativePath = normalize(`${relativeRoot(req)}/${to}`, true)
|
||||||
const queryString = qs.stringify(query)
|
const queryString = qs.stringify(query)
|
||||||
const redirectPath = `${relativePath}${queryString ? `?${queryString}` : ""}`
|
const redirectPath = `${relativePath}${queryString ? `?${queryString}` : ""}`
|
||||||
logger.debug(`redirecting from ${req.originalUrl} to ${redirectPath}`)
|
logger.debug(`redirecting from ${req.originalUrl} to ${redirectPath}`)
|
||||||
|
@ -259,39 +241,3 @@ export function disposer(server: http.Server): Disposable["dispose"] {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the options for setting a cookie. The options must be identical for
|
|
||||||
* setting and unsetting cookies otherwise they are considered separate.
|
|
||||||
*/
|
|
||||||
export const getCookieOptions = (req: express.Request): express.CookieOptions => {
|
|
||||||
// Normally we set paths relatively. However browsers do not appear to allow
|
|
||||||
// cookies to be set relatively which means we need an absolute path. We
|
|
||||||
// cannot be guaranteed we know the path since a reverse proxy might have
|
|
||||||
// rewritten it. That means we need to get the path from the frontend.
|
|
||||||
|
|
||||||
// The reason we need to set the path (as opposed to defaulting to /) is to
|
|
||||||
// avoid code-server instances on different sub-paths clobbering each other or
|
|
||||||
// from accessing each other's tokens (and to prevent other services from
|
|
||||||
// accessing code-server's tokens).
|
|
||||||
|
|
||||||
// When logging in or out the request must include the href (the full current
|
|
||||||
// URL of that page) and the relative path to the root as given to it by the
|
|
||||||
// backend. Using these two we can determine the true absolute root.
|
|
||||||
const url = new URL(
|
|
||||||
req.query.base || req.body.base || "/",
|
|
||||||
req.query.href || req.body.href || "http://" + (req.headers.host || "localhost"),
|
|
||||||
)
|
|
||||||
return {
|
|
||||||
domain: getCookieDomain(url.host, req.args["proxy-domain"]),
|
|
||||||
path: normalize(url.pathname) || "/",
|
|
||||||
sameSite: "lax",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the full path to the current page, preserving any trailing slash.
|
|
||||||
*/
|
|
||||||
export const self = (req: express.Request): string => {
|
|
||||||
return normalize(`${req.baseUrl}${req.originalUrl.endsWith("/") ? "/" : ""}`, true)
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { field, logger } from "@coder/logger"
|
import { field, logger } from "@coder/logger"
|
||||||
import http from "http"
|
|
||||||
import * as os from "os"
|
import * as os from "os"
|
||||||
|
import http from "http"
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import { Disposable } from "../common/emitter"
|
import { Disposable } from "../common/emitter"
|
||||||
import { plural } from "../common/util"
|
import { plural } from "../common/util"
|
||||||
import { createApp, ensureAddress } from "./app"
|
import { createApp, ensureAddress } from "./app"
|
||||||
import { AuthType, DefaultedArgs, Feature, toVsCodeArgs, UserProvidedArgs } from "./cli"
|
import { AuthType, DefaultedArgs, Feature, UserProvidedArgs } from "./cli"
|
||||||
import { coderCloudBind } from "./coder_cloud"
|
import { coderCloudBind } from "./coder_cloud"
|
||||||
import { commit, version } from "./constants"
|
import { commit, version } from "./constants"
|
||||||
import { register } from "./routes"
|
import { register } from "./routes"
|
||||||
|
@ -35,7 +35,11 @@ export const runVsCodeCli = async (args: DefaultedArgs): Promise<void> => {
|
||||||
const spawnCli = await loadAMDModule<CodeServerLib.SpawnCli>("vs/server/remoteExtensionHostAgent", "spawnCli")
|
const spawnCli = await loadAMDModule<CodeServerLib.SpawnCli>("vs/server/remoteExtensionHostAgent", "spawnCli")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await spawnCli(await toVsCodeArgs(args))
|
await spawnCli({
|
||||||
|
...args,
|
||||||
|
// For some reason VS Code takes the port as a string.
|
||||||
|
port: typeof args.port !== "undefined" ? args.port.toString() : undefined,
|
||||||
|
})
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.error("Got error from VS Code", error)
|
logger.error("Got error from VS Code", error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Coder Technologies. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import ProxyAgent from "proxy-agent"
|
||||||
|
import { getProxyForUrl } from "proxy-from-env"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file has nothing to do with the code-server proxy.
|
||||||
|
* It is to support $HTTP_PROXY, $HTTPS_PROXY and $NO_PROXY.
|
||||||
|
*
|
||||||
|
* - https://github.com/cdr/code-server/issues/124
|
||||||
|
* - https://www.npmjs.com/package/proxy-agent
|
||||||
|
* - https://www.npmjs.com/package/proxy-from-env
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* monkeyPatch patches the node http,https modules to route all requests through the
|
||||||
|
* agent we get from the proxy-agent package.
|
||||||
|
*
|
||||||
|
* This approach only works if there is no code specifying an explicit agent when making
|
||||||
|
* a request.
|
||||||
|
*
|
||||||
|
* None of our code ever passes in a explicit agent to the http,https modules.
|
||||||
|
* VS Code's does sometimes but only when a user sets the http.proxy configuration.
|
||||||
|
* See https://code.visualstudio.com/docs/setup/network#_legacy-proxy-server-support
|
||||||
|
*
|
||||||
|
* Even if they do, it's probably the same proxy so we should be fine! And those knobs
|
||||||
|
* are deprecated anyway.
|
||||||
|
*/
|
||||||
|
export function monkeyPatchProxyProtocols(): void {
|
||||||
|
if (!shouldEnableProxy()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const http = require("http")
|
||||||
|
const https = require("https")
|
||||||
|
|
||||||
|
// If we do not pass in a proxy URL, proxy-agent will get the URL from the environment.
|
||||||
|
// See https://www.npmjs.com/package/proxy-from-env.
|
||||||
|
// Also see shouldEnableProxy.
|
||||||
|
const pa = new ProxyAgent()
|
||||||
|
http.globalAgent = pa
|
||||||
|
https.globalAgent = pa
|
||||||
|
}
|
||||||
|
|
||||||
|
const sampleUrls = [new URL("http://example.com"), new URL("https://example.com")]
|
||||||
|
|
||||||
|
// If they have $NO_PROXY set to example.com then this check won't work!
|
||||||
|
// But that's drastically unlikely.
|
||||||
|
export function shouldEnableProxy(): boolean {
|
||||||
|
const testedProxyEndpoints = sampleUrls.map((url) => {
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
proxyUrl: getProxyForUrl(url.toString()),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let shouldEnable = false
|
||||||
|
|
||||||
|
for (const { url, proxyUrl } of testedProxyEndpoints) {
|
||||||
|
if (proxyUrl) {
|
||||||
|
console.debug(`${url.protocol} -- Using "${proxyUrl}"`)
|
||||||
|
shouldEnable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shouldEnable
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import { Request, Router } from "express"
|
import { Request, Router } from "express"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { authenticated, ensureAuthenticated, redirect, self } from "../http"
|
import { normalize } from "../../common/util"
|
||||||
|
import { authenticated, ensureAuthenticated, redirect } from "../http"
|
||||||
import { proxy } from "../proxy"
|
import { proxy } from "../proxy"
|
||||||
import { Router as WsRouter } from "../wsRouter"
|
import { Router as WsRouter } from "../wsRouter"
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ router.all("*", async (req, res, next) => {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
// Redirect all other pages to the login.
|
// Redirect all other pages to the login.
|
||||||
const to = self(req)
|
const to = normalize(`${req.baseUrl}${req.path}`)
|
||||||
return redirect(req, res, "login", {
|
return redirect(req, res, "login", {
|
||||||
to: to !== "/" ? to : undefined,
|
to: to !== "/" ? to : undefined,
|
||||||
})
|
})
|
||||||
|
|
|
@ -8,36 +8,14 @@ import { rootPath } from "../constants"
|
||||||
import { replaceTemplates } from "../http"
|
import { replaceTemplates } from "../http"
|
||||||
import { escapeHtml, getMediaMime } from "../util"
|
import { escapeHtml, getMediaMime } from "../util"
|
||||||
|
|
||||||
interface ErrorWithStatusCode {
|
const notFoundCodes = ["ENOENT", "EISDIR"]
|
||||||
statusCode: number
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ErrorWithCode {
|
|
||||||
code: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Error is network related. */
|
|
||||||
export const errorHasStatusCode = (error: any): error is ErrorWithStatusCode => {
|
|
||||||
return error && "statusCode" in error
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Error originates from file system. */
|
|
||||||
export const errorHasCode = (error: any): error is ErrorWithCode => {
|
|
||||||
return error && "code" in error
|
|
||||||
}
|
|
||||||
|
|
||||||
const notFoundCodes = [404, "ENOENT", "EISDIR"]
|
|
||||||
|
|
||||||
export const errorHandler: express.ErrorRequestHandler = async (err, req, res, next) => {
|
export const errorHandler: express.ErrorRequestHandler = async (err, req, res, next) => {
|
||||||
let statusCode = 500
|
if (notFoundCodes.includes(err.code)) {
|
||||||
|
err.status = HttpCode.NotFound
|
||||||
if (errorHasStatusCode(err)) {
|
|
||||||
statusCode = err.statusCode
|
|
||||||
} else if (errorHasCode(err) && notFoundCodes.includes(err.code)) {
|
|
||||||
statusCode = HttpCode.NotFound
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res.status(statusCode)
|
const status = err.status ?? err.statusCode ?? 500
|
||||||
|
res.status(status)
|
||||||
|
|
||||||
// Assume anything that explicitly accepts text/html is a user browsing a
|
// Assume anything that explicitly accepts text/html is a user browsing a
|
||||||
// page (as opposed to an xhr request). Don't use `req.accepts()` since
|
// page (as opposed to an xhr request). Don't use `req.accepts()` since
|
||||||
|
@ -49,8 +27,8 @@ export const errorHandler: express.ErrorRequestHandler = async (err, req, res, n
|
||||||
const content = await fs.readFile(resourcePath, "utf8")
|
const content = await fs.readFile(resourcePath, "utf8")
|
||||||
res.send(
|
res.send(
|
||||||
replaceTemplates(req, content)
|
replaceTemplates(req, content)
|
||||||
.replace(/{{ERROR_TITLE}}/g, statusCode.toString())
|
.replace(/{{ERROR_TITLE}}/g, status)
|
||||||
.replace(/{{ERROR_HEADER}}/g, statusCode.toString())
|
.replace(/{{ERROR_HEADER}}/g, status)
|
||||||
.replace(/{{ERROR_BODY}}/g, escapeHtml(err.message)),
|
.replace(/{{ERROR_BODY}}/g, escapeHtml(err.message)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,8 +14,6 @@ import { commit, rootPath } from "../constants"
|
||||||
import { Heart } from "../heart"
|
import { Heart } from "../heart"
|
||||||
import { ensureAuthenticated, redirect } from "../http"
|
import { ensureAuthenticated, redirect } from "../http"
|
||||||
import { PluginAPI } from "../plugin"
|
import { PluginAPI } from "../plugin"
|
||||||
import { CoderSettings, SettingsProvider } from "../settings"
|
|
||||||
import { UpdateProvider } from "../update"
|
|
||||||
import { getMediaMime, paths } from "../util"
|
import { getMediaMime, paths } from "../util"
|
||||||
import * as apps from "./apps"
|
import * as apps from "./apps"
|
||||||
import * as domainProxy from "./domainProxy"
|
import * as domainProxy from "./domainProxy"
|
||||||
|
@ -49,9 +47,6 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
||||||
app.router.use(cookieParser())
|
app.router.use(cookieParser())
|
||||||
app.wsRouter.use(cookieParser())
|
app.wsRouter.use(cookieParser())
|
||||||
|
|
||||||
const settings = new SettingsProvider<CoderSettings>(path.join(args["user-data-dir"], "coder.json"))
|
|
||||||
const updater = new UpdateProvider("https://api.github.com/repos/coder/code-server/releases/latest", settings)
|
|
||||||
|
|
||||||
const common: express.RequestHandler = (req, _, next) => {
|
const common: express.RequestHandler = (req, _, next) => {
|
||||||
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
|
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
|
||||||
// it look like code-server is always in use.
|
// it look like code-server is always in use.
|
||||||
|
@ -62,8 +57,6 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
|
||||||
// Add common variables routes can use.
|
// Add common variables routes can use.
|
||||||
req.args = args
|
req.args = args
|
||||||
req.heart = heart
|
req.heart = heart
|
||||||
req.settings = settings
|
|
||||||
req.updater = updater
|
|
||||||
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,14 @@ import { promises as fs } from "fs"
|
||||||
import { RateLimiter as Limiter } from "limiter"
|
import { RateLimiter as Limiter } from "limiter"
|
||||||
import * as os from "os"
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { CookieKeys } from "../../common/http"
|
|
||||||
import { rootPath } from "../constants"
|
import { rootPath } from "../constants"
|
||||||
import { authenticated, getCookieOptions, redirect, replaceTemplates } from "../http"
|
import { authenticated, getCookieDomain, redirect, replaceTemplates } from "../http"
|
||||||
import { getPasswordMethod, handlePasswordValidation, humanPath, sanitizeString, escapeHtml } from "../util"
|
import { getPasswordMethod, handlePasswordValidation, humanPath, sanitizeString, escapeHtml } from "../util"
|
||||||
|
|
||||||
|
export enum Cookie {
|
||||||
|
Key = "key",
|
||||||
|
}
|
||||||
|
|
||||||
// RateLimiter wraps around the limiter library for logins.
|
// RateLimiter wraps around the limiter library for logins.
|
||||||
// It allows 2 logins every minute plus 12 logins every hour.
|
// It allows 2 logins every minute plus 12 logins every hour.
|
||||||
export class RateLimiter {
|
export class RateLimiter {
|
||||||
|
@ -59,7 +62,7 @@ router.get("/", async (req, res) => {
|
||||||
res.send(await getRoot(req))
|
res.send(await getRoot(req))
|
||||||
})
|
})
|
||||||
|
|
||||||
router.post<{}, string, { password: string; base?: string }, { to?: string }>("/", async (req, res) => {
|
router.post("/", async (req, res) => {
|
||||||
const password = sanitizeString(req.body.password)
|
const password = sanitizeString(req.body.password)
|
||||||
const hashedPasswordFromArgs = req.args["hashed-password"]
|
const hashedPasswordFromArgs = req.args["hashed-password"]
|
||||||
|
|
||||||
|
@ -84,7 +87,15 @@ router.post<{}, string, { password: string; base?: string }, { to?: string }>("/
|
||||||
if (isPasswordValid) {
|
if (isPasswordValid) {
|
||||||
// The hash does not add any actual security but we do it for
|
// The hash does not add any actual security but we do it for
|
||||||
// obfuscation purposes (and as a side effect it handles escaping).
|
// obfuscation purposes (and as a side effect it handles escaping).
|
||||||
res.cookie(CookieKeys.Session, hashedPassword, getCookieOptions(req))
|
res.cookie(Cookie.Key, hashedPassword, {
|
||||||
|
domain: getCookieDomain(req.headers.host || "", req.args["proxy-domain"]),
|
||||||
|
// Browsers do not appear to allow cookies to be set relatively so we
|
||||||
|
// need to get the root path from the browser since the proxy rewrites
|
||||||
|
// it out of the path. Otherwise code-server instances hosted on
|
||||||
|
// separate sub-paths will clobber each other.
|
||||||
|
path: req.body.base ? path.posix.join(req.body.base, "..") : "/",
|
||||||
|
sameSite: "lax",
|
||||||
|
})
|
||||||
|
|
||||||
const to = (typeof req.query.to === "string" && req.query.to) || "/"
|
const to = (typeof req.query.to === "string" && req.query.to) || "/"
|
||||||
return redirect(req, res, to, { to: undefined })
|
return redirect(req, res, to, { to: undefined })
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
import { Router } from "express"
|
import { Router } from "express"
|
||||||
import { CookieKeys } from "../../common/http"
|
import { getCookieDomain, redirect } from "../http"
|
||||||
import { getCookieOptions, redirect } from "../http"
|
import { Cookie } from "./login"
|
||||||
import { sanitizeString } from "../util"
|
|
||||||
|
|
||||||
export const router = Router()
|
export const router = Router()
|
||||||
|
|
||||||
router.get<{}, undefined, undefined, { base?: string; to?: string }>("/", async (req, res) => {
|
router.get("/", async (req, res) => {
|
||||||
// Must use the *identical* properties used to set the cookie.
|
// Must use the *identical* properties used to set the cookie.
|
||||||
res.clearCookie(CookieKeys.Session, getCookieOptions(req))
|
res.clearCookie(Cookie.Key, {
|
||||||
|
domain: getCookieDomain(req.headers.host || "", req.args["proxy-domain"]),
|
||||||
|
path: req.query.base || "/",
|
||||||
|
sameSite: "lax",
|
||||||
|
})
|
||||||
|
|
||||||
const to = sanitizeString(req.query.to) || "/"
|
const to = (typeof req.query.to === "string" && req.query.to) || "/"
|
||||||
return redirect(req, res, to, { to: undefined, base: undefined, href: undefined })
|
return redirect(req, res, to, { to: undefined, base: undefined })
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { Request, Response } from "express"
|
import { Request, Response } from "express"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import * as qs from "qs"
|
import qs from "qs"
|
||||||
import * as pluginapi from "../../../typings/pluginapi"
|
import * as pluginapi from "../../../typings/pluginapi"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { authenticated, ensureAuthenticated, redirect, self } from "../http"
|
import { normalize } from "../../common/util"
|
||||||
|
import { authenticated, ensureAuthenticated, redirect } from "../http"
|
||||||
import { proxy as _proxy } from "../proxy"
|
import { proxy as _proxy } from "../proxy"
|
||||||
|
|
||||||
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
|
const getProxyTarget = (req: Request, passthroughPath?: boolean): string => {
|
||||||
|
@ -24,7 +25,7 @@ export function proxy(
|
||||||
if (!authenticated(req)) {
|
if (!authenticated(req)) {
|
||||||
// If visiting the root (/:port only) redirect to the login page.
|
// If visiting the root (/:port only) redirect to the login page.
|
||||||
if (!req.params[0] || req.params[0] === "/") {
|
if (!req.params[0] || req.params[0] === "/") {
|
||||||
const to = self(req)
|
const to = normalize(`${req.baseUrl}${req.path}`)
|
||||||
return redirect(req, res, "login", {
|
return redirect(req, res, "login", {
|
||||||
to: to !== "/" ? to : undefined,
|
to: to !== "/" ? to : undefined,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
import { Router } from "express"
|
import { Router } from "express"
|
||||||
import { version } from "../constants"
|
import { version } from "../constants"
|
||||||
import { ensureAuthenticated } from "../http"
|
import { ensureAuthenticated } from "../http"
|
||||||
|
import { UpdateProvider } from "../update"
|
||||||
|
|
||||||
export const router = Router()
|
export const router = Router()
|
||||||
|
|
||||||
|
const provider = new UpdateProvider()
|
||||||
|
|
||||||
router.get("/check", ensureAuthenticated, async (req, res) => {
|
router.get("/check", ensureAuthenticated, async (req, res) => {
|
||||||
const update = await req.updater.getUpdate(req.query.force === "true")
|
const update = await provider.getUpdate(req.query.force === "true")
|
||||||
res.json({
|
res.json({
|
||||||
checked: update.checked,
|
checked: update.checked,
|
||||||
latest: update.version,
|
latest: update.version,
|
||||||
current: version,
|
current: version,
|
||||||
isLatest: req.updater.isLatestVersion(update),
|
isLatest: provider.isLatestVersion(update),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,11 +2,9 @@ import { logger } from "@coder/logger"
|
||||||
import * as express from "express"
|
import * as express from "express"
|
||||||
import { WebsocketRequest } from "../../../typings/pluginapi"
|
import { WebsocketRequest } from "../../../typings/pluginapi"
|
||||||
import { logError } from "../../common/util"
|
import { logError } from "../../common/util"
|
||||||
import { toVsCodeArgs } from "../cli"
|
|
||||||
import { isDevMode } from "../constants"
|
import { isDevMode } from "../constants"
|
||||||
import { authenticated, ensureAuthenticated, redirect, self } from "../http"
|
import { ensureAuthenticated, authenticated, redirect } from "../http"
|
||||||
import { SocketProxyProvider } from "../socket"
|
import { loadAMDModule, readCompilationStats } from "../util"
|
||||||
import { loadAMDModule } from "../util"
|
|
||||||
import { Router as WsRouter } from "../wsRouter"
|
import { Router as WsRouter } from "../wsRouter"
|
||||||
import { errorHandler } from "./errors"
|
import { errorHandler } from "./errors"
|
||||||
|
|
||||||
|
@ -14,7 +12,6 @@ export class CodeServerRouteWrapper {
|
||||||
/** Assigned in `ensureCodeServerLoaded` */
|
/** Assigned in `ensureCodeServerLoaded` */
|
||||||
private _codeServerMain!: CodeServerLib.IServerAPI
|
private _codeServerMain!: CodeServerLib.IServerAPI
|
||||||
private _wsRouterWrapper = WsRouter()
|
private _wsRouterWrapper = WsRouter()
|
||||||
private _socketProxyProvider = new SocketProxyProvider()
|
|
||||||
public router = express.Router()
|
public router = express.Router()
|
||||||
|
|
||||||
public get wsRouter() {
|
public get wsRouter() {
|
||||||
|
@ -27,39 +24,12 @@ export class CodeServerRouteWrapper {
|
||||||
const isAuthenticated = await authenticated(req)
|
const isAuthenticated = await authenticated(req)
|
||||||
|
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
const to = self(req)
|
|
||||||
return redirect(req, res, "login", {
|
return redirect(req, res, "login", {
|
||||||
to: to !== "/" ? to : undefined,
|
// req.baseUrl can be blank if already at the root.
|
||||||
|
to: req.baseUrl && req.baseUrl !== "/" ? req.baseUrl : undefined,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const { query } = await req.settings.read()
|
|
||||||
if (query) {
|
|
||||||
// Ew means the workspace was closed so clear the last folder/workspace.
|
|
||||||
if (req.query.ew) {
|
|
||||||
delete query.folder
|
|
||||||
delete query.workspace
|
|
||||||
}
|
|
||||||
|
|
||||||
// Redirect to the last folder/workspace if nothing else is opened.
|
|
||||||
if (
|
|
||||||
!req.query.folder &&
|
|
||||||
!req.query.workspace &&
|
|
||||||
(query.folder || query.workspace) &&
|
|
||||||
!req.args["ignore-last-opened"] // This flag disables this behavior.
|
|
||||||
) {
|
|
||||||
const to = self(req)
|
|
||||||
return redirect(req, res, to, {
|
|
||||||
folder: query.folder,
|
|
||||||
workspace: query.workspace,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the query parameters so we can use them on the next load. This
|
|
||||||
// also allows users to create functionality around query parameters.
|
|
||||||
await req.settings.write({ query: req.query })
|
|
||||||
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,10 +49,9 @@ export class CodeServerRouteWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
private $proxyWebsocket = async (req: WebsocketRequest) => {
|
private $proxyWebsocket = async (req: WebsocketRequest) => {
|
||||||
const wrappedSocket = await this._socketProxyProvider.createProxy(req.ws)
|
this._codeServerMain.handleUpgrade(req, req.socket)
|
||||||
this._codeServerMain.handleUpgrade(req, wrappedSocket)
|
|
||||||
|
|
||||||
req.ws.resume()
|
req.socket.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
@ -96,6 +65,15 @@ export class CodeServerRouteWrapper {
|
||||||
return next()
|
return next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isDevMode) {
|
||||||
|
// Is the development mode file watcher still busy?
|
||||||
|
const compileStats = await readCompilationStats()
|
||||||
|
|
||||||
|
if (!compileStats || !compileStats.lastCompiledAt) {
|
||||||
|
return next(new Error("VS Code may still be compiling..."))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the server...
|
// Create the server...
|
||||||
|
|
||||||
const { args } = req
|
const { args } = req
|
||||||
|
@ -110,16 +88,14 @@ export class CodeServerRouteWrapper {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this._codeServerMain = await createVSServer(null, {
|
this._codeServerMain = await createVSServer(null, {
|
||||||
...(await toVsCodeArgs(args)),
|
connectionToken: "0000",
|
||||||
// TODO: Make the browser helper script work.
|
...args,
|
||||||
"without-browser-env-var": true,
|
// For some reason VS Code takes the port as a string.
|
||||||
|
port: args.port?.toString(),
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (createServerError) {
|
||||||
logError(logger, "CodeServerRouteWrapper", error)
|
logError(logger, "CodeServerRouteWrapper", createServerError)
|
||||||
if (isDevMode) {
|
return next(createServerError)
|
||||||
return next(new Error((error instanceof Error ? error.message : error) + " (VS Code may still be compiling)"))
|
|
||||||
}
|
|
||||||
return next(error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
|
@ -133,6 +109,5 @@ export class CodeServerRouteWrapper {
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this._codeServerMain?.dispose()
|
this._codeServerMain?.dispose()
|
||||||
this._socketProxyProvider.stop()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { logger } from "@coder/logger"
|
import { logger } from "@coder/logger"
|
||||||
import { Query } from "express-serve-static-core"
|
import { Query } from "express-serve-static-core"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
|
import * as path from "path"
|
||||||
|
import { paths } from "./util"
|
||||||
|
|
||||||
export type Settings = { [key: string]: Settings | string | boolean | number }
|
export type Settings = { [key: string]: Settings | string | boolean | number }
|
||||||
|
|
||||||
|
@ -52,5 +54,14 @@ export interface UpdateSettings {
|
||||||
* Global code-server settings.
|
* Global code-server settings.
|
||||||
*/
|
*/
|
||||||
export interface CoderSettings extends UpdateSettings {
|
export interface CoderSettings extends UpdateSettings {
|
||||||
query?: Query
|
lastVisited: {
|
||||||
|
url: string
|
||||||
|
workspace: boolean
|
||||||
|
}
|
||||||
|
query: Query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global code-server settings file.
|
||||||
|
*/
|
||||||
|
export const settings = new SettingsProvider<CoderSettings>(path.join(paths.data, "coder.json"))
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { field, logger } from "@coder/logger"
|
import { field, logger } from "@coder/logger"
|
||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
import * as https from "https"
|
import * as https from "https"
|
||||||
import ProxyAgent from "proxy-agent"
|
|
||||||
import * as semver from "semver"
|
import * as semver from "semver"
|
||||||
import * as url from "url"
|
import * as url from "url"
|
||||||
import { httpProxyUri, version } from "./constants"
|
import { version } from "./constants"
|
||||||
import { SettingsProvider, UpdateSettings } from "./settings"
|
import { settings as globalSettings, SettingsProvider, UpdateSettings } from "./settings"
|
||||||
|
|
||||||
export interface Update {
|
export interface Update {
|
||||||
checked: number
|
checked: number
|
||||||
|
@ -28,11 +27,12 @@ export class UpdateProvider {
|
||||||
* The URL for getting the latest version of code-server. Should return JSON
|
* The URL for getting the latest version of code-server. Should return JSON
|
||||||
* that fulfills `LatestResponse`.
|
* that fulfills `LatestResponse`.
|
||||||
*/
|
*/
|
||||||
private readonly latestUrl: string,
|
private readonly latestUrl = "https://api.github.com/repos/cdr/code-server/releases/latest",
|
||||||
/**
|
/**
|
||||||
* Update information will be stored here.
|
* Update information will be stored here. If not provided, the global
|
||||||
|
* settings will be used.
|
||||||
*/
|
*/
|
||||||
private readonly settings: SettingsProvider<UpdateSettings>,
|
private readonly settings: SettingsProvider<UpdateSettings> = globalSettings,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,10 +103,8 @@ export class UpdateProvider {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request = (uri: string): void => {
|
const request = (uri: string): void => {
|
||||||
logger.debug("Making request", field("uri", uri))
|
logger.debug("Making request", field("uri", uri))
|
||||||
const isHttps = uri.startsWith("https")
|
const httpx = uri.startsWith("https") ? https : http
|
||||||
const agent = httpProxyUri ? new ProxyAgent(httpProxyUri) : undefined
|
const client = httpx.get(uri, { headers: { "User-Agent": "code-server" } }, (response) => {
|
||||||
const httpx = isHttps ? https : http
|
|
||||||
const client = httpx.get(uri, { headers: { "User-Agent": "code-server" }, agent }, (response) => {
|
|
||||||
if (!response.statusCode || response.statusCode < 200 || response.statusCode >= 400) {
|
if (!response.statusCode || response.statusCode < 200 || response.statusCode >= 400) {
|
||||||
response.destroy()
|
response.destroy()
|
||||||
return reject(new Error(`${uri}: ${response.statusCode || "500"}`))
|
return reject(new Error(`${uri}: ${response.statusCode || "500"}`))
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
|
import { logger } from "@coder/logger"
|
||||||
import * as argon2 from "argon2"
|
import * as argon2 from "argon2"
|
||||||
import * as cp from "child_process"
|
import * as cp from "child_process"
|
||||||
import * as crypto from "crypto"
|
import * as crypto from "crypto"
|
||||||
import envPaths from "env-paths"
|
import envPaths from "env-paths"
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs, Stats } from "fs"
|
||||||
import * as net from "net"
|
import * as net from "net"
|
||||||
import * as os from "os"
|
import * as os from "os"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import safeCompare from "safe-compare"
|
import safeCompare from "safe-compare"
|
||||||
import * as util from "util"
|
import * as util from "util"
|
||||||
import xdgBasedir from "xdg-basedir"
|
import xdgBasedir from "xdg-basedir"
|
||||||
import { vsRootPath } from "./constants"
|
import { logError } from "../common/util"
|
||||||
|
import { isDevMode, rootPath, vsRootPath } from "./constants"
|
||||||
|
|
||||||
export interface Paths {
|
export interface Paths {
|
||||||
data: string
|
data: string
|
||||||
|
@ -57,10 +59,10 @@ export const paths = getEnvPaths()
|
||||||
* On MacOS this function gets the standard XDG directories instead of using the native macOS
|
* On MacOS this function gets the standard XDG directories instead of using the native macOS
|
||||||
* ones. Most CLIs do this as in practice only GUI apps use the standard macOS directories.
|
* ones. Most CLIs do this as in practice only GUI apps use the standard macOS directories.
|
||||||
*/
|
*/
|
||||||
export function getEnvPaths(platform = process.platform): Paths {
|
export function getEnvPaths(): Paths {
|
||||||
const paths = envPaths("code-server", { suffix: "" })
|
const paths = envPaths("code-server", { suffix: "" })
|
||||||
const append = (p: string): string => path.join(p, "code-server")
|
const append = (p: string): string => path.join(p, "code-server")
|
||||||
switch (platform) {
|
switch (process.platform) {
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return {
|
return {
|
||||||
// envPaths uses native directories so force Darwin to use the XDG spec
|
// envPaths uses native directories so force Darwin to use the XDG spec
|
||||||
|
@ -156,7 +158,12 @@ export const generatePassword = async (length = 24): Promise<string> => {
|
||||||
* Used to hash the password.
|
* Used to hash the password.
|
||||||
*/
|
*/
|
||||||
export const hash = async (password: string): Promise<string> => {
|
export const hash = async (password: string): Promise<string> => {
|
||||||
return await argon2.hash(password)
|
try {
|
||||||
|
return await argon2.hash(password)
|
||||||
|
} catch (error: any) {
|
||||||
|
logger.error(error)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,7 +173,11 @@ export const isHashMatch = async (password: string, hash: string) => {
|
||||||
if (password === "" || hash === "" || !hash.startsWith("$")) {
|
if (password === "" || hash === "" || !hash.startsWith("$")) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return await argon2.verify(hash, password)
|
try {
|
||||||
|
return await argon2.verify(hash, password)
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,10 +321,10 @@ export async function isCookieValid({
|
||||||
* - greater than 0 characters
|
* - greater than 0 characters
|
||||||
* - trims whitespace
|
* - trims whitespace
|
||||||
*/
|
*/
|
||||||
export function sanitizeString(str: unknown): string {
|
export function sanitizeString(str: string): string {
|
||||||
// Very basic sanitization of string
|
// Very basic sanitization of string
|
||||||
// Credit: https://stackoverflow.com/a/46719000/3015595
|
// Credit: https://stackoverflow.com/a/46719000/3015595
|
||||||
return typeof str === "string" ? str.trim() : ""
|
return typeof str === "string" && str.trim().length > 0 ? str.trim() : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
const mimeTypes: { [key: string]: string } = {
|
const mimeTypes: { [key: string]: string } = {
|
||||||
|
@ -512,3 +523,41 @@ export const loadAMDModule = async <T>(amdPath: string, exportName: string): Pro
|
||||||
|
|
||||||
return module[exportName] as T
|
return module[exportName] as T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const enum VSCodeCompileStatus {
|
||||||
|
Loading = "Loading",
|
||||||
|
Compiling = "Compiling",
|
||||||
|
Compiled = "Compiled",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CompilationStats {
|
||||||
|
status: VSCodeCompileStatus
|
||||||
|
lastCompiledAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
export const readCompilationStats = async (): Promise<null | CompilationStats> => {
|
||||||
|
if (!isDevMode) {
|
||||||
|
throw new Error("Compilation stats are only present in development")
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = path.join(rootPath, "out/watcher.json")
|
||||||
|
let stat: Stats
|
||||||
|
try {
|
||||||
|
stat = await fs.stat(filePath)
|
||||||
|
} catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stat.isFile()) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const file = await fs.readFile(filePath)
|
||||||
|
return JSON.parse(file.toString("utf-8"))
|
||||||
|
} catch (error) {
|
||||||
|
logError(logger, "VS Code", error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
|
@ -50,5 +50,4 @@ export function Router(): WebsocketRouter {
|
||||||
return new WebsocketRouter()
|
return new WebsocketRouter()
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-named-as-default-member -- the typings are not updated correctly
|
|
||||||
export const wss = new Websocket.Server({ noServer: true })
|
export const wss = new Websocket.Server({ noServer: true })
|
||||||
|
|
|
@ -9,15 +9,10 @@ import { CodeServer, CodeServerPage } from "./models/CodeServer"
|
||||||
*
|
*
|
||||||
* If `includeCredentials` is `true` page requests will be authenticated.
|
* If `includeCredentials` is `true` page requests will be authenticated.
|
||||||
*/
|
*/
|
||||||
export const describe = (
|
export const describe = (name: string, includeCredentials: boolean, fn: (codeServer: CodeServer) => void) => {
|
||||||
name: string,
|
|
||||||
includeCredentials: boolean,
|
|
||||||
codeServerArgs: string[],
|
|
||||||
fn: (codeServer: CodeServer) => void,
|
|
||||||
) => {
|
|
||||||
test.describe(name, () => {
|
test.describe(name, () => {
|
||||||
// This will spawn on demand so nothing is necessary on before.
|
// This will spawn on demand so nothing is necessary on before.
|
||||||
const codeServer = new CodeServer(name, codeServerArgs)
|
const codeServer = new CodeServer(name)
|
||||||
|
|
||||||
// Kill code-server after the suite has ended. This may happen even without
|
// Kill code-server after the suite has ended. This may happen even without
|
||||||
// doing it explicitly but it seems prudent to be sure.
|
// doing it explicitly but it seems prudent to be sure.
|
||||||
|
@ -41,9 +36,6 @@ export const describe = (
|
||||||
authenticated: includeCredentials,
|
authenticated: includeCredentials,
|
||||||
// This provides a cookie that authenticates with code-server.
|
// This provides a cookie that authenticates with code-server.
|
||||||
storageState: includeCredentials ? storageState : {},
|
storageState: includeCredentials ? storageState : {},
|
||||||
// NOTE@jsjoeio some tests use --cert which uses a self-signed certificate
|
|
||||||
// without this option, those tests will fail.
|
|
||||||
ignoreHTTPSErrors: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
fn(codeServer)
|
fn(codeServer)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect } from "./baseFixture"
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
describe("CodeServer", true, [], () => {
|
describe("CodeServer", true, () => {
|
||||||
test("should navigate to home page", async ({ codeServerPage }) => {
|
test("should navigate to home page", async ({ codeServerPage }) => {
|
||||||
// We navigate codeServer before each test
|
// We navigate codeServer before each test
|
||||||
// and we start the test with a storage state
|
// and we start the test with a storage state
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
import { describe, test } from "./baseFixture"
|
|
||||||
|
|
||||||
function runTestExtensionTests() {
|
|
||||||
// This will only work if the test extension is loaded into code-server.
|
|
||||||
test("should have access to VSCODE_PROXY_URI", async ({ codeServerPage }) => {
|
|
||||||
const address = await codeServerPage.address()
|
|
||||||
|
|
||||||
await codeServerPage.executeCommandViaMenus("code-server: Get proxy URI")
|
|
||||||
|
|
||||||
await codeServerPage.page.waitForSelector(`text=${address}/proxy/{{port}}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Extensions", true, [], () => {
|
|
||||||
runTestExtensionTests()
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("Extensions with --cert", true, ["--cert"], () => {
|
|
||||||
runTestExtensionTests()
|
|
||||||
})
|
|
|
@ -1 +0,0 @@
|
||||||
/extension.js
|
|
|
@ -1,13 +0,0 @@
|
||||||
import * as vscode from "vscode"
|
|
||||||
|
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
|
||||||
context.subscriptions.push(
|
|
||||||
vscode.commands.registerCommand("codeServerTest.proxyUri", () => {
|
|
||||||
if (process.env.VSCODE_PROXY_URI) {
|
|
||||||
vscode.window.showInformationMessage(process.env.VSCODE_PROXY_URI)
|
|
||||||
} else {
|
|
||||||
vscode.window.showErrorMessage("No proxy URI was set")
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
{
|
|
||||||
"name": "code-server-extension",
|
|
||||||
"description": "code-server test extension",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"publisher": "coder",
|
|
||||||
"activationEvents": [
|
|
||||||
"onCommand:codeServerTest.proxyUri"
|
|
||||||
],
|
|
||||||
"engines": {
|
|
||||||
"vscode": "^1.56.0"
|
|
||||||
},
|
|
||||||
"main": "./extension.js",
|
|
||||||
"contributes": {
|
|
||||||
"commands": [
|
|
||||||
{
|
|
||||||
"command": "codeServerTest.proxyUri",
|
|
||||||
"title": "Get proxy URI",
|
|
||||||
"category": "code-server"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/vscode": "^1.56.0",
|
|
||||||
"typescript": "^4.0.5"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es2020",
|
|
||||||
"module": "commonjs",
|
|
||||||
"outDir": ".",
|
|
||||||
"strict": true,
|
|
||||||
"baseUrl": "./",
|
|
||||||
"skipLibCheck": true
|
|
||||||
},
|
|
||||||
"include": ["./extension.ts"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
||||||
# yarn lockfile v1
|
|
||||||
|
|
||||||
|
|
||||||
"@types/vscode@^1.56.0":
|
|
||||||
version "1.57.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.57.0.tgz#cc648e0573b92f725cd1baf2621f8da9f8bc689f"
|
|
||||||
integrity sha512-FeznBFtIDCWRluojTsi9c3LLcCHOXP5etQfBK42+ixo1CoEAchkw39tuui9zomjZuKfUVL33KZUDIwHZ/xvOkQ==
|
|
||||||
|
|
||||||
typescript@^4.0.5:
|
|
||||||
version "4.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805"
|
|
||||||
integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==
|
|
|
@ -2,7 +2,7 @@ import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
// This test is to make sure the globalSetup works as expected
|
// This test is to make sure the globalSetup works as expected
|
||||||
// meaning globalSetup ran and stored the storageState
|
// meaning globalSetup ran and stored the storageState
|
||||||
describe("globalSetup", true, [], () => {
|
describe("globalSetup", true, () => {
|
||||||
test("should keep us logged in using the storageState", async ({ codeServerPage }) => {
|
test("should keep us logged in using the storageState", async ({ codeServerPage }) => {
|
||||||
// Make sure the editor actually loaded
|
// Make sure the editor actually loaded
|
||||||
expect(await codeServerPage.isEditorVisible()).toBe(true)
|
expect(await codeServerPage.isEditorVisible()).toBe(true)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { PASSWORD } from "../utils/constants"
|
import { PASSWORD } from "../utils/constants"
|
||||||
import { describe, test, expect } from "./baseFixture"
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
describe("login", false, [], () => {
|
describe("login", false, () => {
|
||||||
test("should see the login page", async ({ codeServerPage }) => {
|
test("should see the login page", async ({ codeServerPage }) => {
|
||||||
// It should send us to the login page
|
// It should send us to the login page
|
||||||
expect(await codeServerPage.page.title()).toBe("code-server login")
|
expect(await codeServerPage.page.title()).toBe("code-server login")
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// NOTE@jsjoeio commenting out until we can figure out what's wrong
|
// NOTE@jsjoeio commenting out until we can figure out what's wrong
|
||||||
// import { describe, test, expect } from "./baseFixture"
|
// import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
// describe("logout", true, [], () => {
|
// describe("logout", true, () => {
|
||||||
// test("should be able logout", async ({ codeServerPage }) => {
|
// test("should be able logout", async ({ codeServerPage }) => {
|
||||||
// // Recommended by Playwright for async navigation
|
// // Recommended by Playwright for async navigation
|
||||||
// // https://github.com/microsoft/playwright/issues/1987#issuecomment-620182151
|
// // https://github.com/microsoft/playwright/issues/1987#issuecomment-620182151
|
||||||
|
|
|
@ -31,7 +31,7 @@ export class CodeServer {
|
||||||
public readonly logger: Logger
|
public readonly logger: Logger
|
||||||
private closed = false
|
private closed = false
|
||||||
|
|
||||||
constructor(name: string, private readonly codeServerArgs: string[]) {
|
constructor(name: string) {
|
||||||
this.logger = logger.named(name)
|
this.logger = logger.named(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,6 @@ export class CodeServer {
|
||||||
"node",
|
"node",
|
||||||
[
|
[
|
||||||
process.env.CODE_SERVER_TEST_ENTRY || ".",
|
process.env.CODE_SERVER_TEST_ENTRY || ".",
|
||||||
...this.codeServerArgs,
|
|
||||||
// Using port zero will spawn on a random port.
|
// Using port zero will spawn on a random port.
|
||||||
"--bind-addr",
|
"--bind-addr",
|
||||||
"127.0.0.1:0",
|
"127.0.0.1:0",
|
||||||
|
@ -89,8 +88,6 @@ export class CodeServer {
|
||||||
path.join(dir, "config.yaml"),
|
path.join(dir, "config.yaml"),
|
||||||
"--user-data-dir",
|
"--user-data-dir",
|
||||||
dir,
|
dir,
|
||||||
"--extensions-dir",
|
|
||||||
path.join(__dirname, "../extensions"),
|
|
||||||
// The last argument is the workspace to open.
|
// The last argument is the workspace to open.
|
||||||
dir,
|
dir,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { describe, test, expect } from "./baseFixture"
|
import { describe, test, expect } from "./baseFixture"
|
||||||
|
|
||||||
describe("Open Help > About", true, [], () => {
|
describe("Open Help > About", true, () => {
|
||||||
test("should see code-server version in about dialog", async ({ codeServerPage }) => {
|
test("should see code-server version in about dialog", async ({ codeServerPage }) => {
|
||||||
// Open using the menu.
|
// Open using the menu.
|
||||||
await codeServerPage.navigateMenus(["Help", "About"])
|
await codeServerPage.navigateMenus(["Help", "About"])
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
import * as cp from "child_process"
|
import * as cp from "child_process"
|
||||||
|
import * as fs from "fs"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import util from "util"
|
import util from "util"
|
||||||
import { clean, tmpdir } from "../utils/helpers"
|
import { tmpdir } from "../utils/helpers"
|
||||||
import { describe, expect, test } from "./baseFixture"
|
import { describe, expect, test } from "./baseFixture"
|
||||||
|
|
||||||
describe("Integrated Terminal", true, [], () => {
|
describe("Integrated Terminal", true, () => {
|
||||||
const testName = "integrated-terminal"
|
// Create a new context with the saved storage state
|
||||||
|
// so we don't have to logged in
|
||||||
|
const testFileName = "pipe"
|
||||||
|
const testString = "new string test from e2e test"
|
||||||
|
let tmpFolderPath = ""
|
||||||
|
let tmpFile = ""
|
||||||
|
|
||||||
test.beforeAll(async () => {
|
test.beforeAll(async () => {
|
||||||
await clean(testName)
|
tmpFolderPath = await tmpdir("integrated-terminal")
|
||||||
|
tmpFile = path.join(tmpFolderPath, testFileName)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("should have access to VSCODE_PROXY_URI", async ({ codeServerPage }) => {
|
test.afterAll(async () => {
|
||||||
const tmpFolderPath = await tmpdir(testName)
|
// Ensure directory was removed
|
||||||
const tmpFile = path.join(tmpFolderPath, "pipe")
|
await fs.promises.rmdir(tmpFolderPath, { recursive: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
test("should echo a string to a file", async ({ codeServerPage }) => {
|
||||||
const command = `mkfifo '${tmpFile}' && cat '${tmpFile}'`
|
const command = `mkfifo '${tmpFile}' && cat '${tmpFile}'`
|
||||||
const exec = util.promisify(cp.exec)
|
const exec = util.promisify(cp.exec)
|
||||||
const output = exec(command, { encoding: "utf8" })
|
const output = exec(command, { encoding: "utf8" })
|
||||||
|
@ -22,12 +32,12 @@ describe("Integrated Terminal", true, [], () => {
|
||||||
await codeServerPage.focusTerminal()
|
await codeServerPage.focusTerminal()
|
||||||
|
|
||||||
await codeServerPage.page.waitForLoadState("load")
|
await codeServerPage.page.waitForLoadState("load")
|
||||||
await codeServerPage.page.keyboard.type(`printenv VSCODE_PROXY_URI > ${tmpFile}`)
|
await codeServerPage.page.keyboard.type(`echo ${testString} > ${tmpFile}`)
|
||||||
await codeServerPage.page.keyboard.press("Enter")
|
await codeServerPage.page.keyboard.press("Enter")
|
||||||
// It may take a second to process
|
// It may take a second to process
|
||||||
await codeServerPage.page.waitForTimeout(1000)
|
await codeServerPage.page.waitForTimeout(1000)
|
||||||
|
|
||||||
const { stdout } = await output
|
const { stdout } = await output
|
||||||
expect(stdout).toMatch(await codeServerPage.address())
|
expect(stdout).toMatch(testString)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
"argon2/@mapbox/node-pre-gyp/tar": "^6.1.9",
|
"argon2/@mapbox/node-pre-gyp/tar": "^6.1.9",
|
||||||
"set-value": "^4.0.1",
|
"set-value": "^4.0.1",
|
||||||
"tmpl": "^1.0.5",
|
"tmpl": "^1.0.5",
|
||||||
"path-parse": "^1.0.7",
|
"path-parse": "^1.0.7"
|
||||||
"json-schema": "^0.4.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ const config: PlaywrightTestConfig = {
|
||||||
testDir: path.join(__dirname, "e2e"), // Search for tests in this directory.
|
testDir: path.join(__dirname, "e2e"), // Search for tests in this directory.
|
||||||
timeout: 60000, // Each test is given 60 seconds.
|
timeout: 60000, // Each test is given 60 seconds.
|
||||||
retries: process.env.CI ? 2 : 1, // Retry in CI due to flakiness.
|
retries: process.env.CI ? 2 : 1, // Retry in CI due to flakiness.
|
||||||
globalSetup: require.resolve("./utils/globalE2eSetup.ts"),
|
globalSetup: require.resolve("./utils/globalSetup.ts"),
|
||||||
reporter: "list",
|
reporter: "list",
|
||||||
// Put any shared options on the top level.
|
// Put any shared options on the top level.
|
||||||
use: {
|
use: {
|
||||||
|
@ -25,10 +25,12 @@ const config: PlaywrightTestConfig = {
|
||||||
name: "Chromium",
|
name: "Chromium",
|
||||||
use: { browserName: "chromium" },
|
use: { browserName: "chromium" },
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "Firefox",
|
name: "Firefox",
|
||||||
use: { browserName: "firefox" },
|
use: { browserName: "firefox" },
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "WebKit",
|
name: "WebKit",
|
||||||
use: { browserName: "webkit" },
|
use: { browserName: "webkit" },
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
|
// Note: we need to import logger from the root
|
||||||
|
// because this is the logger used in logError in ../src/common/util
|
||||||
import { logger } from "@coder/logger"
|
import { logger } from "@coder/logger"
|
||||||
|
|
||||||
import { Emitter } from "../../../src/common/emitter"
|
import { Emitter } from "../../../src/common/emitter"
|
||||||
import { mockLogger } from "../../utils/helpers"
|
|
||||||
|
|
||||||
describe("emitter", () => {
|
describe("emitter", () => {
|
||||||
|
let spy: jest.SpyInstance
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockLogger()
|
spy = jest.spyOn(logger, "error")
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
it("should run the correct callbacks", async () => {
|
it("should run the correct callbacks", async () => {
|
||||||
const HELLO_WORLD = "HELLO_WORLD"
|
const HELLO_WORLD = "HELLO_WORLD"
|
||||||
const GOODBYE_WORLD = "GOODBYE_WORLD"
|
const GOODBYE_WORLD = "GOODBYE_WORLD"
|
||||||
|
@ -77,8 +85,8 @@ describe("emitter", () => {
|
||||||
await emitter.emit({ event: HELLO_WORLD, callback: mockCallback })
|
await emitter.emit({ event: HELLO_WORLD, callback: mockCallback })
|
||||||
|
|
||||||
// Check that error was called
|
// Check that error was called
|
||||||
expect(logger.error).toHaveBeenCalled()
|
expect(spy).toHaveBeenCalled()
|
||||||
expect(logger.error).toHaveBeenCalledTimes(1)
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
expect(logger.error).toHaveBeenCalledWith(message)
|
expect(spy).toHaveBeenCalledWith(message)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,7 +19,7 @@ describe("http", () => {
|
||||||
const httpError = new HttpError(message, HttpCode.BadRequest)
|
const httpError = new HttpError(message, HttpCode.BadRequest)
|
||||||
|
|
||||||
expect(httpError.message).toBe(message)
|
expect(httpError.message).toBe(message)
|
||||||
expect(httpError.statusCode).toBe(400)
|
expect(httpError.status).toBe(400)
|
||||||
expect(httpError.details).toBeUndefined()
|
expect(httpError.details).toBeUndefined()
|
||||||
})
|
})
|
||||||
it("should have details if provided", () => {
|
it("should have details if provided", () => {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { logger } from "@coder/logger"
|
|
||||||
import { JSDOM } from "jsdom"
|
import { JSDOM } from "jsdom"
|
||||||
import * as util from "../../../src/common/util"
|
import * as util from "../../../src/common/util"
|
||||||
import { mockLogger } from "../../utils/helpers"
|
import { createLoggerMock } from "../../utils/helpers"
|
||||||
|
|
||||||
const dom = new JSDOM()
|
const dom = new JSDOM()
|
||||||
global.document = dom.window.document
|
global.document = dom.window.document
|
||||||
|
@ -75,6 +74,42 @@ describe("util", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("resolveBase", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const location: LocationLike = {
|
||||||
|
pathname: "/healthz",
|
||||||
|
origin: "http://localhost:8080",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because resolveBase is not a pure function
|
||||||
|
// and relies on the global location to be set
|
||||||
|
// we set it before all the tests
|
||||||
|
// and tell TS that our location should be looked at
|
||||||
|
// as Location (even though it's missing some properties)
|
||||||
|
global.location = location as Location
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should resolve a base", () => {
|
||||||
|
expect(util.resolveBase("localhost:8080")).toBe("/localhost:8080")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should resolve a base with a forward slash at the beginning", () => {
|
||||||
|
expect(util.resolveBase("/localhost:8080")).toBe("/localhost:8080")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should resolve a base with query params", () => {
|
||||||
|
expect(util.resolveBase("localhost:8080?folder=hello-world")).toBe("/localhost:8080")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should resolve a base with a path", () => {
|
||||||
|
expect(util.resolveBase("localhost:8080/hello/world")).toBe("/localhost:8080/hello/world")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should resolve a base to an empty string when not provided", () => {
|
||||||
|
expect(util.resolveBase()).toBe("")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("arrayify", () => {
|
describe("arrayify", () => {
|
||||||
it("should return value it's already an array", () => {
|
it("should return value it's already an array", () => {
|
||||||
expect(util.arrayify(["hello", "world"])).toStrictEqual(["hello", "world"])
|
expect(util.arrayify(["hello", "world"])).toStrictEqual(["hello", "world"])
|
||||||
|
@ -95,29 +130,31 @@ describe("util", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("logError", () => {
|
describe("logError", () => {
|
||||||
beforeAll(() => {
|
|
||||||
mockLogger()
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
const loggerModule = createLoggerMock()
|
||||||
|
|
||||||
it("should log an error with the message and stack trace", () => {
|
it("should log an error with the message and stack trace", () => {
|
||||||
const message = "You don't have access to that folder."
|
const message = "You don't have access to that folder."
|
||||||
const error = new Error(message)
|
const error = new Error(message)
|
||||||
|
|
||||||
util.logError(logger, "ui", error)
|
util.logError(loggerModule.logger, "ui", error)
|
||||||
|
|
||||||
expect(logger.error).toHaveBeenCalled()
|
expect(loggerModule.logger.error).toHaveBeenCalled()
|
||||||
expect(logger.error).toHaveBeenCalledWith(`ui: ${error.message} ${error.stack}`)
|
expect(loggerModule.logger.error).toHaveBeenCalledWith(`ui: ${error.message} ${error.stack}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should log an error, even if not an instance of error", () => {
|
it("should log an error, even if not an instance of error", () => {
|
||||||
util.logError(logger, "api", "oh no")
|
util.logError(loggerModule.logger, "api", "oh no")
|
||||||
|
|
||||||
expect(logger.error).toHaveBeenCalled()
|
expect(loggerModule.logger.error).toHaveBeenCalled()
|
||||||
expect(logger.error).toHaveBeenCalledWith("api: oh no")
|
expect(loggerModule.logger.error).toHaveBeenCalledWith("api: oh no")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
import { promises as fs } from "fs"
|
import { promises as fs } from "fs"
|
||||||
import { clean, getAvailablePort, tmpdir, useEnv } from "../../test/utils/helpers"
|
import { getAvailablePort, tmpdir, useEnv } from "../../test/utils/helpers"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file is for testing test helpers (not core code).
|
* This file is for testing test helpers (not core code).
|
||||||
*/
|
*/
|
||||||
describe("test helpers", () => {
|
describe("test helpers", () => {
|
||||||
const testName = "temp-dir"
|
|
||||||
beforeAll(async () => {
|
|
||||||
await clean(testName)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("should return a temp directory", async () => {
|
it("should return a temp directory", async () => {
|
||||||
|
const testName = "temp-dir"
|
||||||
const pathToTempDir = await tmpdir(testName)
|
const pathToTempDir = await tmpdir(testName)
|
||||||
expect(pathToTempDir).toContain(testName)
|
expect(pathToTempDir).toContain(testName)
|
||||||
expect(fs.access(pathToTempDir)).resolves.toStrictEqual(undefined)
|
expect(fs.access(pathToTempDir)).resolves.toStrictEqual(undefined)
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue