From aee3b344ae1448f846d0065260028738c225ba12 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Tue, 8 Sep 2026 06:46:37 +0000 Subject: [PATCH] chore: update task and agents content Signed-off-by: GitHub --- AGENTS.md | 46 ++++------------- Taskfile.yml | 8 --- desktop/e2e/integration.e2e.ts | 6 +-- .../src/lib/components/update/channel.test.ts | 4 +- desktop/src/renderer/src/lib/ipc/mock.ts | 2 +- e2e/tests/ide/browser_returns.go | 4 +- e2e/tests/up/up_behaviors.go | 2 +- mise.agent.toml | 51 ------------------- pkg/agent/delivery/factory_test.go | 2 +- pkg/apple/helper_test.go | 4 +- pkg/devcontainer/config/substitute.go | 2 +- pkg/devcontainer/graph/graph_test.go | 14 ++--- pkg/devcontainer/setup/lifecyclehooks_test.go | 2 +- pkg/git/git.go | 2 +- pkg/ide/opener/browser_tunnel_test.go | 2 +- pkg/provider/version_cache.go | 2 +- pkg/provider/versions_test.go | 2 +- pkg/ssh/server/exec.go | 9 +--- pkg/ssh/server/exit.go | 1 - pkg/workspace/exec_shared_test.go | 4 +- 20 files changed, 39 insertions(+), 130 deletions(-) delete mode 100644 mise.agent.toml diff --git a/AGENTS.md b/AGENTS.md index 1a28cc8a2..cc3cfc7e6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,5 @@ # AGENTS.md -Guide for AI coding agents working in the Devsy repository. - --- ## Environment Setup @@ -10,24 +8,18 @@ Devsy is a monorepo with a Go-based CLI and an Electron-based Svelte 5 desktop a ### Prerequisites and Tooling -- **Go 1.26**: The repository targets Go 1.26 (`go.mod`). With `GOTOOLCHAIN=auto`, an older Go toolchain automatically downloads the required Go version. -- **NodeJS 24**: Required for building and testing the desktop workspace (`.nvmrc`, CI `node-version`). -- **Taskfile (go-task)**: All build, test, and setup commands run through `task`. Installation: - - ```bash - sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin - ``` +Toolchain is managed by mise. Install mise using `curl https://mise.run | sh`. Install toolchain dependencies with `mise install`. --- ## Common Developer Commands -`task --list` shows all available commands. The most common tasks: +`task --list` shows developer commands. The most common tasks: ### CLI (Go) Development - **Tidy Go modules**: `task cli:tidy` -- **Lint CLI**: `task cli:lint` (or `task cli:lint:fix` to apply fixes) +- **Lint CLI**: `task cli:lint` and `task cli:lint:ci` (or `task cli:lint:fix` to apply fixes) - **Format CLI**: `task cli:format` - **Run unit tests**: `task cli:test` (writes coverage to `dist/profile.out`; a `dist` directory is required, e.g. `mkdir -p dist`) - **Build development binary**: `task cli:build:dev` (output under `dist/devsy-dev_linux_amd64_v1/`) @@ -69,14 +61,12 @@ The agent binary runs inside the (Linux) workspace, so it is a Linux binary (`de ### Headless / Xvfb Requirements -Desktop tests run inside an Electron browser environment. In headless or container environments (CI, automated sandbox agents), Electron-dependent commands require an `xvfb-run` prefix to emulate a display server: +Desktop tests run inside an Electron browser environment. In headless or container environments, Electron commands require an `xvfb-run` prefix to emulate a display server: ```bash -# Desktop unit tests headlessly -xvfb-run task desktop:test +xvfb-run task desktop:test # Desktop unit tests headlessly -# Desktop E2E tests headlessly -xvfb-run task desktop:test:e2e +xvfb-run task desktop:test:e2e # Desktop E2E tests headlessly ``` ### E2E (Ginkgo) Tests @@ -93,8 +83,9 @@ Devsy uses [Ginkgo](https://onsi.github.io/ginkgo/) for Go E2E and integration t ### Go Code Style +- **Idiomatic**: Focus on simplicity, reliability, and efficiency when writing clear, idiomatic Go code. +- **Style Guide**: Use the Uber style guide https://github.com/uber-go/guide/blob/master/style.md. - **Linter**: `golangci-lint` via `task cli:lint` (or `task cli:lint:fix`). Run `task cli:lint:ci` before pushing changes. -- **Logs**: Log messages and logging strings are lowercase. ### TypeScript / Svelte Code Style @@ -105,24 +96,7 @@ Biome formats and checks web frontend files. ## Pull Request and Commit Guidelines 1. **Contributor License Agreement (CLA)**: All contributors sign the CLA. -2. **Commit messages**: Conventional Commits, with a concise subject line (50 characters max). +2. **Commit messages**: Conventional Commits, with a concise subject line. 3. **Commit signing**: All commits are required to be signed. 4. **Branch name**: Branch should be named according to the task. - -4. **Pre-commit checks**: Linters, checkers, and relevant unit tests run before pushing. `prek` (a pre-commit hook manager) manages them. - - Installation (Linux and macOS): - ```bash - curl --proto '=https' --tlsv1.2 -LsSf https://github.com/j178/prek/releases/latest/download/prek-installer.sh | sh - ``` - - Installation (Windows): - ```powershell - powershell -ExecutionPolicy ByPass -c "irm https://github.com/j178/prek/releases/latest/download/prek-installer.ps1 | iex" - ``` - - Manual run on all files: - ```bash - prek run --all-files - ``` - - Git hook installation: - ```bash - prek install - ``` +5. **Pre-commit checks**: Linters, checkers, and relevant unit tests run before pushing. `prek` (a pre-commit hook manager) manages them. diff --git a/Taskfile.yml b/Taskfile.yml index 922bbec0a..1abb174a2 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -13,14 +13,6 @@ tasks: desc: verify THIRD_PARTY_LICENSES.md is in sync and all licenses are allowed (CI) cmd: go run ./hack/licenses --check - automations:generate: - desc: regenerate .agents/agents//agent.md from hack/automations - cmd: go run ./hack/automations - - automations:check: - desc: verify generated agent prompts are in sync (CI / pre-commit) - cmd: go run ./hack/automations -check - cli:lint: desc: lint go code using golangci-lint deps: [cli:lint:version] diff --git a/desktop/e2e/integration.e2e.ts b/desktop/e2e/integration.e2e.ts index 07ce89190..30ffdf810 100644 --- a/desktop/e2e/integration.e2e.ts +++ b/desktop/e2e/integration.e2e.ts @@ -105,7 +105,7 @@ test.describe // Click Continue to add the provider await wizard.getByRole("button", { name: /^Continue$/ }).click() - // Docker mock has no required options → wizard jumps to init then complete. + // Docker mock has no required options -> wizard jumps to init then complete. // Wait for the "Done" button on the Complete step. await wizard .getByRole("button", { name: "Done" }) @@ -269,7 +269,7 @@ test.describe }) test("should show new workspace in table", async () => { - // Workspace ID from template name: 'Node.js' → 'node-js' + // Workspace ID from template name: 'Node.js' -> 'node-js' await expect(page.locator("table")).toContainText("node-js", { timeout: 10000, }) @@ -408,7 +408,7 @@ test.describe }) test("should show python workspace in table", async () => { - // Template name 'Python' → workspace id 'python' + // Template name 'Python' -> workspace id 'python' await expect(page.locator("table")).toContainText("python", { timeout: 10000, }) diff --git a/desktop/src/renderer/src/lib/components/update/channel.test.ts b/desktop/src/renderer/src/lib/components/update/channel.test.ts index f4b409138..a9e03dc1a 100644 --- a/desktop/src/renderer/src/lib/components/update/channel.test.ts +++ b/desktop/src/renderer/src/lib/components/update/channel.test.ts @@ -21,11 +21,11 @@ describe("channel labels", () => { }) describe("isDowngrade", () => { - it("treats Preview → Stable as a downgrade", () => { + it("treats Preview -> Stable as a downgrade", () => { expect(isDowngrade("beta", "stable")).toBe(true) }) - it("treats Stable → Preview as not a downgrade", () => { + it("treats Stable -> Preview as not a downgrade", () => { expect(isDowngrade("stable", "beta")).toBe(false) }) diff --git a/desktop/src/renderer/src/lib/ipc/mock.ts b/desktop/src/renderer/src/lib/ipc/mock.ts index eba85f5d3..ab5ff1c82 100644 --- a/desktop/src/renderer/src/lib/ipc/mock.ts +++ b/desktop/src/renderer/src/lib/ipc/mock.ts @@ -300,7 +300,7 @@ export async function invoke( await new Promise((r) => setTimeout(r, 50 + Math.random() * 100)) const result = handler(args ?? {}) - console.debug(`[mock] ${cmd}`, args ?? {}, "→", result) + console.debug(`[mock] ${cmd}`, args ?? {}, "->", result) return result as T } diff --git a/e2e/tests/ide/browser_returns.go b/e2e/tests/ide/browser_returns.go index ad49b90d7..9699abf47 100644 --- a/e2e/tests/ide/browser_returns.go +++ b/e2e/tests/ide/browser_returns.go @@ -92,7 +92,7 @@ var _ = ginkgo.Describe( // Run up with a browser IDE. --ide-launch=headless suppresses the // host browser launch (no display available in CI) but still runs - // openIDE → startDetachedBrowserTunnel → writes tunnel.json. + // openIDE -> startDetachedBrowserTunnel -> writes tunnel.json. // --ide-launch=skip would skip openIDE entirely, which is not what // the test exercises. With the old blocking behavior this would // still hang past SpecTimeout; with the new behavior the CLI @@ -180,7 +180,7 @@ var _ = ginkgo.Describe( "expected --recreate to spawn a new helper (PID1=%d, PID2=%d)", pid1, pid2) // PID1 should now be dead. Use Eventually because the kill is - // best-effort SIGTERM → wait → SIGKILL. + // best-effort SIGTERM -> wait -> SIGKILL. gomega.Eventually(func() error { return syscall.Kill(pid1, 0) }).WithTimeout(5*time.Second).WithPolling(100*time.Millisecond). diff --git a/e2e/tests/up/up_behaviors.go b/e2e/tests/up/up_behaviors.go index d049141a7..393c021b6 100644 --- a/e2e/tests/up/up_behaviors.go +++ b/e2e/tests/up/up_behaviors.go @@ -412,6 +412,6 @@ var _ = ginkgo.Describe("up command behaviors", ginkgo.Label("up-behaviors"), fu "postCreate", "dotfiles-before-postStart", "postStart", - }), "lifecycle ordering should be: postCreate → dotfiles → postStart") + }), "lifecycle ordering should be: postCreate -> dotfiles -> postStart") }, ginkgo.SpecTimeout(framework.TimeoutShort())) }) diff --git a/mise.agent.toml b/mise.agent.toml deleted file mode 100644 index 0806490ae..000000000 --- a/mise.agent.toml +++ /dev/null @@ -1,51 +0,0 @@ -[env] -DEVSY_GIT_SIGNING_PRIVATE_KEY = { age = "YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQTHlMQmxra00yOWRKTUI0bithV0xtNkVwRXVreDFPT1BYR1UzN1VXdHo4CnVSOVdYUDdPeGJFSjFrN0lkQjBVRndheUhwRjdKNitlWVBYSEgrMEp3YzAKLT4gP0xhOi0tZ3JlYXNlIDUoYiBqaFUgbUsjIHooSXM9ajgqCm84VDdsS3ZtcEk0UkhQUHVXQzhCbmxpSXBkSmh0eTVNV25VNGZhYUJ5SER6NUFiZE03WDRFV212YkVRCi0tLSA2dmZZK3QzZFpGRDY5a29hQ2t4dnhyemJjMlFaVU9ncmdmeTlYbUVNTkFRCuB0Lsu02r99Y/DkyFleuWJzSoCVggBIG1Se9AD04rF38nRhmAXSDk5G7s2BGW2fWs8HSsrohaaMS2EmTxFx/FlGXHzaqlxLXhxvDErI2oU/oqXKNtEKVTMYo5LzHTCRovVKVR+ELDpkTpClYoQi17ukjMXelOZRsEQ6wDhiO/3YXqcX738Kh7rzdqA2W3CgYOxLjoYnBtHL0dzsXpFj339mCOI/naDgCn5lfMiNplqlTuGG2RO/f+nfT9/c0+QtibWaAuq2OwNb/kzQctPFFBg4YeAjraMtgWuBYEau6S8juGgF6DsPpC1emUpAIZHibyFaIDuLYBWyjgZ1GJUC4ZztJ+uYHdFewSlgXT2xXNfOS2fASaxi9A1wpkcjbuIXqv6aGIkZL16/JeBBFLzyrPuEy7rIqG/ly1IYWSi7RUJuMay6m02FD6uJzlp8Yo1S+AgAvFFNP1nzlUlE5Cu/+ffhmp1soHqY53LptCf/OyS74Emcu/L9eaa99X1SsZE7J+aOnwatDaPBBR/KCp96q8oTbMxKiEq+ZP6CzAlukzGS9nI" } - -[tasks."setup:agent"] -run = ''' -set -eu - -if [ -z "${DEVSY_GIT_SIGNING_PRIVATE_KEY:-}" ]; then - echo "ERROR: DEVSY_GIT_SIGNING_PRIVATE_KEY is not set" - exit 1 -fi -if [ -z "${DEVSY_GIT_AUTHOR_NAME:-}" ]; then - echo "ERROR: DEVSY_GIT_AUTHOR_NAME is not set" - exit 1 -fi -if [ -z "${DEVSY_GIT_AUTHOR_EMAIL:-}" ]; then - echo "ERROR: DEVSY_GIT_AUTHOR_EMAIL is not set" - exit 1 -fi - -SIGNING_DIR="$HOME/.local/share/devsy/signing" -SIGNING_PRIVATE_KEY="$SIGNING_DIR/devsy-agent-signing" -SIGNING_PUBLIC_KEY="$SIGNING_DIR/devsy-agent-signing.pub" -ALLOWED_SIGNERS="$SIGNING_DIR/allowed_signers" - -mkdir -p "$SIGNING_DIR" -chmod 700 "$SIGNING_DIR" - -printf '%s\n' "$DEVSY_GIT_SIGNING_PRIVATE_KEY" > "$SIGNING_PRIVATE_KEY" -chmod 600 "$SIGNING_PRIVATE_KEY" - -ssh-keygen -y -f "$SIGNING_PRIVATE_KEY" > "$SIGNING_PUBLIC_KEY" -chmod 644 "$SIGNING_PUBLIC_KEY" - -printf '%s %s\n' \ - "$DEVSY_GIT_AUTHOR_EMAIL" \ - "$(cat "$SIGNING_PUBLIC_KEY")" \ - > "$ALLOWED_SIGNERS" - -chmod 600 "$ALLOWED_SIGNERS" - -git config --global user.name "$DEVSY_GIT_AUTHOR_NAME" -git config --global user.email "$DEVSY_GIT_AUTHOR_EMAIL" -git config --global user.useConfigOnly true -git config --global gpg.format ssh -git config --global user.signingkey "$SIGNING_PRIVATE_KEY" -git config --global commit.gpgsign true -git config --global tag.gpgsign true -git config --global gpg.ssh.allowedSignersFile "$ALLOWED_SIGNERS" -git config --global --unset-all core.hooksPath 2>/dev/null || true -''' diff --git a/pkg/agent/delivery/factory_test.go b/pkg/agent/delivery/factory_test.go index feeded6ae..e72181df1 100644 --- a/pkg/agent/delivery/factory_test.go +++ b/pkg/agent/delivery/factory_test.go @@ -153,7 +153,7 @@ func TestNewAgentDelivery_KubernetesDriver_FallsBackWhenNoPodExec(t *testing.T) ExecFunc: execFn, DownloadURL: "https://artifacts.example.test/devsy", KubernetesAgentInstallPath: testKubernetesInstallPath, - // PodExec intentionally nil → legacy fallback. + // PodExec intentionally nil -> legacy fallback. } d := NewAgentDelivery(opts) diff --git a/pkg/apple/helper_test.go b/pkg/apple/helper_test.go index bfcec156f..d35cda0cf 100644 --- a/pkg/apple/helper_test.go +++ b/pkg/apple/helper_test.go @@ -124,7 +124,7 @@ func TestParseImageTag(t *testing.T) { } func TestWaitContainerRunningFailsFastOnExit(t *testing.T) { - // A container reporting a terminal (stopped→exited) state must error + // A container reporting a terminal (stopped->exited) state must error // immediately rather than block for the full poll timeout. stdout := `[{"id":"c1","configuration":{"id":"c1"},"status":{"state":"stopped"}}]` h := &AppleHelper{Command: stubContainer(t, stdout, 0)} @@ -143,7 +143,7 @@ func TestWaitContainerRunningFailsFastOnExit(t *testing.T) { } func TestEnsureBuilderRunning(t *testing.T) { - // Exit 0 (the real CLI's behavior even when already running) → no error. + // Exit 0 (the real CLI's behavior even when already running) -> no error. okHelper := &AppleHelper{Command: stubContainer(t, "", 0)} if err := okHelper.EnsureBuilderRunning(context.Background()); err != nil { t.Errorf("exit 0 must succeed, got %v", err) diff --git a/pkg/devcontainer/config/substitute.go b/pkg/devcontainer/config/substitute.go index e711c349c..e0bfa5446 100644 --- a/pkg/devcontainer/config/substitute.go +++ b/pkg/devcontainer/config/substitute.go @@ -327,7 +327,7 @@ func ListToObject(list []string) map[string]string { } // ComputeDevContainerID implements the official devcontainer CLI algorithm: -// SHA-256(JSON.stringify(labels, sorted keys)) → BigInt → base-32 (0-9a-v) → left-pad to 52 chars. +// SHA-256(JSON.stringify(labels, sorted keys)) -> BigInt -> base-32 (0-9a-v) -> left-pad to 52 chars. func ComputeDevContainerID(labels map[string]string) string { keys := make([]string, 0, len(labels)) for k := range labels { diff --git a/pkg/devcontainer/graph/graph_test.go b/pkg/devcontainer/graph/graph_test.go index 0c2768848..bd496014f 100644 --- a/pkg/devcontainer/graph/graph_test.go +++ b/pkg/devcontainer/graph/graph_test.go @@ -492,9 +492,9 @@ func (suite *GraphTestSuite) TestLargeGraph() { } func (suite *GraphTestSuite) TestSortNodeIDsRoundBased() { - // A→B edge means B depends on A. - // Round 1: A and C both have in-degree 0 → sorted alpha → [A, C] - // Round 2: B (now in-degree 0 after A processed) → [B] + // A->B edge means B depends on A. + // Round 1: A and C both have in-degree 0 -> sorted alpha -> [A, C] + // Round 2: B (now in-degree 0 after A processed) -> [B] // Final: [A, C, B] suite.Require().NoError(suite.graph.AddNode("A", "dataA")) suite.Require().NoError(suite.graph.AddNode("B", "dataB")) @@ -507,10 +507,10 @@ func (suite *GraphTestSuite) TestSortNodeIDsRoundBased() { } func (suite *GraphTestSuite) TestSortNodeIDsRoundBasedMultiLevel() { - // A→B→D, C→D (independent chains with shared sink) - // Round 1: A, C (in-degree 0) → [A, C] - // Round 2: B (depends on A only) → [B] - // Round 3: D (depends on B and C, but C was processed in round 1) → [D] + // A->B->D, C->D (independent chains with shared sink) + // Round 1: A, C (in-degree 0) -> [A, C] + // Round 2: B (depends on A only) -> [B] + // Round 3: D (depends on B and C, but C was processed in round 1) -> [D] suite.Require().NoError(suite.graph.AddNode("A", "dataA")) suite.Require().NoError(suite.graph.AddNode("B", "dataB")) suite.Require().NoError(suite.graph.AddNode("C", "dataC")) diff --git a/pkg/devcontainer/setup/lifecyclehooks_test.go b/pkg/devcontainer/setup/lifecyclehooks_test.go index cb5f30c26..4c5819921 100644 --- a/pkg/devcontainer/setup/lifecyclehooks_test.go +++ b/pkg/devcontainer/setup/lifecyclehooks_test.go @@ -762,7 +762,7 @@ func (s *LifecycleHookTestSuite) TestPostCreateHookUsesOnceSemantics() { hooks := preAttachPhaseParams(result, env, false) - // postCreateCommand should have content = Created (non-empty → once semantics). + // postCreateCommand should have content = Created (non-empty -> once semantics). var postCreate, postStart hookRunParams for _, h := range hooks { if h.phase == PhasePostCreate { diff --git a/pkg/git/git.go b/pkg/git/git.go index 2693a684f..4e4ddcadb 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -65,7 +65,7 @@ func NormalizeRepository(str string) *GitInfo { // canonicalizeURL strips the workspace-source "git:" scheme (the form // WorkspaceSource.String emits; without this strip, a value that round-trips -// through workspace list → up becomes "https://git:https://...") and upgrades +// through workspace list -> up becomes "https://git:https://...") and upgrades // bare host[/path] inputs to https://. func canonicalizeURL(str string) string { str = strings.TrimPrefix(str, "git:") diff --git a/pkg/ide/opener/browser_tunnel_test.go b/pkg/ide/opener/browser_tunnel_test.go index 1c795a86f..81e410012 100644 --- a/pkg/ide/opener/browser_tunnel_test.go +++ b/pkg/ide/opener/browser_tunnel_test.go @@ -403,7 +403,7 @@ func relistenAfter(addr string, delay, hold time.Duration) <-chan error { } // checkRelistenOrSkip drains a non-blocking read from listenErr. A non-nil -// error means the OS reassigned the port in the close→relisten window; +// error means the OS reassigned the port in the close->relisten window; // skip rather than fail to avoid spurious CI failures on busy hosts. func checkRelistenOrSkip(t *testing.T, addr string, listenErr <-chan error) { t.Helper() diff --git a/pkg/provider/version_cache.go b/pkg/provider/version_cache.go index dabf40122..3a2cd709a 100644 --- a/pkg/provider/version_cache.go +++ b/pkg/provider/version_cache.go @@ -73,7 +73,7 @@ func LoadProviderVersionCache() (ProviderVersionCache, error) { } cache := ProviderVersionCache{} if err := json.Unmarshal(data, &cache); err != nil { - // Corrupt cache → start fresh. + // Corrupt cache -> start fresh. return ProviderVersionCache{}, nil } return cache, nil diff --git a/pkg/provider/versions_test.go b/pkg/provider/versions_test.go index c65b9c750..ed52ce5f7 100644 --- a/pkg/provider/versions_test.go +++ b/pkg/provider/versions_test.go @@ -78,7 +78,7 @@ func TestMarkCurrent_NoTag(t *testing.T) { versions := []ProviderVersion{{Tag: testTagV100}} got := MarkCurrent(versions, "github.com/foo/bar") if got[0].Current { - t.Fatal("no pinned tag → none current") + t.Fatal("no pinned tag -> none current") } } diff --git a/pkg/ssh/server/exec.go b/pkg/ssh/server/exec.go index 4f77ba90b..a4dcc2574 100644 --- a/pkg/ssh/server/exec.go +++ b/pkg/ssh/server/exec.go @@ -19,9 +19,6 @@ import ( // Process group isolation (SysProcAttr) ensures child processes can be // properly signaled on shutdown. SSH client signals are forwarded to the // process. -// -// Loosely modeled after Coder's startNonPTYSession: -// - https://github.com/coder/coder/blob/main/agent/agentssh/agentssh.go func execNonPTY(sess ssh.Session, cmd *exec.Cmd) (err error) { log.Debugf("execute SSH server command: %s", strings.Join(cmd.Args, " ")) @@ -125,13 +122,11 @@ type ptyExecParams struct { // SSH signal forwarding. Output is copied on the main goroutine to ensure all // buffered data is flushed before process.Wait(). // -// DisablePTYEmulation prevents double NL→CRNL translation. The kernel's line +// DisablePTYEmulation prevents double NL->CRNL translation. The kernel's line // discipline already performs this; the gliderlabs/ssh library's own conversion // would corrupt terminal escape sequences. // -// Ported from coder/ssh (Coder's fork of gliderlabs/ssh): -// - Coder issue: https://github.com/coder/coder/issues/3371 -// - Neovim issue: https://github.com/neovim/neovim/issues/3875 +// - Neovim issue: https://github.com/neovim/neovim/issues/3875 func execPTY(p ptyExecParams) (retErr error) { log.Debugf("execute SSH server PTY command: %s", strings.Join(p.cmd.Args, " ")) p.sess.DisablePTYEmulation() diff --git a/pkg/ssh/server/exit.go b/pkg/ssh/server/exit.go index 244ebc8de..0a1bfe9d1 100644 --- a/pkg/ssh/server/exit.go +++ b/pkg/ssh/server/exit.go @@ -43,7 +43,6 @@ func exitCode(err error) int { // Map -1 to 255 to match OpenSSH behavior. -1 would be // transmitted as uint32(4294967295). // OpenSSH returns 255 for this case, and the shell does the same. - // - https://github.com/coder/coder/blob/main/agent/agentssh/agentssh.go // - https://github.com/openssh/openssh-portable/blob/master/session.c code = 255 } diff --git a/pkg/workspace/exec_shared_test.go b/pkg/workspace/exec_shared_test.go index c5220999d..61f94c6e7 100644 --- a/pkg/workspace/exec_shared_test.go +++ b/pkg/workspace/exec_shared_test.go @@ -65,7 +65,7 @@ func TestExecWithRunnerExitCode(t *testing.T) { } func TestProbeEnvWithRunner(t *testing.T) { - // /proc/self/environ succeeds → NUL-separated parse. + // /proc/self/environ succeeds -> NUL-separated parse. run := func(_ context.Context, _ []string, _ io.Reader, stdout, _ io.Writer) error { _, _ = stdout.Write([]byte("PATH=/bin\x00HOME=/root\x00")) return nil @@ -76,7 +76,7 @@ func TestProbeEnvWithRunner(t *testing.T) { t.Errorf("probed env = %v", env) } - // Total failure → empty map (documented contract), never a panic. + // Total failure -> empty map (documented contract), never a panic. failRun := func(_ context.Context, _ []string, _ io.Reader, _, _ io.Writer) error { return errors.New("exec failed") }