mirror of
https://github.com/coder/code-server.git
synced 2026-04-14 15:19:07 -05:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
072b5a8f92 | ||
|
|
a2e464d06d | ||
|
|
4ad763ad59 |
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -3,5 +3,3 @@
|
||||
ci/helm-chart/ @Matthew-Beckett @alexgorbatchev
|
||||
|
||||
docs/install.md @GNUxeava
|
||||
|
||||
src/node/i18n/locales/zh-cn.json @zhaozhiming
|
||||
|
||||
60
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
60
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
@@ -1,5 +1,6 @@
|
||||
name: Bug report
|
||||
description: File a bug report
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "triage"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
@@ -9,7 +10,6 @@ body:
|
||||
options:
|
||||
- label: I have searched the existing issues
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: OS/Web Information
|
||||
@@ -28,82 +28,58 @@ body:
|
||||
- `code-server --version`:
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: |
|
||||
Please describe exactly how to reproduce the bug. For example:
|
||||
1. Open code-server in Firefox
|
||||
2. Install extension `foo.bar` from the extensions sidebar
|
||||
3. Run command `foo.bar.baz`
|
||||
1. open code-server
|
||||
2. install extension
|
||||
3. run command
|
||||
value: |
|
||||
1.
|
||||
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`).
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshot/Video
|
||||
description: Please include a screenshot, gif or screen recording of your issue.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Does this bug reproduce in native VS Code?
|
||||
description: If the bug reproduces in native VS Code, submit the issue upstream instead (https://github.com/microsoft/vscode).
|
||||
options:
|
||||
- Yes, this is also broken in native VS Code
|
||||
- No, this works as expected in native VS Code
|
||||
- This cannot be tested in native VS Code
|
||||
- I did not test native VS Code
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Does this bug reproduce in GitHub Codespaces?
|
||||
description: If the bug reproduces in GitHub Codespaces, submit the issue upstream instead (https://github.com/microsoft/vscode).
|
||||
options:
|
||||
- Yes, this is also broken in GitHub Codespaces
|
||||
- No, this works as expected in GitHub Codespaces
|
||||
- This cannot be tested in GitHub Codespaces
|
||||
- I did not test GitHub Codespaces
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you accessing code-server over a secure context?
|
||||
description: code-server relies on service workers (which only work in secure contexts) for many features. Double-check that you are using a secure context like HTTPS or localhost.
|
||||
label: Does this issue happen in VS Code or GitHub Codespaces?
|
||||
description: Please try reproducing this issue in VS Code or GitHub Codespaces
|
||||
options:
|
||||
- label: I am using a secure context.
|
||||
required: false
|
||||
|
||||
- label: I cannot reproduce this in VS Code.
|
||||
required: true
|
||||
- label: I cannot reproduce this in GitHub Codespaces.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Are you accessing code-server over HTTPS?
|
||||
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
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/doc.md
vendored
2
.github/ISSUE_TEMPLATE/doc.md
vendored
@@ -1,7 +1,9 @@
|
||||
---
|
||||
name: Documentation improvement
|
||||
about: Suggest a documentation improvement
|
||||
title: "[Docs]: "
|
||||
labels: "docs"
|
||||
assignees: "@jsjoeio"
|
||||
---
|
||||
|
||||
## What is your suggestion?
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -1,7 +1,9 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea to improve code-server
|
||||
title: "[Feat]: "
|
||||
labels: enhancement
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
## What is your suggestion?
|
||||
|
||||
31
.github/dependabot.yaml
vendored
31
.github/dependabot.yaml
vendored
@@ -1,31 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
time: "06:00"
|
||||
timezone: "America/Chicago"
|
||||
labels: []
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
time: "06:00"
|
||||
timezone: "America/Chicago"
|
||||
commit-message:
|
||||
prefix: "chore"
|
||||
labels: []
|
||||
ignore:
|
||||
# Ignore patch updates for all dependencies
|
||||
- dependency-name: "*"
|
||||
update-types:
|
||||
- version-update:semver-patch
|
||||
# Ignore major updates to Node.js types, because they need to
|
||||
# correspond to the Node.js engine version
|
||||
- dependency-name: "@types/node"
|
||||
update-types:
|
||||
- version-update:semver-major
|
||||
255
.github/workflows/build.yaml
vendored
255
.github/workflows/build.yaml
vendored
@@ -24,37 +24,37 @@ concurrency:
|
||||
jobs:
|
||||
prettier:
|
||||
name: Format with Prettier
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run prettier with actionsx/prettier
|
||||
uses: actionsx/prettier@v3
|
||||
uses: actionsx/prettier@v2
|
||||
with:
|
||||
args: --check --loglevel=warn .
|
||||
|
||||
doctoc:
|
||||
name: Doctoc markdown files
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
uses: tj-actions/changed-files@v26.1
|
||||
with:
|
||||
files: |
|
||||
docs/**
|
||||
|
||||
- name: Install Node.js
|
||||
- name: Install Node.js v16
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
cache: "yarn"
|
||||
|
||||
- name: Install doctoc
|
||||
@@ -66,24 +66,24 @@ jobs:
|
||||
|
||||
lint-helm:
|
||||
name: Lint Helm chart
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
uses: tj-actions/changed-files@v26.1
|
||||
with:
|
||||
files: |
|
||||
ci/helm-chart/**
|
||||
|
||||
- name: Install helm
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: azure/setup-helm@v4
|
||||
uses: azure/setup-helm@v3.4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -97,17 +97,17 @@ jobs:
|
||||
|
||||
lint-ts:
|
||||
name: Lint TypeScript files
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
uses: tj-actions/changed-files@v26.1
|
||||
with:
|
||||
files: |
|
||||
**/*.ts
|
||||
@@ -115,16 +115,16 @@ jobs:
|
||||
files_ignore: |
|
||||
lib/vscode/**
|
||||
|
||||
- name: Install Node.js
|
||||
- name: Install Node.js v16
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -139,83 +139,18 @@ jobs:
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: yarn lint:ts
|
||||
|
||||
lint-actions:
|
||||
name: Lint GitHub Actions
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- name: Check workflow files
|
||||
run: |
|
||||
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/7fdc9630cc360ea1a469eed64ac6d78caeda1234/scripts/download-actionlint.bash)
|
||||
./actionlint -color -shellcheck= -ignore "set-output"
|
||||
shell: bash
|
||||
|
||||
test-unit:
|
||||
name: Run unit tests
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
with:
|
||||
files: |
|
||||
**/*.ts
|
||||
files_ignore: |
|
||||
lib/vscode/**
|
||||
|
||||
- name: Install Node.js
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.changed-files.outputs.any_changed == 'true' && steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
|
||||
|
||||
- name: Run unit tests
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
run: yarn test:unit
|
||||
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
if: success()
|
||||
|
||||
build:
|
||||
name: Build code-server
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
DISABLE_V8_COMPILE_CACHE: 1
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install system dependencies
|
||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
|
||||
- name: Install quilt
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
@@ -225,34 +160,36 @@ jobs:
|
||||
- name: Patch Code
|
||||
run: quilt push -a
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-code-server-${{ hashFiles('**/yarn.lock') }}
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-code-server-
|
||||
yarn-build-
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
- name: Build code-server
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: yarn build
|
||||
|
||||
# Get Code's git hash. When this changes it means the content is
|
||||
# different and we need to rebuild.
|
||||
- name: Get latest lib/vscode rev
|
||||
id: vscode-rev
|
||||
run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
|
||||
run: echo "::set-output name=rev::$(git rev-parse HEAD:./lib/vscode)"
|
||||
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq -r .version package.json)"
|
||||
|
||||
# We need to rebuild when we have a new version of Code, when any of
|
||||
# the patches changed, or when the code-server version changes (since
|
||||
@@ -260,17 +197,28 @@ jobs:
|
||||
# force a rebuild.
|
||||
- name: Fetch prebuilt Code package from cache
|
||||
id: cache-vscode
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: lib/vscode-reh-web-*
|
||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
||||
key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ steps.version.outputs.version }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
|
||||
|
||||
- name: Build vscode
|
||||
env:
|
||||
VERSION: "0.0.0"
|
||||
if: steps.cache-vscode.outputs.cache-hit != 'true'
|
||||
run: yarn build:vscode
|
||||
|
||||
# Our code imports code from VS Code's `out` directory meaning VS Code
|
||||
# must be built before running these tests.
|
||||
# TODO: Move to its own step?
|
||||
- name: Run code-server unit tests
|
||||
run: yarn test:unit
|
||||
if: success()
|
||||
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
if: success()
|
||||
|
||||
# The release package does not contain any native modules
|
||||
# and is neutral to architecture/os/libc version.
|
||||
- name: Create release package
|
||||
@@ -282,31 +230,81 @@ jobs:
|
||||
run: tar -czf package.tar.gz release
|
||||
|
||||
- name: Upload npm package artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: npm-package
|
||||
path: ./package.tar.gz
|
||||
|
||||
npm:
|
||||
name: Publish npm package
|
||||
# the npm-package gets uploaded as an artifact in Build
|
||||
# so we need that to complete before this runs
|
||||
needs: build
|
||||
# This environment "npm" requires someone from
|
||||
# coder/code-server-reviewers to approve the PR before this job runs.
|
||||
environment: npm
|
||||
# Only run if PR comes from base repo or event is not a PR
|
||||
# Reason: forks cannot access secrets and this will always fail
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v3
|
||||
id: download
|
||||
with:
|
||||
name: "npm-package"
|
||||
path: release-npm-package
|
||||
|
||||
- name: Run ./ci/steps/publish-npm.sh
|
||||
run: yarn publish:npm
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
# NOTE@jsjoeio
|
||||
# NPM_ENVIRONMENT intentionally not set here.
|
||||
# Instead, itis determined in publish-npm.sh script
|
||||
# using GITHUB environment variables
|
||||
|
||||
- name: Comment npm information
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
header: npm-dev-build
|
||||
message: |
|
||||
✨ code-server dev build published to npm for PR #${{ github.event.number }}!
|
||||
* _Last publish status_: success
|
||||
* _Commit_: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
To install in a local project, run:
|
||||
```shell-session
|
||||
npm install @coder/code-server-pr@${{ github.event.number }}
|
||||
```
|
||||
|
||||
To install globally, run:
|
||||
```shell-session
|
||||
npm install -g @coder/code-server-pr@${{ github.event.number }}
|
||||
```
|
||||
|
||||
test-e2e:
|
||||
name: Run e2e tests
|
||||
needs: build
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 25
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install system dependencies
|
||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -314,7 +312,7 @@ jobs:
|
||||
yarn-build-
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: npm-package
|
||||
|
||||
@@ -322,7 +320,7 @@ jobs:
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
- name: Install release package dependencies
|
||||
run: cd release && npm install --unsafe-perm --omit=dev
|
||||
run: cd release && yarn install
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
@@ -334,11 +332,11 @@ jobs:
|
||||
./test/node_modules/.bin/playwright install
|
||||
|
||||
- name: Run end-to-end tests
|
||||
run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e
|
||||
run: CODE_SERVER_TEST_ENTRY=./release yarn test:e2e --global-timeout 840000
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-test-videos
|
||||
path: ./test/test-results
|
||||
@@ -349,23 +347,20 @@ jobs:
|
||||
test-e2e-proxy:
|
||||
name: Run e2e tests behind proxy
|
||||
needs: build
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 25
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install system dependencies
|
||||
run: sudo apt update && sudo apt install -y libkrb5-dev
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
@@ -373,7 +368,7 @@ jobs:
|
||||
yarn-build-
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: npm-package
|
||||
|
||||
@@ -381,7 +376,7 @@ jobs:
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
- name: Install release package dependencies
|
||||
run: cd release && npm install --unsafe-perm --omit=dev
|
||||
run: cd release && yarn install
|
||||
|
||||
- name: Install dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
@@ -393,7 +388,7 @@ jobs:
|
||||
./test/node_modules/.bin/playwright install
|
||||
|
||||
- name: Cache Caddy
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v2
|
||||
id: caddy-cache
|
||||
with:
|
||||
path: |
|
||||
@@ -406,7 +401,7 @@ jobs:
|
||||
if: steps.caddy-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
|
||||
mkdir -p ~/.cache/caddy
|
||||
mkdir -p ~/.cache/caddy
|
||||
tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
|
||||
|
||||
- name: Start Caddy
|
||||
@@ -421,7 +416,7 @@ jobs:
|
||||
|
||||
- name: Upload test artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: failed-test-videos-proxy
|
||||
path: ./test/test-results
|
||||
|
||||
46
.github/workflows/docs-preview.yaml
vendored
Normal file
46
.github/workflows/docs-preview.yaml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Docs preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "docs/**"
|
||||
|
||||
permissions:
|
||||
actions: none
|
||||
checks: none
|
||||
contents: read
|
||||
deployments: none
|
||||
issues: none
|
||||
packages: none
|
||||
pull-requests: write
|
||||
repository-projects: none
|
||||
security-events: none
|
||||
statuses: none
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
name: Docs preview
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
|
||||
- name: Comment Credentials
|
||||
uses: marocchino/sticky-pull-request-comment@v2
|
||||
# Only run if PR comes from base repo
|
||||
# Reason: forks cannot access secrets and this will always fail
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
header: codercom-preview-docs
|
||||
message: |
|
||||
✨ code-server docs for PR #${{ github.event.number }} is ready! It will be updated on every commit.
|
||||
* _Host_: https://coder.com/docs/code-server/${{ steps.vars.outputs.sha_short }}
|
||||
* _Last deploy status_: success
|
||||
* _Commit_: ${{ github.event.pull_request.head.sha }}
|
||||
* _Workflow status_: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
8
.github/workflows/installer.yaml
vendored
8
.github/workflows/installer.yaml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install code-server
|
||||
run: ./install.sh
|
||||
@@ -41,10 +41,10 @@ jobs:
|
||||
alpine:
|
||||
name: Test installer on Alpine
|
||||
runs-on: ubuntu-latest
|
||||
container: "alpine:3.17"
|
||||
container: "alpine:3.16"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install curl
|
||||
run: apk add curl
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install code-server
|
||||
run: ./install.sh
|
||||
|
||||
109
.github/workflows/publish.yaml
vendored
109
.github/workflows/publish.yaml
vendored
@@ -4,11 +4,6 @@ on:
|
||||
# Shows the manual trigger in GitHub UI
|
||||
# helpful as a back-up in case the GitHub Actions Workflow fails
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: The version to publish (include "v", i.e. "v4.9.1").
|
||||
type: string
|
||||
required: true
|
||||
|
||||
release:
|
||||
types: [released]
|
||||
@@ -27,33 +22,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
cache: "yarn"
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq -r .version package.json)"
|
||||
|
||||
- name: Download npm package from release artifacts
|
||||
uses: robinraju/release-downloader@v1.10
|
||||
uses: robinraju/release-downloader@v1.5
|
||||
with:
|
||||
repository: "coder/code-server"
|
||||
tag: ${{ github.event.inputs.version || github.ref_name }}
|
||||
tag: v${{ steps.version.outputs.version }}
|
||||
fileName: "package.tar.gz"
|
||||
out-file-path: "release-npm-package"
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Publish npm package and tag with "latest"
|
||||
run: yarn publish:npm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_ENVIRONMENT: "production"
|
||||
@@ -70,25 +55,16 @@ jobs:
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --global user.name cdrci
|
||||
git config --global user.email opensource@coder.com
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Bump code-server homebrew version
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
HOMEBREW_GITHUB_API_TOKEN: ${{secrets.HOMEBREW_GITHUB_API_TOKEN}}
|
||||
|
||||
run: ./ci/steps/brew-bump.sh
|
||||
|
||||
aur:
|
||||
@@ -97,17 +73,23 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
|
||||
steps:
|
||||
# We need to checkout code-server so we can get the version
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: "./code-server"
|
||||
|
||||
- name: Get code-server version
|
||||
id: version
|
||||
run: |
|
||||
pushd code-server
|
||||
echo "::set-output name=version::$(jq -r .version package.json)"
|
||||
popd
|
||||
|
||||
- name: Checkout code-server-aur repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: "cdrci/code-server-aur"
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
|
||||
@@ -124,83 +106,60 @@ jobs:
|
||||
git config --global user.name cdrci
|
||||
git config --global user.email opensource@coder.com
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Validate package
|
||||
uses: heyhusen/archlinux-package-action@v2.2.1
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
uses: hapakaien/archlinux-package-action@v2
|
||||
with:
|
||||
pkgver: ${{ env.VERSION }}
|
||||
pkgver: ${{ steps.version.outputs.version }}
|
||||
updpkgsums: true
|
||||
srcinfo: true
|
||||
|
||||
- name: Open PR
|
||||
# We need to git push -u otherwise gh will prompt
|
||||
# asking where to push the branch.
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
git checkout -b update-version-${{ env.VERSION }}
|
||||
git add .
|
||||
git commit -m "chore: updating version to ${{ env.VERSION }}"
|
||||
git checkout -b update-version-${{ steps.version.outputs.version }}
|
||||
git add .
|
||||
git commit -m "chore: updating version to ${{ steps.version.outputs.version }}"
|
||||
git push -u origin $(git branch --show)
|
||||
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
||||
gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ steps.version.outputs.version }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR
|
||||
docker:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout code-server
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ github.event.inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
- name: Get version
|
||||
id: version
|
||||
run: echo "::set-output name=version::$(jq -r .version package.json)"
|
||||
|
||||
- name: Download deb artifacts
|
||||
uses: robinraju/release-downloader@v1.10
|
||||
- name: Download release artifacts
|
||||
uses: robinraju/release-downloader@v1.5
|
||||
with:
|
||||
repository: "coder/code-server"
|
||||
tag: v${{ env.VERSION }}
|
||||
tag: v${{ steps.version.outputs.version }}
|
||||
fileName: "*.deb"
|
||||
out-file-path: "release-packages"
|
||||
|
||||
- name: Download rpm artifacts
|
||||
uses: robinraju/release-downloader@v1.10
|
||||
with:
|
||||
repository: "coder/code-server"
|
||||
tag: v${{ env.VERSION }}
|
||||
fileName: "*.rpm"
|
||||
out-file-path: "release-packages"
|
||||
|
||||
- name: Publish to Docker
|
||||
run: ./ci/steps/docker-buildx-push.sh
|
||||
run: yarn publish:docker
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
269
.github/workflows/release.yaml
vendored
269
.github/workflows/release.yaml
vendored
@@ -2,11 +2,6 @@ name: Draft release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: The version to publish (include "v", i.e. "v4.9.1").
|
||||
type: string
|
||||
required: true
|
||||
|
||||
permissions:
|
||||
contents: write # For creating releases.
|
||||
@@ -26,31 +21,28 @@ jobs:
|
||||
name: x86-64 Linux build
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
container: "centos:8"
|
||||
container: "centos:7"
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Install development tools
|
||||
run: |
|
||||
cd /etc/yum.repos.d/
|
||||
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
|
||||
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
|
||||
yum install -y gcc-c++ make jq rsync python3 libsecret-devel krb5-devel
|
||||
yum install -y epel-release centos-release-scl make
|
||||
yum install -y devtoolset-9-{make,gcc,gcc-c++} jq rsync python3
|
||||
|
||||
- name: Install nfpm and envsubst
|
||||
run: |
|
||||
mkdir -p ~/.local/bin
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.22.2/nfpm_2.22.2_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
curl -sSfL https://github.com/a8m/envsubst/releases/download/v1.1.0/envsubst-`uname -s`-`uname -m` -o envsubst
|
||||
chmod +x envsubst
|
||||
mv envsubst ~/.local/bin
|
||||
@@ -59,101 +51,102 @@ jobs:
|
||||
- name: Install yarn
|
||||
run: npm install -g yarn
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
name: npm-release-package
|
||||
branch: ${{ github.ref }}
|
||||
workflow: build.yaml
|
||||
workflow_conclusion: completed
|
||||
check_artifacts: true
|
||||
name: npm-package
|
||||
|
||||
- name: Decompress npm package
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
# NOTE: && here is deliberate - GitHub puts each line in its own `.sh`
|
||||
# file when running inside a docker container.
|
||||
- name: Build standalone release
|
||||
run: npm run release:standalone
|
||||
run: source scl_source enable devtoolset-9 && yarn release:standalone
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
|
||||
- name: Install test dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
|
||||
|
||||
- name: Run integration tests on standalone release
|
||||
run: yarn test:integration
|
||||
|
||||
- name: Upload coverage report to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
if: success()
|
||||
continue-on-error: true
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build packages with nfpm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: yarn package
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./release-packages/*
|
||||
|
||||
# NOTE@oxy:
|
||||
# We use Ubuntu 16.04 here, so that our build is more compatible
|
||||
# with older libc versions. We used to (Q1'20) use CentOS 7 here,
|
||||
# but it has a full update EOL of Q4'20 and a 'critical security'
|
||||
# update EOL of 2024. We're dropping full support a few years before
|
||||
# the final EOL, but I don't believe CentOS 7 has a large arm64 userbase.
|
||||
# It is not feasible to cross-compile with CentOS.
|
||||
|
||||
# Cross-compile notes: To compile native dependencies for arm64,
|
||||
# we install the aarch64/armv7l cross toolchain and then set it as the default
|
||||
# compiler/linker/etc. with the AR/CC/CXX/LINK environment variables.
|
||||
# qemu-user-static on ubuntu-16.04 currently doesn't run Node correctly,
|
||||
# so we just build with "native"/x86_64 node, then download arm64/armv7l node
|
||||
# and then put it in our release. We can't smoke test the cross build this way,
|
||||
# but this means we don't need to maintain a self-hosted runner!
|
||||
|
||||
# NOTE@jsjoeio:
|
||||
# We used to use 16.04 until GitHub deprecated it on September 20, 2021
|
||||
# See here: https://github.com/actions/virtual-environments/pull/3862/files
|
||||
package-linux-cross:
|
||||
name: Linux cross-compile builds
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-18.04
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
container: "debian:buster"
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- prefix: aarch64-linux-gnu
|
||||
npm_arch: arm64
|
||||
apt_arch: arm64
|
||||
arch: arm64
|
||||
- prefix: arm-linux-gnueabihf
|
||||
npm_arch: armv7l
|
||||
apt_arch: armhf
|
||||
arch: armv7l
|
||||
|
||||
env:
|
||||
AR: ${{ format('{0}-ar', matrix.prefix) }}
|
||||
AS: ${{ format('{0}-as', matrix.prefix) }}
|
||||
CC: ${{ format('{0}-gcc', matrix.prefix) }}
|
||||
CPP: ${{ format('{0}-cpp', matrix.prefix) }}
|
||||
CXX: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
FC: ${{ format('{0}-gfortran', matrix.prefix) }}
|
||||
LD: ${{ format('{0}-ld', matrix.prefix) }}
|
||||
STRIP: ${{ format('{0}-strip', matrix.prefix) }}
|
||||
PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
|
||||
TARGET_ARCH: ${{ matrix.apt_arch }}
|
||||
npm_config_arch: ${{ matrix.npm_arch }}
|
||||
# Not building from source results in an x86_64 argon2, as if
|
||||
# npm_config_arch is being ignored.
|
||||
npm_config_build_from_source: true
|
||||
LINK: ${{ format('{0}-g++', matrix.prefix) }}
|
||||
NPM_CONFIG_ARCH: ${{ matrix.arch }}
|
||||
NODE_VERSION: v16.13.0
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
|
||||
- name: Install cross-compiler and system dependencies
|
||||
run: |
|
||||
dpkg --add-architecture $TARGET_ARCH
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
crossbuild-essential-$TARGET_ARCH \
|
||||
libx11-dev:$TARGET_ARCH \
|
||||
libx11-xcb-dev:$TARGET_ARCH \
|
||||
libxkbfile-dev:$TARGET_ARCH \
|
||||
libsecret-1-dev:$TARGET_ARCH \
|
||||
libkrb5-dev:$TARGET_ARCH \
|
||||
ca-certificates \
|
||||
curl wget rsync gettext-base
|
||||
node-version: "16"
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
@@ -161,37 +154,37 @@ jobs:
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Install cross-compiler
|
||||
run: sudo apt update && sudo apt install $PACKAGE
|
||||
env:
|
||||
PACKAGE: ${{ format('g++-{0}', matrix.prefix) }}
|
||||
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
name: npm-release-package
|
||||
branch: ${{ github.ref }}
|
||||
workflow: build.yaml
|
||||
workflow_conclusion: completed
|
||||
check_artifacts: true
|
||||
name: npm-package
|
||||
|
||||
- name: Decompress npm package
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
- name: Build standalone release
|
||||
run: npm run release:standalone
|
||||
run: yarn release:standalone
|
||||
|
||||
- name: Replace node with cross-compile equivalent
|
||||
run: |
|
||||
node_version=$(node --version)
|
||||
wget https://nodejs.org/dist/${node_version}/node-${node_version}-linux-${npm_config_arch}.tar.xz
|
||||
tar -xf node-${node_version}-linux-${npm_config_arch}.tar.xz node-${node_version}-linux-${npm_config_arch}/bin/node --strip-components=2
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-linux-${NPM_CONFIG_ARCH}.tar.xz
|
||||
tar -xf node-${NODE_VERSION}-linux-${NPM_CONFIG_ARCH}.tar.xz node-${NODE_VERSION}-linux-${NPM_CONFIG_ARCH}/bin/node --strip-components=2
|
||||
mv ./node ./release-standalone/lib/node
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build packages with nfpm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: npm run package ${npm_config_arch}
|
||||
run: yarn package ${NPM_CONFIG_ARCH}
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
@@ -201,15 +194,14 @@ jobs:
|
||||
name: x86-64 macOS build
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Install nfpm
|
||||
run: |
|
||||
@@ -217,43 +209,42 @@ jobs:
|
||||
curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
# The version of node-gyp we use depends on distutils but it was removed
|
||||
# in Python 3.12. It seems to be fixed in the latest node-gyp so when we
|
||||
# next update Node we can probably remove this. For now, install
|
||||
# setuptools since it contains distutils.
|
||||
- name: Install Python utilities
|
||||
run: brew install python-setuptools
|
||||
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
name: npm-release-package
|
||||
branch: ${{ github.ref }}
|
||||
workflow: build.yaml
|
||||
workflow_conclusion: completed
|
||||
check_artifacts: true
|
||||
name: npm-package
|
||||
|
||||
- name: Decompress npm package
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
- name: Build standalone release
|
||||
run: npm run release:standalone
|
||||
run: yarn release:standalone
|
||||
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-node-modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
|
||||
- name: Install test dependencies
|
||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn install
|
||||
|
||||
- name: Run native module tests on standalone release
|
||||
run: yarn test:native
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build packages with nfpm
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: yarn package
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
@@ -263,63 +254,19 @@ jobs:
|
||||
name: Upload npm package
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
needs: npm-version
|
||||
steps:
|
||||
- name: Download npm package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: npm-release-package
|
||||
|
||||
- uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./package.tar.gz
|
||||
|
||||
npm-version:
|
||||
name: Modify package.json version
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: dawidd6/action-download-artifact@v3
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
id: download
|
||||
with:
|
||||
branch: ${{ github.ref }}
|
||||
workflow: build.yaml
|
||||
workflow_conclusion: completed
|
||||
check_artifacts: true
|
||||
name: npm-package
|
||||
check_artifacts: false
|
||||
if_no_artifact_found: fail
|
||||
|
||||
- name: Decompress npm package
|
||||
run: tar -xzf package.tar.gz
|
||||
|
||||
# NOTE@jsjoeio - we do this so we can strip out the v
|
||||
# i.e. v4.9.1 -> 4.9.1
|
||||
- name: Get and set VERSION
|
||||
run: |
|
||||
TAG="${{ inputs.version || github.ref_name }}"
|
||||
echo "VERSION=${TAG#v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Modify version
|
||||
env:
|
||||
VERSION: ${{ env.VERSION }}
|
||||
run: |
|
||||
echo "Updating version in root package.json"
|
||||
npm version --prefix release "$VERSION"
|
||||
|
||||
echo "Updating version in lib/vscode/product.json"
|
||||
tmp=$(mktemp)
|
||||
jq ".codeServerVersion = \"$VERSION\"" release/lib/vscode/product.json > "$tmp" && mv "$tmp" release/lib/vscode/product.json
|
||||
# Ensure it has the same permissions as before
|
||||
chmod 644 release/lib/vscode/product.json
|
||||
|
||||
- name: Compress release package
|
||||
run: tar -czf package.tar.gz release
|
||||
|
||||
- name: Upload npm package artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
- uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: npm-release-package
|
||||
path: ./package.tar.gz
|
||||
draft: true
|
||||
discussion_category_name: "📣 Announcements"
|
||||
files: ./package.tar.gz
|
||||
|
||||
6
.github/workflows/scripts.yaml
vendored
6
.github/workflows/scripts.yaml
vendored
@@ -38,10 +38,10 @@ jobs:
|
||||
name: Run script unit tests
|
||||
runs-on: ubuntu-latest
|
||||
# This runs on Alpine to make sure we're testing with actual sh.
|
||||
container: "alpine:3.17"
|
||||
container: "alpine:3.16"
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install test utilities
|
||||
run: apk add bats checkbashisms
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install lint utilities
|
||||
run: sudo apt install shellcheck
|
||||
|
||||
46
.github/workflows/security.yaml
vendored
46
.github/workflows/security.yaml
vendored
@@ -12,8 +12,9 @@ on:
|
||||
# Runs every Monday morning PST
|
||||
- cron: "17 15 * * 1"
|
||||
|
||||
# Cancel in-progress runs for pull requests when developers push additional
|
||||
# changes, and serialize builds in branches.
|
||||
# Cancel in-progress runs for pull requests when developers push
|
||||
# additional changes, and serialize builds in branches.
|
||||
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
@@ -25,21 +26,30 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
- name: Install Node.js v16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: .node-version
|
||||
node-version: "16"
|
||||
|
||||
- name: Audit yarn for vulnerabilities
|
||||
run: yarn audit
|
||||
if: success()
|
||||
- name: Fetch dependencies from cache
|
||||
id: cache-yarn
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: yarn-build-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
yarn-build-
|
||||
|
||||
- name: Audit npm for vulnerabilities
|
||||
run: npm shrinkwrap && npm audit
|
||||
- name: Install dependencies
|
||||
if: steps.cache-yarn.outputs.cache-hit != 'true'
|
||||
run: SKIP_SUBMODULE_DEPS=1 yarn --frozen-lockfile
|
||||
|
||||
- name: Audit for vulnerabilities
|
||||
run: yarn _audit
|
||||
if: success()
|
||||
|
||||
trivy-scan-repo:
|
||||
@@ -50,12 +60,12 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
uses: aquasecurity/trivy-action@fd25fed6972e341ff0007ddb61f77e88103953c2
|
||||
uses: aquasecurity/trivy-action@e55de85beea5fcec743de6bb6bc56943a0af3c33
|
||||
with:
|
||||
scan-type: "fs"
|
||||
scan-ref: "."
|
||||
@@ -66,7 +76,7 @@ jobs:
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: "trivy-repo-results.sarif"
|
||||
|
||||
@@ -80,17 +90,17 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
config-file: ./.github/codeql-config.yml
|
||||
languages: javascript
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
6
.github/workflows/trivy-docker.yaml
vendored
6
.github/workflows/trivy-docker.yaml
vendored
@@ -48,10 +48,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run Trivy vulnerability scanner in image mode
|
||||
uses: aquasecurity/trivy-action@fd25fed6972e341ff0007ddb61f77e88103953c2
|
||||
uses: aquasecurity/trivy-action@e55de85beea5fcec743de6bb6bc56943a0af3c33
|
||||
with:
|
||||
image-ref: "docker.io/codercom/code-server:latest"
|
||||
ignore-unfixed: true
|
||||
@@ -60,6 +60,6 @@ jobs:
|
||||
severity: "HIGH,CRITICAL"
|
||||
|
||||
- name: Upload Trivy scan results to GitHub Security tab
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: "trivy-image-results.sarif"
|
||||
|
||||
@@ -1 +1 @@
|
||||
20.11.1
|
||||
16
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
lib/vscode
|
||||
lib/vscode-reh-web-linux-x64
|
||||
release-standalone
|
||||
release-packages
|
||||
release
|
||||
helm-chart
|
||||
test/scripts
|
||||
|
||||
378
CHANGELOG.md
378
CHANGELOG.md
@@ -20,386 +20,10 @@ Code v99.99.999
|
||||
|
||||
-->
|
||||
|
||||
## Unreleased
|
||||
|
||||
Code v1.90.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Cache a call to get CPU information used in telemetry that could result in a
|
||||
lack responsiveness if it was particularly slow.
|
||||
|
||||
## [4.90.0](https://github.com/coder/code-server/releases/tag/v4.90.0) - 2024-06-11
|
||||
|
||||
Code v1.90.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.90.0.
|
||||
- Updated Node to 20.11.1.
|
||||
|
||||
### Added
|
||||
|
||||
- Send contents to the clipboard in the integrated terminal by piping to
|
||||
`code-server --stdin-to-clipboard` or `code-server -c`.
|
||||
|
||||
You may want to make this an alias:
|
||||
|
||||
```
|
||||
alias xclip="code-server --stdin-to-clipboard"
|
||||
echo -n "hello world" | xclip
|
||||
```
|
||||
|
||||
## [4.89.1](https://github.com/coder/code-server/releases/tag/v4.89.1) - 2024-04-14
|
||||
|
||||
Code v1.89.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.89.1.
|
||||
|
||||
## [4.89.0](https://github.com/coder/code-server/releases/tag/v4.89.0) - 2024-04-08
|
||||
|
||||
Code v1.89.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.89.0.
|
||||
|
||||
## [4.23.1](https://github.com/coder/code-server/releases/tag/v4.23.1) - 2024-04-15
|
||||
|
||||
Code v1.88.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.88.1.
|
||||
|
||||
## [4.23.0](https://github.com/coder/code-server/releases/tag/v4.23.0) - 2024-04-08
|
||||
|
||||
Code v1.88.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.88.0.
|
||||
- Updated Node to 18.18.2.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix masking the exit code when failing to install extensions on the command
|
||||
line outside the integrated terminal. Installing extensions inside the
|
||||
integrated terminal still masks the exit code and is an upstream bug.
|
||||
|
||||
## [4.22.1](https://github.com/coder/code-server/releases/tag/v4.22.1) - 2024-03-14
|
||||
|
||||
Code v1.87.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.87.2.
|
||||
- Enable keep-alive for proxy agent.
|
||||
|
||||
## [4.22.0](https://github.com/coder/code-server/releases/tag/v4.22.0) - 2024-03-03
|
||||
|
||||
Code v1.87.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.87.0.
|
||||
|
||||
## [4.21.2](https://github.com/coder/code-server/releases/tag/v4.21.2) - 2024-02-28
|
||||
|
||||
Code v1.86.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.86.2.
|
||||
|
||||
## [4.21.1](https://github.com/coder/code-server/releases/tag/v4.21.1) - 2024-02-09
|
||||
|
||||
Code v1.86.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.86.1.
|
||||
- Updated to Node 18.17.1.
|
||||
|
||||
### Added
|
||||
|
||||
- Docker images for Fedora and openSUSE.
|
||||
|
||||
## [4.21.0](https://github.com/coder/code-server/releases/tag/v4.21.0) - 2024-02-05
|
||||
|
||||
Code v1.86.0
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.86.0.
|
||||
|
||||
## [4.20.1](https://github.com/coder/code-server/releases/tag/v4.20.1) - 2024-01-22
|
||||
|
||||
Code v1.85.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.85.2.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Query variables are no longer double-encoded when going over the path proxy.
|
||||
|
||||
## [4.20.0](https://github.com/coder/code-server/releases/tag/v4.20.0) - 2023-12-21
|
||||
|
||||
Code v1.85.1
|
||||
|
||||
### Added
|
||||
|
||||
- New flag `--disable-file-uploads` to disable uploading files to the remote by
|
||||
drag and drop and to disable opening local files via the "show local" button
|
||||
in the file open prompt. Note that you can still open local files by drag and
|
||||
dropping the file onto the editor pane.
|
||||
- Added `wget` to the release image.
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.85.1.
|
||||
- The `--disable-file-downloads` flag will now disable the "show local" button
|
||||
in the file save prompt as well.
|
||||
- Debian release image updated to use Bookworm.
|
||||
|
||||
## [4.19.1](https://github.com/coder/code-server/releases/tag/v4.19.1) - 2023-11-29
|
||||
|
||||
Code v1.84.2
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue where parts of the editor would not load (like the file
|
||||
explorer, source control, etc) when using a workspace file.
|
||||
|
||||
## [4.19.0](https://github.com/coder/code-server/releases/tag/v4.19.0) - 2023-11-18
|
||||
|
||||
Code v1.84.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.84.2.
|
||||
|
||||
## [4.18.0](https://github.com/coder/code-server/releases/tag/v4.18.0) - 2023-10-20
|
||||
|
||||
Code v1.83.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.83.1.
|
||||
|
||||
## [4.17.1](https://github.com/coder/code-server/releases/tag/v4.17.1) - 2023-09-29
|
||||
|
||||
Code v1.82.2
|
||||
|
||||
### Fixed
|
||||
|
||||
- Make secret storage persistent. For example, logging in with GitHub should
|
||||
persist between browser refreshes and code-server restarts.
|
||||
- Issues with argon2 on arm builds should be fixed now.
|
||||
|
||||
## [4.17.0](https://github.com/coder/code-server/releases/tag/v4.17.0) - 2023-09-22
|
||||
|
||||
Code v1.82.2
|
||||
|
||||
### Added
|
||||
|
||||
- Japanese locale.
|
||||
- `CODE_SERVER_HOST` environment variable.
|
||||
|
||||
### Changed
|
||||
|
||||
- Update to Code 1.82.2. This includes an update to Node 18, which also means
|
||||
that the minimum glibc is now 2.28. If you need to maintain a lower glibc then
|
||||
you can take a version of Node 18 that is compiled with a lower glibc and use
|
||||
that to build code-server (or at a minimum rebuild the native modules).
|
||||
- Display paths to config files in full rather than abbreviated. If you have
|
||||
trouble with the password not working please update and make sure the
|
||||
displayed config paths are what you expect.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix some dependency issues for the standalone arm64 and armv7l releases. If
|
||||
you had issues with missing or failing modules please try these new builds.
|
||||
|
||||
## [4.16.1](https://github.com/coder/code-server/releases/tag/v4.16.1) - 2023-07-31
|
||||
|
||||
Code v1.80.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.80.2.
|
||||
|
||||
## [4.16.0](https://github.com/coder/code-server/releases/tag/v4.16.0) - 2023-07-28
|
||||
|
||||
Code v1.80.1
|
||||
|
||||
### Added
|
||||
|
||||
- `--disable-proxy` flag. This disables the domain and path proxies but it does
|
||||
not disable the ports panel in Code. That can be disabled by using
|
||||
`remote.autoForwardPorts=false` in your settings.
|
||||
|
||||
## [4.15.0](https://github.com/coder/code-server/releases/tag/v4.15.0) - 2023-07-21
|
||||
|
||||
Code v1.80.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.80.1.
|
||||
|
||||
### Added
|
||||
|
||||
- `--trusted-origin` flag for specifying origins that you trust but do not
|
||||
control (for example a reverse proxy).
|
||||
|
||||
Code v1.79.2
|
||||
|
||||
## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26
|
||||
|
||||
Code v1.79.2
|
||||
|
||||
### Security
|
||||
|
||||
- Remove extra write permissions on the Node binary bundled with the linux-amd64
|
||||
tarball. If you extract the tar without a umask this could mean the Node
|
||||
binary would be unexpectedly writable.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Inability to launch multiple instances of code-server for different users.
|
||||
|
||||
### Added
|
||||
|
||||
- `--session-socket` CLI flag to configure the location of the session socket.
|
||||
By default it will be placed in `<user data dir>/code-server-ipc.sock`.
|
||||
|
||||
## [4.14.0](https://github.com/coder/code-server/releases/tag/v4.14.0) - 2023-06-16
|
||||
|
||||
Code v1.79.2
|
||||
|
||||
### Added
|
||||
|
||||
- `--domain-proxy` now supports `{{port}}` and `{{host}}` template variables.
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.79.2
|
||||
- Files opened from an external terminal will now open in the most closely
|
||||
related window rather than in the last opened window.
|
||||
|
||||
## [4.13.0](https://github.com/coder/code-server/releases/tag/v4.13.0) - 2023-05-19
|
||||
|
||||
Code v1.78.2
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.78.2.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Proxying files that contain non-ASCII characters.
|
||||
- Origin check when X-Forwarded-Host contains comma-separated hosts.
|
||||
|
||||
## [4.12.0](https://github.com/coder/code-server/releases/tag/v4.12.0) - 2023-04-21
|
||||
|
||||
Code v1.77.3
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.77.3
|
||||
- Ports panel will use domain-based proxy (instead of the default path-based
|
||||
proxy) when set via --proxy-domain.
|
||||
- Apply --app-name to the PWA title.
|
||||
|
||||
### Added
|
||||
|
||||
- Thai translation for login page.
|
||||
- Debug logs around the origin security check. If you are getting forbidden
|
||||
errors on web sockets please run code-server with `--log debug` to see why the
|
||||
requests are being blocked.
|
||||
|
||||
## [4.11.0](https://github.com/coder/code-server/releases/tag/v4.11.0) - 2023-03-16
|
||||
|
||||
Code v1.76.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.76.1
|
||||
|
||||
## [4.10.1](https://github.com/coder/code-server/releases/tag/v4.10.1) - 2023-03-04
|
||||
|
||||
Code v1.75.1
|
||||
|
||||
### Security
|
||||
|
||||
Added an origin check to web sockets to prevent cross-site hijacking attacks on
|
||||
users using older or niche browser that do not support SameSite cookies and
|
||||
attacks across sub-domains that share the same root domain.
|
||||
|
||||
The check requires the host header to be set so if you use a reverse proxy
|
||||
ensure it forwards that information otherwise web sockets will be blocked.
|
||||
|
||||
## [4.10.0](https://github.com/coder/code-server/releases/tag/v4.10.0) - 2023-02-15
|
||||
|
||||
Code v1.75.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated to Code 1.75.1
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed `--link` (was deprecated over thirteen months ago in 4.0.1).
|
||||
|
||||
## [4.9.1](https://github.com/coder/code-server/releases/tag/v4.9.1) - 2022-12-15
|
||||
|
||||
Code v1.73.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated a couple steps in the build and release process to ensure we're using
|
||||
`npm` and `yarn` consistently depending on the step.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed an issue with code-server version not displaying in the Help > About window.
|
||||
- Fixed terminal not loading on macOS clients.
|
||||
|
||||
## [4.9.0](https://github.com/coder/code-server/releases/tag/v4.9.0) - 2022-12-06
|
||||
|
||||
Code v1.73.1
|
||||
|
||||
### Changed
|
||||
|
||||
- Upgraded to Code 1.73.1
|
||||
|
||||
### Added
|
||||
|
||||
- `/security.txt` added as a route with info on our security policy information thanks to @ghuntley
|
||||
|
||||
### Fixed
|
||||
|
||||
- Installing on majaro images should now work thanks to @MrPeacockNLB for
|
||||
adding the `--noconfirm` flag in `install.sh`
|
||||
|
||||
### Known Issues
|
||||
|
||||
- `--cert` on Ubuntu 22.04: OpenSSL v3 is used which breaks `pem` meaning the
|
||||
`--cert` feature will not work. [Reference](https://github.com/adobe/fetch/pull/318#issuecomment-1306070259)
|
||||
|
||||
## [4.8.3](https://github.com/coder/code-server/releases/tag/v4.8.3) - 2022-11-07
|
||||
|
||||
Code v1.72.1
|
||||
|
||||
### Added
|
||||
|
||||
- install script now supports arch-like (i.e. manjaro, endeavourous, etc.)
|
||||
architectures
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated text in the Getting Started page.
|
||||
@@ -477,7 +101,7 @@ Code v1.71.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- Add flags --unsafe-perm --legacy-peer-deps in `npm-postinstall.sh` which ensures installing with npm works correctly
|
||||
- Add flags --unsafe-perm --legacy-peer-deps in `npm-postinstsall.sh` which ensures installing with npm works correctly
|
||||
|
||||
## [4.6.1](https://github.com/coder/code-server/releases/tag/v4.6.1) - 2022-09-31
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ This directory contains scripts used for the development of code-server.
|
||||
- [./ci/dev/watch.ts](./dev/watch.ts) (`yarn watch`)
|
||||
- Starts a process to build and launch code-server and restart on any code changes.
|
||||
- Example usage in [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md).
|
||||
- [./ci/dev/gen_icons.sh](./dev/gen_icons.sh) (`yarn icons`)
|
||||
- [./ci/dev/gen_icons.sh](./ci/dev/gen_icons.sh) (`yarn icons`)
|
||||
- Generates the various icons from a single `.svg` favicon in
|
||||
`src/browser/media/favicon.svg`.
|
||||
- Requires [imagemagick](https://imagemagick.org/index.php)
|
||||
@@ -75,7 +75,7 @@ You can disable minification by setting `MINIFY=`.
|
||||
|
||||
This directory contains the release docker container image.
|
||||
|
||||
- [./ci/steps/build-docker-buildx-push.sh](./steps/docker-buildx-push.sh)
|
||||
- [./ci/steps/build-docker-buildx-push.sh](./ci/steps/docker-buildx-push.sh)
|
||||
- Builds the release containers with tags `codercom/code-server-$ARCH:$VERSION` for amd64 and arm64 with `docker buildx` and pushes them.
|
||||
- Assumes debian releases are ready in `./release-packages`.
|
||||
|
||||
|
||||
@@ -14,6 +14,22 @@ main() {
|
||||
sed -i.bak "1s;^;#!/usr/bin/env node\n;" out/node/entry.js && rm out/node/entry.js.bak
|
||||
chmod +x out/node/entry.js
|
||||
fi
|
||||
|
||||
# for arch; we do not use OS from lib.sh and get our own.
|
||||
# lib.sh normalizes macos to darwin - but cloud-agent's binaries do not
|
||||
source ./ci/lib.sh
|
||||
OS="$(uname | tr '[:upper:]' '[:lower:]')"
|
||||
|
||||
mkdir -p ./lib
|
||||
|
||||
if ! [ -f ./lib/coder-cloud-agent ]; then
|
||||
echo "Downloading the cloud agent..."
|
||||
|
||||
set +e
|
||||
curl -fsSL "https://github.com/coder/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent
|
||||
chmod +x ./lib/coder-cloud-agent
|
||||
set -e
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -27,7 +27,7 @@ main() {
|
||||
release_archive() {
|
||||
local release_name="code-server-$VERSION-$OS-$ARCH"
|
||||
if [[ $OS == "linux" ]]; then
|
||||
tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^\.\/release-standalone/$release_name/" ./release-standalone
|
||||
tar -czf "release-packages/$release_name.tar.gz" --transform "s/^\.\/release-standalone/$release_name/" ./release-standalone
|
||||
else
|
||||
tar -czf "release-packages/$release_name.tar.gz" -s "/^release-standalone/$release_name/" release-standalone
|
||||
fi
|
||||
|
||||
@@ -56,12 +56,15 @@ bundle_code_server() {
|
||||
}
|
||||
EOF
|
||||
) > "$RELEASE_PATH/package.json"
|
||||
rsync yarn.lock "$RELEASE_PATH"
|
||||
mv npm-shrinkwrap.json "$RELEASE_PATH"
|
||||
|
||||
rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"
|
||||
|
||||
if [ "$KEEP_MODULES" = 1 ]; then
|
||||
rsync node_modules/ "$RELEASE_PATH/node_modules"
|
||||
mkdir -p "$RELEASE_PATH/lib"
|
||||
rsync ./lib/coder-cloud-agent "$RELEASE_PATH/lib"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -94,10 +97,12 @@ bundle_vscode() {
|
||||
"$VSCODE_SRC_PATH/remote/package.json" \
|
||||
"$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
|
||||
|
||||
rsync "$VSCODE_SRC_PATH/remote/yarn.lock" "$VSCODE_OUT_PATH/yarn.lock"
|
||||
mv "$VSCODE_SRC_PATH/remote/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/npm-shrinkwrap.json"
|
||||
|
||||
# Include global extension dependencies as well.
|
||||
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions/yarn.lock"
|
||||
mv "$VSCODE_SRC_PATH/extensions/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/extensions/npm-shrinkwrap.json"
|
||||
rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
|
||||
main() {
|
||||
cd "$(dirname "${0}")/../.."
|
||||
|
||||
@@ -9,19 +13,17 @@ main() {
|
||||
rsync "$RELEASE_PATH/" "$RELEASE_PATH-standalone"
|
||||
RELEASE_PATH+=-standalone
|
||||
|
||||
# We cannot get the path to Node from $PATH (for example via `which node`)
|
||||
# because Yarn shims a script called `node` and we would end up just copying
|
||||
# that script. Instead we run Node and have it print its actual path.
|
||||
# We cannot find the path to node from $PATH because yarn shims a script to ensure
|
||||
# we use the same version it's using so we instead run a script with yarn that
|
||||
# will print the path to node.
|
||||
local node_path
|
||||
node_path="$(node <<< 'console.info(process.execPath)')"
|
||||
node_path="$(yarn -s node <<< 'console.info(process.execPath)')"
|
||||
|
||||
mkdir -p "$RELEASE_PATH/bin"
|
||||
mkdir -p "$RELEASE_PATH/lib"
|
||||
rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
|
||||
rsync "$node_path" "$RELEASE_PATH/lib/node"
|
||||
|
||||
chmod 755 "$RELEASE_PATH/lib/node"
|
||||
|
||||
pushd "$RELEASE_PATH"
|
||||
npm install --unsafe-perm --omit=dev
|
||||
popd
|
||||
|
||||
@@ -15,7 +15,7 @@ copy-bin-script() {
|
||||
local dest="lib/vscode-reh-web-linux-x64/bin/$script"
|
||||
cp "lib/vscode/resources/server/bin/$script" "$dest"
|
||||
sed -i.bak "s/@@VERSION@@/$(vscode_version)/g" "$dest"
|
||||
sed -i.bak "s/@@COMMIT@@/$BUILD_SOURCEVERSION/g" "$dest"
|
||||
sed -i.bak "s/@@COMMIT@@/$VSCODE_DISTRO_COMMIT/g" "$dest"
|
||||
sed -i.bak "s/@@APPNAME@@/code-server/g" "$dest"
|
||||
|
||||
# Fix Node path on Darwin and Linux.
|
||||
@@ -40,29 +40,16 @@ main() {
|
||||
|
||||
source ./ci/lib.sh
|
||||
|
||||
pushd lib/vscode
|
||||
|
||||
# Set the commit Code will embed into the product.json. We need to do this
|
||||
# since Code tries to get the commit from the `.git` directory which will fail
|
||||
# as it is a submodule.
|
||||
#
|
||||
# Also, we use code-server's commit rather than VS Code's otherwise it would
|
||||
# not update when only our patch files change, and that will cause caching
|
||||
# issues where the browser keeps using outdated code.
|
||||
export BUILD_SOURCEVERSION
|
||||
BUILD_SOURCEVERSION=$(git rev-parse HEAD)
|
||||
export VSCODE_DISTRO_COMMIT
|
||||
VSCODE_DISTRO_COMMIT=$(git rev-parse HEAD)
|
||||
|
||||
pushd lib/vscode
|
||||
|
||||
if [[ ! ${VERSION-} ]]; then
|
||||
echo "VERSION not set. Please set before running this script:"
|
||||
echo "VERSION='0.0.0' yarn build:vscode"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add the date, our name, links, enable telemetry (this just makes telemetry
|
||||
# available; telemetry can still be disabled by flag or setting), and
|
||||
# configure trusted extensions (since some, like github.copilot-chat, never
|
||||
# ask to be trusted and this is the only way to get auth working).
|
||||
#
|
||||
# Add the date, our name, links, and enable telemetry (this just makes
|
||||
# telemetry available; telemetry can still be disabled by flag or setting).
|
||||
# This needs to be done before building as Code will read this file and embed
|
||||
# it into the client-side code.
|
||||
git checkout product.json # Reset in case the script exited early.
|
||||
@@ -96,11 +83,6 @@ main() {
|
||||
"linkProtectionTrustedDomains": [
|
||||
"https://open-vsx.org"
|
||||
],
|
||||
"trustedExtensionAuthAccess": [
|
||||
"vscode.git", "vscode.github",
|
||||
"github.vscode-pull-request-github",
|
||||
"github.copilot", "github.copilot-chat"
|
||||
],
|
||||
"aiConfig": {
|
||||
"ariaKey": "code-server"
|
||||
}
|
||||
@@ -121,15 +103,6 @@ EOF
|
||||
|
||||
popd
|
||||
|
||||
pushd lib/vscode-reh-web-linux-x64
|
||||
# Make sure Code took the version we set in the environment variable. Not
|
||||
# having a version will break display languages.
|
||||
if ! jq -e .commit product.json; then
|
||||
echo "'commit' is missing from product.json"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
|
||||
# These provide a `code-server` command in the integrated terminal to open
|
||||
# files in the current instance.
|
||||
delete-bin-script remote-cli/code-server
|
||||
|
||||
@@ -4,7 +4,7 @@ platform: "linux"
|
||||
version: "v${VERSION}"
|
||||
section: "devel"
|
||||
priority: "optional"
|
||||
maintainer: "Joe Previte <joe@coder.com>"
|
||||
maintainer: "Anmol Sethi <hi@nhooyr.io>"
|
||||
description: |
|
||||
Run VS Code in the browser.
|
||||
vendor: "Coder"
|
||||
@@ -22,4 +22,4 @@ contents:
|
||||
dst: /usr/lib/systemd/user/code-server.service
|
||||
|
||||
- src: ./release-standalone/*
|
||||
dst: /usr/lib/code-server
|
||||
dst: /usr/lib/code-server/
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
# Copied from ../lib.sh except we do not rename Darwin and we do not need to
|
||||
# detect Alpine.
|
||||
# Copied from ../lib.sh.
|
||||
arch() {
|
||||
cpu="$(uname -m)"
|
||||
case "$cpu" in
|
||||
aarch64) cpu=arm64 ;;
|
||||
x86_64) cpu=amd64 ;;
|
||||
esac
|
||||
echo "$cpu"
|
||||
}
|
||||
|
||||
# Copied from ../lib.sh except we do not rename Darwin since the cloud agent
|
||||
# uses "darwin" in the release names and we do not need to detect Alpine.
|
||||
os() {
|
||||
osname=$(uname | tr '[:upper:]' '[:lower:]')
|
||||
case $osname in
|
||||
@@ -51,20 +61,13 @@ symlink_bin_script() {
|
||||
cd "$oldpwd"
|
||||
}
|
||||
|
||||
command_exists() {
|
||||
if [ ! "$1" ]; then return 1; fi
|
||||
command -v "$@" > /dev/null
|
||||
}
|
||||
|
||||
is_root() {
|
||||
if command_exists id && [ "$(id -u)" = 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
ARCH="${NPM_CONFIG_ARCH:-$(arch)}"
|
||||
OS="$(os)"
|
||||
|
||||
# This is due to an upstream issue with RHEL7/CentOS 7 comptability with node-argon2
|
||||
# See: https://github.com/cdr/code-server/pull/3422#pullrequestreview-677765057
|
||||
export npm_config_build_from_source=true
|
||||
|
||||
main() {
|
||||
# Grabs the major version of node from $npm_config_user_agent which looks like
|
||||
# yarn/1.21.1 npm/? node/v14.2.0 darwin x64
|
||||
@@ -76,8 +79,8 @@ main() {
|
||||
echo "USE AT YOUR OWN RISK!"
|
||||
fi
|
||||
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-20}" ]; then
|
||||
echo "ERROR: code-server currently requires node v20."
|
||||
if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-16}" ]; then
|
||||
echo "ERROR: code-server currently requires node v16."
|
||||
if [ -n "$FORCE_NODE_VERSION" ]; then
|
||||
echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
|
||||
fi
|
||||
@@ -87,19 +90,24 @@ main() {
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Under npm, if we are running as root, we need --unsafe-perm otherwise
|
||||
# post-install scripts will not have sufficient permissions to do their thing.
|
||||
if is_root; then
|
||||
case "${npm_config_user_agent-}" in npm*)
|
||||
if [ "${npm_config_unsafe_perm-}" != "true" ]; then
|
||||
echo "Please pass --unsafe-perm to npm to install code-server"
|
||||
echo "Otherwise post-install scripts will not have permissions to run"
|
||||
echo "See https://docs.npmjs.com/misc/config#unsafe-perm"
|
||||
echo "See https://stackoverflow.com/questions/49084929/npm-sudo-global-installation-unsafe-perm"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
case "${npm_config_user_agent-}" in npm*)
|
||||
# We are running under npm.
|
||||
if [ "${npm_config_unsafe_perm-}" != "true" ]; then
|
||||
echo "Please pass --unsafe-perm to npm to install code-server"
|
||||
echo "Otherwise the postinstall script does not have permissions to run"
|
||||
echo "See https://docs.npmjs.com/misc/config#unsafe-perm"
|
||||
echo "See https://stackoverflow.com/questions/49084929/npm-sudo-global-installation-unsafe-perm"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
mkdir -p ./lib
|
||||
|
||||
if curl -fsSL "https://github.com/coder/cloud-agent/releases/latest/download/cloud-agent-$OS-$ARCH" -o ./lib/coder-cloud-agent; then
|
||||
chmod +x ./lib/coder-cloud-agent
|
||||
else
|
||||
echo "Failed to download cloud agent; --link will not work"
|
||||
fi
|
||||
|
||||
if ! vscode_install; then
|
||||
@@ -116,21 +124,26 @@ main() {
|
||||
}
|
||||
|
||||
install_with_yarn_or_npm() {
|
||||
echo "User agent: ${npm_config_user_agent-none}"
|
||||
# NOTE@edvincent: We want to keep using the package manager that the end-user was using to install the package.
|
||||
# This also ensures that when *we* run `yarn` in the development process, the yarn.lock file is used.
|
||||
case "${npm_config_user_agent-}" in
|
||||
npm*)
|
||||
# HACK: NPM's use of semver doesn't like resolving some peerDependencies that vscode (upstream) brings in the form of pre-releases.
|
||||
# The legacy behavior doesn't complain about pre-releases being used, falling back to that for now.
|
||||
# See https://github.com//pull/5071
|
||||
if ! npm install --unsafe-perm --legacy-peer-deps --omit=dev; then
|
||||
return 1
|
||||
yarn*)
|
||||
if [ -f "yarn.lock" ]; then
|
||||
yarn --production --frozen-lockfile --no-default-rc
|
||||
else
|
||||
echo "yarn.lock file not present, not running in development mode. use npm to install code-server!"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
yarn*)
|
||||
if ! yarn --production --frozen-lockfile --no-default-rc; then
|
||||
return 1
|
||||
npm*)
|
||||
if [ -f "yarn.lock" ]; then
|
||||
echo "yarn.lock file present, running in development mode. use yarn to install code-server!"
|
||||
exit 1
|
||||
else
|
||||
# HACK: NPM's use of semver doesn't like resolving some peerDependencies that vscode (upstream) brings in the form of pre-releases.
|
||||
# The legacy behavior doesn't complain about pre-releases being used, falling back to that for now.
|
||||
# See https://github.com//pull/5071
|
||||
npm install --unsafe-perm --legacy-peer-deps --omit=dev
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
@@ -138,26 +151,19 @@ install_with_yarn_or_npm() {
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
vscode_install() {
|
||||
echo 'Installing Code dependencies...'
|
||||
cd lib/vscode
|
||||
if ! install_with_yarn_or_npm; then
|
||||
return 1
|
||||
fi
|
||||
install_with_yarn_or_npm
|
||||
|
||||
symlink_asar
|
||||
symlink_bin_script remote-cli code code-server
|
||||
symlink_bin_script helpers browser browser .sh
|
||||
|
||||
cd extensions
|
||||
if ! install_with_yarn_or_npm; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
install_with_yarn_or_npm
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
103
ci/build/release-prep.sh
Executable file
103
ci/build/release-prep.sh
Executable file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env bash
|
||||
# Description: This is a script to make the release process easier
|
||||
# Run it with `yarn release:prep` and it will do the following:
|
||||
# 1. Check that you have gh installed and that you're signed in
|
||||
# 2. Update the version of code-server (package.json, docs, etc.)
|
||||
# 3. Update the code coverage badge in the README
|
||||
# 4. Open a draft PR using the release_template.md and view in browser
|
||||
# If you want to perform a dry run of this script run DRY_RUN=1 yarn release:prep
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
CHECKMARK="\xE2\x9C\x94"
|
||||
DASH="-"
|
||||
|
||||
main() {
|
||||
if [ "${DRY_RUN-}" = 1 ]; then
|
||||
echo "Performing a dry run..."
|
||||
CMD="echo"
|
||||
else
|
||||
CMD=''
|
||||
fi
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
# Check that gh is installed
|
||||
if ! command -v gh &> /dev/null; then
|
||||
echo "gh could not be found."
|
||||
echo "We use this with the release-github-draft.sh and release-github-assets.sh scripts."
|
||||
echo -e "See docs here: https://github.com/cli/cli#installation"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check that they have jq installed
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "jq could not be found."
|
||||
echo "We use this to parse the package.json and grab the current version of code-server."
|
||||
echo -e "See docs here: https://stedolan.github.io/jq/download/"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check that they have rg installed
|
||||
if ! command -v rg &> /dev/null; then
|
||||
echo "rg could not be found."
|
||||
echo "We use this when updating files across the codebase."
|
||||
echo -e "See docs here: https://github.com/BurntSushi/ripgrep#installation"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check that they have node installed
|
||||
if ! command -v node &> /dev/null; then
|
||||
echo "node could not be found."
|
||||
echo "That's surprising..."
|
||||
echo "We use it in this script for getting the package.json version"
|
||||
echo -e "See docs here: https://nodejs.org/en/download/"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Check that gh is authenticated
|
||||
if ! gh auth status -h github.com &> /dev/null; then
|
||||
echo "gh isn't authenticated to github.com."
|
||||
echo "This is needed for our scripts that use gh."
|
||||
echo -e "See docs regarding authentication: https://cli.github.com/manual/gh_auth_login"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Note: we need to set upstream as well or the gh pr create step will fail
|
||||
# See: https://github.com/cli/cli/issues/575
|
||||
CURRENT_BRANCH=$(git branch | grep '\*' | cut -d' ' -f2-)
|
||||
if [[ -z $(git config "branch.${CURRENT_BRANCH}.remote") ]]; then
|
||||
echo "Doesn't look like you've pushed this branch to remote"
|
||||
# Note: we need to set upstream as well or the gh pr create step will fail
|
||||
# See: https://github.com/cli/cli/issues/575
|
||||
echo "Please set the upstream and then run the script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# credit to jakwuh for this solution
|
||||
# https://gist.github.com/DarrenN/8c6a5b969481725a4413#gistcomment-1971123
|
||||
CODE_SERVER_CURRENT_VERSION=$(node -pe "require('./package.json').version")
|
||||
# Ask which version we should update to
|
||||
# In the future, we'll automate this and determine the latest version automatically
|
||||
echo -e "$DASH Current version: ${CODE_SERVER_CURRENT_VERSION}"
|
||||
# The $'\n' adds a line break. See: https://stackoverflow.com/a/39581815/3015595
|
||||
CODE_SERVER_VERSION_TO_UPDATE=$(git rev-parse --abbrev-ref HEAD | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/')
|
||||
echo -e "$CHECKMARK Version in branch name"
|
||||
echo -e "$CHECKMARK Updating to: $CODE_SERVER_VERSION_TO_UPDATE"
|
||||
|
||||
$CMD rg -g '!yarn.lock' -g '!*.svg' -g '!CHANGELOG.md' -g '!lib/vscode/**' --files-with-matches --fixed-strings "${CODE_SERVER_CURRENT_VERSION}" | $CMD xargs sd "$CODE_SERVER_CURRENT_VERSION" "$CODE_SERVER_VERSION_TO_UPDATE"
|
||||
|
||||
$CMD git commit --no-verify -am "chore(release): bump version to $CODE_SERVER_VERSION_TO_UPDATE"
|
||||
|
||||
# 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)
|
||||
|
||||
echo -e "\nOpening a draft PR on GitHub"
|
||||
# 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 --repo coder/code-server --draft --assignee "@me"
|
||||
|
||||
# Open PR in browser
|
||||
$CMD gh pr view --web
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -11,6 +11,22 @@ main() {
|
||||
make -s out/index.js
|
||||
popd
|
||||
|
||||
# Our code imports from `out` in order to work during development but if you
|
||||
# have only built for production you will have not have this directory. In
|
||||
# that case symlink `out` to a production build directory.
|
||||
if [[ ! -e lib/vscode/out ]]; then
|
||||
pushd lib
|
||||
local out=(vscode-reh-web-*)
|
||||
if [[ -d "${out[0]}" ]]; then
|
||||
ln -s "../${out[0]}/out" ./vscode/out
|
||||
else
|
||||
echo "Could not find lib/vscode/out or lib/vscode-reh-web-*"
|
||||
echo "Code must be built before running unit tests"
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
fi
|
||||
|
||||
# We must keep jest in a sub-directory. See ../../test/package.json for more
|
||||
# information. We must also run it from the root otherwise coverage will not
|
||||
# include our source files.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { spawn, ChildProcess } from "child_process"
|
||||
import { spawn, fork, ChildProcess } from "child_process"
|
||||
import * as path from "path"
|
||||
import { onLine, OnLineCallback } from "../../src/node/util"
|
||||
|
||||
@@ -30,13 +30,12 @@ class Watcher {
|
||||
|
||||
// Pass CLI args, save for `node` and the initial script name.
|
||||
const args = process.argv.slice(2)
|
||||
this.webServer = spawn("node", [path.join(this.rootPath, "out/node/entry.js"), ...args])
|
||||
onLine(this.webServer, (line) => console.log("[code-server]", line))
|
||||
this.webServer = fork(path.join(this.rootPath, "out/node/entry.js"), args)
|
||||
const { pid } = this.webServer
|
||||
|
||||
this.webServer.on("exit", () => console.log("[code-server]", `Web process ${pid} exited`))
|
||||
this.webServer.on("exit", () => console.log("[Code Server]", `Web process ${pid} exited`))
|
||||
|
||||
console.log("\n[code-server]", `Spawned web server process ${pid}`)
|
||||
console.log("\n[Code Server]", `Spawned web server process ${pid}`)
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -83,10 +82,10 @@ class Watcher {
|
||||
private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
|
||||
if (!strippedLine.length) return
|
||||
|
||||
console.log("[Code OSS]", originalLine)
|
||||
console.log("[VS Code]", originalLine)
|
||||
|
||||
if (strippedLine.includes("Finished compilation with")) {
|
||||
console.log("[Code OSS] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
|
||||
console.log("[VS Code] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
|
||||
this.reloadWebServer()
|
||||
}
|
||||
}
|
||||
@@ -94,10 +93,10 @@ class Watcher {
|
||||
private parseCodeServerLine: OnLineCallback = (strippedLine, originalLine) => {
|
||||
if (!strippedLine.length) return
|
||||
|
||||
console.log("[Compiler][code-server]", originalLine)
|
||||
console.log("[Compiler][Code Server]", originalLine)
|
||||
|
||||
if (strippedLine.includes("Watching for file changes")) {
|
||||
console.log("[Compiler][code-server]", "Finished compiling!", "(Refresh your web browser ♻️)")
|
||||
console.log("[Compiler][Code Server]", "Finished compiling!", "(Refresh your web browser ♻️)")
|
||||
this.reloadWebServer()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 3.20.0
|
||||
version: 3.3.3
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 4.89.1
|
||||
appVersion: 4.8.3
|
||||
|
||||
@@ -20,9 +20,6 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- if .Values.podAnnotations }}
|
||||
annotations: {{- toYaml .Values.podAnnotations | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }}
|
||||
{{- if .Values.hostnameOverride }}
|
||||
@@ -105,7 +102,6 @@ spec:
|
||||
{{- range .Values.extraSecretMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .mountPath }}
|
||||
subPath: {{ .subPath | default "" }}
|
||||
readOnly: {{ .readOnly }}
|
||||
{{- end }}
|
||||
{{- range .Values.extraVolumeMounts }}
|
||||
@@ -118,11 +114,6 @@ spec:
|
||||
- name: http
|
||||
containerPort: 8080
|
||||
protocol: TCP
|
||||
{{- range .Values.extraPorts }}
|
||||
- name: {{ .name }}
|
||||
containerPort: {{ .port }}
|
||||
protocol: {{ .protocol }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
@@ -177,12 +168,9 @@ spec:
|
||||
{{- if .existingClaim }}
|
||||
persistentVolumeClaim:
|
||||
claimName: {{ .existingClaim }}
|
||||
{{- else if .hostPath }}
|
||||
{{- else }}
|
||||
hostPath:
|
||||
path: {{ .hostPath }}
|
||||
type: Directory
|
||||
{{- else }}
|
||||
emptyDir:
|
||||
{{- toYaml .emptyDir | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
{{- if not .Values.existingSecret }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
@@ -12,9 +11,8 @@ metadata:
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
type: Opaque
|
||||
data:
|
||||
{{- if .Values.password }}
|
||||
{{ if .Values.password }}
|
||||
password: "{{ .Values.password | b64enc }}"
|
||||
{{- else }}
|
||||
{{ else }}
|
||||
password: "{{ randAlphaNum 24 | b64enc }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -14,12 +14,6 @@ spec:
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
name: http
|
||||
{{- range .Values.extraPorts }}
|
||||
- port: {{ .port }}
|
||||
targetPort: {{ .port }}
|
||||
protocol: {{ .protocol }}
|
||||
name: {{ .name }}
|
||||
{{- end }}
|
||||
selector:
|
||||
app.kubernetes.io/name: {{ include "code-server.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
|
||||
@@ -6,7 +6,7 @@ replicaCount: 1
|
||||
|
||||
image:
|
||||
repository: codercom/code-server
|
||||
tag: '4.89.1'
|
||||
tag: '4.8.3'
|
||||
pullPolicy: Always
|
||||
|
||||
# Specifies one or more secrets to be used when pulling images from a
|
||||
@@ -71,7 +71,7 @@ extraArgs: []
|
||||
# Optional additional environment variables
|
||||
extraVars: []
|
||||
# - name: DISABLE_TELEMETRY
|
||||
# value: "true"
|
||||
# value: true
|
||||
# - name: DOCKER_HOST
|
||||
# value: "tcp://localhost:2375"
|
||||
|
||||
@@ -179,7 +179,6 @@ extraInitContainers: |
|
||||
extraSecretMounts: []
|
||||
# - name: secret-files
|
||||
# mountPath: /etc/secrets
|
||||
# subPath: private.key # (optional)
|
||||
# secretName: code-server-secret-files
|
||||
# readOnly: true
|
||||
|
||||
@@ -190,7 +189,6 @@ extraVolumeMounts: []
|
||||
# readOnly: true
|
||||
# existingClaim: volume-claim
|
||||
# hostPath: ""
|
||||
# emptyDir: {}
|
||||
|
||||
extraConfigmapMounts: []
|
||||
# - name: certs-configmap
|
||||
@@ -198,8 +196,3 @@ extraConfigmapMounts: []
|
||||
# subPath: certificates.crt # (optional)
|
||||
# configMap: certs-configmap
|
||||
# readOnly: true
|
||||
|
||||
extraPorts: []
|
||||
# - name: minecraft
|
||||
# port: 25565
|
||||
# protocol: tcp
|
||||
|
||||
@@ -9,6 +9,10 @@ popd() {
|
||||
builtin popd > /dev/null
|
||||
}
|
||||
|
||||
pkg_json_version() {
|
||||
jq -r .version package.json
|
||||
}
|
||||
|
||||
vscode_version() {
|
||||
jq -r .version lib/vscode/package.json
|
||||
}
|
||||
@@ -44,6 +48,8 @@ rsync() {
|
||||
command rsync -a --del "$@"
|
||||
}
|
||||
|
||||
VERSION="$(pkg_json_version)"
|
||||
export VERSION
|
||||
ARCH="$(arch)"
|
||||
export ARCH
|
||||
OS=$(os)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:experimental
|
||||
|
||||
ARG BASE=debian:12
|
||||
ARG BASE=debian:11
|
||||
FROM scratch AS packages
|
||||
COPY release-packages/code-server*.deb /tmp/
|
||||
|
||||
@@ -10,19 +10,18 @@ RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
curl \
|
||||
dumb-init \
|
||||
git \
|
||||
git-lfs \
|
||||
zsh \
|
||||
htop \
|
||||
locales \
|
||||
lsb-release \
|
||||
man-db \
|
||||
man \
|
||||
nano \
|
||||
openssh-client \
|
||||
git \
|
||||
git-lfs \
|
||||
procps \
|
||||
openssh-client \
|
||||
sudo \
|
||||
vim-tiny \
|
||||
wget \
|
||||
zsh \
|
||||
vim.tiny \
|
||||
lsb-release \
|
||||
&& git lfs install \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -35,7 +34,7 @@ RUN adduser --gecos '' --disabled-password coder \
|
||||
&& echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
||||
|
||||
RUN ARCH="$(dpkg --print-architecture)" \
|
||||
&& curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
|
||||
&& curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.5/fixuid-0.5-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
|
||||
&& chown root:root /usr/local/bin/fixuid \
|
||||
&& chmod 4755 /usr/local/bin/fixuid \
|
||||
&& mkdir -p /etc/fixuid \
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# syntax=docker/dockerfile:experimental
|
||||
|
||||
ARG BASE=fedora:39
|
||||
FROM scratch AS packages
|
||||
COPY release-packages/code-server*.rpm /tmp/
|
||||
|
||||
FROM $BASE
|
||||
|
||||
RUN dnf update -y \
|
||||
&& dnf install -y \
|
||||
curl \
|
||||
git \
|
||||
git-lfs \
|
||||
htop \
|
||||
nano \
|
||||
openssh-clients \
|
||||
procps \
|
||||
wget \
|
||||
zsh \
|
||||
dumb-init \
|
||||
glibc-langpack-en \
|
||||
&& rm -rf /var/cache/dnf
|
||||
RUN git lfs install
|
||||
|
||||
ENV LANG=en_US.UTF-8
|
||||
RUN echo 'LANG="en_US.UTF-8"' > /etc/locale.conf
|
||||
|
||||
RUN useradd -u 1000 coder && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
||||
|
||||
RUN ARCH="$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')" \
|
||||
&& curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
|
||||
&& chown root:root /usr/local/bin/fixuid \
|
||||
&& chmod 4755 /usr/local/bin/fixuid \
|
||||
&& mkdir -p /etc/fixuid \
|
||||
&& printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
|
||||
|
||||
COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
|
||||
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages rpm -i /tmp/packages/code-server*$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g').rpm
|
||||
|
||||
# Allow users to have scripts run on container startup to prepare workspace.
|
||||
# https://github.com/coder/code-server/issues/5177
|
||||
ENV ENTRYPOINTD=${HOME}/entrypoint.d
|
||||
|
||||
EXPOSE 8080
|
||||
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
|
||||
# the uid will remain the same. note: only relevant if -u isn't passed to
|
||||
# docker-run.
|
||||
USER 1000
|
||||
ENV USER=coder
|
||||
WORKDIR /home/coder
|
||||
ENTRYPOINT ["/usr/bin/entrypoint.sh", "--bind-addr", "0.0.0.0:8080", "."]
|
||||
@@ -1,51 +0,0 @@
|
||||
# syntax=docker/dockerfile:experimental
|
||||
|
||||
ARG BASE=opensuse/tumbleweed
|
||||
FROM scratch AS packages
|
||||
COPY release-packages/code-server*.rpm /tmp/
|
||||
|
||||
FROM $BASE
|
||||
|
||||
RUN zypper dup -y \
|
||||
&& zypper in -y \
|
||||
curl \
|
||||
git \
|
||||
git-lfs \
|
||||
htop \
|
||||
nano \
|
||||
openssh-clients \
|
||||
procps \
|
||||
wget \
|
||||
zsh \
|
||||
sudo \
|
||||
catatonit \
|
||||
&& rm -rf /var/cache/zypp /var/cache/zypper
|
||||
RUN git lfs install
|
||||
|
||||
ENV LANG=en_US.UTF-8
|
||||
RUN echo 'LANG="en_US.UTF-8"' > /etc/locale.conf
|
||||
|
||||
RUN useradd -u 1000 coder && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
||||
|
||||
RUN ARCH="$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')" \
|
||||
&& curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
|
||||
&& chown root:root /usr/local/bin/fixuid \
|
||||
&& chmod 4755 /usr/local/bin/fixuid \
|
||||
&& mkdir -p /etc/fixuid \
|
||||
&& printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
|
||||
|
||||
COPY ci/release-image/entrypoint-catatonit.sh /usr/bin/entrypoint-catatonit.sh
|
||||
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages rpm -i /tmp/packages/code-server*$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g').rpm
|
||||
|
||||
# Allow users to have scripts run on container startup to prepare workspace.
|
||||
# https://github.com/coder/code-server/issues/5177
|
||||
ENV ENTRYPOINTD=${HOME}/entrypoint.d
|
||||
|
||||
EXPOSE 8080
|
||||
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
|
||||
# the uid will remain the same. note: only relevant if -u isn't passed to
|
||||
# docker-run.
|
||||
USER 1000
|
||||
ENV USER=coder
|
||||
WORKDIR /home/coder
|
||||
ENTRYPOINT ["/usr/bin/entrypoint-catatonit.sh", "--bind-addr", "0.0.0.0:8080", "."]
|
||||
@@ -16,11 +16,8 @@ variable "GITHUB_REGISTRY" {
|
||||
|
||||
group "default" {
|
||||
targets = [
|
||||
"code-server-debian-12",
|
||||
"code-server-debian-11",
|
||||
"code-server-ubuntu-focal",
|
||||
"code-server-ubuntu-noble",
|
||||
"code-server-fedora-39",
|
||||
"code-server-opensuse-tumbleweed",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -48,12 +45,12 @@ function "gen_tags_for_docker_and_ghcr" {
|
||||
)
|
||||
}
|
||||
|
||||
target "code-server-debian-12" {
|
||||
target "code-server-debian-11" {
|
||||
dockerfile = "ci/release-image/Dockerfile"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr(""),
|
||||
gen_tags_for_docker_and_ghcr("debian"),
|
||||
gen_tags_for_docker_and_ghcr("bookworm"),
|
||||
gen_tags_for_docker_and_ghcr("bullseye"),
|
||||
)
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
@@ -69,38 +66,3 @@ target "code-server-ubuntu-focal" {
|
||||
}
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
target "code-server-ubuntu-noble" {
|
||||
dockerfile = "ci/release-image/Dockerfile"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr("noble"),
|
||||
)
|
||||
args = {
|
||||
BASE = "ubuntu:noble"
|
||||
}
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
target "code-server-fedora-39" {
|
||||
dockerfile = "ci/release-image/Dockerfile.fedora"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr("fedora"),
|
||||
gen_tags_for_docker_and_ghcr("39"),
|
||||
)
|
||||
args = {
|
||||
BASE = "fedora:39"
|
||||
}
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
target "code-server-opensuse-tumbleweed" {
|
||||
dockerfile = "ci/release-image/Dockerfile.opensuse"
|
||||
tags = concat(
|
||||
gen_tags_for_docker_and_ghcr("opensuse"),
|
||||
gen_tags_for_docker_and_ghcr("tumbleweed"),
|
||||
)
|
||||
args = {
|
||||
BASE = "opensuse/tumbleweed"
|
||||
}
|
||||
platforms = ["linux/amd64", "linux/arm64"]
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
# We do this first to ensure sudo works below when renaming the user.
|
||||
# Otherwise the current container UID may not exist in the passwd database.
|
||||
eval "$(fixuid -q)"
|
||||
|
||||
if [ "${DOCKER_USER-}" ]; then
|
||||
USER="$DOCKER_USER"
|
||||
if [ "$DOCKER_USER" != "$(whoami)" ]; then
|
||||
echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
|
||||
# Unfortunately we cannot change $HOME as we cannot move any bind mounts
|
||||
# nor can we bind mount $HOME into a new home as that requires a privileged container.
|
||||
sudo usermod --login "$DOCKER_USER" coder
|
||||
sudo groupmod -n "$DOCKER_USER" coder
|
||||
|
||||
sudo sed -i "/coder/d" /etc/sudoers.d/nopasswd
|
||||
fi
|
||||
fi
|
||||
|
||||
# Allow users to have scripts run on container startup to prepare workspace.
|
||||
# https://github.com/coder/code-server/issues/5177
|
||||
if [ -d "${ENTRYPOINTD}" ]; then
|
||||
find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
|
||||
fi
|
||||
|
||||
exec catatonit -- /usr/bin/code-server "$@"
|
||||
@@ -3,8 +3,9 @@ set -euo pipefail
|
||||
|
||||
main() {
|
||||
cd "$(dirname "$0")/../.."
|
||||
# NOTE@jsjoeio - this script assumes VERSION exists as an
|
||||
# environment variable.
|
||||
# ci/lib.sh sets VERSION so it's available to ci/release-image/docker-bake.hcl
|
||||
# to push the VERSION tag.
|
||||
source ./ci/lib.sh
|
||||
|
||||
# NOTE@jsjoeio - this script assumes that you've downloaded
|
||||
# the release-packages artifact to ./release-packages before
|
||||
|
||||
@@ -19,6 +19,12 @@ main() {
|
||||
# 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."
|
||||
@@ -96,7 +102,6 @@ main() {
|
||||
# This means the npm version will be tagged with "beta"
|
||||
# and installed when a user runs `yarn install code-server@beta`
|
||||
NPM_TAG="beta"
|
||||
PACKAGE_NAME="@coder/code-server-pr"
|
||||
fi
|
||||
|
||||
if [[ "$NPM_ENVIRONMENT" == "development" ]]; then
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
- [Version updates to Code](#version-updates-to-code)
|
||||
- [Patching Code](#patching-code)
|
||||
- [Build](#build)
|
||||
- [Creating a Standalone Release](#creating-a-standalone-release)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [I see "Forbidden access" when I load code-server in the browser](#i-see-forbidden-access-when-i-load-code-server-in-the-browser)
|
||||
- ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
|
||||
- ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
|
||||
- [Help](#help)
|
||||
- [Test](#test)
|
||||
- [Unit tests](#unit-tests)
|
||||
@@ -37,7 +36,7 @@ for [VS
|
||||
Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||
Here is what is needed:
|
||||
|
||||
- `node` v20.x
|
||||
- `node` v16.x
|
||||
- `git` v2.x or greater
|
||||
- [`git-lfs`](https://git-lfs.github.com)
|
||||
- [`yarn`](https://classic.yarnpkg.com/en/)
|
||||
@@ -63,7 +62,7 @@ Here is what is needed:
|
||||
If you're developing code-server on Linux, make sure you have installed or install the following dependencies:
|
||||
|
||||
```shell
|
||||
sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev libkrb5-dev python-is-python3
|
||||
sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev python-is-python3
|
||||
```
|
||||
|
||||
These are required by Code. See [their Wiki](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites) for more information.
|
||||
@@ -127,13 +126,13 @@ while quilt push; do quilt refresh; done
|
||||
|
||||
0. You can go through the patch stack with `quilt push` and `quilt pop`.
|
||||
1. Create a new patch (`quilt new {name}.diff`) or use an existing patch.
|
||||
1. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
|
||||
2. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
|
||||
**must** be added before you make changes to it.
|
||||
1. Make your changes. Patches do not need to be independent of each other but
|
||||
3. Make your changes. Patches do not need to be independent of each other but
|
||||
each patch must result in a working code-server without any broken in-between
|
||||
states otherwise they are difficult to test and modify.
|
||||
1. Add your changes to the patch (`quilt refresh`)
|
||||
1. Add a comment in the patch about the reason for the patch and how to
|
||||
4. Add your changes to the patch (`quilt refresh`)
|
||||
5. Add a comment in the patch about the reason for the patch and how to
|
||||
reproduce the behavior it fixes or adds. Every patch should have an e2e test
|
||||
as well.
|
||||
|
||||
@@ -171,22 +170,6 @@ yarn package
|
||||
> If you need your builds to support older distros, run the build commands
|
||||
> inside a Docker container with all the build requirements installed.
|
||||
|
||||
#### Creating a Standalone Release
|
||||
|
||||
Part of the build process involves creating standalone releases. At the time of
|
||||
writing, we do this for the following platforms/architectures:
|
||||
|
||||
- Linux amd64 (.tar.gz, .deb, and .rpm)
|
||||
- Linux arm64 (.tar.gz, .deb, and .rpm)
|
||||
- Linux arm7l (.tar.gz)
|
||||
- Linux armhf.deb
|
||||
- Linux armhf.rpm
|
||||
- macOS amd64 (Intel-based)
|
||||
|
||||
Currently, these are compiled in CI using the `yarn release-standalone` command
|
||||
in the `release.yaml` workflow. We then upload them to the draft release and
|
||||
distribute via GitHub Releases.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
#### I see "Forbidden access" when I load code-server in the browser
|
||||
@@ -195,7 +178,7 @@ This means your patches didn't apply correctly. We have a patch to remove the au
|
||||
|
||||
Try popping off the patches with `quilt pop -a` and reapplying with `quilt push -a`.
|
||||
|
||||
#### "Can only have one anonymous define call per script"
|
||||
### "Can only have one anonymous define call per script"
|
||||
|
||||
Code might be trying to use a dev or prod HTML in the wrong context. You can try re-running code-server and setting `VSCODE_DEV=1`.
|
||||
|
||||
|
||||
100
docs/FAQ.md
100
docs/FAQ.md
@@ -14,7 +14,6 @@
|
||||
- [How do I install an extension manually?](#how-do-i-install-an-extension-manually)
|
||||
- [How do I use my own extensions marketplace?](#how-do-i-use-my-own-extensions-marketplace)
|
||||
- [Where are extensions stored?](#where-are-extensions-stored)
|
||||
- [Where is VS Code configuration stored?](#where-is-vs-code-configuration-stored)
|
||||
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
|
||||
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
|
||||
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
|
||||
@@ -27,7 +26,6 @@
|
||||
- [Is multi-tenancy possible?](#is-multi-tenancy-possible)
|
||||
- [Can I use Docker in a code-server container?](#can-i-use-docker-in-a-code-server-container)
|
||||
- [How do I disable telemetry?](#how-do-i-disable-telemetry)
|
||||
- [What's the difference between code-server and Coder?](#whats-the-difference-between-code-server-and-coder)
|
||||
- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
|
||||
- [What's the difference between code-server and OpenVSCode-Server?](#whats-the-difference-between-code-server-and-openvscode-server)
|
||||
- [What's the difference between code-server and GitHub Codespaces?](#whats-the-difference-between-code-server-and-github-codespaces)
|
||||
@@ -35,8 +33,6 @@
|
||||
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
|
||||
- [How do I change the port?](#how-do-i-change-the-port)
|
||||
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
|
||||
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
|
||||
- [How do I disable file download?](#how-do-i-disable-file-download)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -90,12 +86,6 @@ app (PWA):
|
||||
1. Start the editor
|
||||
2. Click the **plus** icon in the URL toolbar to install the PWA
|
||||
|
||||
If you use Firefox, you can use the appropriate extension to install PWA.
|
||||
|
||||
1. Go to the installation [website](https://addons.mozilla.org/en-US/firefox/addon/pwas-for-firefox/) of the add-on
|
||||
2. Add the add-on to Firefox
|
||||
3. Follow the os-specific instructions on how to install the runtime counterpart
|
||||
|
||||
For other browsers, you'll have to remap keybindings for shortcuts to work.
|
||||
|
||||
## Why can't code-server use Microsoft's extension marketplace?
|
||||
@@ -177,10 +167,10 @@ If you own a marketplace that implements the VS Code Extension Gallery API, you
|
||||
can point code-server to it by setting `$EXTENSIONS_GALLERY`.
|
||||
This corresponds directly with the `extensionsGallery` entry in in VS Code's `product.json`.
|
||||
|
||||
For example:
|
||||
For example, to use the legacy Coder extensions marketplace:
|
||||
|
||||
```bash
|
||||
export EXTENSIONS_GALLERY='{"serviceUrl": "https://my-extensions/api"}'
|
||||
export EXTENSIONS_GALLERY='{"serviceUrl": "https://extensions.coder.com/api"}'
|
||||
```
|
||||
|
||||
Though you can technically use Microsoft's marketplace in this manner, we
|
||||
@@ -193,20 +183,10 @@ docs](https://github.com/VSCodium/vscodium/blob/master/DOCS.md#extensions--marke
|
||||
|
||||
## Where are extensions stored?
|
||||
|
||||
Extensions are stored in `~/.local/share/code-server/extensions` by default.
|
||||
Extensions are store, by default, to `~/.local/share/code-server/extensions`.
|
||||
|
||||
On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the
|
||||
extensions directory will be `$XDG_DATA_HOME/code-server/extensions`. In
|
||||
general, we try to follow the XDG directory spec.
|
||||
|
||||
## Where is VS Code configuration stored?
|
||||
|
||||
VS Code configuration such as settings and keybindings are stored in
|
||||
`~/.local/share/code-server` by default.
|
||||
|
||||
On Linux and macOS if you set the `XDG_DATA_HOME` environment variable, the data
|
||||
directory will be `$XDG_DATA_HOME/code-server`. In general, we try to follow the
|
||||
XDG directory spec.
|
||||
If you set the `XDG_DATA_HOME` environment variable, the data directory will be
|
||||
`$XDG_DATA_HOME/code-server/extensions`. In general, we try to follow the XDG directory spec.
|
||||
|
||||
## How can I reuse my VS Code configuration?
|
||||
|
||||
@@ -356,12 +336,6 @@ hashed-password: "$argon2i$v=19$m=4096,t=3,p=1$wST5QhBgk2lu1ih4DMuxvg$LS1alrVdIW
|
||||
|
||||
The `hashed-password` field takes precedence over `password`.
|
||||
|
||||
If you're using Docker Compose file, in order to make this work, you need to change all the single $ to $$. For example:
|
||||
|
||||
```yaml
|
||||
- HASHED_PASSWORD=$$argon2i$$v=19$$m=4096,t=3,p=1$$wST5QhBgk2lu1ih4DMuxvg$$LS1alrVdIWtvZHwnzCM1DUGg+5DTO3Dt1d5v9XtLws4
|
||||
```
|
||||
|
||||
## Is multi-tenancy possible?
|
||||
|
||||
If you want to run multiple code-servers on shared infrastructure, we recommend
|
||||
@@ -388,15 +362,6 @@ Use the `--disable-telemetry` flag to disable telemetry.
|
||||
|
||||
> We use the data collected only to improve code-server.
|
||||
|
||||
## What's the difference between code-server and Coder?
|
||||
|
||||
code-server and Coder are both applications that can be installed on any
|
||||
machine. The main difference is who they serve. Out of the box, code-server is
|
||||
simply VS Code in the browser while Coder is a tool for provisioning remote
|
||||
development environments via Terraform.
|
||||
|
||||
code-server was built for individuals while Coder was built for teams. In Coder, you create Workspaces which can have applications like code-server. If you're looking for a team solution, you should reach for [Coder](https://github.com/coder/coder).
|
||||
|
||||
## What's the difference between code-server and Theia?
|
||||
|
||||
At a high level, code-server is a patched fork of VS Code that runs in the
|
||||
@@ -414,13 +379,19 @@ Theia doesn't allow you to reuse your existing VS Code config.
|
||||
## What's the difference between code-server and OpenVSCode-Server?
|
||||
|
||||
code-server and OpenVSCode-Server both allow you to access VS Code via a
|
||||
browser. OpenVSCode-Server is a direct fork of VS Code with changes comitted
|
||||
directly while code-server pulls VS Code in via a submodule and makes changes
|
||||
via patch files.
|
||||
browser. The two projects also use their own [forks of VS Code](https://github.com/coder/vscode) to
|
||||
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 as-is in
|
||||
the web browser. code-server contains additional changes to make the self-hosted
|
||||
experience better (see the next section for details).
|
||||
However, OpenVSCode-Server is scoped at only making VS Code available in the web browser.
|
||||
code-server includes some other features:
|
||||
|
||||
- password auth
|
||||
- proxy web ports
|
||||
- certificate support
|
||||
- plugin API
|
||||
- settings sync (coming soon)
|
||||
|
||||
For more details, see [this discussion post](https://github.com/coder/code-server/discussions/4267#discussioncomment-1411583).
|
||||
|
||||
## What's the difference between code-server and GitHub Codespaces?
|
||||
|
||||
@@ -428,24 +399,8 @@ Both code-server and GitHub Codespaces allow you to access VS Code via a
|
||||
browser. GitHub Codespaces, however, is a closed-source, paid service offered by
|
||||
GitHub and Microsoft.
|
||||
|
||||
On the other hand, code-server is self-hosted, free, open-source, and can be run
|
||||
on any machine with few limitations.
|
||||
|
||||
Specific changes include:
|
||||
|
||||
- Password authentication
|
||||
- The ability to host at sub-paths
|
||||
- Self-contained web views that do not call out to Microsoft's servers
|
||||
- The ability to use your own marketplace and collect your own telemetry
|
||||
- Built-in proxy for accessing ports on the remote machine integrated into
|
||||
VS Code's ports panel
|
||||
- Wrapper process that spawns VS Code on-demand and has a separate CLI
|
||||
- Notification when updates are available
|
||||
- [Some other things](https://github.com/coder/code-server/tree/main/patches)
|
||||
|
||||
Some of these changes appear very unlikely to ever be adopted by Microsoft.
|
||||
Some may make their way upstream, further closing the gap, but at the moment it
|
||||
looks like there will always be some subtle differences.
|
||||
On the other hand, code-server is self-hosted, free, open-source, and
|
||||
can be run on any machine with few limitations.
|
||||
|
||||
## Does code-server have any security login validation?
|
||||
|
||||
@@ -470,20 +425,3 @@ There are two ways to change the port on which code-server runs:
|
||||
You can pass the flag `--disable-getting-started-override` to `code-server` or
|
||||
you can set the environment variable `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
|
||||
`CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.
|
||||
|
||||
## How do I disable the proxy?
|
||||
|
||||
You can pass the flag `--disable-proxy` to `code-server` or
|
||||
you can set the environment variable `CS_DISABLE_PROXY=1` or
|
||||
`CS_DISABLE_PROXY=true`.
|
||||
|
||||
Note, this option currently only disables the proxy routes to forwarded ports, including
|
||||
the domain and path proxy routes over HTTP and WebSocket; however, it does not
|
||||
disable the automatic port forwarding in the VS Code workbench itself. In other words,
|
||||
user will still see the Ports tab and notifications, but will not be able to actually
|
||||
use access the ports. It is recommended to set `remote.autoForwardPorts` to `false`
|
||||
when using the option.
|
||||
|
||||
## How do I disable file download?
|
||||
|
||||
You can pass the flag `--disable-file-downloads` to `code-server`
|
||||
|
||||
@@ -142,28 +142,24 @@ changelog](https://github.com/emacs-mirror/emacs/blob/master/etc/NEWS).
|
||||
|
||||
### Publishing a release
|
||||
|
||||
1. Go to GitHub Actions > Draft release > Run workflow on the commit you want to
|
||||
release. Make sure CI has finished the build workflow on that commit or this
|
||||
will fail.
|
||||
2. CI will automatically grab the build artifact on that commit, inject the
|
||||
version into the `package.json`, put together platform-specific packages, and
|
||||
upload those packages to a draft release.
|
||||
3. Summarize the major changes in the `CHANGELOG.md`.
|
||||
4. Copy the relevant changelog section to the release then publish it.
|
||||
5. CI will automatically publish the NPM package, Docker image, and update
|
||||
Homebrew using the published release assets.
|
||||
6. Bump the chart version in `Chart.yaml` and merge in the changelog updates.
|
||||
1. Create a new branch called `release/v0.0.0` (replace 0s with actual version aka v4.5.0)
|
||||
1. Run `yarn release:prep`
|
||||
1. Bump chart version in `Chart.yaml`.
|
||||
1. Summarize the major changes in the `CHANGELOG.md`
|
||||
1. Download CI artifacts and make sure code-server works locally.
|
||||
1. Merge PR and wait for CI build on `main` to finish.
|
||||
1. Go to GitHub Actions > Draft release > Run workflow off `main`. CI will automatically upload the artifacts to the release.
|
||||
1. Add the release notes from the `CHANGELOG.md` and publish release. CI will automatically grab the
|
||||
artifacts, publish the NPM package from `npm-package`, and publish the Docker
|
||||
Hub image from `release-images`.
|
||||
|
||||
#### Release Candidates
|
||||
|
||||
We prefer to do release candidates so the community can test things before a
|
||||
full-blown release. To do this follow the same steps as above but:
|
||||
We prefer to do release candidates so the community can test things before a full-blown release. To do this follow the same steps as above but:
|
||||
|
||||
1. Add a `-rc.<number>` suffix to the version.
|
||||
2. When you publish the release select "pre-release". CI will not automatically
|
||||
publish pre-releases.
|
||||
3. Do not update the chart version or merge in the changelog until the final
|
||||
release.
|
||||
1. Only bump version in `package.json`
|
||||
1. use `0.0.0-rc.0`
|
||||
1. When you publish the release, select "pre-release"
|
||||
|
||||
#### AUR
|
||||
|
||||
@@ -171,7 +167,7 @@ We publish to AUR as a package [here](https://aur.archlinux.org/packages/code-se
|
||||
|
||||
#### Docker
|
||||
|
||||
We publish code-server as a Docker image [here](https://hub.docker.com/r/codercom/code-server), tagging it both with the version and latest.
|
||||
We publish code-server as a Docker image [here](https://registry.hub.docker.com/r/codercom/code-server), tagging it both with the version and latest.
|
||||
|
||||
This is currently automated with the release process.
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
Run [VS Code](https://github.com/Microsoft/vscode) on any machine anywhere and
|
||||
access it in the browser.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
## Highlights
|
||||
|
||||
@@ -17,7 +16,7 @@ access it in the browser.
|
||||
|
||||
## Requirements
|
||||
|
||||
See [requirements](https://coder.com/docs/code-server/latest/requirements) for minimum specs, as well as instructions
|
||||
See [requirements](requirements.md) for minimum specs, as well as instructions
|
||||
on how to set up a Google VM on which you can install code-server.
|
||||
|
||||
**TL;DR:** Linux machine with WebSockets enabled, 1 GB RAM, and 2 vCPUs
|
||||
@@ -73,7 +72,7 @@ details.
|
||||
Interested in [working at Coder](https://coder.com/careers)? Check out [our open
|
||||
positions](https://coder.com/careers#openings)!
|
||||
|
||||
## For Teams
|
||||
## For Organizations
|
||||
|
||||
We develop [coder/coder](https://cdr.co/coder-github) to help teams to
|
||||
adopt remote development.
|
||||
Want remote development for your organization or enterprise? Visit [our
|
||||
website](https://coder.com) to learn more about Coder.
|
||||
|
||||
@@ -11,21 +11,13 @@ 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 20:
|
||||
7. Install and use Node.js 16:
|
||||
|
||||
```shell
|
||||
nvm install 18
|
||||
nvm use 18
|
||||
nvm install 16
|
||||
nvm use 16
|
||||
```
|
||||
|
||||
8. Install code-server globally on device with: `npm install --global code-server`
|
||||
8. Install code-server globally on device with: `npm install --global code-server --unsafe-perm`
|
||||
9. Run code-server with `code-server`
|
||||
10. Access on localhost:8080 in your browser
|
||||
|
||||
# Running code-server using Nix-on-Droid
|
||||
|
||||
1. Install Nix-on-Droid from [F-Droid](https://f-droid.org/packages/com.termux.nix/)
|
||||
2. Start app
|
||||
3. Spawn a shell with code-server by running `nix-shell -p code-server`
|
||||
4. Run code-server with `code-server`
|
||||
5. Access on localhost:8080 in your browser
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 114 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 267 KiB |
BIN
docs/assets/screenshot.png
Normal file
BIN
docs/assets/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 357 KiB |
@@ -1,48 +0,0 @@
|
||||
# Coder
|
||||
|
||||
To install and run code-server in a Coder workspace, we suggest using the `install.sh`
|
||||
script in your template like so:
|
||||
|
||||
```terraform
|
||||
resource "coder_agent" "dev" {
|
||||
arch = "amd64"
|
||||
os = "linux"
|
||||
startup_script = <<EOF
|
||||
#!/bin/sh
|
||||
set -x
|
||||
# install and start code-server
|
||||
curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3
|
||||
code-server --auth none --port 13337 &
|
||||
EOF
|
||||
}
|
||||
|
||||
resource "coder_app" "code-server" {
|
||||
agent_id = coder_agent.dev.id
|
||||
slug = "code-server"
|
||||
display_name = "code-server"
|
||||
url = "http://localhost:13337/"
|
||||
icon = "/icon/code.svg"
|
||||
subdomain = false
|
||||
share = "owner"
|
||||
|
||||
healthcheck {
|
||||
url = "http://localhost:13337/healthz"
|
||||
interval = 3
|
||||
threshold = 10
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or use our official [`code-server`](https://registry.coder.com/modules/code-server) module from the Coder [module registry](htpps://registry.coder.com/modules):
|
||||
|
||||
```terraform
|
||||
module "code-server" {
|
||||
source = "registry.coder.com/modules/code-server/coder"
|
||||
version = "1.0.5"
|
||||
agent_id = coder_agent.example.id
|
||||
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
|
||||
}
|
||||
```
|
||||
|
||||
If you run into issues, ask for help on the `coder/coder` [Discussions
|
||||
here](https://github.com/coder/coder/discussions).
|
||||
@@ -14,12 +14,10 @@
|
||||
- [Accessing web services](#accessing-web-services)
|
||||
- [Using a subdomain](#using-a-subdomain)
|
||||
- [Using a subpath](#using-a-subpath)
|
||||
- [Using your own proxy](#using-your-own-proxy)
|
||||
- [Stripping `/proxy/<port>` from the request path](#stripping-proxyport-from-the-request-path)
|
||||
- [Proxying to create a React app](#proxying-to-create-a-react-app)
|
||||
- [Proxying to a Vue app](#proxying-to-a-vue-app)
|
||||
- [Proxying to an Angular app](#proxying-to-an-angular-app)
|
||||
- [Proxying to a Svelte app](#proxying-to-a-svelte-app)
|
||||
- [SSH into code-server on VS Code](#ssh-into-code-server-on-vs-code)
|
||||
- [Option 1: cloudflared tunnel](#option-1-cloudflared-tunnel)
|
||||
- [Option 2: ngrok tunnel](#option-2-ngrok-tunnel)
|
||||
@@ -139,9 +137,9 @@ sudo apt install caddy
|
||||
1. Replace `/etc/caddy/Caddyfile` using `sudo` so that the file looks like this:
|
||||
|
||||
```text
|
||||
mydomain.com {
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
}
|
||||
mydomain.com
|
||||
|
||||
reverse_proxy 127.0.0.1:8080
|
||||
```
|
||||
|
||||
If you want to serve code-server from a sub-path, you can do so as follows:
|
||||
@@ -191,7 +189,7 @@ At this point, you should be able to access code-server via
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8080/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection upgrade;
|
||||
proxy_set_header Accept-Encoding gzip;
|
||||
@@ -318,32 +316,12 @@ To set your domain, start code-server with the `--proxy-domain` flag:
|
||||
code-server --proxy-domain <domain>
|
||||
```
|
||||
|
||||
For instance, if you have code-server exposed on `domain.tld` and a Python
|
||||
server running on port 8080 of the same machine code-server is running on, you
|
||||
could run code-server with `--proxy-domain domain.tld` and access the Python
|
||||
server via `8080.domain.tld`.
|
||||
|
||||
Note that this uses the host header, so ensure your reverse proxy (if you're
|
||||
using one) forwards that information.
|
||||
Now you can browse to `<port>.<domain>`. Note that this uses the host header, so
|
||||
ensure your reverse proxy (if you're using one) forwards that information.
|
||||
|
||||
### Using a subpath
|
||||
|
||||
Simply browse to `/proxy/<port>/`. For instance, if you have code-server
|
||||
exposed on `domain.tld` and a Python server running on port 8080 of the same
|
||||
machine code-server is running on, you could access the Python server via
|
||||
`domain.tld/proxy/8000`.
|
||||
|
||||
### Using your own proxy
|
||||
|
||||
You can make extensions and the ports panel use your own proxy by setting
|
||||
`VSCODE_PROXY_URI`. For example if you set
|
||||
`VSCODE_PROXY_URI=https://{{port}}.kyle.dev` when an application is detected
|
||||
running on port 3000 of the same machine code-server is running on the ports
|
||||
panel will create a link to https://3000.kyle.dev instead of pointing to the
|
||||
built-in subpath-based proxy.
|
||||
|
||||
Note: relative paths are also supported i.e.
|
||||
`VSCODE_PROXY_URI=./proxy/{{port}}`
|
||||
Simply browse to `/proxy/<port>/`.
|
||||
|
||||
### Stripping `/proxy/<port>` from the request path
|
||||
|
||||
@@ -415,27 +393,6 @@ In order to use code-server's built-in proxy with Angular, you need to make the
|
||||
|
||||
For additional context, see [this GitHub Discussion](https://github.com/coder/code-server/discussions/5439#discussioncomment-3371983).
|
||||
|
||||
### Proxying to a Svelte app
|
||||
|
||||
In order to use code-server's built-in proxy with Svelte, you need to make the following changes in your app:
|
||||
|
||||
1. Add `svelte.config.js` if you don't already have one
|
||||
2. Update the values to match this (you can use any free port):
|
||||
|
||||
```js
|
||||
const config = {
|
||||
kit: {
|
||||
paths: {
|
||||
base: "/absproxy/5173",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
3. Access app at `<code-server-root>/absproxy/5173/` e.g. `http://localhost:8080/absproxy/5173/
|
||||
|
||||
For additional context, see [this Github Issue](https://github.com/sveltejs/kit/issues/2958)
|
||||
|
||||
## SSH into code-server on VS Code
|
||||
|
||||
[](https://ohmyz.sh/) [](https://img.shields.io/badge/Terminal-2E2E2E?style=for-the-badge&logo=Windows+Terminal&logoColor=ffffff) [](vscode:extension/ms-vscode-remote.remote-ssh)
|
||||
|
||||
@@ -59,7 +59,6 @@ following flags:
|
||||
- `--prefix=/usr/local`: install a standalone release archive system-wide.
|
||||
- `--version=X.X.X`: install version `X.X.X` instead of latest version.
|
||||
- `--help`: see usage docs.
|
||||
- `--edge`: install the latest edge version (i.e. pre-release)
|
||||
|
||||
When done, the install script prints out instructions for running and starting
|
||||
code-server.
|
||||
@@ -103,9 +102,10 @@ _exact_ same commands presented in the rest of this document.
|
||||
We recommend installing with `npm` when:
|
||||
|
||||
1. You aren't using a machine with `amd64` or `arm64`.
|
||||
2. You are installing code-server on Windows.
|
||||
3. You're on Linux with `glibc` < v2.28 or `glibcxx` < v3.4.21.
|
||||
4. You're running Alpine Linux or are using a non-glibc libc. See
|
||||
1. You are installing code-server on Windows
|
||||
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`.
|
||||
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)
|
||||
for more information.
|
||||
|
||||
@@ -122,8 +122,8 @@ node binary and node modules.
|
||||
We create the standalone releases using the [npm package](#npm), and we
|
||||
then create the remaining releases using the standalone version.
|
||||
|
||||
The only requirement to use the standalone release is `glibc` >= 2.28 and
|
||||
`glibcxx` >= v3.4.21 on Linux (for macOS, there is no minimum system
|
||||
The only requirement to use the standalone release is `glibc` >= 2.17 and
|
||||
`glibcxx` >= v3.4.18 on Linux (for macOS, there is no minimum system
|
||||
requirement).
|
||||
|
||||
To use a standalone release:
|
||||
@@ -279,7 +279,6 @@ brew services start code-server
|
||||
# outside the container.
|
||||
mkdir -p ~/.config
|
||||
docker run -it --name code-server -p 127.0.0.1:8080:8080 \
|
||||
-v "$HOME/.local:/home/coder/.local" \
|
||||
-v "$HOME/.config:/home/coder/.config" \
|
||||
-v "$PWD:/home/coder/project" \
|
||||
-u "$(id -u):$(id -g)" \
|
||||
@@ -297,9 +296,9 @@ You can install code-server using the [Helm package manager](https://coder.com/d
|
||||
|
||||
## Windows
|
||||
|
||||
We currently [do not publish Windows
|
||||
releases](https://github.com/coder/code-server/issues/1397). We recommend
|
||||
installing code-server onto Windows with [`npm`](#npm).
|
||||
We currently [do not publish Windows releases](https://github.com/coder/code-server/issues/1397). We recommend installing code-server onto Windows with [`npm`](#npm).
|
||||
|
||||
> Note: You will also need to [build coder/cloud-agent manually](https://github.com/coder/cloud-agent/issues/17) if you would like to use `code-server --link` on Windows.
|
||||
|
||||
## Raspberry Pi
|
||||
|
||||
|
||||
11
docs/link.md
Normal file
11
docs/link.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# code-server --link
|
||||
|
||||
> Note: This feature is no longer recommended due to instability. Stay tuned for a revised version.
|
||||
|
||||
Run code-server with the flag `--link` and you'll get TLS, authentication, and a dedicated URL
|
||||
for accessing your IDE out of the box.
|
||||
|
||||
```console
|
||||
$ code-server --link
|
||||
Proxying code-server, you can access your IDE at https://example.coder.co
|
||||
```
|
||||
@@ -38,9 +38,9 @@
|
||||
"path": "./guide.md",
|
||||
"children": [
|
||||
{
|
||||
"title": "Coder",
|
||||
"description": "How to run code-server in Coder",
|
||||
"path": "./coder.md"
|
||||
"title": "--link",
|
||||
"description": "How to run code-server --link",
|
||||
"path": "./link.md"
|
||||
},
|
||||
{
|
||||
"title": "iPad",
|
||||
|
||||
14
docs/npm.md
14
docs/npm.md
@@ -30,7 +30,7 @@ includes installing instructions based on your operating system.
|
||||
## Node.js version
|
||||
|
||||
We use the same major version of Node.js shipped with Code's remote, which is
|
||||
currently `20.x`. VS Code also [lists Node.js
|
||||
currently `16.x`. VS Code also [lists Node.js
|
||||
requirements](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites).
|
||||
|
||||
Using other versions of Node.js [may lead to unexpected
|
||||
@@ -79,7 +79,7 @@ Proceed to [installing](#installing)
|
||||
## FreeBSD
|
||||
|
||||
```sh
|
||||
pkg install -y git python npm-node20 pkgconf
|
||||
pkg install -y git python npm-node16 pkgconf
|
||||
pkg install -y libinotify
|
||||
```
|
||||
|
||||
@@ -92,12 +92,12 @@ Installing code-server requires all of the [prerequisites for VS Code developmen
|
||||
Next, install code-server with:
|
||||
|
||||
```bash
|
||||
npm install --global code-server
|
||||
npm install --global code-server --unsafe-perm
|
||||
code-server
|
||||
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
||||
```
|
||||
|
||||
A `postinstall.sh` script will attempt to run. Select your terminal (e.g., Git bash) as the default shell for npm run-scripts. If an additional dialog does not appear, run the install command again.
|
||||
A `postinstall.sh` script will attempt to run. Select your terminal (e.g., Git bash) as the default application for `.sh` files. If an additional dialog does not appear, run the install command again.
|
||||
|
||||
If the `code-server` command is not found, you'll need to [add a directory to your PATH](https://www.architectryan.com/2018/03/17/add-to-the-path-on-windows-10/). To find the directory, use the following command:
|
||||
|
||||
@@ -112,7 +112,7 @@ For help and additional troubleshooting, see [#1397](https://github.com/coder/co
|
||||
After adding the dependencies for your OS, install the code-server package globally:
|
||||
|
||||
```bash
|
||||
npm install --global code-server
|
||||
npm install --global code-server --unsafe-perm
|
||||
code-server
|
||||
# Now visit http://127.0.0.1:8080. Your password is in ~/.config/code-server/config.yaml
|
||||
```
|
||||
@@ -144,8 +144,8 @@ To debug installation issues, install with `npm`:
|
||||
|
||||
```shell
|
||||
# Uninstall
|
||||
npm uninstall --global code-server > /dev/null 2>&1
|
||||
npm uninstall --global --unsafe-perm code-server > /dev/null 2>&1
|
||||
|
||||
# Install with logging
|
||||
npm install --loglevel verbose --global code-server
|
||||
npm install --loglevel verbose --global --unsafe-perm code-server
|
||||
```
|
||||
|
||||
@@ -22,7 +22,7 @@ The following steps walk you through setting up a VM running Debian using Google
|
||||
Cloud (though you are welcome to use any machine or VM provider).
|
||||
|
||||
If you're [signing up with Google](https://console.cloud.google.com/getting-started) for the first time, you should get a 3-month trial with
|
||||
\$300 of credits.
|
||||
$300 of credits.
|
||||
|
||||
After you sign up and create a new Google Cloud Provider (GCP) project, create a
|
||||
new Compute Engine VM instance:
|
||||
|
||||
131
docs/termux.md
131
docs/termux.md
@@ -8,12 +8,11 @@
|
||||
- [Upgrade](#upgrade)
|
||||
- [Known Issues](#known-issues)
|
||||
- [Git won't work in `/sdcard`](#git-wont-work-in-sdcard)
|
||||
- [Many extensions including language packs fail to install](#many-extensions-including-language-packs-fail-to-install)
|
||||
- [Extra](#extra)
|
||||
- [Keyboard Shortcuts and Tab Key](#keyboard-shortcuts-and-tab-key)
|
||||
- [Create a new user](#create-a-new-user)
|
||||
- [Install Go](#install-go)
|
||||
- [Install Python](#install-python)
|
||||
- [Working with PRoot](#working-with-proot)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- prettier-ignore-end -->
|
||||
@@ -21,9 +20,53 @@
|
||||
## Install
|
||||
|
||||
1. Get [Termux](https://f-droid.org/en/packages/com.termux/) from **F-Droid**.
|
||||
2. Run `pkg install tur-repo`
|
||||
3. Run `pkg install code-server`
|
||||
4. You can now start code server by simply running `code-server`.
|
||||
2. Install Debian by running the following:
|
||||
- Run `termux-setup-storage` to allow storage access, or else code-server won't be able to read from `/sdcard`.\
|
||||
> The following command is from [proot-distro](https://github.com/termux/proot-distro), but you can also use [Andronix](https://andronix.app/).
|
||||
> After Debian is installed the `~ $` will change to `root@localhost`.
|
||||
|
||||
```bash
|
||||
pkg update -y && pkg install proot-distro -y && proot-distro install debian && proot-distro login debian
|
||||
```
|
||||
|
||||
3. Run the following commands to setup Debian:
|
||||
|
||||
```bash
|
||||
apt update && apt upgrade -y && apt-get install sudo vim git -y
|
||||
```
|
||||
|
||||
4. Install [NVM](https://github.com/nvm-sh/nvm#install--update-script) by following the install guide in the README, just a curl/wget command.
|
||||
|
||||
5. Set up NVM for multi-user. After installing NVM it automatically adds the necessary commands for it to work, but it will only work if you are logged in as root:
|
||||
|
||||
- Copy the lines NVM asks you to run after running the install script.
|
||||
- Run `nano /root/.bashrc` and comment out those lines by adding a `#` at the start.
|
||||
- Run `nano /etc/profile` and paste those lines at the end of the file. Make sure to replace `$HOME` with `/root` on the first line.
|
||||
- Now run `exit`
|
||||
- Start Debian again `proot-distro login debian`
|
||||
|
||||
6. After following the instructions and setting up NVM you can now install the [required node version](https://coder.com/docs/code-server/latest/npm#nodejs-version) by running:
|
||||
|
||||
```bash
|
||||
nvm install v<major_version_here>
|
||||
```
|
||||
|
||||
7. To install `code-server` run the following:
|
||||
> To check the install process (Will not actually install code-server)
|
||||
> If it all looks good, you can install code-server by running the second command
|
||||
|
||||
```bash
|
||||
curl -fsSL https://code-server.dev/install.sh | sh -s -- --dry-run
|
||||
```
|
||||
|
||||
```bash
|
||||
curl -fsSL https://code-server.dev/install.sh | sh
|
||||
```
|
||||
|
||||
8. You can now start code server by simply running `code-server`.
|
||||
|
||||
> Consider using a new user instead of root, read [here](https://www.howtogeek.com/124950/htg-explains-why-you-shouldnt-log-into-your-linux-system-as-root/) why using root is not recommended.\
|
||||
> Learn how to add a user [here](#create-a-new-user).
|
||||
|
||||
## NPM Installation
|
||||
|
||||
@@ -57,7 +100,7 @@ npm config set python python3
|
||||
node -v
|
||||
```
|
||||
|
||||
you will get Node version `v20`
|
||||
you will get node version `v16.15.0`
|
||||
|
||||
5. Now install code-server following our guide on [installing with npm](./npm.md)
|
||||
|
||||
@@ -70,7 +113,7 @@ code-server --auth none
|
||||
7. If already installed then use the following command for upgradation.
|
||||
|
||||
```
|
||||
npm update --global code-server
|
||||
npm update --global code-server --unsafe-perm
|
||||
```
|
||||
|
||||
## Upgrade
|
||||
@@ -89,50 +132,8 @@ Potential Workaround :
|
||||
1. Create a soft-link from the debian-fs to your folder in `/sdcard`
|
||||
2. Use git from termux (preferred)
|
||||
|
||||
### Many extensions including language packs fail to install
|
||||
|
||||
Issue: Android is not seen as a Linux environment but as a separate, unsupported platform, so code-server only allows [Web Extensions](https://code.visualstudio.com/api/extension-guides/web-extensions), refusing to download extensions that run on the server.\
|
||||
Fix: None\
|
||||
Potential workarounds :
|
||||
|
||||
Either
|
||||
|
||||
- Manually download extensions as `.vsix` file and install them via `Extensions: Install from VSIX...` in the Command Palette.
|
||||
|
||||
- Use an override to pretend the platform is Linux:
|
||||
|
||||
Create a JS script that patches `process.platform`:
|
||||
|
||||
```js
|
||||
// android-as-linux.js
|
||||
Object.defineProperty(process, "platform", {
|
||||
get() {
|
||||
return "linux"
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Then use Node's `--require` option to make sure it is loaded before `code-server` starts:
|
||||
|
||||
```sh
|
||||
NODE_OPTIONS="--require /path/to/android-as-linux.js" code-server
|
||||
```
|
||||
|
||||
⚠️ Note that Android and Linux are not 100% compatible, so use these workarounds at your own risk. Extensions that have native dependencies other than Node or that directly interact with the OS might cause issues.
|
||||
|
||||
## Extra
|
||||
|
||||
### Keyboard Shortcuts and Tab Key
|
||||
|
||||
In order to support the tab key and use keyboard shortcuts, add this to your
|
||||
settings.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"keyboard.dispatch": "keyCode"
|
||||
}
|
||||
```
|
||||
|
||||
### Create a new user
|
||||
|
||||
To create a new user follow these simple steps -
|
||||
@@ -201,3 +202,35 @@ eval "$(pyenv virtualenv-init -)"
|
||||
7. Run `touch /root/.pyenv/version && echo "your_version_here" > /root/.pyenv/version`
|
||||
8. (You may have to start Debian again) Run `python3 -V` to verify if PATH works or not.
|
||||
> If `python3` doesn't work but pyenv says that the install was successful in step 6 then try running `$PYENV_ROOT/versions/your_version/bin/python3`.
|
||||
|
||||
### Working with PRoot
|
||||
|
||||
Debian PRoot Distro Dev Environment
|
||||
|
||||
- Since Node and code-server are installed in the Debian PRoot distro, your `~/.ssh/` configuration, `~/.bashrc`, git, npm packages, etc. should be setup in PRoot as well.
|
||||
- The terminal accessible in code-server will bring up the filesystem and `~/.bashrc` in the Debian PRoot distro.
|
||||
|
||||
Accessing files in the Debian PRoot Distro
|
||||
|
||||
- The `/data/data/com.termux/files/home` directory in PRoot accesses the termux home directory (`~`)
|
||||
- The `/sdcard` directory in PRoot accesses the Android storage directory, though there are [known issues with git and files in the `/sdcard` path](#git-wont-work-in-sdcard)
|
||||
|
||||
Accessing the Debian PRoot distro/Starting code-server
|
||||
|
||||
- Run the following command to access the Debian PRoot distro, from the termux shell:
|
||||
|
||||
```bash
|
||||
proot-distro login debian
|
||||
```
|
||||
|
||||
- Run the following command to start code-server directly in the Debian PRoot distro, from the termux shell:
|
||||
|
||||
```bash
|
||||
proot-distro login debian -- code-server
|
||||
```
|
||||
|
||||
- If you [created a new user](#create-a-new-user), you'll need to insert the `--user <username>` option between `login` and `debian` in the commands above to run as the user instead of root in PRoot.
|
||||
|
||||
Additional information on PRoot and Termux
|
||||
|
||||
- Additional information on using your Debian PRoot Distro can be [found here](https://github.com/termux/proot-distro#functionality-overview).
|
||||
|
||||
35
flake.lock
generated
35
flake.lock
generated
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -20,11 +17,12 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1716137900,
|
||||
"narHash": "sha256-sowPU+tLQv8GlqtVtsXioTKeaQvlMz/pefcdwg8MvfM=",
|
||||
"path": "/nix/store/r8nhgnkxacbnf4kv8kdi8b6ks3k9b16i-source",
|
||||
"rev": "6c0b7a92c30122196a761b440ac0d46d3d9954f1",
|
||||
"type": "path"
|
||||
"lastModified": 1660639432,
|
||||
"narHash": "sha256-2WDiboOCfB0LhvnDVMXOAr8ZLDfm3WdO54CkoDPwN1A=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6c6409e965a6c883677be7b9d87a95fab6c3472e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
@@ -36,21 +34,6 @@
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
flake-utils.lib.eachDefaultSystem
|
||||
(system:
|
||||
let pkgs = nixpkgs.legacyPackages.${system};
|
||||
nodejs = pkgs.nodejs_20;
|
||||
nodejs = pkgs.nodejs-16_x;
|
||||
yarn' = pkgs.yarn.override { inherit nodejs; };
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
nodejs yarn' python3 pkg-config git rsync jq moreutils quilt bats openssl
|
||||
nodejs yarn' python pkg-config git rsync jq moreutils quilt bats
|
||||
];
|
||||
buildInputs = with pkgs; (lib.optionals (!stdenv.isDarwin) [ libsecret libkrb5 ]
|
||||
buildInputs = with pkgs; (lib.optionals (!stdenv.isDarwin) [ libsecret ]
|
||||
++ (with xorg; [ libX11 libxkbfile ])
|
||||
++ lib.optionals stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [
|
||||
++ lib.optionals stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [
|
||||
AppKit Cocoa CoreServices Security xcbuild
|
||||
]));
|
||||
};
|
||||
|
||||
@@ -46,7 +46,7 @@ Usage:
|
||||
Sets the prefix used by standalone release archives. Defaults to ~/.local
|
||||
The release is unarchived into ~/.local/lib/code-server-X.X.X
|
||||
and the binary symlinked into ~/.local/bin/code-server
|
||||
To install system wide pass --prefix=/usr/local
|
||||
To install system wide pass ---prefix=/usr/local
|
||||
|
||||
--rsh <bin>
|
||||
Specifies the remote shell for remote installation. Defaults to ssh.
|
||||
@@ -387,7 +387,7 @@ install_aur() {
|
||||
if [ ! "${DRY_RUN-}" ]; then
|
||||
cd "$CACHE_DIR/code-server-aur"
|
||||
fi
|
||||
sh_c makepkg -si --noconfirm
|
||||
sh_c makepkg -si
|
||||
|
||||
echo_systemd_postinstall AUR
|
||||
}
|
||||
@@ -441,7 +441,7 @@ install_npm() {
|
||||
return
|
||||
fi
|
||||
echoerr "Please install npm to install code-server!"
|
||||
echoerr "You will need at least node v20 and a few C dependencies."
|
||||
echoerr "You will need at least node v12 and a few C dependencies."
|
||||
echoerr "See the docs https://coder.com/docs/code-server/latest/install#npm"
|
||||
|
||||
exit 1
|
||||
|
||||
Submodule lib/vscode updated: 611f9bfce6...129500ee4c
118
package.json
118
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-server",
|
||||
"license": "MIT",
|
||||
"version": "0.0.0",
|
||||
"version": "4.8.3",
|
||||
"description": "Run VS Code on a remote server.",
|
||||
"homepage": "https://github.com/coder/code-server",
|
||||
"bugs": {
|
||||
@@ -38,57 +38,74 @@
|
||||
},
|
||||
"main": "out/node/entry.js",
|
||||
"devDependencies": {
|
||||
"@schemastore/package": "^0.0.10",
|
||||
"@types/compression": "^1.7.3",
|
||||
"@types/cookie-parser": "^1.4.4",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/http-proxy": "1.17.7",
|
||||
"@types/js-yaml": "^4.0.6",
|
||||
"@types/node": "20.x",
|
||||
"@types/pem": "^1.14.1",
|
||||
"@schemastore/package": "^0.0.6",
|
||||
"@types/compression": "^1.7.0",
|
||||
"@types/cookie-parser": "^1.4.2",
|
||||
"@types/express": "^4.17.8",
|
||||
"@types/http-proxy": "^1.17.4",
|
||||
"@types/js-yaml": "^4.0.0",
|
||||
"@types/node": "^16.0.0",
|
||||
"@types/pem": "^1.9.5",
|
||||
"@types/proxy-from-env": "^1.0.1",
|
||||
"@types/safe-compare": "^1.1.0",
|
||||
"@types/semver": "^7.5.2",
|
||||
"@types/trusted-types": "^2.0.4",
|
||||
"@types/ws": "^8.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
"audit-ci": "^6.6.1",
|
||||
"doctoc": "^2.2.1",
|
||||
"eslint": "^8.49.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.0",
|
||||
"eslint-plugin-import": "^2.28.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-sh": "^0.14.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "^3.0.1",
|
||||
"argon2": "^0.31.1",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"env-paths": "^2.2.1",
|
||||
"express": "5.0.0-beta.3",
|
||||
"http-proxy": "^1.18.1",
|
||||
"httpolyglot": "^0.1.2",
|
||||
"i18next": "^23.5.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"limiter": "^2.1.0",
|
||||
"pem": "^1.14.8",
|
||||
"proxy-agent": "^6.3.1",
|
||||
"qs": "6.12.1",
|
||||
"rotating-file-stream": "^3.1.1",
|
||||
"safe-buffer": "^5.2.1",
|
||||
"safe-compare": "^1.1.4",
|
||||
"semver": "^7.5.4",
|
||||
"ws": "^8.14.2",
|
||||
"xdg-basedir": "^4.0.0"
|
||||
"@types/semver": "^7.1.0",
|
||||
"@types/split2": "^3.2.0",
|
||||
"@types/trusted-types": "^2.0.2",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||
"@typescript-eslint/parser": "^5.41.0",
|
||||
"audit-ci": "^6.0.0",
|
||||
"doctoc": "2.2.1",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.2",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"prettier": "2.7.1",
|
||||
"prettier-plugin-sh": "^0.12.8",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "20.x"
|
||||
"ansi-regex": "^5.0.1",
|
||||
"normalize-package-data": "^5.0.0",
|
||||
"doctoc/underscore": "^1.13.1",
|
||||
"doctoc/**/trim": "^1.0.0",
|
||||
"postcss": "^8.2.1",
|
||||
"browserslist": "^4.16.5",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"vfile-message": "^2.0.2",
|
||||
"tar": "^6.1.9",
|
||||
"path-parse": "^1.0.7",
|
||||
"vm2": "^3.9.11",
|
||||
"follow-redirects": "^1.14.8",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nanoid": "^3.1.31",
|
||||
"minimist": "npm:minimist-lite@2.2.1",
|
||||
"glob-parent": "^6.0.1",
|
||||
"@types/node": "^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coder/logger": "^3.0.0",
|
||||
"argon2": "0.29.0",
|
||||
"compression": "^1.7.4",
|
||||
"cookie-parser": "^1.4.5",
|
||||
"env-paths": "^2.2.0",
|
||||
"express": "5.0.0-alpha.8",
|
||||
"http-proxy": "^1.18.0",
|
||||
"httpolyglot": "^0.1.2",
|
||||
"js-yaml": "^4.0.0",
|
||||
"limiter": "^1.1.5",
|
||||
"pem": "^1.14.2",
|
||||
"proxy-agent": "^5.0.0",
|
||||
"qs": "6.11.0",
|
||||
"rotating-file-stream": "^3.0.0",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"safe-compare": "^1.1.4",
|
||||
"semver": "^7.1.3",
|
||||
"split2": "^4.0.0",
|
||||
"ws": "^8.0.0",
|
||||
"xdg-basedir": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"code-server": "out/node/entry.js"
|
||||
@@ -99,11 +116,10 @@
|
||||
"ide",
|
||||
"coder",
|
||||
"vscode-remote",
|
||||
"browser-ide",
|
||||
"remote-development"
|
||||
"browser-ide"
|
||||
],
|
||||
"engines": {
|
||||
"node": "20"
|
||||
"node": "16"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/network.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/network.ts
|
||||
@@ -212,7 +212,9 @@ class RemoteAuthoritiesImpl {
|
||||
@@ -162,7 +162,9 @@ class RemoteAuthoritiesImpl {
|
||||
return URI.from({
|
||||
scheme: platform.isWeb ? this._preferredWebSchema : Schemas.vscodeRemoteResource,
|
||||
authority: `${host}:${port}`,
|
||||
@@ -99,20 +99,27 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactor
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/browser/browserSocketFactory.ts
|
||||
@@ -281,6 +281,7 @@ export class BrowserSocketFactory implem
|
||||
connect({ host, port }: WebSocketRemoteConnection, path: string, query: string, debugLabel: string): Promise<ISocket> {
|
||||
return new Promise<ISocket>((resolve, reject) => {
|
||||
const webSocketSchema = (/^https:/.test(mainWindow.location.href) ? 'wss' : 'ws');
|
||||
+ path = (mainWindow.location.pathname + "/" + path).replace(/\/\/+/g, "/")
|
||||
const socket = this._webSocketFactory.create(`${webSocketSchema}://${(/:/.test(host) && !/\[/.test(host)) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
const errorListener = socket.onError(reject);
|
||||
socket.onOpen(() => {
|
||||
@@ -274,6 +274,7 @@ export class BrowserSocketFactory implem
|
||||
|
||||
connect(host: string, port: number, path: string, query: string, debugLabel: string, callback: IConnectCallback): void {
|
||||
const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
|
||||
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
|
||||
const socket = this._webSocketFactory.create(`${webSocketSchema}://${(/:/.test(host) && !/\[/.test(host)) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
|
||||
const errorListener = socket.onError((err) => callback(err, undefined));
|
||||
socket.onOpen(() => {
|
||||
@@ -282,6 +283,3 @@ export class BrowserSocketFactory implem
|
||||
});
|
||||
}
|
||||
}
|
||||
-
|
||||
-
|
||||
-
|
||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -270,16 +270,15 @@ export class WebClientServer {
|
||||
return void res.end();
|
||||
@@ -267,12 +267,11 @@ export class WebClientServer {
|
||||
return res.end();
|
||||
}
|
||||
|
||||
- const getFirstHeader = (headerName: string) => {
|
||||
@@ -120,33 +127,33 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
- return Array.isArray(val) ? val[0] : val;
|
||||
- };
|
||||
-
|
||||
const useTestResolver = (!this._environmentService.isBuilt && this._environmentService.args['use-test-resolver']);
|
||||
- const remoteAuthority = getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host;
|
||||
+ // For now we are getting the remote authority from the client to avoid
|
||||
+ // needing specific configuration for reverse proxies to work. Set this to
|
||||
+ // something invalid to make sure we catch code that is using this value
|
||||
+ // from the backend when it should not.
|
||||
const remoteAuthority = (
|
||||
useTestResolver
|
||||
? 'test+test'
|
||||
- : (getFirstHeader('x-original-host') || getFirstHeader('x-forwarded-host') || req.headers.host)
|
||||
+ : 'remote'
|
||||
);
|
||||
+ const remoteAuthority = 'remote';
|
||||
if (!remoteAuthority) {
|
||||
return serveError(req, res, 400, `Bad request.`);
|
||||
@@ -306,8 +305,12 @@ export class WebClientServer {
|
||||
}
|
||||
@@ -298,6 +297,8 @@ export class WebClientServer {
|
||||
scopes: [['user:email'], ['repo']]
|
||||
} : undefined;
|
||||
|
||||
+ const base = relativeRoot(getOriginalUrl(req))
|
||||
+ const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
+
|
||||
const productConfiguration = {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
+ rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -343,8 +346,10 @@ export class WebClientServer {
|
||||
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
@@ -309,6 +310,7 @@ export class WebClientServer {
|
||||
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
+ rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -326,8 +328,10 @@ export class WebClientServer {
|
||||
const values: { [key: string]: string } = {
|
||||
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
|
||||
WORKBENCH_AUTH_SESSION: authSessionInfo ? asJSON(authSessionInfo) : '',
|
||||
@@ -158,18 +165,18 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+ VS_BASE: vscodeBase,
|
||||
};
|
||||
|
||||
if (useTestResolver) {
|
||||
@@ -371,7 +376,7 @@ export class WebClientServer {
|
||||
|
||||
@@ -344,7 +348,7 @@ export class WebClientServer {
|
||||
'default-src \'self\';',
|
||||
'img-src \'self\' https: data: blob:;',
|
||||
'media-src \'self\';',
|
||||
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' ${useTestResolver ? '' : `http://${remoteAuthority}`};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} '${webWorkerExtensionHostIframeScriptSHA}' ${useTestResolver ? '' : ''};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
- `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=' http://${remoteAuthority};`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
+ `script-src 'self' 'unsafe-eval' ${this._getScriptCspHashes(data).join(' ')} 'sha256-fh3TwPMflhsEIpR8g1OYTIMVWhXTLcjQ9kh2tIpmv54=';`, // the sha is the same as in src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html
|
||||
'child-src \'self\';',
|
||||
`frame-src 'self' https://*.vscode-cdn.net data:;`,
|
||||
'worker-src \'self\' data: blob:;',
|
||||
@@ -444,3 +449,70 @@ export class WebClientServer {
|
||||
return void res.end(data);
|
||||
'worker-src \'self\' data:;',
|
||||
@@ -417,3 +421,70 @@ export class WebClientServer {
|
||||
return res.end(data);
|
||||
}
|
||||
}
|
||||
+
|
||||
@@ -243,7 +250,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -56,6 +56,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
@@ -32,6 +32,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
|
||||
export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
@@ -255,61 +262,39 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -304,7 +304,8 @@ class LocalStorageURLCallbackProvider ex
|
||||
this.startListening();
|
||||
}
|
||||
|
||||
- return URI.parse(mainWindow.location.href).with({ path: this._callbackRoute, query: queryParams.join('&') });
|
||||
+ const path = (mainWindow.location.pathname + "/" + this._callbackRoute).replace(/\/\/+/g, "/");
|
||||
+ return URI.parse(mainWindow.location.href).with({ path: path, query: queryParams.join('&') });
|
||||
@@ -489,6 +489,7 @@ function doCreateUri(path: string, query
|
||||
});
|
||||
}
|
||||
|
||||
private startListening(): void {
|
||||
@@ -550,17 +551,6 @@ class WorkspaceProvider implements IWork
|
||||
}
|
||||
+ path = (window.location.pathname + "/" + path).replace(/\/\/+/g, "/")
|
||||
return URI.parse(window.location.href).with({ path, query });
|
||||
}
|
||||
|
||||
-function readCookie(name: string): string | undefined {
|
||||
- const cookies = document.cookie.split('; ');
|
||||
- for (const cookie of cookies) {
|
||||
- if (cookie.startsWith(name + '=')) {
|
||||
- return cookie.substring(name.length + 1);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return undefined;
|
||||
-}
|
||||
-
|
||||
(function () {
|
||||
|
||||
// Find config by checking for DOM
|
||||
@@ -569,8 +559,8 @@ function readCookie(name: string): strin
|
||||
@@ -500,7 +501,7 @@ function doCreateUri(path: string, query
|
||||
if (!configElement || !configElementAttribute) {
|
||||
throw new Error('Missing web configuration element');
|
||||
}
|
||||
- const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = JSON.parse(configElementAttribute);
|
||||
- const secretStorageKeyPath = readCookie('vscode-secret-key-path');
|
||||
+ const config: IWorkbenchConstructionOptions & { folderUri?: UriComponents; workspaceUri?: UriComponents; callbackRoute: string } = { ...JSON.parse(configElementAttribute), remoteAuthority: location.host }
|
||||
+ const secretStorageKeyPath = (window.location.pathname + "/mint-key").replace(/\/\/+/g, "/");
|
||||
const secretStorageCrypto = secretStorageKeyPath && ServerKeyedAESCrypto.supported()
|
||||
? new ServerKeyedAESCrypto(secretStorageKeyPath) : new TransparentCrypto();
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
// Create workbench
|
||||
create(document.body, {
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
@@ -16,7 +16,6 @@ import { getServiceMachineId } from 'vs/
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
-import { RemoteAuthorities } from 'vs/base/common/network';
|
||||
import { TargetPlatform } from 'vs/platform/extensions/common/extensions';
|
||||
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
const WEB_EXTENSION_RESOURCE_END_POINT_SEGMENT = '/web-extension-resource/';
|
||||
@@ -99,7 +98,7 @@ export abstract class AbstractExtensionR
|
||||
: version,
|
||||
path: 'extension'
|
||||
}));
|
||||
export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
|
||||
@@ -75,7 +74,7 @@ export abstract class AbstractExtensionR
|
||||
public getExtensionGalleryResourceURL(galleryExtension: { publisher: string; name: string; version: string }, path?: string): URI | undefined {
|
||||
if (this._extensionGalleryResourceUrlTemplate) {
|
||||
const uri = URI.parse(format2(this._extensionGalleryResourceUrlTemplate, { publisher: galleryExtension.publisher, name: galleryExtension.name, version: galleryExtension.version, path: 'extension' }));
|
||||
- return this._isWebExtensionResourceEndPoint(uri) ? uri.with({ scheme: RemoteAuthorities.getPreferredWebSchema() }) : uri;
|
||||
+ return this._isWebExtensionResourceEndPoint(uri) ? URI.joinPath(URI.parse(window.location.href), uri.path) : uri;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ To test:
|
||||
2. Open code-server
|
||||
3. Open terminal
|
||||
4. Open another code-server window
|
||||
5. Run node ./out/node/entry.js with a file or directory argument
|
||||
5. Run code-server with a file or directory argument
|
||||
|
||||
The file or directory should only open from the instance attached to that
|
||||
terminal.
|
||||
@@ -17,7 +17,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTe
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
@@ -106,10 +106,14 @@ class RemoteTerminalBackend extends Base
|
||||
@@ -100,10 +100,14 @@ class RemoteTerminalBackend extends Base
|
||||
}
|
||||
const reqId = e.reqId;
|
||||
const commandId = e.commandId;
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands.ts
|
||||
@@ -8,6 +8,7 @@ import { isWeb } from 'vs/base/common/pl
|
||||
import { isString } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
+import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionManagementCLI } from 'vs/platform/extensionManagement/common/extensionManagementCLI';
|
||||
@@ -89,6 +90,11 @@ CommandsRegistry.registerCommand('_remot
|
||||
return lines.join('\n');
|
||||
});
|
||||
|
||||
+CommandsRegistry.registerCommand('_remoteCLI.setClipboard', function (accessor: ServicesAccessor, content: string) {
|
||||
+ const clipboardService = accessor.get(IClipboardService);
|
||||
+ clipboardService.writeText(content);
|
||||
+})
|
||||
+
|
||||
class RemoteExtensionManagementCLI extends ExtensionManagementCLI {
|
||||
|
||||
private _location: string | undefined;
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostCLIServer.ts
|
||||
@@ -43,7 +43,12 @@ export interface ExtensionManagementPipe
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
-export type PipeCommand = OpenCommandPipeArgs | StatusPipeArgs | OpenExternalCommandPipeArgs | ExtensionManagementPipeArgs;
|
||||
+export interface ClipboardPipeArgs {
|
||||
+ type: 'clipboard';
|
||||
+ content: string;
|
||||
+}
|
||||
+
|
||||
+export type PipeCommand = OpenCommandPipeArgs | StatusPipeArgs | OpenExternalCommandPipeArgs | ExtensionManagementPipeArgs | ClipboardPipeArgs;
|
||||
|
||||
export interface ICommandsExecuter {
|
||||
executeCommand<T>(id: string, ...args: any[]): Promise<T>;
|
||||
@@ -105,6 +110,9 @@ export class CLIServerBase {
|
||||
case 'extensionManagement':
|
||||
returnObj = await this.manageExtensions(data);
|
||||
break;
|
||||
+ case 'clipboard':
|
||||
+ returnObj = await this.clipboard(data);
|
||||
+ break;
|
||||
default:
|
||||
sendResponse(404, `Unknown message type: ${data.type}`);
|
||||
break;
|
||||
@@ -172,6 +180,10 @@ export class CLIServerBase {
|
||||
return await this._commands.executeCommand<string | undefined>('_remoteCLI.getSystemStatus');
|
||||
}
|
||||
|
||||
+ private async clipboard(data: ClipboardPipeArgs): Promise<undefined> {
|
||||
+ return await this._commands.executeCommand('_remoteCLI.setClipboard', data.content);
|
||||
+ }
|
||||
+
|
||||
dispose(): void {
|
||||
this._server.close();
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/browser/remoteTerminalBackend.ts
|
||||
@@ -97,7 +97,7 @@ class RemoteTerminalBackend extends Base
|
||||
}
|
||||
});
|
||||
|
||||
- const allowedCommands = ['_remoteCLI.openExternal', '_remoteCLI.windowOpen', '_remoteCLI.getSystemStatus', '_remoteCLI.manageExtensions'];
|
||||
+ const allowedCommands = ['_remoteCLI.openExternal', '_remoteCLI.windowOpen', '_remoteCLI.getSystemStatus', '_remoteCLI.manageExtensions', '_remoteCLI.setClipboard'];
|
||||
this._remoteTerminalChannel.onExecuteCommand(async e => {
|
||||
// Ensure this request for for this window
|
||||
const pty = this._ptys.get(e.persistentProcessId);
|
||||
Index: code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/environment/common/argv.ts
|
||||
@@ -119,6 +119,7 @@ export interface NativeParsedArgs {
|
||||
sandbox?: boolean;
|
||||
|
||||
'enable-coi'?: boolean;
|
||||
+ 'stdin-to-clipboard'?: boolean;
|
||||
|
||||
// chromium command line args: https://electronjs.org/docs/all#supported-chrome-command-line-switches
|
||||
'no-proxy-server'?: boolean;
|
||||
Index: code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/environment/node/argv.ts
|
||||
@@ -90,6 +90,7 @@ export const OPTIONS: OptionDescriptions
|
||||
'user-data-dir': { type: 'string', cat: 'o', args: 'dir', description: localize('userDataDir', "Specifies the directory that user data is kept in. Can be used to open multiple distinct instances of Code.") },
|
||||
'profile': { type: 'string', 'cat': 'o', args: 'profileName', description: localize('profileName', "Opens the provided folder or workspace with the given profile and associates the profile with the workspace. If the profile does not exist, a new empty one is created.") },
|
||||
'help': { type: 'boolean', cat: 'o', alias: 'h', description: localize('help', "Print usage.") },
|
||||
+ 'stdin-to-clipboard': { type: 'boolean', cat: 'o', alias: 'c', description: localize('clipboard', "copies the STDIN to the clipboard") },
|
||||
|
||||
'extensions-dir': { type: 'string', deprecates: ['extensionHomePath'], cat: 'e', args: 'dir', description: localize('extensionHomePath', "Set the root path for extensions.") },
|
||||
'extensions-download-dir': { type: 'string' },
|
||||
Index: code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/server.cli.ts
|
||||
@@ -76,6 +76,7 @@ const isSupportedForPipe = (optionId: ke
|
||||
case 'verbose':
|
||||
case 'remote':
|
||||
case 'locate-shell-integration-path':
|
||||
+ case 'stdin-to-clipboard':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -293,6 +294,23 @@ export async function main(desc: Product
|
||||
}
|
||||
}
|
||||
} else {
|
||||
+ if (parsedArgs['stdin-to-clipboard']) {
|
||||
+ if(!hasStdinWithoutTty()) {
|
||||
+ console.error("stdin has a tty.");
|
||||
+ return;
|
||||
+ }
|
||||
+ const fs = require("fs");
|
||||
+ const stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0
|
||||
+ const clipboardContent = stdinBuffer.toString();
|
||||
+ sendToPipe({
|
||||
+ type: 'clipboard',
|
||||
+ content: clipboardContent
|
||||
+ }, verbose).catch(e => {
|
||||
+ console.error('Error when requesting status:', e);
|
||||
+ });
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (parsedArgs.status) {
|
||||
sendToPipe({
|
||||
type: 'status'
|
||||
@@ -7,7 +7,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
|
||||
@@ -285,6 +285,10 @@ export class Extension implements IExten
|
||||
@@ -237,6 +237,10 @@ export class Extension implements IExten
|
||||
if (this.type === ExtensionType.System && this.productService.quality === 'stable') {
|
||||
return false;
|
||||
}
|
||||
@@ -18,3 +18,14 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extens
|
||||
if (!this.local.preRelease && this.gallery.properties.isPreReleaseVersion) {
|
||||
return false;
|
||||
}
|
||||
@@ -1234,6 +1238,10 @@ export class ExtensionsWorkbenchService
|
||||
// Skip if check updates only for builtin extensions and current extension is not builtin.
|
||||
continue;
|
||||
}
|
||||
+ if (installed.type !== ExtensionType.User) {
|
||||
+ // Never update builtin extensions.
|
||||
+ continue;
|
||||
+ }
|
||||
if (installed.isBuiltin && (!installed.local?.identifier.uuid || (!isWeb && this.productService.quality === 'stable'))) {
|
||||
// Skip checking updates for a builtin extension if it does not has Marketplace identifier or the current product is VS Code Desktop stable.
|
||||
continue;
|
||||
|
||||
183
patches/disable-downloads.diff
Normal file
183
patches/disable-downloads.diff
Normal file
@@ -0,0 +1,183 @@
|
||||
Add option to disable file downloads via CLI
|
||||
|
||||
This patch adds support for a new CLI flag called `--disable-file-downloads`
|
||||
which allows a user to remove the "Download..." option that shows up when you
|
||||
right-click files in Code. The default value for this is `false`.
|
||||
|
||||
To test this, start code-server with `--disable-file-downloads`, open editor,
|
||||
right-click on a file (not a folder) and you should **not** see the
|
||||
"Download..." option.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -271,6 +271,11 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly userDataPath?: string
|
||||
|
||||
+ /**
|
||||
+ * Whether the "Download..." option is enabled for files.
|
||||
+ */
|
||||
+ readonly isEnabledFileDownloads?: boolean
|
||||
+
|
||||
//#endregion
|
||||
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -31,6 +31,11 @@ export interface IBrowserWorkbenchEnviro
|
||||
* Options used to configure the workbench.
|
||||
*/
|
||||
readonly options?: IWorkbenchConstructionOptions;
|
||||
+
|
||||
+ /**
|
||||
+ * Enable downloading files via menu actions.
|
||||
+ */
|
||||
+ readonly isEnabledFileDownloads?: boolean;
|
||||
}
|
||||
|
||||
export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
|
||||
@@ -62,6 +67,13 @@ export class BrowserWorkbenchEnvironment
|
||||
return this.options.userDataPath;
|
||||
}
|
||||
|
||||
+ get isEnabledFileDownloads(): boolean {
|
||||
+ if (typeof this.options.isEnabledFileDownloads === "undefined") {
|
||||
+ throw new Error('isEnabledFileDownloads was not provided to the browser');
|
||||
+ }
|
||||
+ return this.options.isEnabledFileDownloads;
|
||||
+ }
|
||||
+
|
||||
@memoize
|
||||
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -14,6 +14,7 @@ export const serverOptions: OptionDescri
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
+ 'disable-file-downloads': { type: 'boolean' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -94,6 +95,7 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
+ 'disable-file-downloads'?: boolean;
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -304,6 +304,7 @@ export class WebClientServer {
|
||||
remoteAuthority,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@@ -7,12 +7,11 @@ import { Event } from 'vs/base/common/ev
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
|
||||
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
@@ -25,6 +24,7 @@ import { IPaneCompositePartService } fro
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
|
||||
export class WorkbenchContextKeysHandler extends Disposable {
|
||||
private inputFocusedContext: IContextKey<boolean>;
|
||||
@@ -77,7 +77,7 @@ export class WorkbenchContextKeysHandler
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
- @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
+ @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
|
||||
@@ -202,6 +202,9 @@ export class WorkbenchContextKeysHandler
|
||||
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
|
||||
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
|
||||
|
||||
+ // code-server
|
||||
+ IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
||||
+
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
|
||||
@@ -22,7 +22,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
|
||||
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
-import { DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey } from 'vs/workbench/common/contextkeys';
|
||||
+import { DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
|
||||
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
@@ -477,13 +477,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||
id: DOWNLOAD_COMMAND_ID,
|
||||
title: DOWNLOAD_LABEL
|
||||
},
|
||||
- when: ContextKeyExpr.or(
|
||||
- // native: for any remote resource
|
||||
- ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
|
||||
- // web: for any files
|
||||
- ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
|
||||
- // web: for any folders if file system API support is provided
|
||||
- ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
|
||||
+ when: ContextKeyExpr.and(
|
||||
+ IsEnabledFileDownloads,
|
||||
+ ContextKeyExpr.or(
|
||||
+ // native: for any remote resource
|
||||
+ ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
|
||||
+ // web: for any files
|
||||
+ ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
|
||||
+ // web: for any folders if file system API support is provided
|
||||
+ ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
|
||||
+ )
|
||||
)
|
||||
}));
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -32,6 +32,8 @@ export const IsFullscreenContext = new R
|
||||
|
||||
export const HasWebFileSystemAccess = new RawContextKey<boolean>('hasWebFileSystemAccess', false, true); // Support for FileSystemAccess web APIs (https://wicg.github.io/file-system-access)
|
||||
|
||||
+export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||
+
|
||||
//#endregion
|
||||
|
||||
|
||||
@@ -14,31 +14,20 @@ We can remove this once upstream supports all language packs.
|
||||
one but is worse because it does not handle non-existent or empty files.
|
||||
7. Replace some caching and Node requires because code-server does not restart
|
||||
when changing the language unlike native Code.
|
||||
8. Make language extensions installable like normal rather than using the
|
||||
special set/clear language actions.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -11,7 +11,7 @@ import * as path from 'vs/base/common/pa
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { getMachineId, getSqmMachineId, getdevDeviceId } from 'vs/base/node/id';
|
||||
import { Promises } from 'vs/base/node/pfs';
|
||||
-import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
|
||||
+import { ClientConnectionEvent, IMessagePassingProtocol, IPCServer, ProxyChannel, StaticRouter } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ProtocolConstants } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||
@@ -238,6 +238,9 @@ export async function setupServerService
|
||||
@@ -209,6 +209,9 @@ export async function setupServerService
|
||||
const channel = new ExtensionManagementChannel(extensionManagementService, (ctx: RemoteAgentConnectionContext) => getUriTransformer(ctx.remoteAuthority));
|
||||
socketServer.registerChannel('extensions', channel);
|
||||
|
||||
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService), disposables);
|
||||
+ const languagePackChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(ILanguagePackService));
|
||||
+ socketServer.registerChannel('languagePacks', languagePackChannel);
|
||||
+
|
||||
// clean up extensions folder
|
||||
remoteExtensionsScanner.whenExtensionsReady().then(() => extensionManagementService.cleanUp());
|
||||
const encryptionChannel = ProxyChannel.fromService<RemoteAgentConnectionContext>(accessor.get(IEncryptionMainService));
|
||||
socketServer.registerChannel('encryption', encryptionChannel);
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
===================================================================
|
||||
@@ -53,7 +42,7 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
export const LANGUAGE_DEFAULT = 'en';
|
||||
|
||||
let _isWindows = false;
|
||||
@@ -112,17 +110,21 @@ else if (typeof navigator === 'object' &
|
||||
@@ -83,17 +81,19 @@ if (typeof navigator === 'object' && !is
|
||||
_isMobile = _userAgent?.indexOf('Mobi') >= 0;
|
||||
_isWeb = true;
|
||||
|
||||
@@ -67,23 +56,21 @@ Index: code-server/lib/vscode/src/vs/base/common/platform.ts
|
||||
-
|
||||
- _locale = configuredLocale || LANGUAGE_DEFAULT;
|
||||
+ _locale = LANGUAGE_DEFAULT;
|
||||
|
||||
_language = _locale;
|
||||
_platformLocale = navigator.language;
|
||||
+ const el = typeof document !== 'undefined' && document.getElementById('vscode-remote-nls-configuration');
|
||||
+ const rawNlsConfig = el && el.getAttribute('data-settings');
|
||||
+ if (rawNlsConfig) {
|
||||
+ try {
|
||||
+ const nlsConfig: NLSConfig = JSON.parse(rawNlsConfig);
|
||||
+ const resolved = nlsConfig.availableLanguages['*'];
|
||||
+ _locale = nlsConfig.locale;
|
||||
+ _platformLocale = nlsConfig.osLocale;
|
||||
+ _language = resolved ? resolved : LANGUAGE_DEFAULT;
|
||||
+ _translationsConfigFile = nlsConfig._translationsConfigFile;
|
||||
+ _language = nlsConfig.availableLanguages['*'] || LANGUAGE_DEFAULT;
|
||||
+ } catch (error) { /* Oh well. */ }
|
||||
+ }
|
||||
}
|
||||
|
||||
// Unknown environment
|
||||
// Native environment
|
||||
Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
@@ -98,10 +85,10 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
<!-- Workbench Icon/Manifest/CSS -->
|
||||
<link rel="icon" href="{{BASE}}/_static/src/browser/media/favicon-dark-support.svg" />
|
||||
<link rel="alternate icon" href="{{BASE}}/_static/src/browser/media/favicon.ico" type="image/x-icon" />
|
||||
@@ -48,15 +51,27 @@
|
||||
// Normalize locale to lowercase because translationServiceUrl is case-sensitive.
|
||||
// ref: https://github.com/microsoft/vscode/issues/187795
|
||||
const locale = localStorage.getItem('vscode.nls.locale') || navigator.language.toLowerCase();
|
||||
@@ -46,15 +49,26 @@
|
||||
// Set up nls if the user is not using the default language (English)
|
||||
const nlsConfig = {};
|
||||
const locale = window.localStorage.getItem('vscode.nls.locale') || navigator.language;
|
||||
- if (!locale.startsWith('en')) {
|
||||
- nlsConfig['vs/nls'] = {
|
||||
- availableLanguages: {
|
||||
@@ -110,7 +97,7 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.html
|
||||
- translationServiceUrl: '{{WORKBENCH_NLS_BASE_URL}}'
|
||||
- };
|
||||
- }
|
||||
|
||||
-
|
||||
+ try {
|
||||
+ nlsConfig['vs/nls'] = JSON.parse(document.getElementById("vscode-remote-nls-configuration").getAttribute("data-settings"))
|
||||
+ if (nlsConfig['vs/nls']._resolvedLanguagePackCoreLocation) {
|
||||
@@ -138,7 +125,7 @@ Index: code-server/lib/vscode/src/vs/platform/environment/common/environmentServ
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/environment/common/environmentService.ts
|
||||
@@ -101,7 +101,7 @@ export abstract class AbstractNativeEnvi
|
||||
@@ -105,7 +105,7 @@ export abstract class AbstractNativeEnvi
|
||||
return URI.file(join(vscodePortable, 'argv.json'));
|
||||
}
|
||||
|
||||
@@ -151,7 +138,7 @@ Index: code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
@@ -32,6 +32,12 @@ export function getNLSConfiguration(lang
|
||||
@@ -30,6 +30,12 @@ export function getNLSConfiguration(lang
|
||||
if (InternalNLSConfiguration.is(value)) {
|
||||
value._languagePackSupport = true;
|
||||
}
|
||||
@@ -164,7 +151,7 @@ Index: code-server/lib/vscode/src/vs/server/node/remoteLanguagePacks.ts
|
||||
return value;
|
||||
});
|
||||
_cache.set(key, result);
|
||||
@@ -46,3 +52,43 @@ export namespace InternalNLSConfiguratio
|
||||
@@ -44,3 +50,43 @@ export namespace InternalNLSConfiguratio
|
||||
return candidate && typeof candidate._languagePackId === 'string';
|
||||
}
|
||||
}
|
||||
@@ -212,47 +199,47 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -27,6 +27,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
@@ -26,6 +26,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
import { streamToBuffer } from 'vs/base/common/buffer';
|
||||
import { IProductConfiguration } from 'vs/base/common/product';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
+import { getLocaleFromConfig, getNLSConfiguration } from 'vs/server/node/remoteLanguagePacks';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
import { IExtensionManifest } from 'vs/platform/extensions/common/extensions';
|
||||
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
@@ -348,6 +349,8 @@ export class WebClientServer {
|
||||
callbackRoute: this._callbackRoute
|
||||
};
|
||||
@@ -299,6 +300,8 @@ export class WebClientServer {
|
||||
|
||||
const base = relativeRoot(getOriginalUrl(req))
|
||||
const vscodeBase = relativePath(getOriginalUrl(req))
|
||||
+ const locale = this._environmentService.args.locale || await getLocaleFromConfig(this._environmentService.argvResource.fsPath);
|
||||
+ const nlsConfiguration = await getNLSConfiguration(locale, this._environmentService.userDataPath)
|
||||
const nlsBaseUrl = this._productService.extensionsGallery?.nlsBaseUrl;
|
||||
const values: { [key: string]: string } = {
|
||||
WORKBENCH_WEB_CONFIGURATION: asJSON(workbenchWebConfiguration),
|
||||
@@ -356,6 +359,7 @@ export class WebClientServer {
|
||||
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
@@ -336,6 +339,7 @@ export class WebClientServer {
|
||||
WORKBENCH_NLS_BASE_URL: vscodeBase + (nlsBaseUrl ? `${nlsBaseUrl}${!nlsBaseUrl.endsWith('/') ? '/' : ''}${this._productService.commit}/${this._productService.version}/` : ''),
|
||||
BASE: base,
|
||||
VS_BASE: vscodeBase,
|
||||
+ NLS_CONFIGURATION: asJSON(nlsConfiguration),
|
||||
};
|
||||
|
||||
if (useTestResolver) {
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -18,6 +18,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -15,6 +15,7 @@ export const serverOptions: OptionDescri
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
'disable-file-uploads': { type: 'boolean' },
|
||||
+ 'locale': { type: 'string' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -103,6 +104,7 @@ export interface ServerParsedArgs {
|
||||
'auth'?: string;
|
||||
@@ -96,6 +97,7 @@ export interface ServerParsedArgs {
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string
|
||||
'disable-file-downloads'?: boolean;
|
||||
'disable-file-uploads'?: boolean;
|
||||
+ 'locale'?: string
|
||||
|
||||
/* ----- server setup ----- */
|
||||
@@ -261,18 +248,9 @@ Index: code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/workbench.web.main.ts
|
||||
@@ -52,7 +52,7 @@ import 'vs/workbench/services/dialogs/br
|
||||
import 'vs/workbench/services/host/browser/browserHostService';
|
||||
import 'vs/workbench/services/lifecycle/browser/lifecycleService';
|
||||
import 'vs/workbench/services/clipboard/browser/clipboardService';
|
||||
-import 'vs/workbench/services/localization/browser/localeService';
|
||||
+import 'vs/workbench/services/localization/electron-sandbox/localeService';
|
||||
import 'vs/workbench/services/path/browser/pathService';
|
||||
import 'vs/workbench/services/themes/browser/browserHostColorSchemeService';
|
||||
import 'vs/workbench/services/encryption/browser/encryptionService';
|
||||
@@ -118,8 +118,9 @@ registerSingleton(ILanguagePackService,
|
||||
// Logs
|
||||
import 'vs/workbench/contrib/logs/browser/logs.contribution';
|
||||
@@ -123,8 +123,9 @@ import 'vs/workbench/contrib/logs/browse
|
||||
// Explorer
|
||||
import 'vs/workbench/contrib/files/browser/files.web.contribution';
|
||||
|
||||
-// Localization
|
||||
-import 'vs/workbench/contrib/localization/browser/localization.contribution';
|
||||
@@ -286,45 +264,37 @@ Index: code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePack
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/languagePacks/browser/languagePacks.ts
|
||||
@@ -5,18 +5,24 @@
|
||||
@@ -4,10 +4,23 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILanguagePackItem, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
+import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionResourceLoaderService } from 'vs/platform/extensionResourceLoader/common/extensionResourceLoader';
|
||||
-import { ILanguagePackItem, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
+import { ILanguagePackItem, ILanguagePackService, LanguagePackBaseService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
+import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
|
||||
+import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
+import { IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
|
||||
export class WebLanguagePacksService extends LanguagePackBaseService {
|
||||
- // Web doesn't have a concept of language packs, so we just return an empty array
|
||||
+ private readonly languagePackService: ILanguagePackService;
|
||||
+
|
||||
constructor(
|
||||
+ constructor(
|
||||
+ @IRemoteAgentService remoteAgentService: IRemoteAgentService,
|
||||
@IExtensionResourceLoaderService private readonly extensionResourceLoaderService: IExtensionResourceLoaderService,
|
||||
@IExtensionGalleryService extensionGalleryService: IExtensionGalleryService,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super(extensionGalleryService);
|
||||
+ this.languagePackService = ProxyChannel.toService<ILanguagePackService>(remoteAgentService.getConnection()!.getChannel('languagePacks'))
|
||||
}
|
||||
|
||||
async getBuiltInExtensionTranslationsUri(id: string, language: string): Promise<URI | undefined> {
|
||||
@@ -72,6 +78,6 @@ export class WebLanguagePacksService ext
|
||||
|
||||
// Web doesn't have a concept of language packs, so we just return an empty array
|
||||
+ @IExtensionGalleryService extensionGalleryService: IExtensionGalleryService
|
||||
+ ) {
|
||||
+ super(extensionGalleryService)
|
||||
+ this.languagePackService = ProxyChannel.toService<ILanguagePackService>(remoteAgentService.getConnection()!.getChannel('languagePacks'));
|
||||
+ }
|
||||
+
|
||||
getInstalledLanguages(): Promise<ILanguagePackItem[]> {
|
||||
- return Promise.resolve([]);
|
||||
+ return this.languagePackService.getInstalledLanguages()
|
||||
}
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/localization/electron-sandbox/localeService.ts
|
||||
@@ -51,7 +51,8 @@ class NativeLocaleService implements ILo
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/localization/electron-sandbox/localeService.ts
|
||||
@@ -41,7 +41,8 @@ export class NativeLocaleService impleme
|
||||
@IProductService private readonly productService: IProductService
|
||||
) { }
|
||||
|
||||
@@ -334,7 +304,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-sa
|
||||
try {
|
||||
const content = await this.textFileService.read(this.environmentService.argvResource, { encoding: 'utf8' });
|
||||
|
||||
@@ -78,9 +79,6 @@ class NativeLocaleService implements ILo
|
||||
@@ -68,9 +69,6 @@ export class NativeLocaleService impleme
|
||||
}
|
||||
|
||||
private async writeLocaleValue(locale: string | undefined): Promise<boolean> {
|
||||
@@ -344,70 +314,3 @@ Index: code-server/lib/vscode/src/vs/workbench/services/localization/electron-sa
|
||||
await this.jsonEditingService.write(this.environmentService.argvResource, [{ path: ['locale'], value: locale }], true);
|
||||
return true;
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
|
||||
@@ -341,9 +341,6 @@ export class InstallAction extends Exten
|
||||
if (this.extension.isBuiltin) {
|
||||
return;
|
||||
}
|
||||
- if (this.extensionsWorkbenchService.canSetLanguage(this.extension)) {
|
||||
- return;
|
||||
- }
|
||||
if (this.extension.state === ExtensionState.Uninstalled && await this.extensionsWorkbenchService.canInstall(this.extension)) {
|
||||
this.enabled = this.options.installPreReleaseVersion ? this.extension.hasPreReleaseVersion : this.extension.hasReleaseVersion;
|
||||
this.updateLabel();
|
||||
@@ -614,7 +611,7 @@ export abstract class InstallInOtherServ
|
||||
}
|
||||
|
||||
if (isLanguagePackExtension(this.extension.local.manifest)) {
|
||||
- return true;
|
||||
+ return false;
|
||||
}
|
||||
|
||||
// Prefers to run on UI
|
||||
@@ -1848,17 +1845,6 @@ export class SetLanguageAction extends E
|
||||
update(): void {
|
||||
this.enabled = false;
|
||||
this.class = SetLanguageAction.DisabledClass;
|
||||
- if (!this.extension) {
|
||||
- return;
|
||||
- }
|
||||
- if (!this.extensionsWorkbenchService.canSetLanguage(this.extension)) {
|
||||
- return;
|
||||
- }
|
||||
- if (this.extension.gallery && language === getLocale(this.extension.gallery)) {
|
||||
- return;
|
||||
- }
|
||||
- this.enabled = true;
|
||||
- this.class = SetLanguageAction.EnabledClass;
|
||||
}
|
||||
|
||||
override async run(): Promise<any> {
|
||||
@@ -1875,7 +1861,6 @@ export class ClearLanguageAction extends
|
||||
private static readonly DisabledClass = `${ClearLanguageAction.EnabledClass} disabled`;
|
||||
|
||||
constructor(
|
||||
- @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@ILocaleService private readonly localeService: ILocaleService,
|
||||
) {
|
||||
super(ClearLanguageAction.ID, ClearLanguageAction.TITLE.value, ClearLanguageAction.DisabledClass, false);
|
||||
@@ -1885,17 +1870,6 @@ export class ClearLanguageAction extends
|
||||
update(): void {
|
||||
this.enabled = false;
|
||||
this.class = ClearLanguageAction.DisabledClass;
|
||||
- if (!this.extension) {
|
||||
- return;
|
||||
- }
|
||||
- if (!this.extensionsWorkbenchService.canSetLanguage(this.extension)) {
|
||||
- return;
|
||||
- }
|
||||
- if (this.extension.gallery && language !== getLocale(this.extension.gallery)) {
|
||||
- return;
|
||||
- }
|
||||
- this.enabled = true;
|
||||
- this.class = ClearLanguageAction.EnabledClass;
|
||||
}
|
||||
|
||||
override async run(): Promise<any> {
|
||||
|
||||
24
patches/exec-argv.diff
Normal file
24
patches/exec-argv.diff
Normal file
@@ -0,0 +1,24 @@
|
||||
Preserve process.execArgv
|
||||
|
||||
This ensures flags like `--prof` are passed down to the code-server process so
|
||||
we can profile everything.
|
||||
|
||||
To test this:
|
||||
1. run `./lib/node --prof .`
|
||||
2. in another terminal, run `ps -ejww`
|
||||
|
||||
You should see `--prof` next to every code-server process.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/extensionHostConnection.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/extensionHostConnection.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/extensionHostConnection.ts
|
||||
@@ -228,7 +228,7 @@ export class ExtensionHostConnection {
|
||||
|
||||
public async start(startParams: IRemoteExtensionHostStartParams): Promise<void> {
|
||||
try {
|
||||
- let execArgv: string[] = [];
|
||||
+ let execArgv: string[] = process.execArgv ? process.execArgv.filter(a => !/^--inspect(-brk)?=/.test(a)) : [];
|
||||
if (startParams.port && !(<any>process).pkg) {
|
||||
execArgv = [`--inspect${startParams.break ? '-brk' : ''}=${startParams.port}`];
|
||||
}
|
||||
@@ -1,357 +0,0 @@
|
||||
Add option to disable file downloads and uploads via cli
|
||||
|
||||
This patch adds support for a new CLI flag called `--disable-file-downloads`
|
||||
which allows a user to remove the "Download..." option that shows up when you
|
||||
right-click files in Code. It also disables the "Show Local" button on the dialog
|
||||
for Save, Save-As and Save Workspace. The default value for this is `false`.
|
||||
|
||||
This patch also add support for a new CLI flag called `--disable-file-uploads`
|
||||
which disables the drag to upload functionality and the "Upload..." option when you
|
||||
right-click folders in Code. It also disables the "Show Local" button on the dialog
|
||||
for opening a file. The default value for this is `false`.
|
||||
|
||||
This patch also adds trace log statements for when a file is read and written to disk.
|
||||
|
||||
To test disabling downloads, start code-server with `--disable-file-downloads`, open editor,
|
||||
right-click on a file (not a folder) and you should **not** see the
|
||||
"Download..." option. When saving a file or workspace, the "Show Local" button
|
||||
should **not** appear on the dialog that comes on screen.
|
||||
|
||||
To test disabling uploads, start code-server with `--disable-file-uploads`, open editor,
|
||||
right-click on a folder (not a file) and you should **not** see the
|
||||
"Upload..." option. If you drag a file into the file navigator, the file should **not** upload
|
||||
and appear in the file navigator. When opening a file, the "Show Local" button
|
||||
should **not** appear on the dialog that comes on screen.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -303,6 +303,16 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly userDataPath?: string
|
||||
|
||||
+ /**
|
||||
+ * Whether the "Download..." option is enabled for files.
|
||||
+ */
|
||||
+ readonly isEnabledFileDownloads?: boolean
|
||||
+
|
||||
+ /**
|
||||
+ * Whether the "Upload..." button is enabled.
|
||||
+ */
|
||||
+ readonly isEnabledFileUploads?: boolean
|
||||
+
|
||||
//#endregion
|
||||
|
||||
//#region Profile options
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -34,6 +34,16 @@ export interface IBrowserWorkbenchEnviro
|
||||
readonly options?: IWorkbenchConstructionOptions;
|
||||
|
||||
/**
|
||||
+ * Enable downloading files via menu actions.
|
||||
+ */
|
||||
+ readonly isEnabledFileDownloads?: boolean;
|
||||
+
|
||||
+ /**
|
||||
+ * Enable uploading files via menu actions.
|
||||
+ */
|
||||
+ readonly isEnabledFileUploads?: boolean;
|
||||
+
|
||||
+ /**
|
||||
* Gets whether a resolver extension is expected for the environment.
|
||||
*/
|
||||
readonly expectsResolverExtension: boolean;
|
||||
@@ -111,6 +121,20 @@ export class BrowserWorkbenchEnvironment
|
||||
return this.options.userDataPath;
|
||||
}
|
||||
|
||||
+ get isEnabledFileDownloads(): boolean {
|
||||
+ if (typeof this.options.isEnabledFileDownloads === "undefined") {
|
||||
+ throw new Error('isEnabledFileDownloads was not provided to the browser');
|
||||
+ }
|
||||
+ return this.options.isEnabledFileDownloads;
|
||||
+ }
|
||||
+
|
||||
+ get isEnabledFileUploads(): boolean {
|
||||
+ if (typeof this.options.isEnabledFileUploads === "undefined") {
|
||||
+ throw new Error('isEnabledFileUploads was not provided to the browser');
|
||||
+ }
|
||||
+ return this.options.isEnabledFileUploads;
|
||||
+ }
|
||||
+
|
||||
@memoize
|
||||
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -16,6 +16,8 @@ export const serverOptions: OptionDescri
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
'auth': { type: 'string' },
|
||||
+ 'disable-file-downloads': { type: 'boolean' },
|
||||
+ 'disable-file-uploads': { type: 'boolean' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -99,6 +101,8 @@ export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
'auth'?: string;
|
||||
+ 'disable-file-downloads'?: boolean;
|
||||
+ 'disable-file-uploads'?: boolean;
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -334,6 +334,8 @@ export class WebClientServer {
|
||||
serverBasePath: this._basePath,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
+ isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
+ isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
||||
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@@ -7,11 +7,11 @@ import { Event } from 'vs/base/common/ev
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
|
||||
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
import { WorkbenchState, IWorkspaceContextService, isTemporaryWorkspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchLayoutService, Parts, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
|
||||
@@ -70,7 +70,7 @@ export class WorkbenchContextKeysHandler
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
- @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
+ @IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@@ -197,6 +197,10 @@ export class WorkbenchContextKeysHandler
|
||||
this.auxiliaryBarVisibleContext = AuxiliaryBarVisibleContext.bindTo(this.contextKeyService);
|
||||
this.auxiliaryBarVisibleContext.set(this.layoutService.isVisible(Parts.AUXILIARYBAR_PART));
|
||||
|
||||
+ // code-server
|
||||
+ IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
||||
+ IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
|
||||
+
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/fileActions.contribution.ts
|
||||
@@ -20,7 +20,7 @@ import { CLOSE_SAVED_EDITORS_COMMAND_ID,
|
||||
import { AutoSaveAfterShortDelayContext } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||
import { WorkbenchListDoubleSelection } from 'vs/platform/list/browser/listService';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
-import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { DirtyWorkingCopiesContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, WorkbenchStateContext, WorkspaceFolderCountContext, SidebarFocusContext, ActiveEditorCanRevertContext, ActiveEditorContext, ResourceContextKey, ActiveEditorAvailableEditorIdsContext, MultipleEditorsSelectedInGroupContext, TwoEditorsSelectedInGroupContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
|
||||
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
@@ -561,13 +561,16 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||
id: DOWNLOAD_COMMAND_ID,
|
||||
title: DOWNLOAD_LABEL
|
||||
},
|
||||
- when: ContextKeyExpr.or(
|
||||
- // native: for any remote resource
|
||||
- ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
|
||||
- // web: for any files
|
||||
- ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
|
||||
- // web: for any folders if file system API support is provided
|
||||
- ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
|
||||
+ when: ContextKeyExpr.and(
|
||||
+ IsEnabledFileDownloads,
|
||||
+ ContextKeyExpr.or(
|
||||
+ // native: for any remote resource
|
||||
+ ContextKeyExpr.and(IsWebContext.toNegated(), ResourceContextKey.Scheme.notEqualsTo(Schemas.file)),
|
||||
+ // web: for any files
|
||||
+ ContextKeyExpr.and(IsWebContext, ExplorerFolderContext.toNegated(), ExplorerRootContext.toNegated()),
|
||||
+ // web: for any folders if file system API support is provided
|
||||
+ ContextKeyExpr.and(IsWebContext, HasWebFileSystemAccess)
|
||||
+ )
|
||||
)
|
||||
}));
|
||||
|
||||
@@ -579,6 +582,7 @@ MenuRegistry.appendMenuItem(MenuId.Explo
|
||||
title: UPLOAD_LABEL,
|
||||
},
|
||||
when: ContextKeyExpr.and(
|
||||
+ IsEnabledFileUploads,
|
||||
// only in web
|
||||
IsWebContext,
|
||||
// only on folders
|
||||
Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -40,6 +40,9 @@ export const HasWebFileSystemAccess = ne
|
||||
|
||||
export const EmbedderIdentifierContext = new RawContextKey<string | undefined>('embedderIdentifier', undefined, localize('embedderIdentifier', 'The identifier of the embedder according to the product service, if one is defined'));
|
||||
|
||||
+export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||
+export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
||||
+
|
||||
//#endregion
|
||||
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts
|
||||
@@ -18,7 +18,7 @@ import { IModelService } from 'vs/editor
|
||||
import { ILanguageService } from 'vs/editor/common/languages/language';
|
||||
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
-import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IContextKeyService, IContextKey, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings';
|
||||
@@ -143,7 +143,7 @@ export class SimpleFileDialog implements
|
||||
@IFileDialogService private readonly fileDialogService: IFileDialogService,
|
||||
@IModelService private readonly modelService: IModelService,
|
||||
@ILanguageService private readonly languageService: ILanguageService,
|
||||
- @IWorkbenchEnvironmentService protected readonly environmentService: IWorkbenchEnvironmentService,
|
||||
+ @IBrowserWorkbenchEnvironmentService protected readonly environmentService: IBrowserWorkbenchEnvironmentService,
|
||||
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService,
|
||||
@IPathService protected readonly pathService: IPathService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@@ -286,20 +286,22 @@ export class SimpleFileDialog implements
|
||||
this.filePickBox.sortByLabel = false;
|
||||
this.filePickBox.ignoreFocusOut = true;
|
||||
this.filePickBox.ok = true;
|
||||
- if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
|
||||
- this.filePickBox.customButton = true;
|
||||
- this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
|
||||
- let action;
|
||||
- if (isSave) {
|
||||
- action = SaveLocalFileCommand;
|
||||
- } else {
|
||||
- action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderCommand : OpenLocalFileCommand) : OpenLocalFolderCommand;
|
||||
- }
|
||||
- const keybinding = this.keybindingService.lookupKeybinding(action.ID);
|
||||
- if (keybinding) {
|
||||
- const label = keybinding.getLabel();
|
||||
- if (label) {
|
||||
- this.filePickBox.customHover = format('{0} ({1})', action.LABEL, label);
|
||||
+ if ((isSave && this.environmentService.isEnabledFileDownloads) || (!isSave && this.environmentService.isEnabledFileUploads)) {
|
||||
+ if ((this.scheme !== Schemas.file) && this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1) && (this.options.availableFileSystems.indexOf(Schemas.file) > -1)) {
|
||||
+ this.filePickBox.customButton = true;
|
||||
+ this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
|
||||
+ let action;
|
||||
+ if (isSave) {
|
||||
+ action = SaveLocalFileCommand;
|
||||
+ } else {
|
||||
+ action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderCommand : OpenLocalFileCommand) : OpenLocalFolderCommand;
|
||||
+ }
|
||||
+ const keybinding = this.keybindingService.lookupKeybinding(action.ID);
|
||||
+ if (keybinding) {
|
||||
+ const label = keybinding.getLabel();
|
||||
+ if (label) {
|
||||
+ this.filePickBox.customHover = format('{0} ({1})', action.LABEL, label);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
|
||||
@@ -65,6 +65,7 @@ import { timeout } from 'vs/base/common/
|
||||
import { IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||
import { mainWindow } from 'vs/base/browser/window';
|
||||
import { IExplorerFileContribution, explorerFileContribRegistry } from 'vs/workbench/contrib/files/browser/explorerFileContrib';
|
||||
+import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
|
||||
|
||||
export class ExplorerDelegate implements IListVirtualDelegate<ExplorerItem> {
|
||||
|
||||
@@ -1001,7 +1002,8 @@ export class FileDragAndDrop implements
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IWorkspaceEditingService private workspaceEditingService: IWorkspaceEditingService,
|
||||
- @IUriIdentityService private readonly uriIdentityService: IUriIdentityService
|
||||
+ @IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
|
||||
+ @IBrowserWorkbenchEnvironmentService protected readonly environmentService: IBrowserWorkbenchEnvironmentService
|
||||
) {
|
||||
const updateDropEnablement = (e: IConfigurationChangeEvent | undefined) => {
|
||||
if (!e || e.affectsConfiguration('explorer.enableDragAndDrop')) {
|
||||
@@ -1226,15 +1228,17 @@ export class FileDragAndDrop implements
|
||||
|
||||
// External file DND (Import/Upload file)
|
||||
if (data instanceof NativeDragAndDropData) {
|
||||
- // Use local file import when supported
|
||||
- if (!isWeb || (isTemporaryWorkspace(this.contextService.getWorkspace()) && WebFileSystemAccess.supported(mainWindow))) {
|
||||
- const fileImport = this.instantiationService.createInstance(ExternalFileImport);
|
||||
- await fileImport.import(resolvedTarget, originalEvent, mainWindow);
|
||||
- }
|
||||
- // Otherwise fallback to browser based file upload
|
||||
- else {
|
||||
- const browserUpload = this.instantiationService.createInstance(BrowserFileUpload);
|
||||
- await browserUpload.upload(target, originalEvent);
|
||||
+ if (this.environmentService.isEnabledFileUploads) {
|
||||
+ // Use local file import when supported
|
||||
+ if (!isWeb || (isTemporaryWorkspace(this.contextService.getWorkspace()) && WebFileSystemAccess.supported(mainWindow))) {
|
||||
+ const fileImport = this.instantiationService.createInstance(ExternalFileImport);
|
||||
+ await fileImport.import(resolvedTarget, originalEvent, mainWindow);
|
||||
+ }
|
||||
+ // Otherwise fallback to browser based file upload
|
||||
+ else {
|
||||
+ const browserUpload = this.instantiationService.createInstance(BrowserFileUpload);
|
||||
+ await browserUpload.upload(target, originalEvent);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/files/node/diskFileSystemProviderServer.ts
|
||||
@@ -92,6 +92,7 @@ export abstract class AbstractDiskFileSy
|
||||
|
||||
private async readFile(uriTransformer: IURITransformer, _resource: UriComponents, opts?: IFileAtomicReadOptions): Promise<VSBuffer> {
|
||||
const resource = this.transformIncoming(uriTransformer, _resource, true);
|
||||
+ this.logService.trace(`File action: readFile ${resource.path}`);
|
||||
const buffer = await this.provider.readFile(resource, opts);
|
||||
|
||||
return VSBuffer.wrap(buffer);
|
||||
@@ -110,6 +111,7 @@ export abstract class AbstractDiskFileSy
|
||||
}
|
||||
});
|
||||
|
||||
+ this.logService.trace(`File action: readFileStream ${resource.path}`);
|
||||
const fileStream = this.provider.readFileStream(resource, opts, cts.token);
|
||||
listenStream(fileStream, {
|
||||
onData: chunk => emitter.fire(VSBuffer.wrap(chunk)),
|
||||
@@ -130,7 +132,7 @@ export abstract class AbstractDiskFileSy
|
||||
|
||||
private writeFile(uriTransformer: IURITransformer, _resource: UriComponents, content: VSBuffer, opts: IFileWriteOptions): Promise<void> {
|
||||
const resource = this.transformIncoming(uriTransformer, _resource);
|
||||
-
|
||||
+ this.logService.trace(`File action: writeFile ${resource.path}`);
|
||||
return this.provider.writeFile(resource, content.buffer, opts);
|
||||
}
|
||||
|
||||
@@ -10,25 +10,16 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
-import { $, Dimension, addDisposableListener, append, clearNode, reset } from 'vs/base/browser/dom';
|
||||
+import { $, Dimension, addDisposableListener, append, clearNode, reset, prepend } from 'vs/base/browser/dom';
|
||||
import { renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
|
||||
@@ -62,7 +62,7 @@ import { GettingStartedIndexList } from
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
@@ -54,7 +54,7 @@ import { IRecentFolder, IRecentWorkspace
|
||||
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
|
||||
import { OpenFileFolderAction, OpenFolderAction, OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { getTelemetryLevel } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
-import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
|
||||
+import { IsEnabledCoderGettingStarted, WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
|
||||
import { IEditorOpenContext, IEditorSerializer } from 'vs/workbench/common/editor';
|
||||
import { IWebviewElement, IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import 'vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedColors';
|
||||
@@ -816,6 +816,72 @@ export class GettingStartedPage extends
|
||||
import { OpenFolderViaWorkspaceAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions';
|
||||
import { Toggle } from 'vs/base/browser/ui/toggle/toggle';
|
||||
@@ -758,6 +758,72 @@ export class GettingStartedPage extends
|
||||
$('p.subtitle.description', {}, localize({ key: 'gettingStarted.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))
|
||||
);
|
||||
|
||||
@@ -64,7 +55,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
+ 'font-size: 13px',
|
||||
+ 'color: #dcdee2',
|
||||
+ ].join(';'),
|
||||
+ }, 'Provision software development environments on your infrastructure with Coder.'),
|
||||
+ }, 'Provision remote development environments on your infrastructure with Coder.'),
|
||||
+ $('p', {
|
||||
+ style: [
|
||||
+ 'margin-top: 8px',
|
||||
@@ -81,7 +72,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
+ 'align-items: center',
|
||||
+ ].join(';'),
|
||||
+ }, 'Get started ', $('span', {
|
||||
+ class: ThemeIcon.asClassName(Codicon.arrowRight),
|
||||
+ class: Codicon.arrowRight.classNames,
|
||||
+ style: [
|
||||
+ 'color: white',
|
||||
+ 'margin-left: 8px',
|
||||
@@ -96,21 +87,38 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
+ ),
|
||||
+ ),
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
|
||||
const leftColumn = $('.categories-column.categories-column-left', {},);
|
||||
const rightColumn = $('.categories-column.categories-column-right', {},);
|
||||
|
||||
@@ -887,6 +953,9 @@ export class GettingStartedPage extends
|
||||
@@ -775,13 +841,23 @@ export class GettingStartedPage extends
|
||||
const layoutLists = () => {
|
||||
if (gettingStartedList.itemCount) {
|
||||
this.container.classList.remove('noWalkthroughs');
|
||||
- reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
||||
- reset(rightColumn, gettingStartedList.getDomElement());
|
||||
+ if (this.contextService.contextMatchesRules(IsEnabledCoderGettingStarted)) {
|
||||
+ reset(leftColumn, startList.getDomElement(), recentList.getDomElement(), gettingStartedList.getDomElement());
|
||||
+ reset(rightColumn, gettingStartedCoder);
|
||||
+ } else {
|
||||
+ reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
||||
+ reset(rightColumn, gettingStartedList.getDomElement());
|
||||
+ }
|
||||
+
|
||||
recentList.setLimit(5);
|
||||
reset(leftColumn, startList.getDomElement(), recentList.getDomElement());
|
||||
}
|
||||
+ if (this.contextService.contextMatchesRules(IsEnabledCoderGettingStarted)) {
|
||||
+ prepend(rightColumn, gettingStartedCoder)
|
||||
+ }
|
||||
};
|
||||
|
||||
gettingStartedList.onDidChange(layoutLists);
|
||||
else {
|
||||
this.container.classList.add('noWalkthroughs');
|
||||
- reset(leftColumn, startList.getDomElement());
|
||||
+ if (this.contextService.contextMatchesRules(IsEnabledCoderGettingStarted)) {
|
||||
+ reset(leftColumn, startList.getDomElement(), gettingStartedCoder);
|
||||
+ } else {
|
||||
+ reset(leftColumn, startList.getDomElement());
|
||||
+ }
|
||||
reset(rightColumn, recentList.getDomElement());
|
||||
recentList.setLimit(10);
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/media/gettingStarted.css
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/browser/media/gettingStarted.css
|
||||
@@ -123,21 +131,21 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/welcomeGettingStarted/bro
|
||||
+ margin-bottom: 0.2em;
|
||||
+}
|
||||
+
|
||||
+.monaco-workbench .part.editor > .content .gettingStartedContainer .coder-coder {
|
||||
+.monaco-workbench .part.editor>.content .gettingStartedContainer .coder-coder {
|
||||
+ font-size: 1em;
|
||||
+ margin-top: 0.2em;
|
||||
+}
|
||||
+
|
||||
.monaco-workbench.hc-black .part.editor > .content .gettingStartedContainer .subtitle,
|
||||
.monaco-workbench.hc-light .part.editor > .content .gettingStartedContainer .subtitle {
|
||||
.monaco-workbench.hc-black .part.editor>.content .gettingStartedContainer .subtitle,
|
||||
.monaco-workbench.hc-light .part.editor>.content .gettingStartedContainer .subtitle {
|
||||
font-weight: 200;
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -313,6 +313,11 @@ export interface IWorkbenchConstructionO
|
||||
@@ -276,6 +276,11 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly isEnabledFileUploads?: boolean
|
||||
readonly isEnabledFileDownloads?: boolean
|
||||
|
||||
+ /**
|
||||
+ * Whether to use Coder's custom Getting Started text.
|
||||
@@ -146,25 +154,25 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+
|
||||
//#endregion
|
||||
|
||||
//#region Profile options
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -44,6 +44,11 @@ export interface IBrowserWorkbenchEnviro
|
||||
readonly isEnabledFileUploads?: boolean;
|
||||
|
||||
/**
|
||||
@@ -36,6 +36,11 @@ export interface IBrowserWorkbenchEnviro
|
||||
* Enable downloading files via menu actions.
|
||||
*/
|
||||
readonly isEnabledFileDownloads?: boolean;
|
||||
+
|
||||
+ /**
|
||||
+ * Enable Coder's custom getting started text.
|
||||
+ */
|
||||
+ readonly isEnabledCoderGettingStarted?: boolean;
|
||||
+
|
||||
+ /**
|
||||
* Gets whether a resolver extension is expected for the environment.
|
||||
*/
|
||||
readonly expectsResolverExtension: boolean;
|
||||
@@ -135,6 +140,13 @@ export class BrowserWorkbenchEnvironment
|
||||
return this.options.isEnabledFileUploads;
|
||||
}
|
||||
|
||||
export class BrowserWorkbenchEnvironmentService implements IBrowserWorkbenchEnvironmentService {
|
||||
@@ -74,6 +79,13 @@ export class BrowserWorkbenchEnvironment
|
||||
return this.options.isEnabledFileDownloads;
|
||||
}
|
||||
|
||||
+ get isEnabledCoderGettingStarted(): boolean {
|
||||
@@ -181,19 +189,19 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -19,6 +19,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -16,6 +16,7 @@ export const serverOptions: OptionDescri
|
||||
'auth': { type: 'string' },
|
||||
'disable-file-downloads': { type: 'boolean' },
|
||||
'disable-file-uploads': { type: 'boolean' },
|
||||
'locale': { type: 'string' },
|
||||
+ 'disable-getting-started-override': { type: 'boolean' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -105,6 +106,7 @@ export interface ServerParsedArgs {
|
||||
@@ -98,6 +99,7 @@ export interface ServerParsedArgs {
|
||||
'auth'?: string
|
||||
'disable-file-downloads'?: boolean;
|
||||
'disable-file-uploads'?: boolean;
|
||||
'locale'?: string
|
||||
+ 'disable-getting-started-override'?: boolean,
|
||||
+ 'disable-getting-started-override'?: boolean;
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -201,10 +209,10 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -339,6 +339,7 @@ export class WebClientServer {
|
||||
@@ -308,6 +308,7 @@ export class WebClientServer {
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
userDataPath: this._environmentService.userDataPath,
|
||||
isEnabledFileDownloads: !this._environmentService.args['disable-file-downloads'],
|
||||
isEnabledFileUploads: !this._environmentService.args['disable-file-uploads'],
|
||||
+ isEnabledCoderGettingStarted: !this._environmentService.args['disable-getting-started-override'],
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
||||
@@ -215,17 +223,17 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/contextkeys.ts
|
||||
@@ -7,7 +7,7 @@ import { Event } from 'vs/base/common/ev
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextKeyService, IContextKey, setConstant as setConstantContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, EmbedderIdentifierContext, EditorTabsVisibleContext, IsMainEditorCenteredLayoutContext, MainEditorAreaVisibleContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsMainWindowFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, TitleBarVisibleContext, TitleBarStyleContext, IsAuxiliaryWindowFocusedContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorGroupLockedContext, MultipleEditorGroupsContext, EditorsVisibleContext, IsEnabledFileDownloads, IsEnabledFileUploads, IsEnabledCoderGettingStarted, } from 'vs/workbench/common/contextkeys';
|
||||
import { trackFocus, addDisposableListener, EventType, onDidRegisterWindow, getActiveWindow } from 'vs/base/browser/dom';
|
||||
-import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads } from 'vs/workbench/common/contextkeys';
|
||||
+import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext, IsEnabledFileDownloads, IsEnabledCoderGettingStarted } from 'vs/workbench/common/contextkeys';
|
||||
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
|
||||
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
|
||||
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -200,6 +200,7 @@ export class WorkbenchContextKeysHandler
|
||||
@@ -204,6 +204,7 @@ export class WorkbenchContextKeysHandler
|
||||
|
||||
// code-server
|
||||
IsEnabledFileDownloads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileDownloads ?? true)
|
||||
IsEnabledFileUploads.bindTo(this.contextKeyService).set(this.environmentService.isEnabledFileUploads ?? true)
|
||||
+ IsEnabledCoderGettingStarted.bindTo(this.contextKeyService).set(this.environmentService.isEnabledCoderGettingStarted ?? true)
|
||||
|
||||
this.registerListeners();
|
||||
@@ -234,10 +242,10 @@ Index: code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/common/contextkeys.ts
|
||||
@@ -42,6 +42,7 @@ export const EmbedderIdentifierContext =
|
||||
@@ -33,6 +33,7 @@ export const IsFullscreenContext = new R
|
||||
export const HasWebFileSystemAccess = new RawContextKey<boolean>('hasWebFileSystemAccess', false, true); // Support for FileSystemAccess web APIs (https://wicg.github.io/file-system-access)
|
||||
|
||||
export const IsEnabledFileDownloads = new RawContextKey<boolean>('isEnabledFileDownloads', true, true);
|
||||
export const IsEnabledFileUploads = new RawContextKey<boolean>('isEnabledFileUploads', true, true);
|
||||
+export const IsEnabledCoderGettingStarted = new RawContextKey<boolean>('isEnabledCoderGettingStarted', true, true);
|
||||
|
||||
//#endregion
|
||||
|
||||
106
patches/github-auth.diff
Normal file
106
patches/github-auth.diff
Normal file
@@ -0,0 +1,106 @@
|
||||
Add the ability to provide a GitHub token
|
||||
|
||||
To test install the GitHub PR extension and start code-server with GITHUB_TOKEN
|
||||
or set github-auth in the config file. The extension should be authenticated.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/credentials/node/credentialsMainService.ts
|
||||
@@ -5,9 +5,18 @@
|
||||
|
||||
import { InMemoryCredentialsProvider } from 'vs/platform/credentials/common/credentials';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
-import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
+import { IServerEnvironmentService } from 'vs/server/node/serverEnvironmentService';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { BaseCredentialsMainService, KeytarModule } from 'vs/platform/credentials/common/credentialsMainService';
|
||||
+import { generateUuid } from 'vs/base/common/uuid';
|
||||
+import { equals as arrayEquals } from 'vs/base/common/arrays';
|
||||
+
|
||||
+interface IToken {
|
||||
+ accessToken: string
|
||||
+ account?: { label: string }
|
||||
+ id: string
|
||||
+ scopes: string[]
|
||||
+}
|
||||
|
||||
export class CredentialsWebMainService extends BaseCredentialsMainService {
|
||||
// Since we fallback to the in-memory credentials provider, we do not need to surface any Keytar load errors
|
||||
@@ -16,10 +25,15 @@ export class CredentialsWebMainService e
|
||||
|
||||
constructor(
|
||||
@ILogService logService: ILogService,
|
||||
- @INativeEnvironmentService private readonly environmentMainService: INativeEnvironmentService,
|
||||
+ @IServerEnvironmentService private readonly environmentMainService: IServerEnvironmentService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
) {
|
||||
super(logService);
|
||||
+ if (this.environmentMainService.args["github-auth"]) {
|
||||
+ this.storeGitHubToken(this.environmentMainService.args["github-auth"]).catch((error) => {
|
||||
+ this.logService.error('Failed to store provided GitHub token', error)
|
||||
+ })
|
||||
+ }
|
||||
}
|
||||
|
||||
// If the credentials service is running on the server, we add a suffix -server to differentiate from the location that the
|
||||
@@ -48,4 +62,59 @@ export class CredentialsWebMainService e
|
||||
}
|
||||
return this._keytarCache;
|
||||
}
|
||||
+
|
||||
+ private async storeGitHubToken(githubToken: string): Promise<void> {
|
||||
+ const extensionId = 'vscode.github-authentication';
|
||||
+ const service = `${await this.getSecretStoragePrefix()}${extensionId}`;
|
||||
+ const account = 'github.auth';
|
||||
+ const scopes = [['read:user', 'user:email', 'repo']]
|
||||
+
|
||||
+ // Oddly the scopes need to match exactly so we cannot just have one token
|
||||
+ // with all the scopes, instead we have to duplicate the token for each
|
||||
+ // expected set of scopes.
|
||||
+ const tokens: IToken[] = scopes.map((scopes) => ({
|
||||
+ id: generateUuid(),
|
||||
+ scopes: scopes.sort(), // Sort for comparing later.
|
||||
+ accessToken: githubToken,
|
||||
+ }));
|
||||
+
|
||||
+ const raw = await this.getPassword(service, account)
|
||||
+
|
||||
+ let existing: {
|
||||
+ content: IToken[]
|
||||
+ } | undefined;
|
||||
+
|
||||
+ if (raw) {
|
||||
+ try {
|
||||
+ const json = JSON.parse(raw);
|
||||
+ json.content = JSON.parse(json.content);
|
||||
+ existing = json;
|
||||
+ } catch (error) {
|
||||
+ this.logService.error('Failed to parse existing GitHub credentials', error)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Keep tokens for account and scope combinations we do not have in case
|
||||
+ // there is an extension that uses scopes we have not accounted for (in
|
||||
+ // these cases the user will need to manually authenticate the extension
|
||||
+ // through the UI) or the user has tokens for other accounts.
|
||||
+ if (existing?.content) {
|
||||
+ existing.content = existing.content.filter((existingToken) => {
|
||||
+ const scopes = existingToken.scopes.sort();
|
||||
+ return !(tokens.find((token) => {
|
||||
+ return arrayEquals(scopes, token.scopes)
|
||||
+ && token.account?.label === existingToken.account?.label;
|
||||
+ }))
|
||||
+ })
|
||||
+ }
|
||||
+
|
||||
+ return this.setPassword(service, account, JSON.stringify({
|
||||
+ extensionId,
|
||||
+ ...(existing || {}),
|
||||
+ content: JSON.stringify([
|
||||
+ ...tokens,
|
||||
+ ...(existing?.content || []),
|
||||
+ ])
|
||||
+ }));
|
||||
+ }
|
||||
}
|
||||
@@ -38,7 +38,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
-const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
|
||||
-const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
|
||||
-args['user-data-dir'] = USER_DATA_PATH;
|
||||
-const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath);
|
||||
-const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
|
||||
-const BUILTIN_EXTENSIONS_FOLDER_PATH = join(APP_ROOT, 'extensions');
|
||||
-args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
|
||||
-args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
|
||||
@@ -58,7 +58,7 @@ Index: code-server/lib/vscode/src/vs/server/node/server.main.ts
|
||||
+ const LOCAL_HISTORY_HOME = join(APP_SETTINGS_HOME, 'History');
|
||||
+ const MACHINE_SETTINGS_HOME = join(USER_DATA_PATH, 'Machine');
|
||||
+ args['user-data-dir'] = USER_DATA_PATH;
|
||||
+ const APP_ROOT = dirname(FileAccess.asFileUri('').fsPath);
|
||||
+ const APP_ROOT = dirname(FileAccess.asFileUri('', require).fsPath);
|
||||
+ const BUILTIN_EXTENSIONS_FOLDER_PATH = args['builtin-extensions-dir'] || join(APP_ROOT, 'extensions');
|
||||
+ args['builtin-extensions-dir'] = BUILTIN_EXTENSIONS_FOLDER_PATH;
|
||||
+ args['extensions-dir'] = args['extensions-dir'] || join(REMOTE_DATA_FOLDER, 'extensions');
|
||||
@@ -95,7 +95,7 @@ Index: code-server/lib/vscode/src/vs/base/common/processes.ts
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/processes.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/processes.ts
|
||||
@@ -111,6 +111,8 @@ export function sanitizeProcessEnvironme
|
||||
/^VSCODE_(?!(PORTABLE|SHELL_LOGIN|ENV_REPLACE|ENV_APPEND|ENV_PREPEND)).+$/,
|
||||
/^VSCODE_(?!SHELL_LOGIN).+$/,
|
||||
/^SNAP(|_.*)$/,
|
||||
/^GDK_PIXBUF_.+$/,
|
||||
+ /^CODE_SERVER_.+$/,
|
||||
@@ -107,7 +107,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandl
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/parts/dialogs/dialogHandler.ts
|
||||
@@ -77,8 +77,11 @@ export class BrowserDialogHandler extend
|
||||
@@ -143,8 +143,11 @@ export class BrowserDialogHandler implem
|
||||
|
||||
async about(): Promise<void> {
|
||||
const detailString = (useAgo: boolean): string => {
|
||||
@@ -176,15 +176,15 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
@@ -64,6 +64,7 @@ import { IOpenerService } from 'vs/platf
|
||||
import { mixin, safeStringify } from 'vs/base/common/objects';
|
||||
import { IndexedDB } from 'vs/base/browser/indexedDB';
|
||||
@@ -69,6 +69,7 @@ import { IndexedDB } from 'vs/base/brows
|
||||
import { BrowserCredentialsService } from 'vs/workbench/services/credentials/browser/credentialsService';
|
||||
import { IWorkspace } from 'vs/workbench/services/host/browser/browserHostService';
|
||||
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
|
||||
+import { CodeServerClient } from 'vs/workbench/browser/client';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IProgressService } from 'vs/platform/progress/common/progress';
|
||||
import { DelayedLogChannel } from 'vs/workbench/services/output/common/delayedLogChannel';
|
||||
@@ -131,6 +132,9 @@ export class BrowserMain extends Disposa
|
||||
@@ -116,6 +117,9 @@ export class BrowserMain extends Disposa
|
||||
// Startup
|
||||
const instantiationService = workbench.startup();
|
||||
|
||||
@@ -198,7 +198,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -55,6 +55,8 @@ export type ExtensionVirtualWorkspaceSup
|
||||
@@ -31,6 +31,8 @@ export type ExtensionVirtualWorkspaceSup
|
||||
};
|
||||
|
||||
export interface IProductConfiguration {
|
||||
@@ -264,11 +264,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -307,6 +307,7 @@ export class WebClientServer {
|
||||
} : undefined;
|
||||
|
||||
const productConfiguration = {
|
||||
+ codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||
...this._productService.extensionsGallery,
|
||||
@@ -308,6 +308,7 @@ export class WebClientServer {
|
||||
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
|
||||
workspaceUri: resolveWorkspaceURI(this._environmentService.args['default-workspace']),
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
+ codeServerVersion: this._productService.codeServerVersion,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
...this._productService.extensionsGallery,
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
This can be removed after upgrading to Node >= 19 as keepAlive is defaulted to
|
||||
true after 19.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/request/node/proxy.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/request/node/proxy.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/request/node/proxy.ts
|
||||
@@ -42,6 +42,7 @@ export async function getProxyAgent(rawR
|
||||
port: (proxyEndpoint.port ? +proxyEndpoint.port : 0) || (proxyEndpoint.protocol === 'https' ? 443 : 80),
|
||||
auth: proxyEndpoint.auth,
|
||||
rejectUnauthorized: isBoolean(options.strictSSL) ? options.strictSSL : true,
|
||||
+ keepAlive: true,
|
||||
};
|
||||
|
||||
return requestURL.protocol === 'http:'
|
||||
@@ -1,26 +1,28 @@
|
||||
Make storage local to the remote server
|
||||
|
||||
This makes user settings will be stored in the file system instead of in browser
|
||||
storage. Using browser storage makes sharing or seeding settings between
|
||||
browsers difficult and remote settings is not a sufficient replacement because
|
||||
some settings are only allowed to be set on the user level.
|
||||
This solves two problems:
|
||||
1. Extensions running in the browser (like Vim) might use these paths
|
||||
directly instead of using the file service and most likely can't write
|
||||
to `/User` on disk.
|
||||
2. Settings will be stored in the file system instead of in browser
|
||||
storage. Using browser storage makes sharing or seeding settings
|
||||
between browsers difficult. We may want to revisit this once/if we get
|
||||
settings sync.
|
||||
|
||||
Unfortunately this does not affect state which uses a separate method with
|
||||
IndexedDB and does not appear nearly as easy to redirect to disk.
|
||||
|
||||
To test change settings from the UI and on disk while making sure they appear on
|
||||
the other side.
|
||||
|
||||
This patch also resolves a bug where a global value for workspace initialization
|
||||
is used in a non async-safe way.
|
||||
To test install the Vim extension and make sure something that uses file storage
|
||||
works (history recall for example) and change settings from the UI and on disk
|
||||
while making sure they appear on the other side.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -329,6 +329,7 @@ export class WebClientServer {
|
||||
@@ -303,6 +303,7 @@ export class WebClientServer {
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
serverBasePath: this._basePath,
|
||||
webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
+ userDataPath: this._environmentService.userDataPath,
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
@@ -30,7 +32,7 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
@@ -298,6 +298,11 @@ export interface IWorkbenchConstructionO
|
||||
@@ -266,6 +266,11 @@ export interface IWorkbenchConstructionO
|
||||
*/
|
||||
readonly configurationDefaults?: Record<string, any>;
|
||||
|
||||
@@ -41,13 +43,13 @@ Index: code-server/lib/vscode/src/vs/workbench/browser/web.api.ts
|
||||
+
|
||||
//#endregion
|
||||
|
||||
//#region Profile options
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -102,7 +102,14 @@ export class BrowserWorkbenchEnvironment
|
||||
get logFile(): URI { return joinPath(this.windowLogsPath, 'window.log'); }
|
||||
@@ -53,7 +53,14 @@ export class BrowserWorkbenchEnvironment
|
||||
get logFile(): URI { return joinPath(this.logsHome, 'window.log'); }
|
||||
|
||||
@memoize
|
||||
- get userRoamingDataHome(): URI { return URI.file('/User').with({ scheme: Schemas.vscodeUserData }); }
|
||||
@@ -62,33 +64,3 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
|
||||
@memoize
|
||||
get argvResource(): URI { return joinPath(this.userRoamingDataHome, 'argv.json'); }
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/configuration/browser/configurationService.ts
|
||||
@@ -145,8 +145,10 @@ export class WorkspaceService extends Di
|
||||
this.workspaceConfiguration = this._register(new WorkspaceConfiguration(configurationCache, fileService, uriIdentityService, logService));
|
||||
this._register(this.workspaceConfiguration.onDidUpdateConfiguration(fromCache => {
|
||||
this.onWorkspaceConfigurationChanged(fromCache).then(() => {
|
||||
- this.workspace.initialized = this.workspaceConfiguration.initialized;
|
||||
- this.checkAndMarkWorkspaceComplete(fromCache);
|
||||
+ if (this.workspace) { // The workspace may not have been created yet.
|
||||
+ this.workspace.initialized = this.workspaceConfiguration.initialized;
|
||||
+ this.checkAndMarkWorkspaceComplete(fromCache);
|
||||
+ }
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -552,6 +554,12 @@ export class WorkspaceService extends Di
|
||||
previousFolders = this.workspace.folders;
|
||||
this.workspace.update(workspace);
|
||||
} else {
|
||||
+ // It is possible for the configuration to become initialized in between
|
||||
+ // when the workspace was created and this function was called, so check
|
||||
+ // the configuration again now.
|
||||
+ if (!workspace.initialized && this.workspaceConfiguration.initialized) {
|
||||
+ workspace.initialized = true;
|
||||
+ }
|
||||
this.workspace = workspace;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -58,6 +58,7 @@ export interface IProductConfiguration {
|
||||
@@ -34,6 +34,7 @@ export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
readonly rootEndpoint?: string
|
||||
readonly updateEndpoint?: string
|
||||
@@ -20,19 +20,19 @@ Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -15,6 +15,7 @@ import { URI } from 'vs/base/common/uri'
|
||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||
@@ -13,6 +13,7 @@ import { IEnvironmentService, INativeEnv
|
||||
export const serverOptions: OptionDescriptions<ServerParsedArgs> = {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check': { type: 'boolean' },
|
||||
+ 'auth': { type: 'string' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -97,6 +98,7 @@ export const serverOptions: OptionDescri
|
||||
@@ -92,6 +93,7 @@ export const serverOptions: OptionDescri
|
||||
export interface ServerParsedArgs {
|
||||
/* ----- code-server ----- */
|
||||
'disable-update-check'?: boolean;
|
||||
+ 'auth'?: string;
|
||||
+ 'auth'?: string
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -40,14 +40,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -312,6 +312,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
} satisfies Partial<IProductConfiguration>;
|
||||
@@ -313,6 +313,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
+ logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/client.ts
|
||||
|
||||
@@ -12,14 +12,14 @@ in-between and has web extensions install directly from the marketplace.
|
||||
|
||||
This can be tested by setting EXTENSIONS_GALLERY set to:
|
||||
|
||||
'{"serviceUrl": "https://my-extensions/api"}'
|
||||
'{"serviceUrl": "https://extensions.coder.com/api"}'
|
||||
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
@@ -47,6 +47,16 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||
@@ -53,6 +53,16 @@ else if (typeof require?.__$__nodeRequir
|
||||
version: pkg.version
|
||||
});
|
||||
}
|
||||
@@ -40,8 +40,8 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -114,7 +114,7 @@ export class WebClientServer {
|
||||
|
||||
@@ -111,7 +111,7 @@ export class WebClientServer {
|
||||
const serverRootPath = getRemoteServerRootPath(_productService);
|
||||
this._staticRoute = `${serverRootPath}/static`;
|
||||
this._callbackRoute = `${serverRootPath}/callback`;
|
||||
- this._webExtensionRoute = `${serverRootPath}/web-extension-resource`;
|
||||
@@ -50,50 +50,39 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
|
||||
/**
|
||||
@@ -312,14 +312,7 @@ export class WebClientServer {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
- extensionsGallery: this._webExtensionResourceUrlTemplate && this._productService.extensionsGallery ? {
|
||||
- ...this._productService.extensionsGallery,
|
||||
- resourceUrlTemplate: this._webExtensionResourceUrlTemplate.with({
|
||||
- scheme: 'http',
|
||||
- authority: remoteAuthority,
|
||||
- path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
||||
- }).toString(true)
|
||||
- } : undefined
|
||||
+ extensionsGallery: this._productService.extensionsGallery,
|
||||
} satisfies Partial<IProductConfiguration>;
|
||||
|
||||
if (!this._environmentService.isBuilt) {
|
||||
Index: code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
embedderIdentifier: 'server-distro',
|
||||
- extensionsGallery: this._webExtensionResourceUrlTemplate ? {
|
||||
- ...this._productService.extensionsGallery,
|
||||
- 'resourceUrlTemplate': this._webExtensionResourceUrlTemplate.with({
|
||||
- scheme: 'http',
|
||||
- authority: remoteAuthority,
|
||||
- path: `${this._webExtensionRoute}/${this._webExtensionResourceUrlTemplate.authority}${this._webExtensionResourceUrlTemplate.path}`
|
||||
- }).toString(true)
|
||||
- } : undefined
|
||||
+ extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
callbackRoute: this._callbackRoute
|
||||
};
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
@@ -140,9 +140,9 @@ export abstract class AbstractExtensionR
|
||||
}
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader.ts
|
||||
@@ -16,7 +16,6 @@ import { getServiceMachineId } from 'vs/
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { getTelemetryLevel, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
-import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
protected _isWebExtensionResourceEndPoint(uri: URI): boolean {
|
||||
- const uriPath = uri.path, serverRootPath = RemoteAuthorities.getServerRootPath();
|
||||
- // test if the path starts with the server root path followed by the web extension resource end point segment
|
||||
- return uriPath.startsWith(serverRootPath) && uriPath.startsWith(WEB_EXTENSION_RESOURCE_END_POINT_SEGMENT, serverRootPath.length);
|
||||
+ const uriPath = uri.path;
|
||||
+ // test if the path starts with the web extension resource end point segment
|
||||
+ return uriPath.startsWith(WEB_EXTENSION_RESOURCE_END_POINT_SEGMENT);
|
||||
}
|
||||
|
||||
}
|
||||
Index: code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/extensionManagement/node/extensionDownloader.ts
|
||||
@@ -114,7 +114,10 @@ export class ExtensionsDownloader extend
|
||||
return false;
|
||||
}
|
||||
|
||||
+ return false
|
||||
+ // @ts-expect-error
|
||||
const value = this.configurationService.getValue('extensions.verifySignature');
|
||||
+ // @ts-expect-error
|
||||
return isBoolean(value) ? value : true;
|
||||
}
|
||||
export const WEB_EXTENSION_RESOURCE_END_POINT = 'web-extension-resource';
|
||||
|
||||
@@ -60,7 +59,7 @@ export abstract class AbstractExtensionR
|
||||
private readonly _environmentService: IEnvironmentService,
|
||||
private readonly _configurationService: IConfigurationService,
|
||||
) {
|
||||
- this._webExtensionResourceEndPoint = `${getRemoteServerRootPath(_productService)}/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
|
||||
+ this._webExtensionResourceEndPoint = `/${WEB_EXTENSION_RESOURCE_END_POINT}/`;
|
||||
if (_productService.extensionsGallery) {
|
||||
this._extensionGalleryResourceUrlTemplate = _productService.extensionsGallery.resourceUrlTemplate;
|
||||
this._extensionGalleryAuthority = this._extensionGalleryResourceUrlTemplate ? this._getExtensionGalleryAuthority(URI.parse(this._extensionGalleryResourceUrlTemplate)) : undefined;
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
Unconditionally enable the proposed API
|
||||
|
||||
To test run an extension that uses the proposed API (i.e.
|
||||
https://github.com/microsoft/vscode-extension-samples/tree/ddae6c0c9ff203b4ed6f6b43bfacdd0834215f83/proposed-api-sample)
|
||||
To test run an extension that uses the proposed API.
|
||||
|
||||
We also override isProposedApiEnabled in case an extension does not declare the
|
||||
APIs it needs correctly (the Jupyter extension had this issue).
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/abstractExtensionService.ts
|
||||
@@ -1462,7 +1462,7 @@ class ProposedApiController {
|
||||
|
||||
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
|
||||
|
||||
- this._envEnablesProposedApiForAll =
|
||||
+ this._envEnablesProposedApiForAll = true ||
|
||||
!_environmentService.isBuilt || // always allow proposed API when running out of sources
|
||||
(_environmentService.isExtensionDevelopment && productService.quality !== 'stable') || // do not allow proposed API against stable builds when developing an extension
|
||||
(this._envEnabledExtensions.size === 0 && Array.isArray(_environmentService.extensionEnabledProposedApi)); // always allow proposed API if --enable-proposed-api is provided without extension ID
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensions.ts
|
||||
@@ -312,10 +312,7 @@ function extensionDescriptionArrayToMap(
|
||||
@@ -359,10 +359,7 @@ function extensionDescriptionArrayToMap(
|
||||
}
|
||||
|
||||
export function isProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): boolean {
|
||||
@@ -22,16 +34,3 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extens
|
||||
}
|
||||
|
||||
export function checkProposedApiEnabled(extension: IExtensionDescription, proposal: ApiProposalName): void {
|
||||
Index: code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/extensions/common/extensionsProposedApi.ts
|
||||
@@ -24,7 +24,7 @@ export class ExtensionsProposedApi {
|
||||
|
||||
this._envEnabledExtensions = new Set((_environmentService.extensionEnabledProposedApi ?? []).map(id => ExtensionIdentifier.toKey(id)));
|
||||
|
||||
- this._envEnablesProposedApiForAll =
|
||||
+ this._envEnablesProposedApiForAll = true ||
|
||||
!_environmentService.isBuilt || // always allow proposed API when running out of sources
|
||||
(_environmentService.isExtensionDevelopment && productService.quality !== 'stable') || // do not allow proposed API against stable builds when developing an extension
|
||||
(this._envEnabledExtensions.size === 0 && Array.isArray(_environmentService.extensionEnabledProposedApi)); // always allow proposed API if --enable-proposed-api is provided without extension ID
|
||||
|
||||
@@ -30,7 +30,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -59,6 +59,7 @@ export interface IProductConfiguration {
|
||||
@@ -35,6 +35,7 @@ export interface IProductConfiguration {
|
||||
readonly rootEndpoint?: string
|
||||
readonly updateEndpoint?: string
|
||||
readonly logoutEndpoint?: string
|
||||
@@ -42,48 +42,70 @@ Index: code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityReso
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/remote/browser/remoteAuthorityResolverService.ts
|
||||
@@ -35,7 +35,7 @@ export class RemoteAuthorityResolverServ
|
||||
connectionToken: Promise<string> | string | undefined,
|
||||
resourceUriProvider: ((uri: URI) => URI) | undefined,
|
||||
serverBasePath: string | undefined,
|
||||
- @IProductService productService: IProductService,
|
||||
+ @IProductService private readonly productService: IProductService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
) {
|
||||
@@ -8,7 +8,7 @@ import { Disposable } from 'vs/base/comm
|
||||
import { RemoteAuthorities } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
-import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
+import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolvedOptions, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { getRemoteServerRootPath, parseAuthorityWithOptionalPort } from 'vs/platform/remote/common/remoteHosts';
|
||||
|
||||
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
|
||||
@@ -23,7 +23,7 @@ export class RemoteAuthorityResolverServ
|
||||
private readonly _connectionToken: Promise<string> | string | undefined;
|
||||
private readonly _connectionTokens: Map<string, string>;
|
||||
|
||||
- constructor(@IProductService productService: IProductService, connectionToken: Promise<string> | string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined) {
|
||||
+ constructor(@IProductService productService: IProductService, connectionToken: Promise<string> | string | undefined, resourceUriProvider: ((uri: URI) => URI) | undefined, private readonly proxyEndpointTemplate?: string) {
|
||||
super();
|
||||
@@ -86,9 +86,14 @@ export class RemoteAuthorityResolverServ
|
||||
this._connectionToken = connectionToken;
|
||||
this._connectionTokens = new Map<string, string>();
|
||||
@@ -61,9 +61,14 @@ export class RemoteAuthorityResolverServ
|
||||
|
||||
private async _doResolveAuthority(authority: string): Promise<ResolverResult> {
|
||||
const connectionToken = await Promise.resolve(this._connectionTokens.get(authority) || this._connectionToken);
|
||||
performance.mark(`code/didResolveConnectionToken/${authorityPrefix}`);
|
||||
this._logService.info(`Resolved connection token (${authorityPrefix}) after ${sw.elapsed()} ms`);
|
||||
+ let options: ResolvedOptions | undefined;
|
||||
+ if (this.productService.proxyEndpointTemplate) {
|
||||
+ const proxyUrl = new URL(this.productService.proxyEndpointTemplate, mainWindow.location.href);
|
||||
+ if (this.proxyEndpointTemplate) {
|
||||
+ const proxyUrl = new URL(this.proxyEndpointTemplate, window.location.href);
|
||||
+ options = { extensionHostEnv: { VSCODE_PROXY_URI: decodeURIComponent(proxyUrl.toString()) }}
|
||||
+ }
|
||||
const defaultPort = (/^https:/.test(mainWindow.location.href) ? 443 : 80);
|
||||
const defaultPort = (/^https:/.test(window.location.href) ? 443 : 80);
|
||||
const { host, port } = parseAuthorityWithOptionalPort(authority, defaultPort);
|
||||
- const result: ResolverResult = { authority: { authority, connectTo: new WebSocketRemoteConnection(host, port), connectionToken } };
|
||||
+ const result: ResolverResult = { authority: { authority, connectTo: new WebSocketRemoteConnection(host, port), connectionToken }, options };
|
||||
RemoteAuthorities.set(authority, host, port);
|
||||
- const result: ResolverResult = { authority: { authority, host: host, port: port, connectionToken } };
|
||||
+ const result: ResolverResult = { authority: { authority, host: host, port: port, connectionToken }, options };
|
||||
RemoteAuthorities.set(authority, result.authority.host, result.authority.port);
|
||||
this._cache.set(authority, result);
|
||||
this._onDidChangeConnectionData.fire();
|
||||
Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -313,6 +313,7 @@ export class WebClientServer {
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
} satisfies Partial<IProductConfiguration>;
|
||||
@@ -314,6 +314,7 @@ export class WebClientServer {
|
||||
rootEndpoint: base,
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
+ proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
Index: code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/browser/web.main.ts
|
||||
@@ -247,7 +247,7 @@ export class BrowserMain extends Disposa
|
||||
|
||||
// Remote
|
||||
const connectionToken = environmentService.options.connectionToken || getCookieValue(connectionTokenCookieName);
|
||||
- const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider);
|
||||
+ const remoteAuthorityResolverService = new RemoteAuthorityResolverService(productService, connectionToken, this.configuration.resourceUriProvider, this.configuration.productConfiguration?.proxyEndpointTemplate);
|
||||
serviceCollection.set(IRemoteAuthorityResolverService, remoteAuthorityResolverService);
|
||||
|
||||
// Signing
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts
|
||||
@@ -291,7 +291,7 @@ export async function createTerminalEnvi
|
||||
@@ -392,7 +392,7 @@ export async function createTerminalEnvi
|
||||
|
||||
// Sanitize the environment, removing any undesirable VS Code and Electron environment
|
||||
// variables
|
||||
@@ -96,32 +118,33 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+++ code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
@@ -19,6 +19,7 @@ import { ISecretStorageProvider } from '
|
||||
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/window/common/window';
|
||||
import type { IWorkbenchConstructionOptions, IWorkspace, IWorkspaceProvider } from 'vs/workbench/browser/web.api';
|
||||
import { AuthenticationSessionInfo } from 'vs/workbench/services/authentication/browser/authenticationService';
|
||||
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
|
||||
@@ -21,6 +21,7 @@ import type { ICredentialsProvider } fro
|
||||
import type { IURLCallbackProvider } from 'vs/workbench/services/url/browser/urlService';
|
||||
import { create } from 'vs/workbench/workbench.web.main';
|
||||
import type { IWorkbenchConstructionOptions } from 'vs/workbench/browser/web.api';
|
||||
import type { IWorkspace, IWorkspaceProvider } from 'vs/workbench/services/host/browser/browserHostService';
|
||||
+import { extractLocalHostUriMetaDataForPortMapping, TunnelOptions, TunnelCreationOptions } from 'vs/platform/tunnel/common/tunnel';
|
||||
|
||||
@@ -571,6 +572,39 @@ class WorkspaceProvider implements IWork
|
||||
settingsSyncOptions: config.settingsSyncOptions ? { enabled: config.settingsSyncOptions.enabled, } : undefined,
|
||||
interface ICredential {
|
||||
service: string;
|
||||
@@ -511,6 +512,38 @@ function doCreateUri(path: string, query
|
||||
} : undefined,
|
||||
workspaceProvider: WorkspaceProvider.create(config),
|
||||
urlCallbackProvider: new LocalStorageURLCallbackProvider(config.callbackRoute),
|
||||
- credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider() // with a remote, we don't use a local credentials provider
|
||||
+ credentialsProvider: config.remoteAuthority ? undefined : new LocalStorageCredentialsProvider(), // with a remote, we don't use a local credentials provider
|
||||
+ resolveExternalUri: (uri: URI): Promise<URI> => {
|
||||
+ let resolvedUri = uri
|
||||
+ const localhostMatch = extractLocalHostUriMetaDataForPortMapping(resolvedUri)
|
||||
+
|
||||
+ if (localhostMatch && resolvedUri.authority !== location.host) {
|
||||
+ if (config.productConfiguration && config.productConfiguration.proxyEndpointTemplate) {
|
||||
+ const renderedTemplate = config.productConfiguration.proxyEndpointTemplate
|
||||
+ .replace('{{port}}', localhostMatch.port.toString())
|
||||
+ .replace('{{host}}', window.location.host)
|
||||
+ resolvedUri = URI.parse(new URL(renderedTemplate, window.location.href).toString())
|
||||
+ resolvedUri = URI.parse(new URL(config.productConfiguration.proxyEndpointTemplate.replace('{{port}}', localhostMatch.port.toString()), window.location.href).toString())
|
||||
+ } else {
|
||||
+ throw new Error(`Failed to resolve external URI: ${uri.toString()}. Could not determine base url because productConfiguration missing.`)
|
||||
+ }
|
||||
+ }
|
||||
+ // If not localhost, return unmodified.
|
||||
+
|
||||
+ // If not localhost, return unmodified
|
||||
+ return Promise.resolve(resolvedUri)
|
||||
+ },
|
||||
+ tunnelProvider: {
|
||||
@@ -140,20 +163,19 @@ Index: code-server/lib/vscode/src/vs/code/browser/workbench/workbench.ts
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+ },
|
||||
secretStorageProvider: config.remoteAuthority && !secretStorageKeyPath
|
||||
? undefined /* with a remote without embedder-preferred storage, store on the remote */
|
||||
: new LocalStorageSecretStorageProvider(secretStorageCrypto),
|
||||
+ }
|
||||
});
|
||||
})();
|
||||
Index: code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/remote/browser/remoteExplorer.ts
|
||||
@@ -77,7 +77,7 @@ export class ForwardedPortsView extends
|
||||
private async enableForwardedPortsView() {
|
||||
this.contextKeyListener.clear();
|
||||
@@ -73,7 +73,7 @@ export class ForwardedPortsView extends
|
||||
this.contextKeyListener = undefined;
|
||||
}
|
||||
|
||||
- const viewEnabled: boolean = !!forwardedPortsViewEnabled.getValue(this.contextKeyService);
|
||||
+ const viewEnabled: boolean = true;
|
||||
|
||||
if (viewEnabled) {
|
||||
if (this.environmentService.remoteAuthority && viewEnabled) {
|
||||
const viewContainer = await this.getViewContainer();
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
Revert back to es2020
|
||||
|
||||
es2022 outputs static blocks when using static properties that are not
|
||||
compatible with Safari, or at least not older versions of Safari.
|
||||
|
||||
Index: code-server/lib/vscode/src/tsconfig.base.json
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/tsconfig.base.json
|
||||
+++ code-server/lib/vscode/src/tsconfig.base.json
|
||||
@@ -17,9 +17,30 @@
|
||||
"./vs/*"
|
||||
]
|
||||
},
|
||||
- "target": "es2022",
|
||||
- "useDefineForClassFields": false,
|
||||
+ "target": "es2020",
|
||||
"lib": [
|
||||
+ "ES2016",
|
||||
+ "ES2017.Object",
|
||||
+ "ES2017.String",
|
||||
+ "ES2017.Intl",
|
||||
+ "ES2017.TypedArrays",
|
||||
+ "ES2018.AsyncIterable",
|
||||
+ "ES2018.AsyncGenerator",
|
||||
+ "ES2018.Promise",
|
||||
+ "ES2018.Regexp",
|
||||
+ "ES2018.Intl",
|
||||
+ "ES2019.Array",
|
||||
+ "ES2019.Object",
|
||||
+ "ES2019.String",
|
||||
+ "ES2019.Symbol",
|
||||
+ "ES2020.BigInt",
|
||||
+ "ES2020.Promise",
|
||||
+ "ES2020.String",
|
||||
+ "ES2020.Symbol.WellKnown",
|
||||
+ "ES2020.Intl",
|
||||
+ "ES2021.Promise",
|
||||
+ "ES2021.String",
|
||||
+ "ES2021.WeakRef",
|
||||
"ES2022",
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
Index: code-server/lib/vscode/build/lib/tsb/transpiler.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/tsb/transpiler.js
|
||||
+++ code-server/lib/vscode/build/lib/tsb/transpiler.js
|
||||
@@ -293,7 +293,7 @@ class SwcTranspiler {
|
||||
tsx: false,
|
||||
decorators: true
|
||||
},
|
||||
- target: 'es2022',
|
||||
+ target: 'es2020',
|
||||
loose: false,
|
||||
minify: {
|
||||
compress: false,
|
||||
Index: code-server/lib/vscode/build/lib/tsb/transpiler.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/lib/tsb/transpiler.ts
|
||||
+++ code-server/lib/vscode/build/lib/tsb/transpiler.ts
|
||||
@@ -376,7 +376,7 @@ export class SwcTranspiler implements IT
|
||||
tsx: false,
|
||||
decorators: true
|
||||
},
|
||||
- target: 'es2022',
|
||||
+ target: 'es2020',
|
||||
loose: false,
|
||||
minify: {
|
||||
compress: false,
|
||||
@@ -9,15 +9,14 @@ update-check.diff
|
||||
logout.diff
|
||||
store-socket.diff
|
||||
proxy-uri.diff
|
||||
github-auth.diff
|
||||
unique-db.diff
|
||||
local-storage.diff
|
||||
service-worker.diff
|
||||
sourcemaps.diff
|
||||
external-file-actions.diff
|
||||
disable-downloads.diff
|
||||
telemetry.diff
|
||||
display-language.diff
|
||||
cli-window-open.diff
|
||||
exec-argv.diff
|
||||
getting-started.diff
|
||||
safari.diff
|
||||
keepalive.diff
|
||||
clipboard.diff
|
||||
|
||||
@@ -6,7 +6,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -60,6 +60,10 @@ export interface IProductConfiguration {
|
||||
@@ -36,6 +36,10 @@ export interface IProductConfiguration {
|
||||
readonly updateEndpoint?: string
|
||||
readonly logoutEndpoint?: string
|
||||
readonly proxyEndpointTemplate?: string
|
||||
@@ -54,14 +54,14 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -314,6 +314,10 @@ export class WebClientServer {
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||
+ serviceWorker: {
|
||||
+ scope: vscodeBase + '/',
|
||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
||||
+ },
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
} satisfies Partial<IProductConfiguration>;
|
||||
@@ -316,6 +316,10 @@ export class WebClientServer {
|
||||
updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
logoutEndpoint: this._environmentService.args['auth'] && this._environmentService.args['auth'] !== "none" ? base + '/logout' : undefined,
|
||||
proxyEndpointTemplate: process.env.VSCODE_PROXY_URI ?? base + '/proxy/{{port}}/',
|
||||
+ serviceWorker: {
|
||||
+ scope: vscodeBase + '/',
|
||||
+ path: base + '/_static/out/browser/serviceWorker.js',
|
||||
+ },
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/build/gulpfile.reh.js
|
||||
+++ code-server/lib/vscode/build/gulpfile.reh.js
|
||||
@@ -236,8 +236,7 @@ function packageTask(type, platform, arc
|
||||
@@ -191,8 +191,7 @@ function packageTask(type, platform, arc
|
||||
|
||||
const src = gulp.src(sourceFolderName + '/**', { base: '.' })
|
||||
.pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); }))
|
||||
@@ -20,7 +20,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
|
||||
const workspaceExtensionPoints = ['debuggers', 'jsonValidation'];
|
||||
const isUIExtension = (manifest) => {
|
||||
@@ -276,9 +275,9 @@ function packageTask(type, platform, arc
|
||||
@@ -231,9 +230,9 @@ function packageTask(type, platform, arc
|
||||
.map(name => `.build/extensions/${name}/**`);
|
||||
|
||||
const extensions = gulp.src(extensionPaths, { base: '.build', dot: true });
|
||||
@@ -32,7 +32,7 @@ Index: code-server/lib/vscode/build/gulpfile.reh.js
|
||||
|
||||
let version = packageJson.version;
|
||||
const quality = product.quality;
|
||||
@@ -439,7 +438,7 @@ function tweakProductForServerWeb(produc
|
||||
@@ -387,7 +386,7 @@ function tweakProductForServerWeb(produc
|
||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
||||
optimizeTask,
|
||||
util.rimraf(`out-vscode-${type}-min`),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Store the IPC socket with workspace metadata.
|
||||
Store a static reference to the IPC socket
|
||||
|
||||
This lets us use it to open files inside code-server from outside of
|
||||
code-server.
|
||||
@@ -9,121 +9,29 @@ To test this:
|
||||
|
||||
It should open in your existing code-server instance.
|
||||
|
||||
When the extension host is terminated, the socket is unregistered.
|
||||
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extHostExtensionService.ts
|
||||
@@ -2,7 +2,7 @@
|
||||
@@ -2,7 +2,9 @@
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
-
|
||||
+import * as _http from 'http';
|
||||
+import { promises as fs } from 'fs';
|
||||
+import * as os from 'os'
|
||||
+import * as path from 'vs/base/common/path';
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
|
||||
@@ -17,6 +17,7 @@ import { ExtensionRuntime } from 'vs/wor
|
||||
import { CLIServer } from 'vs/workbench/api/node/extHostCLIServer';
|
||||
import { realpathSync } from 'vs/base/node/extpath';
|
||||
import { ExtHostConsoleForwarder } from 'vs/workbench/api/node/extHostConsoleForwarder';
|
||||
+import { IExtHostWorkspace } from '../common/extHostWorkspace';
|
||||
import { ExtHostDiskFileSystemProvider } from 'vs/workbench/api/node/extHostDiskFileSystemProvider';
|
||||
|
||||
class NodeModuleRequireInterceptor extends RequireInterceptor {
|
||||
@@ -83,6 +84,52 @@ export class ExtHostExtensionService ext
|
||||
await interceptor.install();
|
||||
performance.mark('code/extHost/didInitAPI');
|
||||
|
||||
+ (async () => {
|
||||
+ const socketPath = process.env['VSCODE_IPC_HOOK_CLI'];
|
||||
+ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET']
|
||||
+ if (!socketPath || !codeServerSocketPath) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const workspace = this._instaService.invokeFunction((accessor) => {
|
||||
+ const workspaceService = accessor.get(IExtHostWorkspace);
|
||||
+ return workspaceService.workspace;
|
||||
+ });
|
||||
+ const entry = {
|
||||
+ workspace,
|
||||
+ socketPath
|
||||
+ };
|
||||
+ const message = JSON.stringify({entry});
|
||||
+ await new Promise<void>((resolve, reject) => {
|
||||
+ const opts: _http.RequestOptions = {
|
||||
+ path: '/add-session',
|
||||
+ socketPath: codeServerSocketPath,
|
||||
+ method: 'POST',
|
||||
+ headers: {
|
||||
+ 'content-type': 'application/json',
|
||||
+ }
|
||||
+ };
|
||||
+ const req = _http.request(opts, (res) => {
|
||||
+ res.on('error', reject);
|
||||
+ res.on('end', () => {
|
||||
+ try {
|
||||
+ if (res.statusCode === 200) {
|
||||
+ resolve();
|
||||
+ } else {
|
||||
+ reject(new Error('Unexpected status code: ' + res.statusCode));
|
||||
+ }
|
||||
+ } catch (e: unknown) {
|
||||
+ reject(e);
|
||||
+ }
|
||||
+ });
|
||||
+ });
|
||||
+ req.on('error', reject);
|
||||
+ req.write(message);
|
||||
+ req.end();
|
||||
+ });
|
||||
+ })().catch(error => {
|
||||
+ this._logService.error(error);
|
||||
+ });
|
||||
@@ -72,6 +74,10 @@ export class ExtHostExtensionService ext
|
||||
if (this._initData.remote.isRemote && this._initData.remote.authority) {
|
||||
const cliServer = this._instaService.createInstance(CLIServer);
|
||||
process.env['VSCODE_IPC_HOOK_CLI'] = cliServer.ipcHandlePath;
|
||||
+
|
||||
// Do this when extension service exists, but extensions are not being activated yet.
|
||||
const configProvider = await this._extHostConfiguration.getConfigProvider();
|
||||
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._logService, this._mainThreadTelemetryProxy, this._initData);
|
||||
Index: code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/api/node/extensionHostProcess.ts
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
+ fs.writeFile(path.join(os.tmpdir(), 'vscode-ipc'), cliServer.ipcHandlePath).catch((error) => {
|
||||
+ this._logService.error(error);
|
||||
+ });
|
||||
}
|
||||
|
||||
+import * as _http from 'http';
|
||||
import * as nativeWatchdog from 'native-watchdog';
|
||||
import * as net from 'net';
|
||||
import * as minimist from 'minimist';
|
||||
@@ -418,7 +419,28 @@ async function startExtensionHostProcess
|
||||
);
|
||||
|
||||
// rewrite onTerminate-function to be a proper shutdown
|
||||
- onTerminate = (reason: string) => extensionHostMain.terminate(reason);
|
||||
+ onTerminate = (reason: string) => {
|
||||
+ extensionHostMain.terminate(reason);
|
||||
+
|
||||
+ const socketPath = process.env['VSCODE_IPC_HOOK_CLI'];
|
||||
+ const codeServerSocketPath = process.env['CODE_SERVER_SESSION_SOCKET']
|
||||
+ if (!socketPath || !codeServerSocketPath) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const message = JSON.stringify({socketPath});
|
||||
+ const opts: _http.RequestOptions = {
|
||||
+ path: '/delete-session',
|
||||
+ socketPath: codeServerSocketPath,
|
||||
+ method: 'POST',
|
||||
+ headers: {
|
||||
+ 'content-type': 'application/json',
|
||||
+ 'accept': 'application/json'
|
||||
+ }
|
||||
+ };
|
||||
+ const req = _http.request(opts);
|
||||
+ req.write(message);
|
||||
+ req.end();
|
||||
+ };
|
||||
}
|
||||
|
||||
startExtensionHostProcess().catch((err) => console.log(err));
|
||||
// Module loading tricks
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
Add support for telemetry endpoint
|
||||
|
||||
To test:
|
||||
1. Create a mock API using [RequestBin](https://requestbin.io/) or [Beeceptor](https://beeceptor.com/)
|
||||
1. Create a RequestBin - https://requestbin.io/
|
||||
2. Run code-server with `CS_TELEMETRY_URL` set:
|
||||
i.e. `CS_TELEMETRY_URL="https://requestbin.io/1ebub9z1" ./code-server-<version>-macos-amd64/bin/code-server`
|
||||
NOTE: it has to be a production build.
|
||||
3. Load code-server in browser an do things (i.e. open a file)
|
||||
4. Refresh RequestBin and you should see logs
|
||||
|
||||
@@ -12,104 +11,72 @@ Index: code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverServices.ts
|
||||
@@ -65,6 +65,7 @@ import { IExtensionsScannerService } fro
|
||||
@@ -71,6 +71,7 @@ import { IExtensionsScannerService } fro
|
||||
import { ExtensionsScannerService } from 'vs/server/node/extensionsScannerService';
|
||||
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
|
||||
import { IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
+import { TelemetryClient } from 'vs/server/node/telemetryClient';
|
||||
import { ExtensionsProfileScannerService, IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
|
||||
import { IUserDataProfilesService, UserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
+import { TelemetryClient } from "vs/server/node/telemetryClient";
|
||||
import { NullPolicyService } from 'vs/platform/policy/common/policy';
|
||||
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
|
||||
import { LoggerService } from 'vs/platform/log/node/loggerService';
|
||||
@@ -147,11 +148,23 @@ export async function setupServerService
|
||||
const requestService = new RequestService(configurationService, environmentService, logService, loggerService);
|
||||
services.set(IRequestService, requestService);
|
||||
|
||||
+ let isContainer = undefined;
|
||||
+ try {
|
||||
+ await Promises.stat('/run/.containerenv');
|
||||
+ isContainer = true;
|
||||
+ } catch (error) { /* Does not exist, probably. */ }
|
||||
+ if (!isContainer) {
|
||||
+ try {
|
||||
+ const content = await Promises.readFile('/proc/self/cgroup', 'utf8')
|
||||
+ isContainer = content.includes('docker');
|
||||
+ } catch (error) { /* Permission denied, probably. */ }
|
||||
+ }
|
||||
+
|
||||
let oneDsAppender: ITelemetryAppender = NullAppender;
|
||||
@@ -133,10 +134,13 @@ export async function setupServerService
|
||||
const machineId = await getMachineId();
|
||||
const isInternal = isInternalTelemetry(productService, configurationService);
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
- if (!isLoggingOnly(productService, environmentService) && productService.aiConfig?.ariaKey) {
|
||||
- oneDsAppender = new OneDataSystemAppender(requestService, isInternal, eventPrefix, null, productService.aiConfig.ariaKey);
|
||||
+ if (!isLoggingOnly(productService, environmentService) && productService.telemetryEndpoint) {
|
||||
+ oneDsAppender = new OneDataSystemAppender(requestService, isInternal, eventPrefix, null, () => new TelemetryClient(productService.telemetryEndpoint!, machineId, isContainer));
|
||||
disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
- if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
+ const telemetryEndpoint = process.env.CS_TELEMETRY_URL || "https://v1.telemetry.coder.com/track";
|
||||
+ if (telemetryEndpoint) {
|
||||
+ oneDsAppender = new OneDataSystemAppender(false, eventPrefix, null, () => new TelemetryClient(telemetryEndpoint));
|
||||
+ } else if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
oneDsAppender = new OneDataSystemAppender(isInternal, eventPrefix, null, productService.aiConfig.ariaKey);
|
||||
- disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
}
|
||||
+ disposables.add(toDisposable(() => oneDsAppender?.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
|
||||
const config: ITelemetryServiceConfig = {
|
||||
appenders: [oneDsAppender],
|
||||
Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts
|
||||
@@ -0,0 +1,71 @@
|
||||
@@ -0,0 +1,49 @@
|
||||
+import { AppInsightsCore, IExtendedTelemetryItem, ITelemetryItem } from '@microsoft/1ds-core-js';
|
||||
+import * as https from 'https';
|
||||
+import * as http from 'http';
|
||||
+import * as os from 'os';
|
||||
+
|
||||
+interface SystemInfo {
|
||||
+ measurements: Record<string, number | undefined>;
|
||||
+ properties: Record<string, string | boolean | null | undefined>;
|
||||
+}
|
||||
+
|
||||
+export class TelemetryClient extends AppInsightsCore {
|
||||
+ private readonly systemInfo: SystemInfo = {
|
||||
+ measurements: {},
|
||||
+ properties: {},
|
||||
+ };
|
||||
+
|
||||
+ public constructor(
|
||||
+ private readonly endpoint: string,
|
||||
+ machineId: string,
|
||||
+ isContainer: boolean | undefined) {
|
||||
+ public constructor(private readonly endpoint: string) {
|
||||
+ super();
|
||||
+
|
||||
+ // os.cpus() can take a very long time sometimes (personally I see 1-2
|
||||
+ // seconds in a Coder workspace). This adds up significantly, especially
|
||||
+ // when many telemetry requests are sent during startup, which can cause
|
||||
+ // connection timeouts. Try to cache as much as we can.
|
||||
+ try {
|
||||
+ const cpus = os.cpus();
|
||||
+ this.systemInfo.measurements.cores = cpus.length;
|
||||
+ this.systemInfo.properties['common.cpuModel'] = cpus[0].model;
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ this.systemInfo.properties['common.shell'] = os.userInfo().shell;
|
||||
+ this.systemInfo.properties['common.release'] = os.release();
|
||||
+ this.systemInfo.properties['common.arch'] = os.arch();
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ this.systemInfo.properties['common.remoteMachineId'] = machineId;
|
||||
+ this.systemInfo.properties['common.isContainer'] = isContainer;
|
||||
+ }
|
||||
+
|
||||
+ public override track(item: IExtendedTelemetryItem | ITelemetryItem): void {
|
||||
+ const options = item.baseData || {}
|
||||
+ options.measurements = {
|
||||
+ ...(options.measurements || {}),
|
||||
+ ...this.systemInfo.measurements,
|
||||
+ if (!options.properties) {
|
||||
+ options.properties = {};
|
||||
+ }
|
||||
+ options.properties = {
|
||||
+ ...(options.properties || {}),
|
||||
+ ...this.systemInfo.properties,
|
||||
+ if (!options.measurements) {
|
||||
+ options.measurements = {};
|
||||
+ }
|
||||
+
|
||||
+ try {
|
||||
+ const cpus = os.cpus();
|
||||
+ options.measurements.cores = cpus.length;
|
||||
+ options.properties['common.cpuModel'] = cpus[0].model;
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ options.measurements.memoryFree = os.freemem();
|
||||
+ options.measurements.memoryTotal = os.totalmem();
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ options.properties['common.shell'] = os.userInfo().shell;
|
||||
+ options.properties['common.release'] = os.release();
|
||||
+ options.properties['common.arch'] = os.arch();
|
||||
+ } catch (error) {}
|
||||
+
|
||||
+ try {
|
||||
+ const request = (/^http:/.test(this.endpoint) ? http : https).request(this.endpoint, {
|
||||
+ method: 'POST',
|
||||
+ headers: {
|
||||
@@ -126,38 +93,11 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -318,6 +318,8 @@ export class WebClientServer {
|
||||
scope: vscodeBase + '/',
|
||||
path: base + '/_static/out/browser/serviceWorker.js',
|
||||
@@ -321,6 +321,7 @@ export class WebClientServer {
|
||||
scope: vscodeBase + '/',
|
||||
path: base + '/_static/out/browser/serviceWorker.js',
|
||||
},
|
||||
+ enableTelemetry: this._productService.enableTelemetry,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
+ enableTelemetry: this._productService.enableTelemetry,
|
||||
+ telemetryEndpoint: this._productService.telemetryEndpoint,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
} satisfies Partial<IProductConfiguration>;
|
||||
Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -64,6 +64,7 @@ export interface IProductConfiguration {
|
||||
readonly path: string;
|
||||
readonly scope: string;
|
||||
}
|
||||
+ readonly telemetryEndpoint?: string
|
||||
|
||||
readonly version: string;
|
||||
readonly date?: string;
|
||||
Index: code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/platform/product/common/product.ts
|
||||
@@ -55,7 +55,8 @@ else if (globalThis._VSCODE_PRODUCT_JSON
|
||||
resourceUrlTemplate: "https://open-vsx.org/vscode/asset/{publisher}/{name}/{version}/Microsoft.VisualStudio.Code.WebResources/{path}",
|
||||
controlUrl: "",
|
||||
recommendationsUrl: "",
|
||||
- })
|
||||
+ }),
|
||||
+ telemetryEndpoint: env.CS_TELEMETRY_URL || product.telemetryEndpoint || "https://v1.telemetry.coder.com/track",
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageService.ts
|
||||
@@ -18,6 +18,7 @@ import { AbstractStorageService, isProfi
|
||||
@@ -17,6 +17,7 @@ import { AbstractStorageService, isProfi
|
||||
import { isUserDataProfile, IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
|
||||
import { IAnyWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
|
||||
import { IUserDataProfileService } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
|
||||
@@ -21,7 +21,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/storage/browser/storageS
|
||||
|
||||
export class BrowserStorageService extends AbstractStorageService {
|
||||
|
||||
@@ -298,7 +299,11 @@ export class IndexedDBStorageDatabase ex
|
||||
@@ -297,7 +298,11 @@ export class IndexedDBStorageDatabase ex
|
||||
}
|
||||
|
||||
static async createWorkspaceStorage(workspaceId: string, logService: ILogService): Promise<IIndexedDBStorageDatabase> {
|
||||
|
||||
@@ -93,7 +93,7 @@ Index: code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/base/common/product.ts
|
||||
+++ code-server/lib/vscode/src/vs/base/common/product.ts
|
||||
@@ -57,6 +57,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
@@ -33,6 +33,7 @@ export type ExtensionVirtualWorkspaceSup
|
||||
export interface IProductConfiguration {
|
||||
readonly codeServerVersion?: string
|
||||
readonly rootEndpoint?: string
|
||||
@@ -105,28 +105,28 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -311,6 +311,7 @@ export class WebClientServer {
|
||||
const productConfiguration = {
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
} satisfies Partial<IProductConfiguration>;
|
||||
@@ -312,6 +312,7 @@ export class WebClientServer {
|
||||
productConfiguration: <Partial<IProductConfiguration>>{
|
||||
codeServerVersion: this._productService.codeServerVersion,
|
||||
rootEndpoint: base,
|
||||
+ updateEndpoint: !this._environmentService.args['disable-update-check'] ? base + '/update/check' : undefined,
|
||||
embedderIdentifier: 'server-distro',
|
||||
extensionsGallery: this._productService.extensionsGallery,
|
||||
},
|
||||
Index: code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/serverEnvironmentService.ts
|
||||
@@ -13,6 +13,8 @@ import { memoize } from 'vs/base/common/
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -11,6 +11,8 @@ import { refineServiceDecorator } from '
|
||||
import { IEnvironmentService, INativeEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
|
||||
export const serverOptions: OptionDescriptions<ServerParsedArgs> = {
|
||||
+ /* ----- code-server ----- */
|
||||
+ 'disable-update-check': { type: 'boolean' },
|
||||
|
||||
/* ----- server setup ----- */
|
||||
|
||||
@@ -93,6 +95,8 @@ export const serverOptions: OptionDescri
|
||||
@@ -88,6 +90,8 @@ export const serverOptions: OptionDescri
|
||||
};
|
||||
|
||||
export interface ServerParsedArgs {
|
||||
|
||||
@@ -41,7 +41,7 @@ Index: code-server/lib/vscode/src/vs/workbench/services/environment/browser/envi
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
+++ code-server/lib/vscode/src/vs/workbench/services/environment/browser/environmentService.ts
|
||||
@@ -225,7 +225,7 @@ export class BrowserWorkbenchEnvironment
|
||||
@@ -177,7 +177,7 @@ export class BrowserWorkbenchEnvironment
|
||||
|
||||
@memoize
|
||||
get webviewExternalEndpoint(): string {
|
||||
@@ -54,10 +54,10 @@ Index: code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
+++ code-server/lib/vscode/src/vs/server/node/webClientServer.ts
|
||||
@@ -325,6 +325,7 @@ export class WebClientServer {
|
||||
@@ -302,6 +302,7 @@ export class WebClientServer {
|
||||
|
||||
const workbenchWebConfiguration = {
|
||||
remoteAuthority,
|
||||
serverBasePath: this._basePath,
|
||||
+ webviewEndpoint: vscodeBase + this._staticRoute + '/out/vs/workbench/contrib/webview/browser/pre',
|
||||
_wrapWebWorkerExtHostInIframe,
|
||||
developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
|
||||
@@ -70,12 +70,12 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
- content="default-src 'none'; script-src 'sha256-bQPwjO6bLiyf6v9eDVtAI67LrfonA1w49aFkRXBy4/g=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
+ content="default-src 'none'; script-src 'sha256-R3BsSkqy7qFbvWSmwr7WqT1eg6Sq4zSe0uIlrUQ4EKE=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
- content="default-src 'none'; script-src 'sha256-wwaDxsm1+SKIUb5YJXiZlYMyV7QPB8+zd6HPcTjigZs=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
+ content="default-src 'none'; script-src 'sha256-IZkGO4jZeUn7pzM6pBZCZc9bUYm8oVNV3z8zEa8gxlk=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
|
||||
|
||||
<!-- Disable pinch zooming -->
|
||||
<meta name="viewport"
|
||||
@@ -344,6 +344,12 @@
|
||||
@@ -331,6 +331,12 @@
|
||||
|
||||
const hostname = location.hostname;
|
||||
|
||||
@@ -92,7 +92,7 @@ Index: code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index
|
||||
===================================================================
|
||||
--- code-server.orig/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
||||
+++ code-server/lib/vscode/src/vs/workbench/contrib/webview/browser/pre/index-no-csp.html
|
||||
@@ -343,6 +343,12 @@
|
||||
@@ -330,6 +330,12 @@
|
||||
|
||||
const hostname = location.hostname;
|
||||
|
||||
@@ -113,8 +113,8 @@ Index: code-server/lib/vscode/src/vs/workbench/services/extensions/worker/webWor
|
||||
<meta http-equiv="Content-Security-Policy" content="
|
||||
default-src 'none';
|
||||
child-src 'self' data: blob:;
|
||||
- script-src 'self' 'unsafe-eval' 'sha256-75NYUUvf+5++1WbfCZOV3PSWxBhONpaxwx+mkOFRv/Y=' https:;
|
||||
+ script-src 'self' 'unsafe-eval' 'sha256-c7vPrYRaSLDtFSrI4CuHYgBQ3a4c4x2LSm/LefSZADQ=' https:;
|
||||
- script-src 'self' 'unsafe-eval' 'sha256-/r7rqQ+yrxt57sxLuQ6AMYcy/lUpvAIzHjIJt/OeLWU=' https:;
|
||||
+ script-src 'self' 'unsafe-eval' 'sha256-TkIM/TmudlFEe0ZRp0ptvN54LClwk30Rql4ZPE0hm/I=' https:;
|
||||
connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*;"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -6,16 +6,10 @@
|
||||
"matchUpdateTypes": ["minor", "patch", "digest"],
|
||||
"automerge": true,
|
||||
"groupName": "Minor dependency updates"
|
||||
},
|
||||
{
|
||||
"matchDepTypes": ["peerDependencies"],
|
||||
"matchUpdateTypes": ["minor", "patch", "digest"],
|
||||
"automerge": true,
|
||||
"groupName": "Peer dependency updates"
|
||||
}
|
||||
],
|
||||
"vulnerabilityAlerts": {
|
||||
"enabled": "true"
|
||||
},
|
||||
"ignoreDeps": ["express", "ansi-regex", "env-paths", "limiter", "node", "prettier"]
|
||||
"ignoreDeps": ["express"]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
@@ -46,9 +46,7 @@ button {
|
||||
.card-box {
|
||||
background-color: rgb(250, 253, 258);
|
||||
border-radius: 5px;
|
||||
box-shadow:
|
||||
rgba(60, 66, 87, 0.117647) 0px 7px 14px 0px,
|
||||
rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
|
||||
box-shadow: rgba(60, 66, 87, 0.117647) 0px 7px 14px 0px, rgba(0, 0, 0, 0.117647) 0px 3px 6px 0px;
|
||||
max-width: 650px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@@ -10,7 +10,7 @@
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="style-src 'self'; script-src 'self' 'unsafe-inline'; manifest-src 'self'; img-src 'self' data:; font-src 'self' data:;"
|
||||
/>
|
||||
<title>{{I18N_LOGIN_TITLE}}</title>
|
||||
<title>{{APP_NAME}} login</title>
|
||||
<link rel="icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon-dark-support.svg" />
|
||||
<link rel="alternate icon" href="{{CS_STATIC_BASE}}/src/browser/media/favicon.ico" />
|
||||
<link rel="manifest" href="{{BASE}}/manifest.json" crossorigin="use-credentials" />
|
||||
@@ -25,7 +25,7 @@
|
||||
<div class="card-box">
|
||||
<div class="header">
|
||||
<h1 class="main">{{WELCOME_TEXT}}</h1>
|
||||
<div class="sub">{{I18N_LOGIN_BELOW}} {{PASSWORD_MSG}}</div>
|
||||
<div class="sub">Please log in below. {{PASSWORD_MSG}}</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<form class="login-form" method="post">
|
||||
@@ -38,11 +38,11 @@
|
||||
autofocus
|
||||
class="password"
|
||||
type="password"
|
||||
placeholder="{{I18N_PASSWORD_PLACEHOLDER}}"
|
||||
placeholder="PASSWORD"
|
||||
name="password"
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
<input class="submit -button" value="{{I18N_SUBMIT}}" type="submit" />
|
||||
<input class="submit -button" value="SUBMIT" type="submit" />
|
||||
</div>
|
||||
{{ERROR}}
|
||||
</form>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Contact: mailto:security@coder.com
|
||||
Acknowledgments: https://coder.com/security/thanks
|
||||
Preferred-Languages: en-US
|
||||
Canonical: https://coder.com/.well-known/security.txt
|
||||
Policy: https://coder.com/security/policy
|
||||
Hiring: https://coder.com/careers
|
||||
@@ -4,7 +4,6 @@ export enum HttpCode {
|
||||
NotFound = 404,
|
||||
BadRequest = 400,
|
||||
Unauthorized = 401,
|
||||
Forbidden = 403,
|
||||
LargePayload = 413,
|
||||
ServerError = 500,
|
||||
}
|
||||
@@ -14,11 +13,7 @@ export enum HttpCode {
|
||||
* used in the HTTP response.
|
||||
*/
|
||||
export class HttpError extends Error {
|
||||
public constructor(
|
||||
message: string,
|
||||
public readonly statusCode: HttpCode,
|
||||
public readonly details?: object,
|
||||
) {
|
||||
public constructor(message: string, public readonly statusCode: HttpCode, public readonly details?: object) {
|
||||
super(message)
|
||||
this.name = this.constructor.name
|
||||
}
|
||||
|
||||
@@ -9,11 +9,9 @@ import * as util from "../common/util"
|
||||
import { DefaultedArgs } from "./cli"
|
||||
import { disposer } from "./http"
|
||||
import { isNodeJSErrnoException } from "./util"
|
||||
import { EditorSessionManager, makeEditorSessionManagerServer } from "./vscodeSocket"
|
||||
import { handleUpgrade } from "./wsRouter"
|
||||
|
||||
type SocketOptions = { socket: string; "socket-mode"?: string }
|
||||
type ListenOptions = DefaultedArgs | SocketOptions
|
||||
type ListenOptions = Pick<DefaultedArgs, "socket-mode" | "socket" | "port" | "host">
|
||||
|
||||
export interface App extends Disposable {
|
||||
/** Handles regular HTTP requests. */
|
||||
@@ -22,18 +20,12 @@ export interface App extends Disposable {
|
||||
wsRouter: Express
|
||||
/** The underlying HTTP server. */
|
||||
server: http.Server
|
||||
/** Handles requests to the editor session management API. */
|
||||
editorSessionManagerServer: http.Server
|
||||
}
|
||||
|
||||
const isSocketOpts = (opts: ListenOptions): opts is SocketOptions => {
|
||||
return !!(opts as SocketOptions).socket || !(opts as DefaultedArgs).host
|
||||
}
|
||||
|
||||
export const listen = async (server: http.Server, opts: ListenOptions) => {
|
||||
if (isSocketOpts(opts)) {
|
||||
export const listen = async (server: http.Server, { host, port, socket, "socket-mode": mode }: ListenOptions) => {
|
||||
if (socket) {
|
||||
try {
|
||||
await fs.unlink(opts.socket)
|
||||
await fs.unlink(socket)
|
||||
} catch (error: any) {
|
||||
handleArgsSocketCatchError(error)
|
||||
}
|
||||
@@ -46,20 +38,18 @@ export const listen = async (server: http.Server, opts: ListenOptions) => {
|
||||
server.on("error", (err) => util.logError(logger, "http server error", err))
|
||||
resolve()
|
||||
}
|
||||
if (isSocketOpts(opts)) {
|
||||
server.listen(opts.socket, onListen)
|
||||
if (socket) {
|
||||
server.listen(socket, onListen)
|
||||
} else {
|
||||
// [] is the correct format when using :: but Node errors with them.
|
||||
server.listen(opts.port, opts.host.replace(/^\[|\]$/g, ""), onListen)
|
||||
server.listen(port, host.replace(/^\[|\]$/g, ""), onListen)
|
||||
}
|
||||
})
|
||||
|
||||
// NOTE@jsjoeio: we need to chmod after the server is finished
|
||||
// listening. Otherwise, the socket may not have been created yet.
|
||||
if (isSocketOpts(opts)) {
|
||||
if (opts["socket-mode"]) {
|
||||
await fs.chmod(opts.socket, opts["socket-mode"])
|
||||
}
|
||||
if (socket && mode) {
|
||||
await fs.chmod(socket, mode)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,22 +70,14 @@ export const createApp = async (args: DefaultedArgs): Promise<App> => {
|
||||
)
|
||||
: http.createServer(router)
|
||||
|
||||
const disposeServer = disposer(server)
|
||||
const dispose = disposer(server)
|
||||
|
||||
await listen(server, args)
|
||||
|
||||
const wsRouter = express()
|
||||
handleUpgrade(wsRouter, server)
|
||||
|
||||
const editorSessionManager = new EditorSessionManager()
|
||||
const editorSessionManagerServer = await makeEditorSessionManagerServer(args["session-socket"], editorSessionManager)
|
||||
const disposeEditorSessionManagerServer = disposer(editorSessionManagerServer)
|
||||
|
||||
const dispose = async () => {
|
||||
await Promise.all([disposeServer(), disposeEditorSessionManagerServer()])
|
||||
}
|
||||
|
||||
return { router, wsRouter, server, dispose, editorSessionManagerServer }
|
||||
return { router, wsRouter, server, dispose }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
187
src/node/cli.ts
187
src/node/cli.ts
@@ -1,9 +1,11 @@
|
||||
import { field, Level, logger } from "@coder/logger"
|
||||
import { promises as fs } from "fs"
|
||||
import { load } from "js-yaml"
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
import { generateCertificate, generatePassword, paths, splitOnFirstEquals } from "./util"
|
||||
import { EditorSessionManagerClient } from "./vscodeSocket"
|
||||
import { canConnect, generateCertificate, generatePassword, humanPath, paths, isNodeJSErrnoException } from "./util"
|
||||
|
||||
const DEFAULT_SOCKET_PATH = path.join(os.tmpdir(), "vscode-ipc")
|
||||
|
||||
export enum Feature {
|
||||
// No current experimental features!
|
||||
@@ -48,11 +50,8 @@ export interface UserProvidedCodeArgs {
|
||||
"github-auth"?: string
|
||||
"disable-update-check"?: boolean
|
||||
"disable-file-downloads"?: boolean
|
||||
"disable-file-uploads"?: boolean
|
||||
"disable-workspace-trust"?: boolean
|
||||
"disable-getting-started-override"?: boolean
|
||||
"disable-proxy"?: boolean
|
||||
"session-socket"?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,12 +79,12 @@ export interface UserProvidedArgs extends UserProvidedCodeArgs {
|
||||
"bind-addr"?: string
|
||||
socket?: string
|
||||
"socket-mode"?: string
|
||||
"trusted-origins"?: string[]
|
||||
version?: boolean
|
||||
"proxy-domain"?: string[]
|
||||
"reuse-window"?: boolean
|
||||
"new-window"?: boolean
|
||||
"ignore-last-opened"?: boolean
|
||||
link?: OptionalString
|
||||
verbose?: boolean
|
||||
"app-name"?: string
|
||||
"welcome-text"?: string
|
||||
@@ -163,18 +162,11 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
|
||||
"then notifies you once every week that a new release is available.",
|
||||
},
|
||||
"session-socket": {
|
||||
type: "string",
|
||||
},
|
||||
"disable-file-downloads": {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Disable file downloads from Code. This can also be set with CS_DISABLE_FILE_DOWNLOADS set to 'true' or '1'.",
|
||||
},
|
||||
"disable-file-uploads": {
|
||||
type: "boolean",
|
||||
description: "Disable file uploads.",
|
||||
},
|
||||
"disable-workspace-trust": {
|
||||
type: "boolean",
|
||||
description: "Disable Workspace Trust feature. This switch only affects the current session.",
|
||||
@@ -183,23 +175,12 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
type: "boolean",
|
||||
description: "Disable the coder/coder override in the Help: Getting Started page.",
|
||||
},
|
||||
"disable-proxy": {
|
||||
type: "boolean",
|
||||
description: "Disable domain and path proxy routes.",
|
||||
},
|
||||
// --enable can be used to enable experimental features. These features
|
||||
// provide no guarantees.
|
||||
enable: { type: "string[]" },
|
||||
help: { type: "boolean", short: "h", description: "Show this output." },
|
||||
json: { type: "boolean" },
|
||||
locale: {
|
||||
// The preferred way to set the locale is via the UI.
|
||||
type: "string",
|
||||
description: `
|
||||
Set vscode display language and language to show on the login page, more info see
|
||||
https://en.wikipedia.org/wiki/IETF_language_tag
|
||||
`,
|
||||
},
|
||||
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." },
|
||||
|
||||
"bind-addr": {
|
||||
@@ -218,11 +199,6 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
|
||||
socket: { type: "string", path: true, description: "Path to a socket (bind-addr will be ignored)." },
|
||||
"socket-mode": { type: "string", description: "File mode of the socket." },
|
||||
"trusted-origins": {
|
||||
type: "string[]",
|
||||
description:
|
||||
"Disables authenticate origin check for trusted origin. Useful if not able to access reverse proxy configuration.",
|
||||
},
|
||||
version: { type: "boolean", short: "v", description: "Display version information." },
|
||||
_: { type: "string[]" },
|
||||
|
||||
@@ -279,6 +255,15 @@ export const options: Options<Required<UserProvidedArgs>> = {
|
||||
short: "w",
|
||||
description: "Text to show on login page",
|
||||
},
|
||||
link: {
|
||||
type: OptionalString,
|
||||
description: `
|
||||
Securely bind code-server via our cloud service with the passed name. You'll get a URL like
|
||||
https://hostname-username.coder.co at which you can easily access your code-server instance.
|
||||
Authorization is done via GitHub.
|
||||
`,
|
||||
deprecated: true,
|
||||
},
|
||||
}
|
||||
|
||||
export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedArgs>>> = options): string[] => {
|
||||
@@ -310,6 +295,19 @@ export const optionDescriptions = (opts: Partial<Options<Required<UserProvidedAr
|
||||
})
|
||||
}
|
||||
|
||||
export function splitOnFirstEquals(str: string): string[] {
|
||||
// we use regex instead of "=" to ensure we split at the first
|
||||
// "=" and return the following substring with it
|
||||
// important for the hashed-password which looks like this
|
||||
// $argon2i$v=19$m=4096,t=3,p=1$0qR/o+0t00hsbJFQCKSfdQ$oFcM4rL6o+B7oxpuA4qlXubypbBPsf+8L531U7P9HYY
|
||||
// 2 means return two items
|
||||
// Source: https://stackoverflow.com/a/4607799/3015595
|
||||
// We use the ? to say the the substr after the = is optional
|
||||
const split = str.split(/=(.+)?/, 2)
|
||||
|
||||
return split
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse arguments into UserProvidedArgs. This should not go beyond checking
|
||||
* that arguments are valid types and have values when required.
|
||||
@@ -443,23 +441,19 @@ export const parse = (
|
||||
throw new Error("--cert-key is missing")
|
||||
}
|
||||
|
||||
logger.debug(() => [`parsed ${opts?.configFile ? "config" : "command line"}`, field("args", redactArgs(args))])
|
||||
logger.debug(() => [
|
||||
`parsed ${opts?.configFile ? "config" : "command line"}`,
|
||||
field("args", {
|
||||
...args,
|
||||
password: args.password ? "<redacted>" : undefined,
|
||||
"hashed-password": args["hashed-password"] ? "<redacted>" : undefined,
|
||||
"github-auth": args["github-auth"] ? "<redacted>" : undefined,
|
||||
}),
|
||||
])
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
/**
|
||||
* Redact sensitive information from arguments for logging.
|
||||
*/
|
||||
export const redactArgs = (args: UserProvidedArgs): UserProvidedArgs => {
|
||||
return {
|
||||
...args,
|
||||
password: args.password ? "<redacted>" : undefined,
|
||||
"hashed-password": args["hashed-password"] ? "<redacted>" : undefined,
|
||||
"github-auth": args["github-auth"] ? "<redacted>" : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User-provided arguments with defaults. The distinction between user-provided
|
||||
* args and defaulted args exists so we can tell the difference between end
|
||||
@@ -478,7 +472,6 @@ export interface DefaultedArgs extends ConfigArgs {
|
||||
usingEnvHashedPassword: boolean
|
||||
"extensions-dir": string
|
||||
"user-data-dir": string
|
||||
"session-socket": string
|
||||
/* Positional arguments. */
|
||||
_: string[]
|
||||
}
|
||||
@@ -499,11 +492,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args["extensions-dir"] = path.join(args["user-data-dir"], "extensions")
|
||||
}
|
||||
|
||||
if (!args["session-socket"]) {
|
||||
args["session-socket"] = path.join(args["user-data-dir"], "code-server-ipc.sock")
|
||||
}
|
||||
process.env.CODE_SERVER_SESSION_SOCKET = args["session-socket"]
|
||||
|
||||
// --verbose takes priority over --log and --log takes priority over the
|
||||
// environment variable.
|
||||
if (args.verbose) {
|
||||
@@ -552,6 +540,17 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args.host = addr.host
|
||||
args.port = addr.port
|
||||
|
||||
// If we're being exposed to the cloud, we listen on a random address and
|
||||
// disable auth.
|
||||
if (args.link) {
|
||||
args.host = "localhost"
|
||||
args.port = 0
|
||||
args.socket = undefined
|
||||
args["socket-mode"] = undefined
|
||||
args.cert = undefined
|
||||
args.auth = AuthType.None
|
||||
}
|
||||
|
||||
if (args.cert && !args.cert.value) {
|
||||
const { cert, certKey } = await generateCertificate(args["cert-host"] || "localhost")
|
||||
args.cert = {
|
||||
@@ -573,10 +572,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
args["disable-getting-started-override"] = true
|
||||
}
|
||||
|
||||
if (process.env.CS_DISABLE_PROXY?.match(/^(1|true)$/)) {
|
||||
args["disable-proxy"] = true
|
||||
}
|
||||
|
||||
const usingEnvHashedPassword = !!process.env.HASHED_PASSWORD
|
||||
if (process.env.HASHED_PASSWORD) {
|
||||
args["hashed-password"] = process.env.HASHED_PASSWORD
|
||||
@@ -594,25 +589,12 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
|
||||
// Filter duplicate proxy domains and remove any leading `*.`.
|
||||
const proxyDomains = new Set((args["proxy-domain"] || []).map((d) => d.replace(/^\*\./, "")))
|
||||
const finalProxies = []
|
||||
args["proxy-domain"] = Array.from(proxyDomains)
|
||||
|
||||
for (const proxyDomain of proxyDomains) {
|
||||
if (!proxyDomain.includes("{{port}}")) {
|
||||
finalProxies.push("{{port}}." + proxyDomain)
|
||||
} else {
|
||||
finalProxies.push(proxyDomain)
|
||||
}
|
||||
if (typeof args._ === "undefined") {
|
||||
args._ = []
|
||||
}
|
||||
|
||||
// all proxies are of format anyprefix-{{port}}-anysuffix.{{host}}, where {{host}} is optional
|
||||
// e.g. code-8080.domain.tld would match for code-{{port}}.domain.tld and code-{{port}}.{{host}}
|
||||
if (finalProxies.length > 0 && !process.env.VSCODE_PROXY_URI) {
|
||||
process.env.VSCODE_PROXY_URI = `//${finalProxies[0]}`
|
||||
}
|
||||
args["proxy-domain"] = finalProxies
|
||||
|
||||
args._ = getResolvedPathsFromArgs(args)
|
||||
|
||||
return {
|
||||
...args,
|
||||
usingEnvPassword,
|
||||
@@ -620,10 +602,6 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
|
||||
} as DefaultedArgs // TODO: Technically no guarantee this is fulfilled.
|
||||
}
|
||||
|
||||
export function getResolvedPathsFromArgs(args: UserProvidedArgs): string[] {
|
||||
return (args._ ?? []).map((p) => path.resolve(p))
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return the default config file.
|
||||
*
|
||||
@@ -667,7 +645,7 @@ export async function readConfigFile(configPath?: string): Promise<ConfigArgs> {
|
||||
await fs.writeFile(configPath, defaultConfigFile(generatedPassword), {
|
||||
flag: "wx", // wx means to fail if the path exists.
|
||||
})
|
||||
logger.info(`Wrote default config file to ${configPath}`)
|
||||
logger.info(`Wrote default config file to ${humanPath(os.homedir(), configPath)}`)
|
||||
} catch (error: any) {
|
||||
// EEXIST is fine; we don't want to overwrite existing configurations.
|
||||
if (error.code !== "EEXIST") {
|
||||
@@ -737,9 +715,6 @@ export function bindAddrFromArgs(addr: Addr, args: UserProvidedArgs): Addr {
|
||||
if (args["bind-addr"]) {
|
||||
addr = parseBindAddr(args["bind-addr"])
|
||||
}
|
||||
if (process.env.CODE_SERVER_HOST) {
|
||||
addr.host = process.env.CODE_SERVER_HOST
|
||||
}
|
||||
if (args.host) {
|
||||
addr.host = args.host
|
||||
}
|
||||
@@ -766,38 +741,47 @@ function bindAddrFromAllSources(...argsConfig: UserProvidedArgs[]): Addr {
|
||||
return addr
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the socketPath based on path passed in.
|
||||
*
|
||||
* The one usually passed in is the DEFAULT_SOCKET_PATH.
|
||||
*
|
||||
* If it can't read the path, it throws an error and returns undefined.
|
||||
*/
|
||||
export async function readSocketPath(path: string): Promise<string | undefined> {
|
||||
try {
|
||||
return await fs.readFile(path, "utf8")
|
||||
} catch (error) {
|
||||
// If it doesn't exist, we don't care.
|
||||
// But if it fails for some reason, we should throw.
|
||||
// We want to surface that to the user.
|
||||
if (!isNodeJSErrnoException(error) || error.code !== "ENOENT") {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if it looks like the user is trying to open a file or folder in an
|
||||
* existing instance. The arguments here should be the arguments the user
|
||||
* explicitly passed on the command line, *NOT DEFAULTS* or the configuration.
|
||||
*/
|
||||
export const shouldOpenInExistingInstance = async (
|
||||
args: UserProvidedArgs,
|
||||
sessionSocket: string,
|
||||
): Promise<string | undefined> => {
|
||||
export const shouldOpenInExistingInstance = async (args: UserProvidedArgs): Promise<string | undefined> => {
|
||||
// Always use the existing instance if we're running from VS Code's terminal.
|
||||
if (process.env.VSCODE_IPC_HOOK_CLI) {
|
||||
logger.debug("Found VSCODE_IPC_HOOK_CLI")
|
||||
return process.env.VSCODE_IPC_HOOK_CLI
|
||||
}
|
||||
|
||||
const paths = getResolvedPathsFromArgs(args)
|
||||
const client = new EditorSessionManagerClient(sessionSocket)
|
||||
|
||||
// If these flags are set then assume the user is trying to open in an
|
||||
// existing instance since these flags have no effect otherwise. That means
|
||||
// if there is no existing instance we should error rather than falling back
|
||||
// to spawning code-server normally.
|
||||
// existing instance since these flags have no effect otherwise.
|
||||
const openInFlagCount = ["reuse-window", "new-window"].reduce((prev, cur) => {
|
||||
return args[cur as keyof UserProvidedArgs] ? prev + 1 : prev
|
||||
}, 0)
|
||||
if (openInFlagCount > 0) {
|
||||
logger.debug("Found --reuse-window or --new-window")
|
||||
const socketPath = await client.getConnectedSocketPath(paths[0])
|
||||
if (!socketPath) {
|
||||
throw new Error(`No opened code-server instances found to handle ${paths[0]}`)
|
||||
}
|
||||
return socketPath
|
||||
return readSocketPath(DEFAULT_SOCKET_PATH)
|
||||
}
|
||||
|
||||
// It's possible the user is trying to spawn another instance of code-server.
|
||||
@@ -805,13 +789,9 @@ export const shouldOpenInExistingInstance = async (
|
||||
// code-server is invoked exactly like this: `code-server my-file`).
|
||||
// 2. That a file or directory was passed.
|
||||
// 3. That the socket is active.
|
||||
// 4. That an instance exists to handle the path (implied by #3).
|
||||
if (Object.keys(args).length === 1 && typeof args._ !== "undefined" && args._.length > 0) {
|
||||
if (!(await client.canConnect())) {
|
||||
return undefined
|
||||
}
|
||||
const socketPath = await client.getConnectedSocketPath(paths[0])
|
||||
if (socketPath) {
|
||||
const socketPath = await readSocketPath(DEFAULT_SOCKET_PATH)
|
||||
if (socketPath && (await canConnect(socketPath))) {
|
||||
logger.debug("Found existing code-server socket")
|
||||
return socketPath
|
||||
}
|
||||
@@ -833,8 +813,7 @@ export interface CodeArgs extends UserProvidedCodeArgs {
|
||||
version: boolean
|
||||
"without-connection-token"?: boolean
|
||||
"without-browser-env-var"?: boolean
|
||||
compatibility?: string
|
||||
log?: string[]
|
||||
compatibility: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -843,16 +822,18 @@ export interface CodeArgs extends UserProvidedCodeArgs {
|
||||
export type SpawnCodeCli = (args: CodeArgs) => Promise<void>
|
||||
|
||||
/**
|
||||
* Convert our arguments to equivalent VS Code server arguments.
|
||||
* Does not add any extra arguments.
|
||||
* Convert our arguments to VS Code server arguments.
|
||||
*/
|
||||
export const toCodeArgs = async (args: DefaultedArgs): Promise<CodeArgs> => {
|
||||
return {
|
||||
...args,
|
||||
"accept-server-license-terms": true,
|
||||
// This seems to be used to make the connection token flags optional (when
|
||||
// set to 1.63) but we have always included them.
|
||||
compatibility: "1.64",
|
||||
/** Type casting. */
|
||||
help: !!args.help,
|
||||
version: !!args.version,
|
||||
port: args.port?.toString(),
|
||||
log: args.log ? [args.log] : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
43
src/node/coder_cloud.ts
Normal file
43
src/node/coder_cloud.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { logger } from "@coder/logger"
|
||||
import { spawn } from "child_process"
|
||||
import path from "path"
|
||||
import split2 from "split2"
|
||||
|
||||
// https://github.com/coder/coder-cloud
|
||||
const coderCloudAgent = path.resolve(__dirname, "../../lib/coder-cloud-agent")
|
||||
|
||||
function runAgent(...args: string[]): Promise<void> {
|
||||
logger.debug(`running agent with ${args}`)
|
||||
|
||||
const agent = spawn(coderCloudAgent, args, {
|
||||
stdio: ["inherit", "inherit", "pipe"],
|
||||
})
|
||||
|
||||
agent.stderr.pipe(split2()).on("data", (line) => {
|
||||
line = line.replace(/^[0-9-]+ [0-9:]+ [^ ]+\t/, "")
|
||||
logger.info(line)
|
||||
})
|
||||
|
||||
return new Promise((res, rej) => {
|
||||
agent.on("error", rej)
|
||||
|
||||
agent.on("close", (code) => {
|
||||
if (code !== 0) {
|
||||
rej({
|
||||
message: `--link agent exited with ${code}`,
|
||||
})
|
||||
return
|
||||
}
|
||||
res()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function coderCloudBind(address: URL | string, serverName = ""): Promise<void> {
|
||||
if (typeof address === "string") {
|
||||
throw new Error("Cannot link socket paths")
|
||||
}
|
||||
|
||||
// Address needs to be in hostname:port format without the protocol.
|
||||
return runAgent("bind", `--code-server-addr=${address.host}`, serverName)
|
||||
}
|
||||
@@ -51,7 +51,7 @@ async function entry(): Promise<void> {
|
||||
return runCodeCli(args)
|
||||
}
|
||||
|
||||
const socketPath = await shouldOpenInExistingInstance(cliArgs, args["session-socket"])
|
||||
const socketPath = await shouldOpenInExistingInstance(cliArgs)
|
||||
if (socketPath) {
|
||||
logger.debug("Trying to open in existing instance")
|
||||
return openInExistingInstance(args, socketPath)
|
||||
|
||||
@@ -9,10 +9,7 @@ export class Heart {
|
||||
private heartbeatInterval = 60000
|
||||
public lastHeartbeat = 0
|
||||
|
||||
public constructor(
|
||||
private readonly heartbeatPath: string,
|
||||
private readonly isActive: () => Promise<boolean>,
|
||||
) {
|
||||
public constructor(private readonly heartbeatPath: string, private readonly isActive: () => Promise<boolean>) {
|
||||
this.beat = this.beat.bind(this)
|
||||
this.alive = this.alive.bind(this)
|
||||
}
|
||||
@@ -31,7 +28,7 @@ export class Heart {
|
||||
return
|
||||
}
|
||||
|
||||
logger.debug("heartbeat")
|
||||
logger.trace("heartbeat")
|
||||
this.lastHeartbeat = Date.now()
|
||||
if (typeof this.heartbeatTimer !== "undefined") {
|
||||
clearTimeout(this.heartbeatTimer)
|
||||
|
||||
121
src/node/http.ts
121
src/node/http.ts
@@ -12,15 +12,7 @@ import { version as codeServerVersion } from "./constants"
|
||||
import { Heart } from "./heart"
|
||||
import { CoderSettings, SettingsProvider } from "./settings"
|
||||
import { UpdateProvider } from "./update"
|
||||
import {
|
||||
getPasswordMethod,
|
||||
IsCookieValidArgs,
|
||||
isCookieValid,
|
||||
sanitizeString,
|
||||
escapeHtml,
|
||||
escapeJSON,
|
||||
splitOnFirstEquals,
|
||||
} from "./util"
|
||||
import { getPasswordMethod, IsCookieValidArgs, isCookieValid, sanitizeString, escapeHtml, escapeJSON } from "./util"
|
||||
|
||||
/**
|
||||
* Base options included on every page.
|
||||
@@ -75,25 +67,6 @@ export const replaceTemplates = <T extends object>(
|
||||
.replace("{{OPTIONS}}", () => escapeJSON(serverOptions))
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error if proxy is not enabled. Call `next` if provided.
|
||||
*/
|
||||
export const ensureProxyEnabled = (req: express.Request, _?: express.Response, next?: express.NextFunction): void => {
|
||||
if (!proxyEnabled(req)) {
|
||||
throw new HttpError("Forbidden", HttpCode.Forbidden)
|
||||
}
|
||||
if (next) {
|
||||
next()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if proxy is enabled.
|
||||
*/
|
||||
export const proxyEnabled = (req: express.Request): boolean => {
|
||||
return !req.args["disable-proxy"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an error if not authorized. Call `next` if provided.
|
||||
*/
|
||||
@@ -319,8 +292,8 @@ export const getCookieOptions = (req: express.Request): express.CookieOptions =>
|
||||
// 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"),
|
||||
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"]),
|
||||
@@ -335,91 +308,3 @@ export const getCookieOptions = (req: express.Request): express.CookieOptions =>
|
||||
export const self = (req: express.Request): string => {
|
||||
return normalize(`${req.baseUrl}${req.originalUrl.endsWith("/") ? "/" : ""}`, true)
|
||||
}
|
||||
|
||||
function getFirstHeader(req: http.IncomingMessage, headerName: string): string | undefined {
|
||||
const val = req.headers[headerName]
|
||||
return Array.isArray(val) ? val[0] : val
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw a forbidden error if origin checks fail. Call `next` if provided.
|
||||
*/
|
||||
export function ensureOrigin(req: express.Request, _?: express.Response, next?: express.NextFunction): void {
|
||||
try {
|
||||
authenticateOrigin(req)
|
||||
if (next) {
|
||||
next()
|
||||
}
|
||||
} catch (error) {
|
||||
logger.debug(`${error instanceof Error ? error.message : error}; blocking request to ${req.originalUrl}`)
|
||||
throw new HttpError("Forbidden", HttpCode.Forbidden)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the request origin against the host. Throw if invalid.
|
||||
*/
|
||||
export function authenticateOrigin(req: express.Request): void {
|
||||
// A missing origin probably means the source is non-browser. Not sure we
|
||||
// have a use case for this but let it through.
|
||||
const originRaw = getFirstHeader(req, "origin")
|
||||
if (!originRaw) {
|
||||
return
|
||||
}
|
||||
|
||||
let origin: string
|
||||
try {
|
||||
origin = new URL(originRaw).host.trim().toLowerCase()
|
||||
} catch (error) {
|
||||
throw new Error(`unable to parse malformed origin "${originRaw}"`)
|
||||
}
|
||||
|
||||
const trustedOrigins = req.args["trusted-origins"] || []
|
||||
if (trustedOrigins.includes(origin) || trustedOrigins.includes("*")) {
|
||||
return
|
||||
}
|
||||
|
||||
const host = getHost(req)
|
||||
if (typeof host === "undefined") {
|
||||
// A missing host likely means the reverse proxy has not been configured to
|
||||
// forward the host which means we cannot perform the check. Emit an error
|
||||
// so an admin can fix the issue.
|
||||
logger.error("No host headers found")
|
||||
logger.error("Are you behind a reverse proxy that does not forward the host?")
|
||||
throw new Error("no host headers found")
|
||||
}
|
||||
|
||||
if (host !== origin) {
|
||||
throw new Error(`host "${host}" does not match origin "${origin}"`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the host from headers. It will be trimmed and lowercased.
|
||||
*/
|
||||
export function getHost(req: express.Request): string | undefined {
|
||||
// Honor Forwarded if present.
|
||||
const forwardedRaw = getFirstHeader(req, "forwarded")
|
||||
if (forwardedRaw) {
|
||||
const parts = forwardedRaw.split(/[;,]/)
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
const [key, value] = splitOnFirstEquals(parts[i])
|
||||
if (key.trim().toLowerCase() === "host" && value) {
|
||||
return value.trim().toLowerCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Honor X-Forwarded-Host if present. Some reverse proxies will set multiple
|
||||
// comma-separated hosts.
|
||||
const xHost = getFirstHeader(req, "x-forwarded-host")
|
||||
if (xHost) {
|
||||
const firstXHost = xHost.split(",")[0]
|
||||
if (firstXHost) {
|
||||
return firstXHost.trim().toLowerCase()
|
||||
}
|
||||
}
|
||||
|
||||
const host = getFirstHeader(req, "host")
|
||||
return host ? host.trim().toLowerCase() : undefined
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import i18next, { init } from "i18next"
|
||||
import * as en from "./locales/en.json"
|
||||
import * as ja from "./locales/ja.json"
|
||||
import * as th from "./locales/th.json"
|
||||
import * as ur from "./locales/ur.json"
|
||||
import * as zhCn from "./locales/zh-cn.json"
|
||||
|
||||
init({
|
||||
lng: "en",
|
||||
fallbackLng: "en", // language to use if translations in user language are not available.
|
||||
returnNull: false,
|
||||
lowerCaseLng: true,
|
||||
debug: process.env.NODE_ENV === "development",
|
||||
resources: {
|
||||
en: {
|
||||
translation: en,
|
||||
},
|
||||
"zh-cn": {
|
||||
translation: zhCn,
|
||||
},
|
||||
th: {
|
||||
translation: th,
|
||||
},
|
||||
ja: {
|
||||
translation: ja,
|
||||
},
|
||||
ur: {
|
||||
translation: ur,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default i18next
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user