Add NPM package, debs, rpms and refactor CI/build process
Closes many issues that I'll prune after adding more docs for users.
This commit is contained in:
parent
4875f6aa87
commit
be032cf735
@ -1,2 +1,3 @@
|
|||||||
**
|
**
|
||||||
!release
|
!release-github
|
||||||
|
!ci
|
||||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,9 +1,9 @@
|
|||||||
*.tsbuildinfo
|
.tsbuildinfo
|
||||||
.cache
|
.cache
|
||||||
build
|
|
||||||
dist*
|
dist*
|
||||||
out*
|
out*
|
||||||
release/
|
release/
|
||||||
release-upload/
|
release-static/
|
||||||
|
release-github/
|
||||||
|
release-gcp/
|
||||||
node_modules
|
node_modules
|
||||||
binaries
|
|
||||||
|
48
.travis.yml
48
.travis.yml
@ -1,28 +1,33 @@
|
|||||||
language: minimal
|
language: node_js
|
||||||
|
node_js: node
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- name: Test
|
- name: Test
|
||||||
if: tag IS blank
|
if: tag IS blank
|
||||||
script: ./ci/image/run.sh "yarn && git submodule update --init && yarn vscode:patch && ./ci/ci.sh"
|
script: ./ci/container/exec.sh ./ci/steps/test.sh
|
||||||
deploy: null
|
deploy: null
|
||||||
|
install: null
|
||||||
- name: Linux Release
|
- name: Linux Release
|
||||||
if: tag IS present
|
if: tag IS present
|
||||||
script:
|
script: ./ci/steps/linux-release.sh
|
||||||
- travis_wait 60 ./ci/image/run.sh "yarn && yarn vscode && ci/release.sh && ./ci/build-test.sh"
|
install: null
|
||||||
- ./ci/release-image/push.sh
|
- name: Linux Release
|
||||||
- name: Linux ARM64 Release
|
|
||||||
if: tag IS present
|
if: tag IS present
|
||||||
script:
|
|
||||||
- ./ci/image/run.sh "yarn && yarn vscode && ci/release.sh && ./ci/build-test.sh"
|
|
||||||
- ./ci/release-image/push.sh
|
|
||||||
arch: arm64
|
arch: arm64
|
||||||
|
script: |
|
||||||
|
sudo apt-get update && sudo apt-get install -y jq || exit 1
|
||||||
|
./ci/steps/linux-release.sh
|
||||||
|
install: null
|
||||||
- name: MacOS Release
|
- name: MacOS Release
|
||||||
if: tag IS present
|
if: tag IS present
|
||||||
os: osx
|
os: osx
|
||||||
language: node_js
|
# node 13/14 crashes in the build process for some reason.
|
||||||
node_js: 12
|
node_js: 12
|
||||||
script: yarn && yarn vscode && travis_wait 60 ci/release.sh && ./ci/build-test.sh
|
script: |
|
||||||
|
HOMEBREW_NO_INSTALL_CLEANUP=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install jq || exit 1
|
||||||
|
travis_wait 60 ./ci/steps/static-release.sh || exit 1
|
||||||
|
install: null
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- echo "$JSON_KEY" | base64 --decode > ./ci/key.json
|
- echo "$JSON_KEY" | base64 --decode > ./ci/key.json
|
||||||
@ -36,8 +41,10 @@ deploy:
|
|||||||
target_commitish: $TRAVIS_COMMIT
|
target_commitish: $TRAVIS_COMMIT
|
||||||
name: $TRAVIS_TAG
|
name: $TRAVIS_TAG
|
||||||
file:
|
file:
|
||||||
- release/*.tar.gz
|
- release-github/*.tar.gz
|
||||||
- release/*.zip
|
- release-github/*.zip
|
||||||
|
- release-github/*.deb
|
||||||
|
- release-github/*.rpm
|
||||||
on:
|
on:
|
||||||
tags: true
|
tags: true
|
||||||
- provider: gcs
|
- provider: gcs
|
||||||
@ -45,14 +52,25 @@ deploy:
|
|||||||
bucket: "codesrv-ci.cdr.sh"
|
bucket: "codesrv-ci.cdr.sh"
|
||||||
upload_dir: "releases"
|
upload_dir: "releases"
|
||||||
key_file: ./ci/key.json
|
key_file: ./ci/key.json
|
||||||
local_dir: release-upload
|
local_dir: ./release-gcp
|
||||||
on:
|
on:
|
||||||
tags: true
|
tags: true
|
||||||
# TODO: The gcs provider fails to install on arm64.
|
# TODO: The gcs provider fails to install on arm64.
|
||||||
condition: $TRAVIS_CPU_ARCH = amd64
|
condition: $TRAVIS_CPU_ARCH == amd64
|
||||||
|
- provider: script
|
||||||
|
edge: true
|
||||||
|
# We do not use the travis npm deploy integration as it does not allow us to
|
||||||
|
# deploy a subpath and and v2 which should, just errors out that the src does not exist
|
||||||
|
script: ./ci/steps/publish-npm.sh
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
condition: $TRAVIS_CPU_ARCH == amd64 && $TRAVIS_OS_NAME == linux
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
timeout: 600
|
timeout: 600
|
||||||
yarn: true
|
yarn: true
|
||||||
directories:
|
directories:
|
||||||
|
- .cache
|
||||||
|
- out
|
||||||
|
- dist
|
||||||
- lib/vscode/.build/extensions
|
- lib/vscode/.build/extensions
|
||||||
|
82
ci/README.md
Normal file
82
ci/README.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# ci
|
||||||
|
|
||||||
|
This directory contains scripts used for code-server's continuous integration infrastructure.
|
||||||
|
|
||||||
|
Many of these scripts contain more detailed documentation and options in comments at the top.
|
||||||
|
|
||||||
|
Any file and directory added into this tree should be documented here.
|
||||||
|
|
||||||
|
## dev
|
||||||
|
|
||||||
|
This directory contains scripts used for the development of code-server.
|
||||||
|
|
||||||
|
- [./dev/container](./dev/container)
|
||||||
|
- See [CONTRIBUTING.md](../doc/CONTRIBUTING.md) for docs on the development container
|
||||||
|
- [./dev/ci.sh](./dev/ci.sh) (`yarn ci`)
|
||||||
|
- Runs formatters, linters and tests
|
||||||
|
- [./dev/fmt.sh](./dev/fmt.sh) (`yarn fmt`)
|
||||||
|
- Runs formatters
|
||||||
|
- [./dev/lint.sh](./dev/lint.sh) (`yarn lint`)
|
||||||
|
- Runs linters
|
||||||
|
- [./dev/test.sh](./dev/test.sh) (`yarn test`)
|
||||||
|
- Runs tests
|
||||||
|
- [./dev/vscode.sh](./dev/vscode.sh) (`yarn vscode`)
|
||||||
|
- Ensures `lib/vscode` is cloned, patched and dependencies are installed
|
||||||
|
- [./dev/vscode.patch](./dev/vscode.patch)
|
||||||
|
- Our patch of VS Code to enable remote browser access
|
||||||
|
- Generate it with `yarn vscode:diff` and apply with `yarn vscode:patch`
|
||||||
|
- [./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 [CONTRIBUTING.md](../doc/CONTRIBUTING.md)
|
||||||
|
|
||||||
|
## build
|
||||||
|
|
||||||
|
This directory contains the scripts used to build code-server.
|
||||||
|
|
||||||
|
- [./build/build-code-server.sh](./build/build-code-server.sh) (`yarn build`)
|
||||||
|
- Builds code-server into ./out and bundles the frontend into ./dist.
|
||||||
|
- [./build/build-vscode.sh](./build/build-vscode.sh) (`yarn build:vscode`)
|
||||||
|
- Builds vscode into ./lib/vscode/out-vscode.
|
||||||
|
- [./build/build-release.sh](./build/build-release.sh) (`yarn release`)
|
||||||
|
- Bundles the output of the above two scripts into a single node module at ./release.
|
||||||
|
- Will build a static release with node/node_modules into `./release-static`
|
||||||
|
if `STATIC=1` is set.
|
||||||
|
- [./build/clean.sh](./build/clean.sh) (`yarn clean`)
|
||||||
|
- Removes all git ignored files like build artifacts.
|
||||||
|
- Will also `git reset --hard lib/vscode`
|
||||||
|
- Useful to do a clean build.
|
||||||
|
- [./build/code-server.sh](./build/code-server.sh)
|
||||||
|
- Copied into static releases to run code-server with the bundled node binary.
|
||||||
|
- [./build/archive-static-release.sh](./build/archive-static-release.sh)
|
||||||
|
- Archives `./release-static` into a tar/zip for CI with the proper directory name scheme
|
||||||
|
- [./build/test-release.sh](./build/test-static-release.sh)
|
||||||
|
- Ensures code-server in the `./release-static` directory runs
|
||||||
|
- [./build/build-static-pkgs.sh](./build/build-static-pkgs.sh) (`yarn pkg`)
|
||||||
|
- Uses [nfpm](https://github.com/goreleaser/nfpm) to generate .deb and .rpm from a static release
|
||||||
|
- [./build/nfpm.yaml](./build/nfpm.yaml)
|
||||||
|
- Used to configure [nfpm](https://github.com/goreleaser/nfpm) to generate .deb and .rpm
|
||||||
|
- [./build/code-server-nfpm.sh](./build/code-server-nfpm.sh)
|
||||||
|
- Entrypoint script for code-server for .deb and .rpm
|
||||||
|
|
||||||
|
## release-container
|
||||||
|
|
||||||
|
This directory contains the release docker container.
|
||||||
|
|
||||||
|
## container
|
||||||
|
|
||||||
|
This directory contains the container for CI.
|
||||||
|
|
||||||
|
## steps
|
||||||
|
|
||||||
|
This directory contains a few scripts used in CI. Just helps avoid clobbering .travis.yml.
|
||||||
|
|
||||||
|
- [./steps/test.sh](./steps/test.sh)
|
||||||
|
- Runs `yarn ci` after ensuring VS Code is patched
|
||||||
|
- [./steps/static-release.sh](./steps/static-release.sh)
|
||||||
|
- Runs the full static build process for CI
|
||||||
|
- [./steps/linux-release.sh](./steps/linux-release.sh)
|
||||||
|
- Runs the full static build process for CI
|
||||||
|
- Packages the release into a .deb and .rpm
|
||||||
|
- Builds and pushes a docker release
|
||||||
|
- [./steps/publish-npm.sh](./steps/publish-npm.sh)
|
||||||
|
- Authenticates yarn and publishes the built package from `./release`
|
372
ci/build.ts
372
ci/build.ts
@ -1,372 +0,0 @@
|
|||||||
import * as cp from "child_process"
|
|
||||||
import * as fs from "fs-extra"
|
|
||||||
import Bundler from "parcel-bundler"
|
|
||||||
import * as path from "path"
|
|
||||||
import * as util from "util"
|
|
||||||
|
|
||||||
enum Task {
|
|
||||||
Build = "build",
|
|
||||||
Watch = "watch",
|
|
||||||
}
|
|
||||||
|
|
||||||
class Builder {
|
|
||||||
private readonly rootPath = path.resolve(__dirname, "..")
|
|
||||||
private readonly vscodeSourcePath = path.join(this.rootPath, "lib/vscode")
|
|
||||||
private readonly buildPath = path.join(this.rootPath, "build")
|
|
||||||
private readonly codeServerVersion: string
|
|
||||||
private currentTask?: Task
|
|
||||||
|
|
||||||
public constructor() {
|
|
||||||
this.ensureArgument("rootPath", this.rootPath)
|
|
||||||
this.codeServerVersion = this.ensureArgument(
|
|
||||||
"codeServerVersion",
|
|
||||||
process.env.VERSION || require(path.join(this.rootPath, "package.json")).version,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public run(task: Task | undefined): void {
|
|
||||||
this.currentTask = task
|
|
||||||
this.doRun(task).catch((error) => {
|
|
||||||
console.error(error.message)
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private async task<T>(message: string, fn: () => Promise<T>): Promise<T> {
|
|
||||||
const time = Date.now()
|
|
||||||
this.log(`${message}...`, !process.env.CI)
|
|
||||||
try {
|
|
||||||
const t = await fn()
|
|
||||||
process.stdout.write(`took ${Date.now() - time}ms\n`)
|
|
||||||
return t
|
|
||||||
} catch (error) {
|
|
||||||
process.stdout.write("failed\n")
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes to stdout with an optional newline.
|
|
||||||
*/
|
|
||||||
private log(message: string, skipNewline = false): void {
|
|
||||||
process.stdout.write(`[${this.currentTask || "default"}] ${message}`)
|
|
||||||
if (!skipNewline) {
|
|
||||||
process.stdout.write("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async doRun(task: Task | undefined): Promise<void> {
|
|
||||||
if (!task) {
|
|
||||||
throw new Error("No task provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (task) {
|
|
||||||
case Task.Watch:
|
|
||||||
return this.watch()
|
|
||||||
case Task.Build:
|
|
||||||
return this.build()
|
|
||||||
default:
|
|
||||||
throw new Error(`No task matching "${task}"`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure the argument is set. Display the value if it is.
|
|
||||||
*/
|
|
||||||
private ensureArgument(name: string, arg?: string): string {
|
|
||||||
if (!arg) {
|
|
||||||
throw new Error(`${name} is missing`)
|
|
||||||
}
|
|
||||||
this.log(`${name} is "${arg}"`)
|
|
||||||
return arg
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build VS Code and code-server.
|
|
||||||
*/
|
|
||||||
private async build(): Promise<void> {
|
|
||||||
process.env.NODE_OPTIONS = "--max-old-space-size=32384 " + (process.env.NODE_OPTIONS || "")
|
|
||||||
process.env.NODE_ENV = "production"
|
|
||||||
|
|
||||||
await this.task("cleaning up old build", async () => {
|
|
||||||
if (!process.env.SKIP_VSCODE) {
|
|
||||||
return fs.remove(this.buildPath)
|
|
||||||
}
|
|
||||||
// If skipping VS Code, keep the existing build if any.
|
|
||||||
try {
|
|
||||||
const files = await fs.readdir(this.buildPath)
|
|
||||||
return Promise.all(files.filter((f) => f !== "lib").map((f) => fs.remove(path.join(this.buildPath, f))))
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code !== "ENOENT") {
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const commit = require(path.join(this.vscodeSourcePath, "build/lib/util")).getVersion(this.rootPath) as string
|
|
||||||
if (!process.env.SKIP_VSCODE) {
|
|
||||||
await this.buildVscode(commit)
|
|
||||||
} else {
|
|
||||||
this.log("skipping vs code build")
|
|
||||||
}
|
|
||||||
await this.buildCodeServer(commit)
|
|
||||||
|
|
||||||
this.log(`final build: ${this.buildPath}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
private async buildCodeServer(commit: string): Promise<void> {
|
|
||||||
await this.task("building code-server", async () => {
|
|
||||||
return util.promisify(cp.exec)("tsc --outDir ./out-build --tsBuildInfoFile ./.prod.tsbuildinfo", {
|
|
||||||
cwd: this.rootPath,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.task("bundling code-server", async () => {
|
|
||||||
return this.createBundler("dist-build", commit).bundle()
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.task("copying code-server into build directory", async () => {
|
|
||||||
await fs.mkdirp(this.buildPath)
|
|
||||||
await Promise.all([
|
|
||||||
fs.copy(path.join(this.rootPath, "out-build"), path.join(this.buildPath, "out")),
|
|
||||||
fs.copy(path.join(this.rootPath, "dist-build"), path.join(this.buildPath, "dist")),
|
|
||||||
// For source maps and images.
|
|
||||||
fs.copy(path.join(this.rootPath, "src"), path.join(this.buildPath, "src")),
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.copyDependencies("code-server", this.rootPath, this.buildPath, false, {
|
|
||||||
commit,
|
|
||||||
version: this.codeServerVersion,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private async buildVscode(commit: string): Promise<void> {
|
|
||||||
await this.task("building vs code", () => {
|
|
||||||
return util.promisify(cp.exec)("yarn gulp compile-build", { cwd: this.vscodeSourcePath })
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.task("building builtin extensions", async () => {
|
|
||||||
const exists = await fs.pathExists(path.join(this.vscodeSourcePath, ".build/extensions"))
|
|
||||||
if (exists && !process.env.CI) {
|
|
||||||
process.stdout.write("already built, skipping...")
|
|
||||||
} else {
|
|
||||||
await util.promisify(cp.exec)("yarn gulp compile-extensions-build", { cwd: this.vscodeSourcePath })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.task("optimizing vs code", async () => {
|
|
||||||
return util.promisify(cp.exec)("yarn gulp optimize --gulpfile ./coder.js", { cwd: this.vscodeSourcePath })
|
|
||||||
})
|
|
||||||
|
|
||||||
if (process.env.MINIFY) {
|
|
||||||
await this.task("minifying vs code", () => {
|
|
||||||
return util.promisify(cp.exec)("yarn gulp minify --gulpfile ./coder.js", { cwd: this.vscodeSourcePath })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const vscodeBuildPath = path.join(this.buildPath, "lib/vscode")
|
|
||||||
await this.task("copying vs code into build directory", async () => {
|
|
||||||
await fs.mkdirp(path.join(vscodeBuildPath, "resources/linux"))
|
|
||||||
await Promise.all([
|
|
||||||
fs.move(
|
|
||||||
path.join(this.vscodeSourcePath, `out-vscode${process.env.MINIFY ? "-min" : ""}`),
|
|
||||||
path.join(vscodeBuildPath, "out"),
|
|
||||||
),
|
|
||||||
fs.copy(path.join(this.vscodeSourcePath, ".build/extensions"), path.join(vscodeBuildPath, "extensions")),
|
|
||||||
fs.copy(
|
|
||||||
path.join(this.vscodeSourcePath, "resources/linux/code.png"),
|
|
||||||
path.join(vscodeBuildPath, "resources/linux/code.png"),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
await this.copyDependencies("vs code", this.vscodeSourcePath, vscodeBuildPath, true, {
|
|
||||||
commit,
|
|
||||||
date: new Date().toISOString(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private async copyDependencies(
|
|
||||||
name: string,
|
|
||||||
sourcePath: string,
|
|
||||||
buildPath: string,
|
|
||||||
ignoreScripts: boolean,
|
|
||||||
merge: object,
|
|
||||||
): Promise<void> {
|
|
||||||
await this.task(`copying ${name} dependencies`, async () => {
|
|
||||||
return Promise.all(
|
|
||||||
["node_modules", "package.json", "yarn.lock"].map((fileName) => {
|
|
||||||
return fs.copy(path.join(sourcePath, fileName), path.join(buildPath, fileName))
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const fileName = name === "code-server" ? "package" : "product"
|
|
||||||
await this.task(`writing final ${name} ${fileName}.json`, async () => {
|
|
||||||
const json = JSON.parse(await fs.readFile(path.join(sourcePath, `${fileName}.json`), "utf8"))
|
|
||||||
return fs.writeFile(
|
|
||||||
path.join(buildPath, `${fileName}.json`),
|
|
||||||
JSON.stringify(
|
|
||||||
{
|
|
||||||
...json,
|
|
||||||
...merge,
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (process.env.MINIFY) {
|
|
||||||
await this.task(`restricting ${name} to production dependencies`, async () => {
|
|
||||||
await util.promisify(cp.exec)(`yarn --production ${ignoreScripts ? "--ignore-scripts" : ""}`, {
|
|
||||||
cwd: buildPath,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async watch(): Promise<void> {
|
|
||||||
let server: cp.ChildProcess | undefined
|
|
||||||
const restartServer = (): void => {
|
|
||||||
if (server) {
|
|
||||||
server.kill()
|
|
||||||
}
|
|
||||||
const s = cp.fork(path.join(this.rootPath, "out/node/entry.js"), process.argv.slice(3))
|
|
||||||
console.log(`[server] spawned process ${s.pid}`)
|
|
||||||
s.on("exit", () => console.log(`[server] process ${s.pid} exited`))
|
|
||||||
server = s
|
|
||||||
}
|
|
||||||
|
|
||||||
const vscode = cp.spawn("yarn", ["watch"], { cwd: this.vscodeSourcePath })
|
|
||||||
const tsc = cp.spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath })
|
|
||||||
const bundler = this.createBundler()
|
|
||||||
|
|
||||||
const cleanup = (code?: number | null): void => {
|
|
||||||
this.log("killing vs code watcher")
|
|
||||||
vscode.removeAllListeners()
|
|
||||||
vscode.kill()
|
|
||||||
|
|
||||||
this.log("killing tsc")
|
|
||||||
tsc.removeAllListeners()
|
|
||||||
tsc.kill()
|
|
||||||
|
|
||||||
if (server) {
|
|
||||||
this.log("killing server")
|
|
||||||
server.removeAllListeners()
|
|
||||||
server.kill()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.log("killing bundler")
|
|
||||||
process.exit(code || 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
process.on("SIGINT", () => cleanup())
|
|
||||||
process.on("SIGTERM", () => cleanup())
|
|
||||||
|
|
||||||
vscode.on("exit", (code) => {
|
|
||||||
this.log("vs code watcher terminated unexpectedly")
|
|
||||||
cleanup(code)
|
|
||||||
})
|
|
||||||
tsc.on("exit", (code) => {
|
|
||||||
this.log("tsc terminated unexpectedly")
|
|
||||||
cleanup(code)
|
|
||||||
})
|
|
||||||
const bundle = bundler.bundle().catch(() => {
|
|
||||||
this.log("parcel watcher terminated unexpectedly")
|
|
||||||
cleanup(1)
|
|
||||||
})
|
|
||||||
bundler.on("buildEnd", () => {
|
|
||||||
console.log("[parcel] bundled")
|
|
||||||
})
|
|
||||||
bundler.on("buildError", (error) => {
|
|
||||||
console.error("[parcel]", error)
|
|
||||||
})
|
|
||||||
|
|
||||||
vscode.stderr.on("data", (d) => process.stderr.write(d))
|
|
||||||
tsc.stderr.on("data", (d) => process.stderr.write(d))
|
|
||||||
|
|
||||||
// From https://github.com/chalk/ansi-regex
|
|
||||||
const pattern = [
|
|
||||||
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
|
|
||||||
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))",
|
|
||||||
].join("|")
|
|
||||||
const re = new RegExp(pattern, "g")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Split stdout on newlines and strip ANSI codes.
|
|
||||||
*/
|
|
||||||
const onLine = (proc: cp.ChildProcess, callback: (strippedLine: string, originalLine: string) => void): void => {
|
|
||||||
let buffer = ""
|
|
||||||
if (!proc.stdout) {
|
|
||||||
throw new Error("no stdout")
|
|
||||||
}
|
|
||||||
proc.stdout.setEncoding("utf8")
|
|
||||||
proc.stdout.on("data", (d) => {
|
|
||||||
const data = buffer + d
|
|
||||||
const split = data.split("\n")
|
|
||||||
const last = split.length - 1
|
|
||||||
|
|
||||||
for (let i = 0; i < last; ++i) {
|
|
||||||
callback(split[i].replace(re, ""), split[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// The last item will either be an empty string (the data ended with a
|
|
||||||
// newline) or a partial line (did not end with a newline) and we must
|
|
||||||
// wait to parse it until we get a full line.
|
|
||||||
buffer = split[last]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let startingVscode = false
|
|
||||||
let startedVscode = false
|
|
||||||
onLine(vscode, (line, original) => {
|
|
||||||
console.log("[vscode]", original)
|
|
||||||
// Wait for watch-client since "Finished compilation" will appear multiple
|
|
||||||
// times before the client starts building.
|
|
||||||
if (!startingVscode && line.includes("Starting watch-client")) {
|
|
||||||
startingVscode = true
|
|
||||||
} else if (startingVscode && line.includes("Finished compilation")) {
|
|
||||||
if (startedVscode) {
|
|
||||||
bundle.then(restartServer)
|
|
||||||
}
|
|
||||||
startedVscode = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onLine(tsc, (line, original) => {
|
|
||||||
// tsc outputs blank lines; skip them.
|
|
||||||
if (line !== "") {
|
|
||||||
console.log("[tsc]", original)
|
|
||||||
}
|
|
||||||
if (line.includes("Watching for file changes")) {
|
|
||||||
bundle.then(restartServer)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private createBundler(out = "dist", commit?: string): Bundler {
|
|
||||||
return new Bundler(
|
|
||||||
[
|
|
||||||
path.join(this.rootPath, "src/browser/pages/app.ts"),
|
|
||||||
path.join(this.rootPath, "src/browser/register.ts"),
|
|
||||||
path.join(this.rootPath, "src/browser/serviceWorker.ts"),
|
|
||||||
],
|
|
||||||
{
|
|
||||||
cache: true,
|
|
||||||
cacheDir: path.join(this.rootPath, ".cache"),
|
|
||||||
detailedReport: true,
|
|
||||||
minify: !!process.env.MINIFY,
|
|
||||||
hmr: false,
|
|
||||||
logLevel: 1,
|
|
||||||
outDir: path.join(this.rootPath, out),
|
|
||||||
publicUrl: `/static/${commit || "development"}/dist`,
|
|
||||||
target: "browser",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const builder = new Builder()
|
|
||||||
builder.run(process.argv[2] as Task)
|
|
41
ci/build/archive-static-release.sh
Executable file
41
ci/build/archive-static-release.sh
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Generates static code-server releases for CI.
|
||||||
|
# This script assumes that a static release is built already.
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
VERSION="$(pkg_json_version)"
|
||||||
|
|
||||||
|
local OS
|
||||||
|
OS="$(os)"
|
||||||
|
|
||||||
|
local ARCH
|
||||||
|
ARCH="$(arch)"
|
||||||
|
|
||||||
|
local archive_name="code-server-$VERSION-$OS-$ARCH"
|
||||||
|
mkdir -p release-github
|
||||||
|
|
||||||
|
local ext
|
||||||
|
if [[ $OS == "linux" ]]; then
|
||||||
|
ext=".tar.gz"
|
||||||
|
tar -czf "release-github/$archive_name$ext" --transform "s/^\.\/release-static/$archive_name/" ./release-static
|
||||||
|
else
|
||||||
|
mv ./release-static "./$archive_name"
|
||||||
|
ext=".zip"
|
||||||
|
zip -r "release-github/$archive_name$ext" "./$archive_name"
|
||||||
|
mv "./$archive_name" ./release-static
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "done (release-github/$archive_name)"
|
||||||
|
|
||||||
|
mkdir -p "release-gcp/$VERSION"
|
||||||
|
cp "release-github/$archive_name$ext" "./release-gcp/$VERSION/$OS-$ARCH$ext"
|
||||||
|
mkdir -p "release-gcp/latest"
|
||||||
|
cp "./release-github/$archive_name$ext" "./release-gcp/latest/$OS-$ARCH$ext"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
29
ci/build/build-code-server.sh
Executable file
29
ci/build/build-code-server.sh
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Builds code-server into out and the frontend into dist.
|
||||||
|
|
||||||
|
# MINIFY controls whether parcel minifies dist.
|
||||||
|
MINIFY=${MINIFY-true}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
|
||||||
|
npx tsc --outDir out --tsBuildInfoFile .cache/out.tsbuildinfo
|
||||||
|
# If out/node/entry.js does not already have the shebang,
|
||||||
|
# we make sure to add it and make it executable.
|
||||||
|
if ! grep -q -m1 "^#!/usr/bin/env node" out/node/entry.js; then
|
||||||
|
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
|
||||||
|
|
||||||
|
npx parcel build \
|
||||||
|
--public-url "/static/$(git rev-parse HEAD)/dist" \
|
||||||
|
--out-dir dist \
|
||||||
|
$([[ $MINIFY ]] || echo --no-minify) \
|
||||||
|
src/browser/pages/app.ts \
|
||||||
|
src/browser/register.ts \
|
||||||
|
src/browser/serviceWorker.ts
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
127
ci/build/build-release.sh
Executable file
127
ci/build/build-release.sh
Executable file
@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# This script requires code-server and vscode to be built with
|
||||||
|
# matching MINIFY.
|
||||||
|
|
||||||
|
# RELEASE_PATH is the destination directory for the release from the root.
|
||||||
|
# Defaults to release
|
||||||
|
RELEASE_PATH="${RELEASE_PATH-release}"
|
||||||
|
|
||||||
|
# STATIC controls whether node and node_modules are packaged into the release.
|
||||||
|
# Disabled by default.
|
||||||
|
STATIC="${STATIC-}"
|
||||||
|
|
||||||
|
# MINIFY controls whether minified vscode is bundled and whether
|
||||||
|
# any included node_modules are pruned for production.
|
||||||
|
MINIFY="${MINIFY-true}"
|
||||||
|
|
||||||
|
VSCODE_SRC_PATH="lib/vscode"
|
||||||
|
|
||||||
|
VSCODE_OUT_PATH="$RELEASE_PATH/lib/vscode"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
mkdir -p "$RELEASE_PATH"
|
||||||
|
|
||||||
|
bundle_code_server
|
||||||
|
bundle_vscode
|
||||||
|
|
||||||
|
rsync README.md "$RELEASE_PATH"
|
||||||
|
rsync LICENSE.txt "$RELEASE_PATH"
|
||||||
|
rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
|
||||||
|
|
||||||
|
if [[ $STATIC ]]; then
|
||||||
|
rsync "$RELEASE_PATH/" "$RELEASE_PATH-static"
|
||||||
|
RELEASE_PATH+=-static
|
||||||
|
VSCODE_OUT_PATH="$RELEASE_PATH/lib/vscode"
|
||||||
|
|
||||||
|
bundle_node
|
||||||
|
else
|
||||||
|
rm -Rf "$VSCODE_OUT_PATH/extensions/node_modules"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
rsync() {
|
||||||
|
command rsync -a --del "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle_code_server() {
|
||||||
|
rsync out dist "$RELEASE_PATH"
|
||||||
|
|
||||||
|
# For source maps and images.
|
||||||
|
mkdir -p "$RELEASE_PATH/src/browser"
|
||||||
|
rsync src/browser/media/ "$RELEASE_PATH/src/browser/media"
|
||||||
|
mkdir -p "$RELEASE_PATH/src/browser/pages"
|
||||||
|
rsync src/browser/pages/*.html "$RELEASE_PATH/src/browser/pages"
|
||||||
|
|
||||||
|
rsync yarn.lock "$RELEASE_PATH"
|
||||||
|
|
||||||
|
# Adds the commit to package.json
|
||||||
|
jq --slurp '.[0] * .[1]' package.json <(
|
||||||
|
cat << EOF
|
||||||
|
{
|
||||||
|
"commit": "$(git rev-parse HEAD)",
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "cd lib/vscode && yarn --production && cd extensions && yarn --production"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
) > "$RELEASE_PATH/package.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle_vscode() {
|
||||||
|
mkdir -p "$VSCODE_OUT_PATH"
|
||||||
|
rsync "$VSCODE_SRC_PATH/out-vscode${MINIFY+-min}/" "$VSCODE_OUT_PATH/out"
|
||||||
|
rsync "$VSCODE_SRC_PATH/.build/extensions/" "$VSCODE_OUT_PATH/extensions"
|
||||||
|
rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions"
|
||||||
|
rsync "$VSCODE_SRC_PATH/extensions/yarn.lock" "$VSCODE_OUT_PATH/extensions"
|
||||||
|
rsync "$VSCODE_SRC_PATH/extensions/postinstall.js" "$VSCODE_OUT_PATH/extensions"
|
||||||
|
|
||||||
|
mkdir -p "$VSCODE_OUT_PATH/resources/linux"
|
||||||
|
rsync "$VSCODE_SRC_PATH/resources/linux/code.png" "$VSCODE_OUT_PATH/resources/linux/code.png"
|
||||||
|
|
||||||
|
rsync "$VSCODE_SRC_PATH/yarn.lock" "$VSCODE_OUT_PATH"
|
||||||
|
|
||||||
|
# Adds the commit and date to product.json
|
||||||
|
jq --slurp '.[0] * .[1]' "$VSCODE_SRC_PATH/product.json" <(
|
||||||
|
cat << EOF
|
||||||
|
{
|
||||||
|
"commit": "$(git rev-parse HEAD)",
|
||||||
|
"date": $(jq -n 'now | todate')
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
) > "$VSCODE_OUT_PATH/product.json"
|
||||||
|
|
||||||
|
# We remove the scripts field so that later on we can run
|
||||||
|
# yarn to fetch node_modules if necessary without build scripts
|
||||||
|
# being ran.
|
||||||
|
# We cannot use --no-scripts because we still want dependant package scripts to run
|
||||||
|
# for native modules to be rebuilt.
|
||||||
|
jq 'del(.scripts)' < "$VSCODE_SRC_PATH/package.json" > "$VSCODE_OUT_PATH/package.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle_node() {
|
||||||
|
# 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="$(yarn -s node <<< 'console.info(process.execPath)')"
|
||||||
|
|
||||||
|
mkdir -p "$RELEASE_PATH/bin"
|
||||||
|
rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
|
||||||
|
rsync "$node_path" "$RELEASE_PATH/lib/node"
|
||||||
|
|
||||||
|
rsync node_modules "$RELEASE_PATH"
|
||||||
|
rsync "$VSCODE_SRC_PATH/node_modules" "$VSCODE_OUT_PATH"
|
||||||
|
|
||||||
|
if [[ $MINIFY ]]; then
|
||||||
|
pushd "$RELEASE_PATH"
|
||||||
|
yarn --production
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
24
ci/build/build-static-pkgs.sh
Executable file
24
ci/build/build-static-pkgs.sh
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Generates deb and rpm packages for CI.
|
||||||
|
# Assumes a static release has already been built.
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
VERSION="$(pkg_json_version)"
|
||||||
|
export VERSION
|
||||||
|
|
||||||
|
ARCH="$(arch)"
|
||||||
|
export ARCH
|
||||||
|
|
||||||
|
local nfpm_config
|
||||||
|
nfpm_config=$(envsubst < ./ci/build/nfpm.yaml)
|
||||||
|
|
||||||
|
nfpm pkg -f <(echo "$nfpm_config") --target release-github/code-server-"$VERSION-$ARCH.deb"
|
||||||
|
nfpm pkg -f <(echo "$nfpm_config") --target release-github/code-server-"$VERSION-$ARCH.rpm"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
21
ci/build/build-vscode.sh
Executable file
21
ci/build/build-vscode.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Builds vscode into lib/vscode/out-vscode.
|
||||||
|
|
||||||
|
# MINIFY controls whether a minified version of vscode is built.
|
||||||
|
MINIFY=${MINIFY-true}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
cd lib/vscode
|
||||||
|
|
||||||
|
yarn gulp compile-build
|
||||||
|
yarn gulp compile-extensions-build
|
||||||
|
yarn gulp optimize --gulpfile ./coder.js
|
||||||
|
if [[ $MINIFY ]]; then
|
||||||
|
yarn gulp minify --gulpfile ./coder.js
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
|
||||||
git clean -Xffd
|
git clean -Xffd
|
||||||
git submodule foreach --recursive git clean -xffd
|
git submodule foreach --recursive git clean -xffd
|
||||||
git submodule foreach --recursive git reset --hard
|
git submodule foreach --recursive git reset --hard
|
3
ci/build/code-server-nfpm.sh
Executable file
3
ci/build/code-server-nfpm.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
exec /usr/lib/code-server/bin/code-server "$@"
|
@ -1,18 +1,20 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# This script is intended to be bundled into the static releases.
|
||||||
# Runs code-server with the bundled Node binary.
|
# Runs code-server with the bundled Node binary.
|
||||||
|
|
||||||
# More complicated than readlink -f or realpath to support macOS.
|
# More complicated than readlink -f or realpath to support macOS.
|
||||||
# See https://github.com/cdr/code-server/issues/1537
|
# See https://github.com/cdr/code-server/issues/1537
|
||||||
get_installation_dir() {
|
bin_dir() {
|
||||||
# We read the symlink, which may be relative from $0.
|
# We read the symlink, which may be relative from $0.
|
||||||
dst="$(readlink "$0")"
|
dst="$(readlink "$0")"
|
||||||
# We cd into the $0 directory.
|
# We cd into the $0 directory.
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")" || exit 1
|
||||||
# Now we can cd into the dst directory.
|
# Now we can cd into the dst directory.
|
||||||
cd "$(dirname "$dst")"
|
cd "$(dirname "$dst")" || exit 1
|
||||||
# Finally we use pwd -P to print the absolute path of the directory of $dst.
|
# Finally we use pwd -P to print the absolute path of the directory of $dst.
|
||||||
pwd -P
|
pwd -P || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
dir=$(get_installation_dir)
|
BIN_DIR=$(bin_dir)
|
||||||
exec "$dir/node" "$dir/out/node/entry.js" "$@"
|
exec "$BIN_DIR/../lib/node" "$BIN_DIR/.." "$@"
|
16
ci/build/nfpm.yaml
Normal file
16
ci/build/nfpm.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: "code-server"
|
||||||
|
arch: "${ARCH}"
|
||||||
|
platform: "linux"
|
||||||
|
version: "v${VERSION}"
|
||||||
|
section: "devel"
|
||||||
|
priority: "optional"
|
||||||
|
maintainer: "Anmol Sethi <hi@nhooyr.io>"
|
||||||
|
description: |
|
||||||
|
Run VS Code in the browser.
|
||||||
|
vendor: "Coder"
|
||||||
|
homepage: "https://github.com/cdr/code-server"
|
||||||
|
license: "MIT"
|
||||||
|
bindir: "/usr/bin"
|
||||||
|
files:
|
||||||
|
./ci/build/code-server-nfpm.sh: /usr/bin/code-server
|
||||||
|
./release-static/**/*: "/usr/lib/code-server/"
|
@ -1,21 +1,20 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# build-test.bash -- Make sure the build worked.
|
|
||||||
# This is to make sure we don't have Node version errors or any other
|
|
||||||
# compilation-related errors.
|
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
function main() {
|
# Makes sure the release works.
|
||||||
cd "$(dirname "${0}")/.." || exit 1
|
# This is to make sure we don't have Node version errors or any other
|
||||||
|
# compilation-related errors.
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../.."
|
||||||
|
|
||||||
local output
|
local output
|
||||||
output=$(node ./build/out/node/entry.js --list-extensions 2>&1)
|
output=$(./release-static/bin/code-server --list-extensions 2>&1)
|
||||||
if echo "$output" | grep 'was compiled against a different Node.js version'; then
|
if echo "$output" | grep 'was compiled against a different Node.js version'; then
|
||||||
echo "$output"
|
echo "$output"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
|
||||||
echo "Build ran successfully"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "Build ran successfully"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
30
ci/container/Dockerfile
Normal file
30
ci/container/Dockerfile
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
FROM centos:7
|
||||||
|
|
||||||
|
RUN yum update -y && yum install -y \
|
||||||
|
devtoolset-6 \
|
||||||
|
gcc-c++ \
|
||||||
|
xz \
|
||||||
|
ccache \
|
||||||
|
git \
|
||||||
|
wget \
|
||||||
|
openssl \
|
||||||
|
libxkbfile-devel \
|
||||||
|
libsecret-devel \
|
||||||
|
libx11-devel \
|
||||||
|
gettext
|
||||||
|
|
||||||
|
RUN yum install -y epel-release && \
|
||||||
|
yum install -y ShellCheck jq golang
|
||||||
|
|
||||||
|
RUN go get github.com/goreleaser/nfpm/cmd/nfpm
|
||||||
|
ENV PATH=$PATH:/root/go/bin
|
||||||
|
|
||||||
|
RUN mkdir /usr/share/node && cd /usr/share/node \
|
||||||
|
&& curl "https://nodejs.org/dist/v12.16.3/node-v12.16.3-linux-$(uname -m | sed 's/86_//; s/aarch/arm/').tar.xz" | tar xJ --strip-components=1 --
|
||||||
|
ENV PATH "$PATH:/usr/share/node/bin"
|
||||||
|
RUN npm install -g yarn@1.22.4
|
||||||
|
|
||||||
|
RUN curl -L "https://github.com/mvdan/sh/releases/download/v3.0.1/shfmt_v3.0.1_linux_$(uname -m | sed 's/x86_/amd/; s/aarch64/arm/')" > /usr/local/bin/shfmt \
|
||||||
|
&& chmod +x /usr/local/bin/shfmt
|
||||||
|
|
||||||
|
ENTRYPOINT ["/bin/bash", "-c"]
|
24
ci/container/exec.sh
Executable file
24
ci/container/exec.sh
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
docker build ci/container
|
||||||
|
imageTag="$(docker build -q ci/container)"
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
-e CI \
|
||||||
|
-e GITHUB_TOKEN \
|
||||||
|
-e TRAVIS_TAG \
|
||||||
|
-e NPM_TOKEN \
|
||||||
|
-v "$(yarn cache dir):/usr/local/share/.cache/yarn/v6" \
|
||||||
|
$(if [[ -f ~/.npmrc ]]; then echo -v "$HOME/.npmrc:/root/.npmrc"; fi) \
|
||||||
|
-v "$PWD:/repo" \
|
||||||
|
-w /repo \
|
||||||
|
$(if [[ -t 0 ]]; then echo -it; fi) \
|
||||||
|
"$imageTag" \
|
||||||
|
"$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -1,49 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# exec.sh opens an interactive bash session inside of a docker container
|
|
||||||
# for improved isolation during development
|
|
||||||
# if the container exists it is restarted if necessary, then reused
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
# Ensure submodules are cloned and up to date.
|
|
||||||
git submodule update --init
|
|
||||||
|
|
||||||
container_name=code-server-dev
|
|
||||||
|
|
||||||
enter() {
|
|
||||||
echo "--- Entering $container_name"
|
|
||||||
docker exec -it $container_id /bin/bash
|
|
||||||
}
|
|
||||||
|
|
||||||
run() {
|
|
||||||
echo "--- Spawning $container_name"
|
|
||||||
container_id=$(docker run \
|
|
||||||
-it \
|
|
||||||
--name $container_name \
|
|
||||||
"-v=$PWD:/code-server" \
|
|
||||||
"-w=/code-server" \
|
|
||||||
"-p=127.0.0.1:8080:8080" \
|
|
||||||
$([[ -t 0 ]] && echo -it || true) \
|
|
||||||
$container_name)
|
|
||||||
}
|
|
||||||
|
|
||||||
build() {
|
|
||||||
echo "--- Building $container_name"
|
|
||||||
cd ../../
|
|
||||||
docker build -t $container_name -f ./ci/dev-image/Dockerfile . > /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
container_id=$(docker container inspect --format="{{.Id}}" $container_name 2> /dev/null) || true
|
|
||||||
|
|
||||||
if [ "$container_id" != "" ]; then
|
|
||||||
echo "-- Starting container"
|
|
||||||
docker start $container_id > /dev/null
|
|
||||||
|
|
||||||
enter
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
build
|
|
||||||
run
|
|
||||||
enter
|
|
@ -2,7 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
yarn fmt
|
yarn fmt
|
||||||
yarn lint
|
yarn lint
|
48
ci/dev/container/exec.sh
Executable file
48
ci/dev/container/exec.sh
Executable file
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Opens an interactive bash session inside of a docker container
|
||||||
|
# for improved isolation during development.
|
||||||
|
# If the container exists it is restarted if necessary, then reused.
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "${0}")/../../.."
|
||||||
|
|
||||||
|
local container_name=code-server-dev
|
||||||
|
|
||||||
|
if docker inspect $container_name &> /dev/null; then
|
||||||
|
echo "-- Starting container"
|
||||||
|
docker start "$container_name" > /dev/null
|
||||||
|
|
||||||
|
enter
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
build
|
||||||
|
run
|
||||||
|
enter
|
||||||
|
}
|
||||||
|
|
||||||
|
enter() {
|
||||||
|
echo "--- Entering $container_name"
|
||||||
|
docker exec -it "$container_name" /bin/bash
|
||||||
|
}
|
||||||
|
|
||||||
|
run() {
|
||||||
|
echo "--- Spawning $container_name"
|
||||||
|
docker run \
|
||||||
|
-it \
|
||||||
|
--name $container_name \
|
||||||
|
"-v=$PWD:/code-server" \
|
||||||
|
"-w=/code-server" \
|
||||||
|
"-p=127.0.0.1:8080:8080" \
|
||||||
|
$(if [[ -t 0 ]]; then echo -it; fi) \
|
||||||
|
"$container_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
echo "--- Building $container_name"
|
||||||
|
docker build -t $container_name ./ci/dev/container > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
shfmt -i 2 -w -s -sr $(git ls-files "*.sh")
|
shfmt -i 2 -w -s -sr $(git ls-files "*.sh")
|
||||||
|
|
||||||
local prettierExts
|
local prettierExts
|
@ -1,11 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
eslint --max-warnings=0 --fix $(git ls-files "*.ts" "*.tsx" "*.js")
|
eslint --max-warnings=0 --fix $(git ls-files "*.ts" "*.tsx" "*.js")
|
||||||
stylelint $(git ls-files "*.css")
|
stylelint $(git ls-files "*.css")
|
||||||
tsc --noEmit
|
tsc --noEmit
|
||||||
|
shellcheck -e SC2046,SC2164 $(git ls-files "*.sh")
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
10
ci/dev/test.sh
Executable file
10
ci/dev/test.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
mocha -r ts-node/register ./test/*.test.ts
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -50,7 +50,7 @@ index 7a2320d828..5768890636 100644
|
|||||||
yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron
|
yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron
|
||||||
diff --git a/coder.js b/coder.js
|
diff --git a/coder.js b/coder.js
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000..d0a8f37714
|
index 0000000000..0170b47241
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/coder.js
|
+++ b/coder.js
|
||||||
@@ -0,0 +1,69 @@
|
@@ -0,0 +1,69 @@
|
||||||
@ -83,7 +83,7 @@ index 0000000000..d0a8f37714
|
|||||||
+ "out-build/bootstrap-fork.js",
|
+ "out-build/bootstrap-fork.js",
|
||||||
+ "out-build/bootstrap-amd.js",
|
+ "out-build/bootstrap-amd.js",
|
||||||
+ "out-build/paths.js",
|
+ "out-build/paths.js",
|
||||||
+ 'out-build/vs/**/*.{svg,png,html}',
|
+ 'out-build/vs/**/*.{svg,png,html,ttf}',
|
||||||
+ "!out-build/vs/code/browser/workbench/*.html",
|
+ "!out-build/vs/code/browser/workbench/*.html",
|
||||||
+ '!out-build/vs/code/electron-browser/**',
|
+ '!out-build/vs/code/electron-browser/**',
|
||||||
+ "out-build/vs/base/common/performance.js",
|
+ "out-build/vs/base/common/performance.js",
|
@ -5,7 +5,7 @@ set -euo pipefail
|
|||||||
# 2. Patches it.
|
# 2. Patches it.
|
||||||
# 3. Installs it.
|
# 3. Installs it.
|
||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
|
|
163
ci/dev/watch.ts
Normal file
163
ci/dev/watch.ts
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
import * as cp from "child_process"
|
||||||
|
import Bundler from "parcel-bundler"
|
||||||
|
import * as path from "path"
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const watcher = new Watcher()
|
||||||
|
await watcher.watch()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error.message)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Watcher {
|
||||||
|
private readonly rootPath = path.resolve(__dirname, "../..")
|
||||||
|
private readonly vscodeSourcePath = path.join(this.rootPath, "lib/vscode")
|
||||||
|
|
||||||
|
private static log(message: string, skipNewline = false): void {
|
||||||
|
process.stdout.write(message)
|
||||||
|
if (!skipNewline) {
|
||||||
|
process.stdout.write("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async watch(): Promise<void> {
|
||||||
|
let server: cp.ChildProcess | undefined
|
||||||
|
const restartServer = (): void => {
|
||||||
|
if (server) {
|
||||||
|
server.kill()
|
||||||
|
}
|
||||||
|
const s = cp.fork(path.join(this.rootPath, "out/node/entry.js"), process.argv.slice(2))
|
||||||
|
console.log(`[server] spawned process ${s.pid}`)
|
||||||
|
s.on("exit", () => console.log(`[server] process ${s.pid} exited`))
|
||||||
|
server = s
|
||||||
|
}
|
||||||
|
|
||||||
|
const vscode = cp.spawn("yarn", ["watch"], { cwd: this.vscodeSourcePath })
|
||||||
|
const tsc = cp.spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath })
|
||||||
|
const bundler = this.createBundler()
|
||||||
|
|
||||||
|
const cleanup = (code?: number | null): void => {
|
||||||
|
Watcher.log("killing vs code watcher")
|
||||||
|
vscode.removeAllListeners()
|
||||||
|
vscode.kill()
|
||||||
|
|
||||||
|
Watcher.log("killing tsc")
|
||||||
|
tsc.removeAllListeners()
|
||||||
|
tsc.kill()
|
||||||
|
|
||||||
|
if (server) {
|
||||||
|
Watcher.log("killing server")
|
||||||
|
server.removeAllListeners()
|
||||||
|
server.kill()
|
||||||
|
}
|
||||||
|
|
||||||
|
Watcher.log("killing bundler")
|
||||||
|
process.exit(code || 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
process.on("SIGINT", () => cleanup())
|
||||||
|
process.on("SIGTERM", () => cleanup())
|
||||||
|
|
||||||
|
vscode.on("exit", (code) => {
|
||||||
|
Watcher.log("vs code watcher terminated unexpectedly")
|
||||||
|
cleanup(code)
|
||||||
|
})
|
||||||
|
tsc.on("exit", (code) => {
|
||||||
|
Watcher.log("tsc terminated unexpectedly")
|
||||||
|
cleanup(code)
|
||||||
|
})
|
||||||
|
const bundle = bundler.bundle().catch(() => {
|
||||||
|
Watcher.log("parcel watcher terminated unexpectedly")
|
||||||
|
cleanup(1)
|
||||||
|
})
|
||||||
|
bundler.on("buildEnd", () => {
|
||||||
|
console.log("[parcel] bundled")
|
||||||
|
})
|
||||||
|
bundler.on("buildError", (error) => {
|
||||||
|
console.error("[parcel]", error)
|
||||||
|
})
|
||||||
|
|
||||||
|
vscode.stderr.on("data", (d) => process.stderr.write(d))
|
||||||
|
tsc.stderr.on("data", (d) => process.stderr.write(d))
|
||||||
|
|
||||||
|
// From https://github.com/chalk/ansi-regex
|
||||||
|
const pattern = [
|
||||||
|
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
|
||||||
|
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))",
|
||||||
|
].join("|")
|
||||||
|
const re = new RegExp(pattern, "g")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split stdout on newlines and strip ANSI codes.
|
||||||
|
*/
|
||||||
|
const onLine = (proc: cp.ChildProcess, callback: (strippedLine: string, originalLine: string) => void): void => {
|
||||||
|
let buffer = ""
|
||||||
|
if (!proc.stdout) {
|
||||||
|
throw new Error("no stdout")
|
||||||
|
}
|
||||||
|
proc.stdout.setEncoding("utf8")
|
||||||
|
proc.stdout.on("data", (d) => {
|
||||||
|
const data = buffer + d
|
||||||
|
const split = data.split("\n")
|
||||||
|
const last = split.length - 1
|
||||||
|
|
||||||
|
for (let i = 0; i < last; ++i) {
|
||||||
|
callback(split[i].replace(re, ""), split[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last item will either be an empty string (the data ended with a
|
||||||
|
// newline) or a partial line (did not end with a newline) and we must
|
||||||
|
// wait to parse it until we get a full line.
|
||||||
|
buffer = split[last]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let startingVscode = false
|
||||||
|
let startedVscode = false
|
||||||
|
onLine(vscode, (line, original) => {
|
||||||
|
console.log("[vscode]", original)
|
||||||
|
// Wait for watch-client since "Finished compilation" will appear multiple
|
||||||
|
// times before the client starts building.
|
||||||
|
if (!startingVscode && line.includes("Starting watch-client")) {
|
||||||
|
startingVscode = true
|
||||||
|
} else if (startingVscode && line.includes("Finished compilation")) {
|
||||||
|
if (startedVscode) {
|
||||||
|
bundle.then(restartServer)
|
||||||
|
}
|
||||||
|
startedVscode = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onLine(tsc, (line, original) => {
|
||||||
|
// tsc outputs blank lines; skip them.
|
||||||
|
if (line !== "") {
|
||||||
|
console.log("[tsc]", original)
|
||||||
|
}
|
||||||
|
if (line.includes("Watching for file changes")) {
|
||||||
|
bundle.then(restartServer)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private createBundler(out = "dist"): Bundler {
|
||||||
|
return new Bundler(
|
||||||
|
[
|
||||||
|
path.join(this.rootPath, "src/browser/pages/app.ts"),
|
||||||
|
path.join(this.rootPath, "src/browser/register.ts"),
|
||||||
|
path.join(this.rootPath, "src/browser/serviceWorker.ts"),
|
||||||
|
],
|
||||||
|
{
|
||||||
|
outDir: path.join(this.rootPath, out),
|
||||||
|
cacheDir: path.join(this.rootPath, ".cache"),
|
||||||
|
minify: !!process.env.MINIFY,
|
||||||
|
logLevel: 1,
|
||||||
|
publicUrl: "/static/development/dist",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
@ -1,23 +0,0 @@
|
|||||||
FROM centos:7
|
|
||||||
|
|
||||||
RUN yum update -y && yum install -y \
|
|
||||||
devtoolset-6 \
|
|
||||||
gcc-c++ \
|
|
||||||
xz \
|
|
||||||
ccache \
|
|
||||||
git \
|
|
||||||
wget \
|
|
||||||
openssl \
|
|
||||||
libxkbfile-devel \
|
|
||||||
libsecret-devel \
|
|
||||||
libx11-devel
|
|
||||||
|
|
||||||
RUN mkdir /usr/share/node && cd /usr/share/node \
|
|
||||||
&& curl "https://nodejs.org/dist/v12.16.3/node-v12.16.3-linux-$(uname -m | sed 's/86_//; s/aarch/arm/').tar.xz" | tar xJ --strip-components=1 --
|
|
||||||
ENV PATH "$PATH:/usr/share/node/bin"
|
|
||||||
RUN npm install -g yarn@1.22.4
|
|
||||||
|
|
||||||
RUN curl -L "https://github.com/mvdan/sh/releases/download/v3.0.1/shfmt_v3.0.1_linux_$(uname -m | sed 's/x86_/amd/; s/aarch64/arm/')" > /usr/local/bin/shfmt \
|
|
||||||
&& chmod +x /usr/local/bin/shfmt
|
|
||||||
|
|
||||||
ENTRYPOINT ["/bin/bash", "-c"]
|
|
@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
main() {
|
|
||||||
cd "$(dirname "$0")/../.."
|
|
||||||
|
|
||||||
# This, strangely enough, fixes the arm build being terminated for not having
|
|
||||||
# output on Travis. It's as if output is buffered and only displayed once a
|
|
||||||
# certain amount is collected. Five seconds didn't work but one second seems
|
|
||||||
# to generate enough output to make it work.
|
|
||||||
local pid
|
|
||||||
while true; do
|
|
||||||
echo 'Still running...'
|
|
||||||
sleep 1
|
|
||||||
done &
|
|
||||||
pid=$!
|
|
||||||
|
|
||||||
docker build ci/image
|
|
||||||
imageTag="$(docker build -q ci/image)"
|
|
||||||
docker run -t --rm -e CI -e GITHUB_TOKEN -e TRAVIS_TAG -v "$(yarn cache dir):/usr/local/share/.cache/yarn/v6" -v "$PWD:/repo" -w /repo "$imageTag" "$*"
|
|
||||||
|
|
||||||
kill $pid
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
47
ci/lib.sh
Normal file → Executable file
47
ci/lib.sh
Normal file → Executable file
@ -1,10 +1,43 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
set_version() {
|
pushd() {
|
||||||
local code_server_version=${VERSION:-${TRAVIS_TAG:-}}
|
builtin pushd "$@" > /dev/null
|
||||||
if [[ -z $code_server_version ]]; then
|
}
|
||||||
code_server_version=$(grep version ./package.json | head -1 | awk -F: '{ print $2 }' | sed 's/[",]//g' | tr -d '[:space:]')
|
|
||||||
fi
|
popd() {
|
||||||
export VERSION=$code_server_version
|
builtin popd > /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
pkg_json_version() {
|
||||||
|
jq -r .version package.json
|
||||||
|
}
|
||||||
|
|
||||||
|
os() {
|
||||||
|
local os
|
||||||
|
os=$(uname | tr '[:upper:]' '[:lower:]')
|
||||||
|
if [[ $os == "linux" ]]; then
|
||||||
|
# Alpine's ldd doesn't have a version flag but if you use an invalid flag
|
||||||
|
# (like --version) it outputs the version to stderr and exits with 1.
|
||||||
|
local ldd_output
|
||||||
|
ldd_output=$(ldd --version 2>&1 || true)
|
||||||
|
if echo "$ldd_output" | grep -iq musl; then
|
||||||
|
os="alpine"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "$os"
|
||||||
|
}
|
||||||
|
|
||||||
|
arch() {
|
||||||
|
case "$(uname -m)" in
|
||||||
|
aarch64)
|
||||||
|
echo arm64
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
echo amd64
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown architecture $(uname -a)"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ RUN apt-get update \
|
|||||||
ssh \
|
ssh \
|
||||||
sudo \
|
sudo \
|
||||||
vim \
|
vim \
|
||||||
|
lsb-release \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# https://wiki.debian.org/Locale#Manually
|
# https://wiki.debian.org/Locale#Manually
|
||||||
@ -26,18 +27,20 @@ ENV SHELL=/bin/bash
|
|||||||
RUN adduser --gecos '' --disabled-password coder && \
|
RUN adduser --gecos '' --disabled-password coder && \
|
||||||
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd
|
||||||
|
|
||||||
RUN curl -SsL https://github.com/boxboat/fixuid/releases/download/v0.4/fixuid-0.4-linux-amd64.tar.gz | tar -C /usr/local/bin -xzf - && \
|
SHELL ["/bin/bash", "-c"]
|
||||||
|
|
||||||
|
COPY ci/lib.sh /tmp/lib.sh
|
||||||
|
RUN source /tmp/lib.sh && rm /tmp/lib.sh && \
|
||||||
|
curl -L "https://github.com/boxboat/fixuid/releases/download/v0.4.1/fixuid-0.4.1-linux-$(arch).tar.gz" | tar -C /usr/local/bin -xzf - && \
|
||||||
chown root:root /usr/local/bin/fixuid && \
|
chown root:root /usr/local/bin/fixuid && \
|
||||||
chmod 4755 /usr/local/bin/fixuid && \
|
chmod 4755 /usr/local/bin/fixuid && \
|
||||||
mkdir -p /etc/fixuid && \
|
mkdir -p /etc/fixuid && \
|
||||||
printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
|
printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml
|
||||||
|
|
||||||
COPY release/code-server*.tar.gz /tmp/
|
COPY release-github/code-server*.deb /tmp/
|
||||||
RUN cd /tmp && tar -xzf code-server*.tar.gz && rm code-server*.tar.gz && \
|
RUN dpkg -i /tmp/code-server*.deb && rm /tmp/code-server*.deb
|
||||||
mv code-server* /usr/local/lib/code-server && \
|
|
||||||
ln -s /usr/local/lib/code-server/code-server /usr/local/bin/code-server
|
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
USER coder
|
USER coder
|
||||||
WORKDIR /home/coder
|
WORKDIR /home/coder
|
||||||
ENTRYPOINT ["dumb-init", "fixuid", "-q", "/usr/local/bin/code-server", "--bind-addr", "0.0.0.0:8080", "."]
|
ENTRYPOINT ["dumb-init", "fixuid", "-q", "/usr/bin/code-server", "--bind-addr", "0.0.0.0:8080", "."]
|
@ -5,18 +5,21 @@ set -euo pipefail
|
|||||||
main() {
|
main() {
|
||||||
cd "$(dirname "$0")/../.."
|
cd "$(dirname "$0")/../.."
|
||||||
source ./ci/lib.sh
|
source ./ci/lib.sh
|
||||||
set_version
|
VERSION="$(pkg_json_version)"
|
||||||
|
|
||||||
if [[ ${CI:-} ]]; then
|
if [[ ${CI-} ]]; then
|
||||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
imageTag="codercom/code-server:$VERSION"
|
imageTag="codercom/code-server:$VERSION"
|
||||||
if [[ ${TRAVIS_CPU_ARCH:-} == "arm64" ]]; then
|
if [[ $(arch) == "arm64" ]]; then
|
||||||
imageTag+="-arm64"
|
imageTag+="-arm64"
|
||||||
fi
|
fi
|
||||||
docker build -t "$imageTag" -f ./ci/release-image/Dockerfile .
|
|
||||||
docker push codercom/code-server
|
docker build \
|
||||||
|
-t "$imageTag" \
|
||||||
|
-f ./ci/release-container/Dockerfile .
|
||||||
|
docker push "$imageTag"
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
@ -1,76 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# ci.bash -- Build code-server in the CI.
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
function package() {
|
|
||||||
local target
|
|
||||||
target=$(uname | tr '[:upper:]' '[:lower:]')
|
|
||||||
if [[ $target == "linux" ]]; then
|
|
||||||
# Alpine's ldd doesn't have a version flag but if you use an invalid flag
|
|
||||||
# (like --version) it outputs the version to stderr and exits with 1.
|
|
||||||
local ldd_output
|
|
||||||
ldd_output=$(ldd --version 2>&1 || true)
|
|
||||||
if echo "$ldd_output" | grep -iq musl; then
|
|
||||||
target="alpine"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
local arch
|
|
||||||
arch=$(uname -m | sed 's/aarch/arm/')
|
|
||||||
|
|
||||||
echo -n "Creating release..."
|
|
||||||
|
|
||||||
cp "$(command -v node)" ./build
|
|
||||||
cp README.md ./build
|
|
||||||
cp LICENSE.txt ./build
|
|
||||||
cp ./lib/vscode/ThirdPartyNotices.txt ./build
|
|
||||||
cp ./ci/code-server.sh ./build/code-server
|
|
||||||
|
|
||||||
local archive_name="code-server-$VERSION-$target-$arch"
|
|
||||||
mkdir -p ./release
|
|
||||||
|
|
||||||
local ext
|
|
||||||
if [[ $target == "linux" ]]; then
|
|
||||||
ext=".tar.gz"
|
|
||||||
tar -czf "release/$archive_name$ext" --transform "s/^\.\/build/$archive_name/" ./build
|
|
||||||
else
|
|
||||||
mv ./build "./$archive_name"
|
|
||||||
ext=".zip"
|
|
||||||
zip -r "release/$archive_name$ext" "./$archive_name"
|
|
||||||
mv "./$archive_name" ./build
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "done (release/$archive_name)"
|
|
||||||
|
|
||||||
# release-upload is for uploading to the GCP bucket whereas release is used for GitHub.
|
|
||||||
mkdir -p "./release-upload/$VERSION"
|
|
||||||
cp "./release/$archive_name$ext" "./release-upload/$VERSION/$target-$arch$ext"
|
|
||||||
mkdir -p "./release-upload/latest"
|
|
||||||
cp "./release/$archive_name$ext" "./release-upload/latest/$target-$arch$ext"
|
|
||||||
}
|
|
||||||
|
|
||||||
# This script assumes that yarn has already ran.
|
|
||||||
function build() {
|
|
||||||
# Always minify and package on CI.
|
|
||||||
if [[ ${CI:-} ]]; then
|
|
||||||
export MINIFY="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
yarn build
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
cd "$(dirname "${0}")/.."
|
|
||||||
source ./ci/lib.sh
|
|
||||||
|
|
||||||
set_version
|
|
||||||
|
|
||||||
build
|
|
||||||
|
|
||||||
if [[ ${CI:-} ]]; then
|
|
||||||
package
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
26
ci/steps/linux-release.sh
Executable file
26
ci/steps/linux-release.sh
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
source ./ci/lib.sh
|
||||||
|
|
||||||
|
if [[ $(arch) == arm64 ]]; then
|
||||||
|
# This, strangely enough, fixes the arm build being terminated for not having
|
||||||
|
# output on Travis. It's as if output is buffered and only displayed once a
|
||||||
|
# certain amount is collected. Five seconds didn't work but one second seems
|
||||||
|
# to generate enough output to make it work.
|
||||||
|
while true; do
|
||||||
|
echo 'Still running...'
|
||||||
|
sleep 1
|
||||||
|
done &
|
||||||
|
trap "exit" INT TERM
|
||||||
|
trap "kill 0" EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
./ci/container/exec.sh ./ci/steps/static-release.sh
|
||||||
|
./ci/container/exec.sh yarn pkg
|
||||||
|
./ci/release-container/push.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
11
ci/steps/publish-npm.sh
Executable file
11
ci/steps/publish-npm.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||||
|
./ci/container/exec.sh yarn publish --non-interactive release
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
16
ci/steps/static-release.sh
Executable file
16
ci/steps/static-release.sh
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
yarn
|
||||||
|
yarn vscode
|
||||||
|
yarn build
|
||||||
|
yarn build:vscode
|
||||||
|
STATIC=1 yarn release
|
||||||
|
./ci/build/test-static-release.sh
|
||||||
|
./ci/build/archive-static-release.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
17
ci/steps/test.sh
Executable file
17
ci/steps/test.sh
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cd "$(dirname "$0")/../.."
|
||||||
|
|
||||||
|
yarn
|
||||||
|
|
||||||
|
git submodule update --init
|
||||||
|
# We do not `yarn vscode` to make test.sh faster.
|
||||||
|
# If the patch fails to apply, then it's likely already applied
|
||||||
|
yarn vscode:patch &> /dev/null || true
|
||||||
|
|
||||||
|
yarn ci
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../tsconfig.json",
|
|
||||||
"include": ["./**/*.ts"]
|
|
||||||
}
|
|
@ -1,5 +1,8 @@
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
|
- [Detailed CI and build process docs](../ci)
|
||||||
|
- [Our VS Code Web docs](../src/node/app)
|
||||||
|
|
||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
- [VS Code prerequisites](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites)
|
- [VS Code prerequisites](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites)
|
||||||
@ -13,7 +16,7 @@ yarn watch # Visit http://localhost:8080 once completed.
|
|||||||
To develop inside of an isolated docker container:
|
To develop inside of an isolated docker container:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
./ci/dev-image/exec.sh
|
./ci/dev/container/exec.sh
|
||||||
|
|
||||||
root@12345:/code-server# yarn
|
root@12345:/code-server# yarn
|
||||||
root@12345:/code-server# yarn vscode
|
root@12345:/code-server# yarn vscode
|
||||||
@ -36,5 +39,7 @@ works internally.
|
|||||||
yarn
|
yarn
|
||||||
yarn vscode
|
yarn vscode
|
||||||
yarn build
|
yarn build
|
||||||
node ./build/out/node/entry.js # Run the built JavaScript with Node.
|
yarn build:vscode
|
||||||
|
yarn release
|
||||||
|
node ./release # Run the built JavaScript with Node.
|
||||||
```
|
```
|
||||||
|
53
package.json
53
package.json
@ -1,19 +1,30 @@
|
|||||||
{
|
{
|
||||||
"name": "code-server",
|
"name": "code-server",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"version": "3.3.0",
|
"version": "3.3.0-rc.7",
|
||||||
"scripts": {
|
"description": "Run VS Code on a remote server.",
|
||||||
"clean": "ci/clean.sh",
|
"homepage": "https://github.com/cdr/code-server",
|
||||||
"vscode": "ci/vscode.sh",
|
"bugs": {
|
||||||
"vscode:patch": "cd ./lib/vscode && git apply ../../ci/vscode.patch",
|
"url": "https://github.com/cdr/code-server/issues"
|
||||||
"vscode:diff": "cd ./lib/vscode && git diff HEAD > ../../ci/vscode.patch",
|
|
||||||
"test": "mocha -r ts-node/register ./test/*.test.ts",
|
|
||||||
"lint": "ci/lint.sh",
|
|
||||||
"fmt": "ci/fmt.sh",
|
|
||||||
"runner": "cd ./ci && NODE_OPTIONS=--max_old_space_size=32384 ts-node ./build.ts",
|
|
||||||
"build": "yarn runner build",
|
|
||||||
"watch": "yarn runner watch"
|
|
||||||
},
|
},
|
||||||
|
"repository": "https://github.com/cdr/code-server",
|
||||||
|
"scripts": {
|
||||||
|
"clean": "./ci/build/clean.sh",
|
||||||
|
"vscode": "./ci/dev/vscode.sh",
|
||||||
|
"vscode:patch": "cd ./lib/vscode && git apply ../../ci/dev/vscode.patch",
|
||||||
|
"vscode:diff": "cd ./lib/vscode && git diff HEAD > ../../ci/dev/vscode.patch",
|
||||||
|
"build": "./ci/build/build-code-server.sh",
|
||||||
|
"build:vscode": "./ci/build/build-vscode.sh",
|
||||||
|
"release": "./ci/build/build-release.sh",
|
||||||
|
"pkg": "./ci/build/build-static-pkgs.sh",
|
||||||
|
"_____": "",
|
||||||
|
"fmt": "./ci/dev/fmt.sh",
|
||||||
|
"lint": "./ci/dev/lint.sh",
|
||||||
|
"test": "./ci/dev/test.sh",
|
||||||
|
"ci": "./ci/dev/ci.sh",
|
||||||
|
"watch": "NODE_OPTIONS=--max_old_space_size=32384 ts-node ./ci/dev/watch.ts"
|
||||||
|
},
|
||||||
|
"main": "out/node/entry.js",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/adm-zip": "^0.4.32",
|
"@types/adm-zip": "^0.4.32",
|
||||||
"@types/fs-extra": "^8.0.1",
|
"@types/fs-extra": "^8.0.1",
|
||||||
@ -40,7 +51,8 @@
|
|||||||
"stylelint": "^13.0.0",
|
"stylelint": "^13.0.0",
|
||||||
"stylelint-config-recommended": "^3.0.0",
|
"stylelint-config-recommended": "^3.0.0",
|
||||||
"ts-node": "^8.4.1",
|
"ts-node": "^8.4.1",
|
||||||
"typescript": "3.7.2"
|
"typescript": "3.7.2",
|
||||||
|
"yarn": "^1.22.4"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"@types/node": "^12.12.7",
|
"@types/node": "^12.12.7",
|
||||||
@ -48,7 +60,7 @@
|
|||||||
"vfile-message": "^2.0.2"
|
"vfile-message": "^2.0.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coder/logger": "1.1.11",
|
"@coder/logger": "1.1.14",
|
||||||
"adm-zip": "^0.4.14",
|
"adm-zip": "^0.4.14",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"http-proxy": "^1.18.0",
|
"http-proxy": "^1.18.0",
|
||||||
@ -60,5 +72,16 @@
|
|||||||
"tar": "^6.0.1",
|
"tar": "^6.0.1",
|
||||||
"tar-fs": "^2.0.0",
|
"tar-fs": "^2.0.0",
|
||||||
"ws": "^7.2.0"
|
"ws": "^7.2.0"
|
||||||
}
|
},
|
||||||
|
"bin": {
|
||||||
|
"code-server": "out/node/entry.js"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"vscode",
|
||||||
|
"development",
|
||||||
|
"ide",
|
||||||
|
"coder",
|
||||||
|
"vscode-remote",
|
||||||
|
"browser-ide"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# app
|
||||||
|
|
||||||
Implementation of [VS Code](https://code.visualstudio.com/) remote/web for use
|
Implementation of [VS Code](https://code.visualstudio.com/) remote/web for use
|
||||||
in `code-server`.
|
in `code-server`.
|
||||||
|
|
||||||
|
13
yarn.lock
13
yarn.lock
@ -792,10 +792,10 @@
|
|||||||
lodash "^4.17.13"
|
lodash "^4.17.13"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@coder/logger@1.1.11":
|
"@coder/logger@1.1.14":
|
||||||
version "1.1.11"
|
version "1.1.14"
|
||||||
resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.11.tgz#e6f36dba9436ae61e66e3f66787d75c768617605"
|
resolved "https://registry.yarnpkg.com/@coder/logger/-/logger-1.1.14.tgz#0242da33e0245834361dd078e31280fc1c976b7e"
|
||||||
integrity sha512-EEh1dqSU0AaqjjjMsVqumgZGbrZimKFKIb4t5E6o3FLfVUxJCReSME78Yj2N1xWUVAHMnqafDCxLostpuIotzw==
|
integrity sha512-NuTvsOH3dqrXn/8Pbs5zy7l0gLqOSC/TPRl3nexdP/897lgG/vtHNQHrUwTBTzTzihH1ON4lklDxJjY0hD4UPg==
|
||||||
|
|
||||||
"@iarna/toml@^2.2.0":
|
"@iarna/toml@^2.2.0":
|
||||||
version "2.2.5"
|
version "2.2.5"
|
||||||
@ -7471,6 +7471,11 @@ yargs@^14.0.0:
|
|||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^15.0.1"
|
yargs-parser "^15.0.1"
|
||||||
|
|
||||||
|
yarn@^1.22.4:
|
||||||
|
version "1.22.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.4.tgz#01c1197ca5b27f21edc8bc472cd4c8ce0e5a470e"
|
||||||
|
integrity sha512-oYM7hi/lIWm9bCoDMEWgffW8aiNZXCWeZ1/tGy0DWrN6vmzjCXIKu2Y21o8DYVBUtiktwKcNoxyGl/2iKLUNGA==
|
||||||
|
|
||||||
yn@3.1.1:
|
yn@3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||||
|
Reference in New Issue
Block a user