Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot]
74e8b0c4f5 Bump follow-redirects from 1.16.0 to 1.16.1
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.16.0 to 1.16.1.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.16.0...v1.16.1)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-version: 1.16.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-10-20 18:52:32 +00:00
Harsh Bhanushali
f07405cba3 Expand ~ in path options from the config file (#8055)
The shell expands ~ in command-line arguments, but values read from
config.yaml were passed to path.resolve as-is, so
`user-data-dir: ~/.config/code-server-data` resolved to
`<cwd>/~/.config/code-server-data`.
2026-10-14 13:47:08 -08:00
dependabot[bot]
c5fee2d2f9 Bump brace-expansion from 1.1.18 to 1.1.21 (#8044) 2026-10-13 17:02:46 -08:00
Harsh Bhanushali
83670e50c6 Fix false booleans in config file being parsed as true (#8053)
Options like `enable-remote-storage: false` in config.yaml are converted to
`--enable-remote-storage=false`, but the parser set any boolean option to
true regardless of its value. Booleans set to false are now ignored, the
same way optional strings set to false already are.
2026-10-13 17:01:10 -08:00
KeuqS
41cf6f7eaf Add Turkish locale (#8050) 2026-10-09 22:50:17 +00:00
cdrci
78aad47ce6 Update Helm chart and changelog with 4.141.0 (#8045) 2026-10-08 02:35:52 -08:00
11 changed files with 99 additions and 16 deletions

View File

@@ -22,6 +22,8 @@ Code v99.99.999
## Unreleased
## [4.141.0](https://github.com/coder/code-server/releases/tag/v4.141.0) - 2026-10-08
Code v1.141.0
### Added

View File

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

View File

@@ -6,7 +6,7 @@ replicaCount: 1
image:
repository: codercom/code-server
tag: '4.140.0'
tag: '4.141.0'
pullPolicy: Always
# Specifies one or more secrets to be used when pulling images from a

18
package-lock.json generated
View File

@@ -1055,9 +1055,9 @@
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "5.0.9",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
"integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1779,9 +1779,9 @@
"license": "BSD-2-Clause"
},
"node_modules/brace-expansion": {
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz",
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
"version": "1.1.21",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz",
"integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3245,9 +3245,9 @@
"license": "ISC"
},
"node_modules/follow-redirects": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.1.tgz",
"integrity": "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg==",
"funding": [
{
"type": "individual",

View File

@@ -3,7 +3,7 @@ import * as crypto from "crypto"
import { promises as fs } from "fs"
import { load } from "js-yaml"
import * as path from "path"
import { generateCertificate, generatePassword, paths, splitOnFirstEquals } from "./util"
import { expandTilde, generateCertificate, generatePassword, paths, splitOnFirstEquals } from "./util"
import { EditorSessionManagerClient } from "./vscodeSocket"
export enum Feature {
@@ -436,7 +436,11 @@ export const parse = (
const option = options[key]
if (option.type === "boolean") {
;(args[key] as boolean) = true
// Booleans set to false (for example `--flag=false`, which is also how
// false values from the config file are passed in) are ignored.
if (value !== "false") {
;(args[key] as boolean) = true
}
continue
}
@@ -462,7 +466,7 @@ export const parse = (
}
if (option.path) {
value = path.resolve(value)
value = path.resolve(expandTilde(value))
}
switch (option.type) {

View File

@@ -3,6 +3,7 @@ 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 tr from "./locales/tr.json"
import * as ur from "./locales/ur.json"
import * as zhCn from "./locales/zh-cn.json"
@@ -16,6 +17,9 @@ const defaultResources = {
th: {
translation: th,
},
tr: {
translation: tr,
},
ja: {
translation: ja,
},

View File

@@ -0,0 +1,13 @@
{
"LOGIN_TITLE": "{{app}} girişi",
"LOGIN_BELOW": "Lütfen aşağıdan giriş yapın.",
"WELCOME": "{{app}} uygulamasına hoş geldiniz",
"LOGIN_PASSWORD": "Parola için yapılandırma dosyasını kontrol edin.",
"LOGIN_USING_ENV_PASSWORD": "Parola $PASSWORD ortam değişkeninden ayarlandı.",
"LOGIN_USING_HASHED_PASSWORD": "Parola $HASHED_PASSWORD ortam değişkeninden ayarlandı.",
"SUBMIT": "GÖNDER",
"PASSWORD_PLACEHOLDER": "PAROLA",
"LOGIN_RATE_LIMIT": "Giriş denemesi sınırına ulaşıldı!",
"MISS_PASSWORD": "Parola eksik",
"INCORRECT_PASSWORD": "Parola yanlış."
}

View File

@@ -511,3 +511,18 @@ export function splitOnFirstEquals(str: string): [string, string | undefined] {
const split = str.split(/=(.+)?/, 2)
return [split[0], split[1]]
}
/**
* Expand a leading `~` to the home directory. The shell does this for
* command-line arguments but values from the config file are not expanded.
* `~user` forms are left alone.
*/
export function expandTilde(p: string): string {
if (p === "~") {
return os.homedir()
}
if (p.startsWith("~/") || p.startsWith(`~${path.sep}`)) {
return path.join(os.homedir(), p.slice(2))
}
return p
}

View File

@@ -1,5 +1,6 @@
import { Level, logger } from "@coder/logger"
import { promises as fs } from "fs"
import * as os from "os"
import * as path from "path"
import {
UserProvidedArgs,
@@ -575,9 +576,33 @@ describe("parser", () => {
"install-extension": ["extension.number1", "extension.number2"],
})
})
it("should expand ~ in path options from the config file", () => {
const configContents = `
user-data-dir: ~/.config/code-server-data
extensions-dir: ~/extensions
`
expect(parseConfigFile(configContents, "/fake-config-path")).toEqual({
config: "/fake-config-path",
"user-data-dir": path.join(os.homedir(), ".config/code-server-data"),
"extensions-dir": path.join(os.homedir(), "extensions"),
})
})
it("should ignore optional strings set to false", async () => {
expect(parse(["--cert=false"])).toEqual({})
})
it("should ignore booleans set to false", async () => {
expect(parse(["--disable-telemetry=false"])).toEqual({})
})
it("should parse booleans set to false in the config file", () => {
const configContents = `
disable-telemetry: false
disable-update-check: true
`
expect(parseConfigFile(configContents, "/fake-config-path")).toEqual({
config: "/fake-config-path",
"disable-update-check": true,
})
})
it("should use last flag", async () => {
expect(parse(["--port", "8081", "--port", "8082"])).toEqual({
port: 8082,

View File

@@ -1,9 +1,13 @@
import { promises as fs } from "fs"
import * as os from "os"
import * as path from "path"
import { loadCustomStrings } from "../../../src/node/i18n"
import i18n, { loadCustomStrings } from "../../../src/node/i18n"
describe("i18n", () => {
it("includes Turkish translations", () => {
expect(i18n.getResource("tr", "translation", "WELCOME")).toBe("{{app}} uygulamasına hoş geldiniz")
})
let tempDir: string
let validJsonFile: string
let invalidJsonFile: string

View File

@@ -1,5 +1,6 @@
import * as cp from "child_process"
import { promises as fs } from "fs"
import * as os from "os"
import * as path from "path"
import { generateUuid } from "../../../src/common/util"
import { tmpdir } from "../../../src/node/constants"
@@ -623,3 +624,18 @@ describe("splitOnFirstEquals", () => {
})
})
})
describe("expandTilde", () => {
it("should expand a bare ~", () => {
expect(util.expandTilde("~")).toBe(os.homedir())
})
it("should expand a leading ~/", () => {
expect(util.expandTilde("~/.config/code-server")).toBe(path.join(os.homedir(), ".config/code-server"))
})
it("should leave other paths alone", () => {
expect(util.expandTilde("/tmp/~/data")).toBe("/tmp/~/data")
expect(util.expandTilde("relative/~")).toBe("relative/~")
expect(util.expandTilde("~user/data")).toBe("~user/data")
expect(util.expandTilde("")).toBe("")
})
})