From 26ea10f935fe0920b7bf28564c9750fa6c110ef9 Mon Sep 17 00:00:00 2001 From: TanishqDatabricks Date: Thu, 27 Aug 2026 14:37:56 +0200 Subject: [PATCH 1/3] ssh: move command group out of experimental into cmd/ssh Graduate the ssh command group out of experimental: - Move experimental/ssh/ -> cmd/ssh/. Command files are flattened up from the inner cmd/ subpackage into cmd/ssh/ directly (matching cmd/labs), and the internal/ tree moves to cmd/ssh/internal/, so `databricks ssh` lives alongside the other top-level command groups under cmd/. All import paths rewritten experimental/ssh/... -> cmd/ssh/... - Unhide the command (remove Hidden: true) so it appears in `databricks --help`. - Rename the CI test job test-exp-ssh -> test-ssh across the Taskfile task, tools/testmask (ciTargets + fixtures), the push.yml matrix job, and the pr-checklist skill. Drop the now-redundant ./experimental/ssh/... from TEST_PACKAGES (covered by ./cmd/...). - Update remaining path references (ruff.toml, libs cross-reference comments, moved docs) and add a .nextchanges/cli changelog fragment. Co-authored-by: Isaac --- .agents/skills/pr-checklist/SKILL.md | 4 ++-- .github/workflows/push.yml | 18 +++++++++--------- .nextchanges/cli/ssh-out-of-experimental.md | 1 + Taskfile.yml | 10 +++++----- acceptance/ssh/connect-serverless-cpu/script | 2 +- acceptance/ssh/connect-serverless-gpu/script | 2 +- .../ssh/connect-serverless-gpu/test.toml | 2 +- acceptance/ssh/connection/script | 2 +- acceptance/ssh/connection/test.toml | 2 +- cmd/cmd.go | 2 +- {experimental => cmd}/ssh/CLAUDE.md | 2 +- {experimental => cmd}/ssh/FAILURE_MODES.md | 2 +- {experimental => cmd}/ssh/README.md | 0 {experimental => cmd}/ssh/bench.sh | 2 +- {experimental/ssh/cmd => cmd/ssh}/connect.go | 2 +- {experimental/ssh/cmd => cmd/ssh}/constants.go | 0 .../ssh/internal/client/client.go | 10 +++++----- .../internal/client/client_internal_test.go | 2 +- .../ssh/internal/client/client_test.go | 2 +- .../internal/client/policy_internal_test.go | 0 .../ssh/internal/client/releases.go | 2 +- .../ssh/internal/client/releases_test.go | 0 .../internal/client/ssh-server-bootstrap.py | 0 .../internal/client/submit_internal_test.go | 0 .../ssh/internal/client/websockets.go | 0 .../ssh/internal/client/websockets_test.go | 0 .../ssh/internal/fileutil/backup.go | 0 .../ssh/internal/fileutil/backup_test.go | 2 +- .../ssh/internal/keys/keys.go | 0 .../ssh/internal/keys/keys_test.go | 2 +- .../ssh/internal/keys/secrets.go | 0 .../ssh/internal/proxy/client.go | 0 .../ssh/internal/proxy/client_server_test.go | 0 .../ssh/internal/proxy/connections.go | 0 .../ssh/internal/proxy/connections_test.go | 0 .../ssh/internal/proxy/keepalive_test.go | 0 .../ssh/internal/proxy/proxy.go | 0 .../ssh/internal/proxy/proxy_test.go | 0 .../ssh/internal/proxy/server.go | 0 .../ssh/internal/server/jupyter-init.py | 0 .../ssh/internal/server/logs.go | 0 .../ssh/internal/server/logs_test.go | 0 .../ssh/internal/server/server.go | 4 ++-- .../ssh/internal/server/server_test.go | 0 .../ssh/internal/server/sshd.go | 2 +- .../ssh/internal/server/sshd_test.go | 0 .../ssh/internal/setup/setup.go | 6 +++--- .../ssh/internal/setup/setup_test.go | 2 +- .../ssh/internal/sshconfig/sshconfig.go | 2 +- .../ssh/internal/sshconfig/sshconfig_test.go | 0 .../ssh/internal/vscode/run.go | 0 .../ssh/internal/vscode/run_test.go | 0 .../ssh/internal/vscode/settings.go | 2 +- .../ssh/internal/vscode/settings_test.go | 2 +- .../ssh/internal/workspace/workspace.go | 0 {experimental/ssh/cmd => cmd/ssh}/server.go | 2 +- {experimental/ssh/cmd => cmd/ssh}/setup.go | 2 +- {experimental/ssh/cmd => cmd/ssh}/ssh.go | 5 ++--- libs/process/group.go | 2 +- libs/testserver/ssh.go | 2 +- ruff.toml | 2 +- tools/testmask/targets.go | 2 +- tools/testmask/targets_test.go | 18 +++++++++--------- 63 files changed, 64 insertions(+), 64 deletions(-) create mode 100644 .nextchanges/cli/ssh-out-of-experimental.md rename {experimental => cmd}/ssh/CLAUDE.md (98%) rename {experimental => cmd}/ssh/FAILURE_MODES.md (99%) rename {experimental => cmd}/ssh/README.md (100%) rename {experimental => cmd}/ssh/bench.sh (94%) rename {experimental/ssh/cmd => cmd/ssh}/connect.go (99%) rename {experimental/ssh/cmd => cmd/ssh}/constants.go (100%) rename {experimental => cmd}/ssh/internal/client/client.go (99%) rename {experimental => cmd}/ssh/internal/client/client_internal_test.go (99%) rename {experimental => cmd}/ssh/internal/client/client_test.go (99%) rename {experimental => cmd}/ssh/internal/client/policy_internal_test.go (100%) rename {experimental => cmd}/ssh/internal/client/releases.go (99%) rename {experimental => cmd}/ssh/internal/client/releases_test.go (100%) rename {experimental => cmd}/ssh/internal/client/ssh-server-bootstrap.py (100%) rename {experimental => cmd}/ssh/internal/client/submit_internal_test.go (100%) rename {experimental => cmd}/ssh/internal/client/websockets.go (100%) rename {experimental => cmd}/ssh/internal/client/websockets_test.go (100%) rename {experimental => cmd}/ssh/internal/fileutil/backup.go (100%) rename {experimental => cmd}/ssh/internal/fileutil/backup_test.go (97%) rename {experimental => cmd}/ssh/internal/keys/keys.go (100%) rename {experimental => cmd}/ssh/internal/keys/keys_test.go (97%) rename {experimental => cmd}/ssh/internal/keys/secrets.go (100%) rename {experimental => cmd}/ssh/internal/proxy/client.go (100%) rename {experimental => cmd}/ssh/internal/proxy/client_server_test.go (100%) rename {experimental => cmd}/ssh/internal/proxy/connections.go (100%) rename {experimental => cmd}/ssh/internal/proxy/connections_test.go (100%) rename {experimental => cmd}/ssh/internal/proxy/keepalive_test.go (100%) rename {experimental => cmd}/ssh/internal/proxy/proxy.go (100%) rename {experimental => cmd}/ssh/internal/proxy/proxy_test.go (100%) rename {experimental => cmd}/ssh/internal/proxy/server.go (100%) rename {experimental => cmd}/ssh/internal/server/jupyter-init.py (100%) rename {experimental => cmd}/ssh/internal/server/logs.go (100%) rename {experimental => cmd}/ssh/internal/server/logs_test.go (100%) rename {experimental => cmd}/ssh/internal/server/server.go (98%) rename {experimental => cmd}/ssh/internal/server/server_test.go (100%) rename {experimental => cmd}/ssh/internal/server/sshd.go (98%) rename {experimental => cmd}/ssh/internal/server/sshd_test.go (100%) rename {experimental => cmd}/ssh/internal/setup/setup.go (95%) rename {experimental => cmd}/ssh/internal/setup/setup_test.go (99%) rename {experimental => cmd}/ssh/internal/sshconfig/sshconfig.go (99%) rename {experimental => cmd}/ssh/internal/sshconfig/sshconfig_test.go (100%) rename {experimental => cmd}/ssh/internal/vscode/run.go (100%) rename {experimental => cmd}/ssh/internal/vscode/run_test.go (100%) rename {experimental => cmd}/ssh/internal/vscode/settings.go (99%) rename {experimental => cmd}/ssh/internal/vscode/settings_test.go (99%) rename {experimental => cmd}/ssh/internal/workspace/workspace.go (100%) rename {experimental/ssh/cmd => cmd/ssh}/server.go (98%) rename {experimental/ssh/cmd => cmd/ssh}/setup.go (97%) rename {experimental/ssh/cmd => cmd/ssh}/ssh.go (87%) diff --git a/.agents/skills/pr-checklist/SKILL.md b/.agents/skills/pr-checklist/SKILL.md index 7da1560a156..0fbdf7f5fb6 100644 --- a/.agents/skills/pr-checklist/SKILL.md +++ b/.agents/skills/pr-checklist/SKILL.md @@ -23,9 +23,9 @@ Before submitting a PR, run these commands to match what CI checks. CI uses the # 5. If you changed files in python/: ./task pydabs-codegen pydabs-test pydabs-lint pydabs-docs -# 6. If you changed cmd/aitools/, libs/aitools/, experimental/aitools/, or experimental/ssh/: +# 6. If you changed cmd/aitools/, libs/aitools/, experimental/aitools/, or cmd/ssh/: ./task test-exp-aitools # only if aitools code changed (top-level or experimental) -./task test-exp-ssh # only if ssh code changed +./task test-ssh # only if ssh code changed ``` ## Final cleanup scan diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index b4c5238326b..88093ed8e62 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -245,14 +245,14 @@ jobs: run: | go tool -modfile=tools/task/go.mod task test-exp-aitools - test-exp-ssh: + test-ssh: needs: - cleanups - testmask # Only run if the target is in the list of targets from testmask - if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh') }} - name: "task test-exp-ssh (${{matrix.os.name}})" + if: ${{ contains(fromJSON(needs.testmask.outputs.targets), 'test-ssh') }} + name: "task test-ssh (${{matrix.os.name}})" runs-on: ${{ matrix.os.runner }} defaults: @@ -291,7 +291,7 @@ jobs: - name: Setup build environment uses: ./.github/actions/setup-build-environment with: - cache-key: test-exp-ssh + cache-key: test-ssh # The ssh acceptance test drives a real sshd behind the tunnel; the runner # ships only the client. Install it on Linux (the OS the test is gated to); @@ -302,7 +302,7 @@ jobs: - name: Run tests run: | - go tool -modfile=tools/task/go.mod task test-exp-ssh + go tool -modfile=tools/task/go.mod task test-ssh test-pipelines: needs: @@ -421,7 +421,7 @@ jobs: needs: - test - test-exp-aitools - - test-exp-ssh + - test-ssh - test-pipelines - test-sandbox @@ -504,7 +504,7 @@ jobs: - name: Generate GitHub App Token (check runs) if: >- (github.event_name == 'merge_group') || - (github.event_name == 'pull_request' && !contains(fromJSON(needs.testmask.outputs.targets), 'test') && !contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh')) + (github.event_name == 'pull_request' && !contains(fromJSON(needs.testmask.outputs.targets), 'test') && !contains(fromJSON(needs.testmask.outputs.targets), 'test-ssh')) id: generate-check-token uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 with: @@ -517,7 +517,7 @@ jobs: # Skip integration tests if the primary "test" target is not triggered by this change. # Use Checks API (not Statuses API) to match the required "Integration Tests" check. - name: Skip integration tests (pull request) - if: ${{ github.event_name == 'pull_request' && !contains(fromJSON(needs.testmask.outputs.targets), 'test') && !contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh') }} + if: ${{ github.event_name == 'pull_request' && !contains(fromJSON(needs.testmask.outputs.targets), 'test') && !contains(fromJSON(needs.testmask.outputs.targets), 'test-ssh') }} uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 with: github-token: ${{ steps.generate-check-token.outputs.token }} @@ -563,7 +563,7 @@ jobs: - testmask if: >- - (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && (contains(fromJSON(needs.testmask.outputs.targets), 'test') || contains(fromJSON(needs.testmask.outputs.targets), 'test-exp-ssh'))) || + (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' && (contains(fromJSON(needs.testmask.outputs.targets), 'test') || contains(fromJSON(needs.testmask.outputs.targets), 'test-ssh'))) || (github.event_name == 'push') runs-on: diff --git a/.nextchanges/cli/ssh-out-of-experimental.md b/.nextchanges/cli/ssh-out-of-experimental.md new file mode 100644 index 00000000000..2463e4f97b2 --- /dev/null +++ b/.nextchanges/cli/ssh-out-of-experimental.md @@ -0,0 +1 @@ +The `databricks ssh` command group is no longer experimental and now appears in `databricks --help`. diff --git a/Taskfile.yml b/Taskfile.yml index 8ed24ad0f60..201cd1c48d9 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -7,7 +7,7 @@ vars: # Pinned ruff (linter + formatter). Keep in sync with the version in # .github/workflows/check.yml and python/Taskfile.yml. RUFF: uvx ruff@0.15.17 - TEST_PACKAGES: ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... ./experimental/ssh/... . + TEST_PACKAGES: ./acceptance/internal ./libs/... ./internal/... ./cmd/... ./bundle/... . ACCEPTANCE_TEST_FILTER: "" # Single brace-expansion glob covering every //go:embed target in the repo, # computed by grepping `//go:embed` directives. Evaluated lazily by Task so @@ -675,10 +675,10 @@ tasks: --packages ./acceptance/... \ -- -timeout=${LOCAL_TIMEOUT:-60m} -run "TestAccept/(apps|experimental/aitools)" - test-exp-ssh: - desc: Run experimental SSH unit and acceptance tests + test-ssh: + desc: Run SSH unit and acceptance tests sources: - - experimental/ssh/** + - cmd/ssh/** - acceptance/ssh/** - "{{.EMBED_SOURCES}}" cmds: @@ -686,7 +686,7 @@ tasks: {{.GO_TOOL}} gotestsum \ --format ${GOTESTSUM_FORMAT:-pkgname-and-test-fails} \ --no-summary=skipped \ - --packages ./experimental/ssh/... \ + --packages ./cmd/ssh/... \ -- -timeout=${LOCAL_TIMEOUT:-60m} - | {{.GO_TOOL}} gotestsum \ diff --git a/acceptance/ssh/connect-serverless-cpu/script b/acceptance/ssh/connect-serverless-cpu/script index 40bbb6debc2..85b0e6e73f0 100644 --- a/acceptance/ssh/connect-serverless-cpu/script +++ b/acceptance/ssh/connect-serverless-cpu/script @@ -9,7 +9,7 @@ if [ -n "${CLOUD_ENV:-}" ]; then else # Local: the test server backs the /ssh websocket with a real sshd, so this # asserts the bootstrap job plus a full handshake over the tunnel. Skip when - # sshd is absent (only task test-exp-ssh provisions it). + # sshd is absent (only task test-ssh provisions it). if [ -z "$(command -v sshd || ls /usr/sbin/sshd /usr/local/sbin/sshd /sbin/sshd 2>/dev/null)" ]; then echo "SKIP_TEST sshd (openssh-server) not installed" exit 0 diff --git a/acceptance/ssh/connect-serverless-gpu/script b/acceptance/ssh/connect-serverless-gpu/script index 0943ec9d2b7..9e53e8f7a38 100644 --- a/acceptance/ssh/connect-serverless-gpu/script +++ b/acceptance/ssh/connect-serverless-gpu/script @@ -18,7 +18,7 @@ if [ -n "${CLOUD_ENV:-}" ]; then else # No compute locally: the test server backs the driver-proxy /ssh websocket with a # real sshd, so this one run asserts both the bootstrap job and a full handshake + - # remote exec over the ws:// tunnel. Needs sshd (only task test-exp-ssh provisions + # remote exec over the ws:// tunnel. Needs sshd (only task test-ssh provisions # it); the test server probes the same way, so skip where it's absent. if [ -z "$(command -v sshd || ls /usr/sbin/sshd /usr/local/sbin/sshd /sbin/sshd 2>/dev/null)" ]; then echo "SKIP_TEST sshd (openssh-server) not installed" diff --git a/acceptance/ssh/connect-serverless-gpu/test.toml b/acceptance/ssh/connect-serverless-gpu/test.toml index 9ab5c69e8a2..6612907c32b 100644 --- a/acceptance/ssh/connect-serverless-gpu/test.toml +++ b/acceptance/ssh/connect-serverless-gpu/test.toml @@ -11,7 +11,7 @@ Ignore = [ ] # Linux-only: the local run drives a real sshd, reliable only there (and where -# task test-exp-ssh provisions it). Absent GOOS keys default to enabled, so the +# task test-ssh provisions it). Absent GOOS keys default to enabled, so the # other OSes must be disabled explicitly. GOOS.linux = true GOOS.darwin = false diff --git a/acceptance/ssh/connection/script b/acceptance/ssh/connection/script index c69babb6dd0..d8becdbadcd 100644 --- a/acceptance/ssh/connection/script +++ b/acceptance/ssh/connection/script @@ -18,7 +18,7 @@ if [ -n "${CLOUD_ENV:-}" ]; then else # No compute locally: the test server backs the driver-proxy /ssh websocket with a # real sshd, so this one run asserts both the bootstrap job and a full handshake + - # remote exec over the ws:// tunnel. Needs sshd (only task test-exp-ssh provisions + # remote exec over the ws:// tunnel. Needs sshd (only task test-ssh provisions # it); the test server probes the same way, so skip where it's absent. if [ -z "$(command -v sshd || ls /usr/sbin/sshd /usr/local/sbin/sshd /sbin/sshd 2>/dev/null)" ]; then echo "SKIP_TEST sshd (openssh-server) not installed" diff --git a/acceptance/ssh/connection/test.toml b/acceptance/ssh/connection/test.toml index 3f67650471d..c9eef1892a7 100644 --- a/acceptance/ssh/connection/test.toml +++ b/acceptance/ssh/connection/test.toml @@ -12,7 +12,7 @@ Ignore = [ ] # Linux-only: the local run drives a real sshd, reliable only there (and where -# task test-exp-ssh provisions it). Absent GOOS keys default to enabled, so the +# task test-ssh provisions it). Absent GOOS keys default to enabled, so the # other OSes must be disabled explicitly. GOOS.linux = true GOOS.darwin = false diff --git a/cmd/cmd.go b/cmd/cmd.go index a2c3280b940..54b15ea7c57 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -6,7 +6,7 @@ import ( aitoolscmd "github.com/databricks/cli/cmd/aitools" "github.com/databricks/cli/cmd/psql" - ssh "github.com/databricks/cli/experimental/ssh/cmd" + "github.com/databricks/cli/cmd/ssh" "github.com/databricks/cli/cmd/account" "github.com/databricks/cli/cmd/api" diff --git a/experimental/ssh/CLAUDE.md b/cmd/ssh/CLAUDE.md similarity index 98% rename from experimental/ssh/CLAUDE.md rename to cmd/ssh/CLAUDE.md index 222439b1f69..f7fb8ceb5a9 100644 --- a/experimental/ssh/CLAUDE.md +++ b/cmd/ssh/CLAUDE.md @@ -1,4 +1,4 @@ -# Working on `experimental/ssh` +# Working on `cmd/ssh` This file provides guidance to AI assistants working on the SSH tunnel. See the repository root `CLAUDE.md` for project-wide rules. diff --git a/experimental/ssh/FAILURE_MODES.md b/cmd/ssh/FAILURE_MODES.md similarity index 99% rename from experimental/ssh/FAILURE_MODES.md rename to cmd/ssh/FAILURE_MODES.md index 717de265b1b..973038633eb 100644 --- a/experimental/ssh/FAILURE_MODES.md +++ b/cmd/ssh/FAILURE_MODES.md @@ -154,5 +154,5 @@ The proxy-layer behaviors have unit tests that don't need a cluster: (state message, error trace, run-page URL) using SDK mocks. ```shell -go test ./experimental/ssh/... +go test ./cmd/ssh/... ``` diff --git a/experimental/ssh/README.md b/cmd/ssh/README.md similarity index 100% rename from experimental/ssh/README.md rename to cmd/ssh/README.md diff --git a/experimental/ssh/bench.sh b/cmd/ssh/bench.sh similarity index 94% rename from experimental/ssh/bench.sh rename to cmd/ssh/bench.sh index 466e2104c07..583b82d5440 100755 --- a/experimental/ssh/bench.sh +++ b/cmd/ssh/bench.sh @@ -3,7 +3,7 @@ # SSH Tunnel Performance Test Script # Usage: # 1. Setup ssh config: ./cli ssh setup --cluster --name -# 2. Run: ./experimental/ssh/bench.sh [ssh-tunnel-binary-path] [profile] +# 2. Run: ./cmd/ssh/bench.sh [ssh-tunnel-binary-path] [profile] set -e diff --git a/experimental/ssh/cmd/connect.go b/cmd/ssh/connect.go similarity index 99% rename from experimental/ssh/cmd/connect.go rename to cmd/ssh/connect.go index 7502d70f560..aec55e7ad3a 100644 --- a/experimental/ssh/cmd/connect.go +++ b/cmd/ssh/connect.go @@ -4,7 +4,7 @@ import ( "time" "github.com/databricks/cli/cmd/root" - "github.com/databricks/cli/experimental/ssh/internal/client" + "github.com/databricks/cli/cmd/ssh/internal/client" "github.com/databricks/cli/libs/cmdctx" "github.com/spf13/cobra" ) diff --git a/experimental/ssh/cmd/constants.go b/cmd/ssh/constants.go similarity index 100% rename from experimental/ssh/cmd/constants.go rename to cmd/ssh/constants.go diff --git a/experimental/ssh/internal/client/client.go b/cmd/ssh/internal/client/client.go similarity index 99% rename from experimental/ssh/internal/client/client.go rename to cmd/ssh/internal/client/client.go index 031bbd4d7af..1efeb2ec9f3 100644 --- a/experimental/ssh/internal/client/client.go +++ b/cmd/ssh/internal/client/client.go @@ -20,11 +20,11 @@ import ( "syscall" "time" - "github.com/databricks/cli/experimental/ssh/internal/keys" - "github.com/databricks/cli/experimental/ssh/internal/proxy" - "github.com/databricks/cli/experimental/ssh/internal/sshconfig" - "github.com/databricks/cli/experimental/ssh/internal/vscode" - sshWorkspace "github.com/databricks/cli/experimental/ssh/internal/workspace" + "github.com/databricks/cli/cmd/ssh/internal/keys" + "github.com/databricks/cli/cmd/ssh/internal/proxy" + "github.com/databricks/cli/cmd/ssh/internal/sshconfig" + "github.com/databricks/cli/cmd/ssh/internal/vscode" + sshWorkspace "github.com/databricks/cli/cmd/ssh/internal/workspace" "github.com/databricks/cli/internal/build" "github.com/databricks/cli/libs/auth" "github.com/databricks/cli/libs/cmdio" diff --git a/experimental/ssh/internal/client/client_internal_test.go b/cmd/ssh/internal/client/client_internal_test.go similarity index 99% rename from experimental/ssh/internal/client/client_internal_test.go rename to cmd/ssh/internal/client/client_internal_test.go index cb47cd71bb8..ad553bcf08c 100644 --- a/experimental/ssh/internal/client/client_internal_test.go +++ b/cmd/ssh/internal/client/client_internal_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/databricks/cli/experimental/ssh/internal/sshconfig" + "github.com/databricks/cli/cmd/ssh/internal/sshconfig" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/telemetry/protos" "github.com/databricks/databricks-sdk-go/experimental/mocks" diff --git a/experimental/ssh/internal/client/client_test.go b/cmd/ssh/internal/client/client_test.go similarity index 99% rename from experimental/ssh/internal/client/client_test.go rename to cmd/ssh/internal/client/client_test.go index 09fd1067d4f..8e0c27cb5db 100644 --- a/experimental/ssh/internal/client/client_test.go +++ b/cmd/ssh/internal/client/client_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/databricks/cli/experimental/ssh/internal/client" + "github.com/databricks/cli/cmd/ssh/internal/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/experimental/ssh/internal/client/policy_internal_test.go b/cmd/ssh/internal/client/policy_internal_test.go similarity index 100% rename from experimental/ssh/internal/client/policy_internal_test.go rename to cmd/ssh/internal/client/policy_internal_test.go diff --git a/experimental/ssh/internal/client/releases.go b/cmd/ssh/internal/client/releases.go similarity index 99% rename from experimental/ssh/internal/client/releases.go rename to cmd/ssh/internal/client/releases.go index 141b4def5fd..23f4b2e020a 100644 --- a/experimental/ssh/internal/client/releases.go +++ b/cmd/ssh/internal/client/releases.go @@ -15,7 +15,7 @@ import ( "syscall" "time" - "github.com/databricks/cli/experimental/ssh/internal/workspace" + "github.com/databricks/cli/cmd/ssh/internal/workspace" "github.com/databricks/cli/libs/filer" "github.com/databricks/cli/libs/log" "github.com/databricks/databricks-sdk-go" diff --git a/experimental/ssh/internal/client/releases_test.go b/cmd/ssh/internal/client/releases_test.go similarity index 100% rename from experimental/ssh/internal/client/releases_test.go rename to cmd/ssh/internal/client/releases_test.go diff --git a/experimental/ssh/internal/client/ssh-server-bootstrap.py b/cmd/ssh/internal/client/ssh-server-bootstrap.py similarity index 100% rename from experimental/ssh/internal/client/ssh-server-bootstrap.py rename to cmd/ssh/internal/client/ssh-server-bootstrap.py diff --git a/experimental/ssh/internal/client/submit_internal_test.go b/cmd/ssh/internal/client/submit_internal_test.go similarity index 100% rename from experimental/ssh/internal/client/submit_internal_test.go rename to cmd/ssh/internal/client/submit_internal_test.go diff --git a/experimental/ssh/internal/client/websockets.go b/cmd/ssh/internal/client/websockets.go similarity index 100% rename from experimental/ssh/internal/client/websockets.go rename to cmd/ssh/internal/client/websockets.go diff --git a/experimental/ssh/internal/client/websockets_test.go b/cmd/ssh/internal/client/websockets_test.go similarity index 100% rename from experimental/ssh/internal/client/websockets_test.go rename to cmd/ssh/internal/client/websockets_test.go diff --git a/experimental/ssh/internal/fileutil/backup.go b/cmd/ssh/internal/fileutil/backup.go similarity index 100% rename from experimental/ssh/internal/fileutil/backup.go rename to cmd/ssh/internal/fileutil/backup.go diff --git a/experimental/ssh/internal/fileutil/backup_test.go b/cmd/ssh/internal/fileutil/backup_test.go similarity index 97% rename from experimental/ssh/internal/fileutil/backup_test.go rename to cmd/ssh/internal/fileutil/backup_test.go index 7101fd3afc0..e7825ad9dc6 100644 --- a/experimental/ssh/internal/fileutil/backup_test.go +++ b/cmd/ssh/internal/fileutil/backup_test.go @@ -7,7 +7,7 @@ import ( "runtime" "testing" - "github.com/databricks/cli/experimental/ssh/internal/fileutil" + "github.com/databricks/cli/cmd/ssh/internal/fileutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/experimental/ssh/internal/keys/keys.go b/cmd/ssh/internal/keys/keys.go similarity index 100% rename from experimental/ssh/internal/keys/keys.go rename to cmd/ssh/internal/keys/keys.go diff --git a/experimental/ssh/internal/keys/keys_test.go b/cmd/ssh/internal/keys/keys_test.go similarity index 97% rename from experimental/ssh/internal/keys/keys_test.go rename to cmd/ssh/internal/keys/keys_test.go index 68054311f8c..b753d477b80 100644 --- a/experimental/ssh/internal/keys/keys_test.go +++ b/cmd/ssh/internal/keys/keys_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - "github.com/databricks/cli/experimental/ssh/internal/keys" + "github.com/databricks/cli/cmd/ssh/internal/keys" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) diff --git a/experimental/ssh/internal/keys/secrets.go b/cmd/ssh/internal/keys/secrets.go similarity index 100% rename from experimental/ssh/internal/keys/secrets.go rename to cmd/ssh/internal/keys/secrets.go diff --git a/experimental/ssh/internal/proxy/client.go b/cmd/ssh/internal/proxy/client.go similarity index 100% rename from experimental/ssh/internal/proxy/client.go rename to cmd/ssh/internal/proxy/client.go diff --git a/experimental/ssh/internal/proxy/client_server_test.go b/cmd/ssh/internal/proxy/client_server_test.go similarity index 100% rename from experimental/ssh/internal/proxy/client_server_test.go rename to cmd/ssh/internal/proxy/client_server_test.go diff --git a/experimental/ssh/internal/proxy/connections.go b/cmd/ssh/internal/proxy/connections.go similarity index 100% rename from experimental/ssh/internal/proxy/connections.go rename to cmd/ssh/internal/proxy/connections.go diff --git a/experimental/ssh/internal/proxy/connections_test.go b/cmd/ssh/internal/proxy/connections_test.go similarity index 100% rename from experimental/ssh/internal/proxy/connections_test.go rename to cmd/ssh/internal/proxy/connections_test.go diff --git a/experimental/ssh/internal/proxy/keepalive_test.go b/cmd/ssh/internal/proxy/keepalive_test.go similarity index 100% rename from experimental/ssh/internal/proxy/keepalive_test.go rename to cmd/ssh/internal/proxy/keepalive_test.go diff --git a/experimental/ssh/internal/proxy/proxy.go b/cmd/ssh/internal/proxy/proxy.go similarity index 100% rename from experimental/ssh/internal/proxy/proxy.go rename to cmd/ssh/internal/proxy/proxy.go diff --git a/experimental/ssh/internal/proxy/proxy_test.go b/cmd/ssh/internal/proxy/proxy_test.go similarity index 100% rename from experimental/ssh/internal/proxy/proxy_test.go rename to cmd/ssh/internal/proxy/proxy_test.go diff --git a/experimental/ssh/internal/proxy/server.go b/cmd/ssh/internal/proxy/server.go similarity index 100% rename from experimental/ssh/internal/proxy/server.go rename to cmd/ssh/internal/proxy/server.go diff --git a/experimental/ssh/internal/server/jupyter-init.py b/cmd/ssh/internal/server/jupyter-init.py similarity index 100% rename from experimental/ssh/internal/server/jupyter-init.py rename to cmd/ssh/internal/server/jupyter-init.py diff --git a/experimental/ssh/internal/server/logs.go b/cmd/ssh/internal/server/logs.go similarity index 100% rename from experimental/ssh/internal/server/logs.go rename to cmd/ssh/internal/server/logs.go diff --git a/experimental/ssh/internal/server/logs_test.go b/cmd/ssh/internal/server/logs_test.go similarity index 100% rename from experimental/ssh/internal/server/logs_test.go rename to cmd/ssh/internal/server/logs_test.go diff --git a/experimental/ssh/internal/server/server.go b/cmd/ssh/internal/server/server.go similarity index 98% rename from experimental/ssh/internal/server/server.go rename to cmd/ssh/internal/server/server.go index 4356700d87d..5f561cb2737 100644 --- a/experimental/ssh/internal/server/server.go +++ b/cmd/ssh/internal/server/server.go @@ -17,8 +17,8 @@ import ( "path/filepath" "time" - "github.com/databricks/cli/experimental/ssh/internal/proxy" - "github.com/databricks/cli/experimental/ssh/internal/workspace" + "github.com/databricks/cli/cmd/ssh/internal/proxy" + "github.com/databricks/cli/cmd/ssh/internal/workspace" "github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/log" "github.com/databricks/databricks-sdk-go" diff --git a/experimental/ssh/internal/server/server_test.go b/cmd/ssh/internal/server/server_test.go similarity index 100% rename from experimental/ssh/internal/server/server_test.go rename to cmd/ssh/internal/server/server_test.go diff --git a/experimental/ssh/internal/server/sshd.go b/cmd/ssh/internal/server/sshd.go similarity index 98% rename from experimental/ssh/internal/server/sshd.go rename to cmd/ssh/internal/server/sshd.go index 01fd0e3cdb0..bcf5893df2e 100644 --- a/experimental/ssh/internal/server/sshd.go +++ b/cmd/ssh/internal/server/sshd.go @@ -12,7 +12,7 @@ import ( "strconv" "strings" - "github.com/databricks/cli/experimental/ssh/internal/keys" + "github.com/databricks/cli/cmd/ssh/internal/keys" "github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/log" "github.com/databricks/databricks-sdk-go" diff --git a/experimental/ssh/internal/server/sshd_test.go b/cmd/ssh/internal/server/sshd_test.go similarity index 100% rename from experimental/ssh/internal/server/sshd_test.go rename to cmd/ssh/internal/server/sshd_test.go diff --git a/experimental/ssh/internal/setup/setup.go b/cmd/ssh/internal/setup/setup.go similarity index 95% rename from experimental/ssh/internal/setup/setup.go rename to cmd/ssh/internal/setup/setup.go index 286ab7be7a7..d98a6d7d947 100644 --- a/experimental/ssh/internal/setup/setup.go +++ b/cmd/ssh/internal/setup/setup.go @@ -6,9 +6,9 @@ import ( "fmt" "time" - sshclient "github.com/databricks/cli/experimental/ssh/internal/client" - "github.com/databricks/cli/experimental/ssh/internal/keys" - "github.com/databricks/cli/experimental/ssh/internal/sshconfig" + sshclient "github.com/databricks/cli/cmd/ssh/internal/client" + "github.com/databricks/cli/cmd/ssh/internal/keys" + "github.com/databricks/cli/cmd/ssh/internal/sshconfig" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/service/compute" diff --git a/experimental/ssh/internal/setup/setup_test.go b/cmd/ssh/internal/setup/setup_test.go similarity index 99% rename from experimental/ssh/internal/setup/setup_test.go rename to cmd/ssh/internal/setup/setup_test.go index 9b3267c6b62..d7e4662f553 100644 --- a/experimental/ssh/internal/setup/setup_test.go +++ b/cmd/ssh/internal/setup/setup_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/databricks/cli/experimental/ssh/internal/client" + "github.com/databricks/cli/cmd/ssh/internal/client" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/databricks-sdk-go" "github.com/databricks/databricks-sdk-go/experimental/mocks" diff --git a/experimental/ssh/internal/sshconfig/sshconfig.go b/cmd/ssh/internal/sshconfig/sshconfig.go similarity index 99% rename from experimental/ssh/internal/sshconfig/sshconfig.go rename to cmd/ssh/internal/sshconfig/sshconfig.go index fbbf3b42fee..cc900115da4 100644 --- a/experimental/ssh/internal/sshconfig/sshconfig.go +++ b/cmd/ssh/internal/sshconfig/sshconfig.go @@ -9,7 +9,7 @@ import ( "path/filepath" "strings" - "github.com/databricks/cli/experimental/ssh/internal/fileutil" + "github.com/databricks/cli/cmd/ssh/internal/fileutil" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/env" ) diff --git a/experimental/ssh/internal/sshconfig/sshconfig_test.go b/cmd/ssh/internal/sshconfig/sshconfig_test.go similarity index 100% rename from experimental/ssh/internal/sshconfig/sshconfig_test.go rename to cmd/ssh/internal/sshconfig/sshconfig_test.go diff --git a/experimental/ssh/internal/vscode/run.go b/cmd/ssh/internal/vscode/run.go similarity index 100% rename from experimental/ssh/internal/vscode/run.go rename to cmd/ssh/internal/vscode/run.go diff --git a/experimental/ssh/internal/vscode/run_test.go b/cmd/ssh/internal/vscode/run_test.go similarity index 100% rename from experimental/ssh/internal/vscode/run_test.go rename to cmd/ssh/internal/vscode/run_test.go diff --git a/experimental/ssh/internal/vscode/settings.go b/cmd/ssh/internal/vscode/settings.go similarity index 99% rename from experimental/ssh/internal/vscode/settings.go rename to cmd/ssh/internal/vscode/settings.go index 5b4a0bc34fc..29448c1fc75 100644 --- a/experimental/ssh/internal/vscode/settings.go +++ b/cmd/ssh/internal/vscode/settings.go @@ -11,7 +11,7 @@ import ( "runtime" "strings" - "github.com/databricks/cli/experimental/ssh/internal/fileutil" + "github.com/databricks/cli/cmd/ssh/internal/fileutil" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/log" diff --git a/experimental/ssh/internal/vscode/settings_test.go b/cmd/ssh/internal/vscode/settings_test.go similarity index 99% rename from experimental/ssh/internal/vscode/settings_test.go rename to cmd/ssh/internal/vscode/settings_test.go index 9ec36ec7364..e8e054aa265 100644 --- a/experimental/ssh/internal/vscode/settings_test.go +++ b/cmd/ssh/internal/vscode/settings_test.go @@ -9,7 +9,7 @@ import ( "runtime" "testing" - "github.com/databricks/cli/experimental/ssh/internal/fileutil" + "github.com/databricks/cli/cmd/ssh/internal/fileutil" "github.com/databricks/cli/libs/cmdio" "github.com/databricks/cli/libs/env" "github.com/stretchr/testify/assert" diff --git a/experimental/ssh/internal/workspace/workspace.go b/cmd/ssh/internal/workspace/workspace.go similarity index 100% rename from experimental/ssh/internal/workspace/workspace.go rename to cmd/ssh/internal/workspace/workspace.go diff --git a/experimental/ssh/cmd/server.go b/cmd/ssh/server.go similarity index 98% rename from experimental/ssh/cmd/server.go rename to cmd/ssh/server.go index 3675a4a7fe8..85e56c9001b 100644 --- a/experimental/ssh/cmd/server.go +++ b/cmd/ssh/server.go @@ -4,7 +4,7 @@ import ( "time" "github.com/databricks/cli/cmd/root" - "github.com/databricks/cli/experimental/ssh/internal/server" + "github.com/databricks/cli/cmd/ssh/internal/server" "github.com/databricks/cli/libs/cmdctx" "github.com/spf13/cobra" ) diff --git a/experimental/ssh/cmd/setup.go b/cmd/ssh/setup.go similarity index 97% rename from experimental/ssh/cmd/setup.go rename to cmd/ssh/setup.go index ff67501445e..5478ea11d49 100644 --- a/experimental/ssh/cmd/setup.go +++ b/cmd/ssh/setup.go @@ -4,7 +4,7 @@ import ( "time" "github.com/databricks/cli/cmd/root" - "github.com/databricks/cli/experimental/ssh/internal/setup" + "github.com/databricks/cli/cmd/ssh/internal/setup" "github.com/databricks/cli/libs/cmdctx" "github.com/spf13/cobra" ) diff --git a/experimental/ssh/cmd/ssh.go b/cmd/ssh/ssh.go similarity index 87% rename from experimental/ssh/cmd/ssh.go rename to cmd/ssh/ssh.go index 9939d2f7050..ae73d5251a2 100644 --- a/experimental/ssh/cmd/ssh.go +++ b/cmd/ssh/ssh.go @@ -6,9 +6,8 @@ import ( func New() *cobra.Command { cmd := &cobra.Command{ - Use: "ssh", - Short: "Connect to your Databricks compute and workspace via SSH", - Hidden: true, + Use: "ssh", + Short: "Connect to your Databricks compute and workspace via SSH", Long: `Connect to your Databricks compute and workspace via SSH. Common workflows: diff --git a/libs/process/group.go b/libs/process/group.go index 24b3e289dd0..309a8cb8fca 100644 --- a/libs/process/group.go +++ b/libs/process/group.go @@ -4,6 +4,6 @@ import "time" // processGroupGracePeriod bounds how long WithProcessGroup waits after the // context is cancelled before escalating to SIGKILL. It mirrors the 10s grace -// period used elsewhere for subprocess termination (see experimental/ssh). It is +// period used elsewhere for subprocess termination (see cmd/ssh). It is // a var, not a const, only so the escalation test can shorten it. var processGroupGracePeriod = 10 * time.Second diff --git a/libs/testserver/ssh.go b/libs/testserver/ssh.go index 0cb7eef8846..1a8f9dff408 100644 --- a/libs/testserver/ssh.go +++ b/libs/testserver/ssh.go @@ -29,7 +29,7 @@ func sshTunnelRemoteUser() string { } // sshClientPublicKeySecretKey is the secret the CLI stores its authorized public key -// under (mirrors clientPublicKeyName in experimental/ssh); sshd authorizes it below. +// under (mirrors clientPublicKeyName in cmd/ssh); sshd authorizes it below. const sshClientPublicKeySecretKey = "client-public-key" var sshTunnelUpgrader = websocket.Upgrader{} diff --git a/ruff.toml b/ruff.toml index db6ffa98604..c9a97b217ed 100644 --- a/ruff.toml +++ b/ruff.toml @@ -64,5 +64,5 @@ exclude = [ [lint.per-file-ignores] # dbutils and spark are injected into the global namespace by the Databricks # runtime where these scripts execute; they are never imported. -"experimental/ssh/internal/client/ssh-server-bootstrap.py" = ["F821"] +"cmd/ssh/internal/client/ssh-server-bootstrap.py" = ["F821"] "acceptance/dbr_runner.py" = ["F821"] diff --git a/tools/testmask/targets.go b/tools/testmask/targets.go index bb0dcbfe1bf..d7064394a4d 100644 --- a/tools/testmask/targets.go +++ b/tools/testmask/targets.go @@ -14,7 +14,7 @@ import ( // trigger set for their corresponding CI job of the same name. var ciTargets = []string{ "test-exp-aitools", - "test-exp-ssh", + "test-ssh", "test-pipelines", "test-sandbox", } diff --git a/tools/testmask/targets_test.go b/tools/testmask/targets_test.go index b2b058fc59d..b44a0a855d8 100644 --- a/tools/testmask/targets_test.go +++ b/tools/testmask/targets_test.go @@ -17,12 +17,12 @@ func TestGetTargets(t *testing.T) { targets []string }{ { - name: "experimental_ssh", + name: "ssh", files: []string{ - "experimental/ssh/main.go", - "experimental/ssh/lib/server.go", + "cmd/ssh/main.go", + "cmd/ssh/lib/server.go", }, - targets: []string{"test-exp-ssh"}, + targets: []string{"test-ssh"}, }, { name: "pipelines", @@ -59,29 +59,29 @@ func TestGetTargets(t *testing.T) { files: []string{ "go.mod", }, - targets: []string{"test", "test-exp-aitools", "test-exp-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, }, { name: "go_sum_triggers_all", files: []string{ "go.sum", }, - targets: []string{"test", "test-exp-aitools", "test-exp-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, }, { name: "go_mod_with_other_files_triggers_all", files: []string{ - "experimental/ssh/main.go", + "cmd/ssh/main.go", "go.mod", }, - targets: []string{"test", "test-exp-aitools", "test-exp-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, }, { name: "setup_build_environment_triggers_all", files: []string{ ".github/actions/setup-build-environment/action.yml", }, - targets: []string{"test", "test-exp-aitools", "test-exp-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, }, { name: "empty_files", From 1a6fe68174e726834f29ff0a2a91a387b841cee6 Mon Sep 17 00:00:00 2001 From: TanishqDatabricks Date: Thu, 27 Aug 2026 14:53:25 +0200 Subject: [PATCH 2/3] ssh: fix testmask target ordering and root help golden after graduation Two test fixes for the test-exp-ssh -> test-ssh rename and unhiding of the ssh command in the previous commit: - tools/testmask/targets_test.go: GetTargets returns alphabetically sorted targets, and "test-ssh" sorts after "test-pipelines"/"test-sandbox" whereas the old "test-exp-ssh" sorted before them. Reorder the expected slices in the "triggers all" cases to match; the string rename alone left them stale. - acceptance/help/output.txt: `databricks` root help now lists `ssh` under Additional Commands (it was hidden before), so add the entry. Co-authored-by: Isaac --- acceptance/help/output.txt | 1 + tools/testmask/targets_test.go | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/acceptance/help/output.txt b/acceptance/help/output.txt index 266e1227c48..539163382e9 100644 --- a/acceptance/help/output.txt +++ b/acceptance/help/output.txt @@ -183,6 +183,7 @@ Additional Commands: help Help about any command labs Manage Databricks Labs installations quickstart Print an introduction to the Databricks CLI + ssh Connect to your Databricks compute and workspace via SSH version Retrieve information about the current version of this CLI Flags: diff --git a/tools/testmask/targets_test.go b/tools/testmask/targets_test.go index b44a0a855d8..07e34056f4f 100644 --- a/tools/testmask/targets_test.go +++ b/tools/testmask/targets_test.go @@ -59,14 +59,14 @@ func TestGetTargets(t *testing.T) { files: []string{ "go.mod", }, - targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-pipelines", "test-sandbox", "test-ssh"}, }, { name: "go_sum_triggers_all", files: []string{ "go.sum", }, - targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-pipelines", "test-sandbox", "test-ssh"}, }, { name: "go_mod_with_other_files_triggers_all", @@ -74,14 +74,14 @@ func TestGetTargets(t *testing.T) { "cmd/ssh/main.go", "go.mod", }, - targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-pipelines", "test-sandbox", "test-ssh"}, }, { name: "setup_build_environment_triggers_all", files: []string{ ".github/actions/setup-build-environment/action.yml", }, - targets: []string{"test", "test-exp-aitools", "test-ssh", "test-pipelines", "test-sandbox"}, + targets: []string{"test", "test-exp-aitools", "test-pipelines", "test-sandbox", "test-ssh"}, }, { name: "empty_files", From de0b9a734afd915c9a16ee82e5c90f1898f6cdb7 Mon Sep 17 00:00:00 2001 From: TanishqDatabricks Date: Thu, 27 Aug 2026 14:57:40 +0200 Subject: [PATCH 3/3] onboard-team-area: use sandbox as the top-level-hidden example ssh graduated out of experimental and is no longer hidden, so it can no longer illustrate the "top-level in cmd/cmd.go with Hidden: true" registration option. Point at `sandbox`, which still registers that way. Co-authored-by: Isaac --- .agents/skills/onboard-team-area/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/skills/onboard-team-area/SKILL.md b/.agents/skills/onboard-team-area/SKILL.md index c7bc9165147..0edce8d66b7 100644 --- a/.agents/skills/onboard-team-area/SKILL.md +++ b/.agents/skills/onboard-team-area/SKILL.md @@ -60,5 +60,5 @@ No `.nextchanges/` entry; this is ownership/config only. Write the PR using the ## Experimental vs stable, and graduation -- **Experimental** — code under `experimental//`, tests under `acceptance/experimental//`. Register it under the hidden parent in `cmd/experimental/experimental.go`, or top-level in `cmd/cmd.go` with `Hidden: true` (as `ssh` does). Experimental commands still ship enabled in every release; `Hidden` only removes them from `--help`, it does not gate or compile them out. No `.nextchanges/` entries while experimental. To hand a build to testers, push a `bugbash-` branch (auto-builds a snapshot) and share the `internal/bugbash/exec.sh` one-liner. +- **Experimental** — code under `experimental//`, tests under `acceptance/experimental//`. Register it under the hidden parent in `cmd/experimental/experimental.go`, or top-level in `cmd/cmd.go` with `Hidden: true` (as `sandbox` does). Experimental commands still ship enabled in every release; `Hidden` only removes them from `--help`, it does not gate or compile them out. No `.nextchanges/` entries while experimental. To hand a build to testers, push a `bugbash-` branch (auto-builds a snapshot) and share the `internal/bugbash/exec.sh` one-liner. - **Graduating to stable** — `git mv` the feature-complete commands to `cmd//` + `libs//`, register them top-level in `cmd/cmd.go`, keep the old `experimental` paths as deprecated cobra aliases (`sub.Hidden = true`, `sub.Deprecated = '...'`), add OWNERS rules for the new stable paths, and add a `.nextchanges/` entry. See `experimental/aitools` graduating to top-level `aitools` (PR #4917) as the worked example.