Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit473a105

Browse files
committed
Merge remote-tracking branch 'origin/main' into ssncferreira/feat-add-provisioner-daemon-name
2 parents58d0234 +f8f4dc6 commit473a105

File tree

30 files changed

+795
-377
lines changed

30 files changed

+795
-377
lines changed

‎.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ jobs:
336336
# a separate repository to allow its use before actions/checkout.
337337
-name:Setup RAM Disks
338338
if:runner.os == 'Windows'
339-
uses:coder/setup-ramdisk-action@79dacfe70c47ad6d6c0dd7f45412368802641439
339+
uses:coder/setup-ramdisk-action@81c5c441bda00c6c3d6bcee2e5a33ed4aadbbcc1
340340

341341
-name:Checkout
342342
uses:actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683# v4.2.2

‎.github/workflows/release.yaml

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -924,55 +924,3 @@ jobs:
924924
continue-on-error:true
925925
run:|
926926
make sqlc-push
927-
928-
update-calendar:
929-
name:"Update release calendar in docs"
930-
runs-on:"ubuntu-latest"
931-
needs:[release, publish-homebrew, publish-winget, publish-sqlc]
932-
if:${{ !inputs.dry_run }}
933-
permissions:
934-
contents:write
935-
pull-requests:write
936-
steps:
937-
-name:Harden Runner
938-
uses:step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0# v2.12.0
939-
with:
940-
egress-policy:audit
941-
942-
-name:Checkout repository
943-
uses:actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683# v4.2.2
944-
with:
945-
fetch-depth:0# Needed to get all tags for version calculation
946-
947-
-name:Set up Git
948-
run:|
949-
git config user.name "Coder CI"
950-
git config user.email "cdrci@coder.com"
951-
952-
-name:Run update script
953-
run:|
954-
./scripts/update-release-calendar.sh
955-
make fmt/markdown
956-
957-
-name:Check for changes
958-
id:check_changes
959-
run:|
960-
if git diff --quiet docs/install/releases/index.md; then
961-
echo "No changes detected in release calendar."
962-
echo "changes=false" >> $GITHUB_OUTPUT
963-
else
964-
echo "Changes detected in release calendar."
965-
echo "changes=true" >> $GITHUB_OUTPUT
966-
fi
967-
968-
-name:Create Pull Request
969-
if:steps.check_changes.outputs.changes == 'true'
970-
uses:peter-evans/create-pull-request@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0# v3.0.0
971-
with:
972-
commit-message:"docs: update release calendar"
973-
title:"docs: update release calendar"
974-
body:|
975-
This PR automatically updates the release calendar in the docs.
976-
branch:bot/update-release-calendar
977-
delete-branch:true
978-
labels:docs

‎agent/agent.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ type Options struct {
8989
ServiceBannerRefreshInterval time.Duration
9090
BlockFileTransferbool
9191
Execer agentexec.Execer
92-
SubAgentbool
9392

9493
ExperimentalDevcontainersEnabledbool
9594
ContainerAPIOptions []agentcontainers.Option// Enable ExperimentalDevcontainersEnabled for these to be effective.
@@ -191,8 +190,6 @@ func New(options Options) Agent {
191190
metrics:newAgentMetrics(prometheusRegistry),
192191
execer:options.Execer,
193192

194-
subAgent:options.SubAgent,
195-
196193
experimentalDevcontainersEnabled:options.ExperimentalDevcontainersEnabled,
197194
containerAPIOptions:options.ContainerAPIOptions,
198195
}
@@ -275,8 +272,6 @@ type agent struct {
275272
metrics*agentMetrics
276273
execer agentexec.Execer
277274

278-
subAgentbool
279-
280275
experimentalDevcontainersEnabledbool
281276
containerAPIOptions []agentcontainers.Option
282277
containerAPI atomic.Pointer[agentcontainers.API]// Set by apiHandler.

‎cli/agent.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
5454
blockFileTransferbool
5555
agentHeaderCommandstring
5656
agentHeader []string
57-
subAgentbool
5857

5958
experimentalDevcontainersEnabledbool
6059
)
@@ -362,7 +361,6 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
362361
PrometheusRegistry:prometheusRegistry,
363362
BlockFileTransfer:blockFileTransfer,
364363
Execer:execer,
365-
SubAgent:subAgent,
366364
ExperimentalDevcontainersEnabled:experimentalDevcontainersEnabled,
367365
})
368366

@@ -509,17 +507,6 @@ func (r *RootCmd) workspaceAgent() *serpent.Command {
509507
Description:"Allow the agent to automatically detect running devcontainers.",
510508
Value:serpent.BoolOf(&experimentalDevcontainersEnabled),
511509
},
512-
{
513-
Flag:"is-sub-agent",
514-
Default:"false",
515-
Env:"CODER_AGENT_IS_SUB_AGENT",
516-
Description:"Specify whether this is a sub agent or not.",
517-
Value:serpent.BoolOf(&subAgent),
518-
// As `coderd` handles the creation of sub-agents, it does not make
519-
// sense for this to be exposed. We do not want people setting an
520-
// agent as a sub-agent if it is not.
521-
Hidden:true,
522-
},
523510
}
524511

525512
returncmd

‎cli/ssh.go

Lines changed: 56 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,33 @@ func (r *RootCmd) ssh() *serpent.Command {
9090
wsClient:=workspacesdk.New(client)
9191
cmd:=&serpent.Command{
9292
Annotations:workspaceCommand,
93-
Use:"ssh <workspace>",
94-
Short:"Start a shell into a workspace",
95-
Long:"This command does not have full parity with the standard SSH command. For users who need the full functionality of SSH, create an ssh configuration with `coder config-ssh`.",
93+
Use:"ssh <workspace> [command]",
94+
Short:"Start a shell into a workspace or run a command",
95+
Long:"This command does not have full parity with the standard SSH command. For users who need the full functionality of SSH, create an ssh configuration with `coder config-ssh`.\n\n"+
96+
FormatExamples(
97+
Example{
98+
Description:"Use `--` to separate and pass flags directly to the command executed via SSH.",
99+
Command:"coder ssh <workspace> -- ls -la",
100+
},
101+
),
96102
Middleware:serpent.Chain(
97-
serpent.RequireNArgs(1),
103+
// Require at least one arg for the workspace name
104+
func(next serpent.HandlerFunc) serpent.HandlerFunc {
105+
returnfunc(i*serpent.Invocation)error {
106+
got:=len(i.Args)
107+
ifgot<1 {
108+
returnxerrors.New("expected the name of a workspace")
109+
}
110+
111+
returnnext(i)
112+
}
113+
},
98114
r.InitClient(client),
99115
initAppearance(client,&appearanceConfig),
100116
),
101117
Handler:func(inv*serpent.Invocation) (retErrerror) {
118+
command:=strings.Join(inv.Args[1:]," ")
119+
102120
// Before dialing the SSH server over TCP, capture Interrupt signals
103121
// so that if we are interrupted, we have a chance to tear down the
104122
// TCP session cleanly before exiting. If we don't, then the TCP
@@ -548,40 +566,46 @@ func (r *RootCmd) ssh() *serpent.Command {
548566
sshSession.Stdout=inv.Stdout
549567
sshSession.Stderr=inv.Stderr
550568

551-
err=sshSession.Shell()
552-
iferr!=nil {
553-
returnxerrors.Errorf("start shell: %w",err)
554-
}
569+
ifcommand!="" {
570+
err:=sshSession.Run(command)
571+
iferr!=nil {
572+
returnxerrors.Errorf("run command: %w",err)
573+
}
574+
}else {
575+
err=sshSession.Shell()
576+
iferr!=nil {
577+
returnxerrors.Errorf("start shell: %w",err)
578+
}
555579

556-
// Put cancel at the top of the defer stack to initiate
557-
// shutdown of services.
558-
defercancel()
580+
// Put cancel at the top of the defer stack to initiate
581+
// shutdown of services.
582+
defercancel()
559583

560-
ifvalidOut {
561-
// Set initial window size.
562-
width,height,err:=term.GetSize(int(stdoutFile.Fd()))
563-
iferr==nil {
564-
_=sshSession.WindowChange(height,width)
584+
ifvalidOut {
585+
// Set initial window size.
586+
width,height,err:=term.GetSize(int(stdoutFile.Fd()))
587+
iferr==nil {
588+
_=sshSession.WindowChange(height,width)
589+
}
565590
}
566-
}
567591

568-
err=sshSession.Wait()
569-
conn.SendDisconnectedTelemetry()
570-
iferr!=nil {
571-
ifexitErr:= (&gossh.ExitError{});errors.As(err,&exitErr) {
572-
// Clear the error since it's not useful beyond
573-
// reporting status.
574-
returnExitError(exitErr.ExitStatus(),nil)
575-
}
576-
// If the connection drops unexpectedly, we get an
577-
// ExitMissingError but no other error details, so try to at
578-
// least give the user a better message
579-
iferrors.Is(err,&gossh.ExitMissingError{}) {
580-
returnExitError(255,xerrors.New("SSH connection ended unexpectedly"))
592+
err=sshSession.Wait()
593+
conn.SendDisconnectedTelemetry()
594+
iferr!=nil {
595+
ifexitErr:= (&gossh.ExitError{});errors.As(err,&exitErr) {
596+
// Clear the error since it's not useful beyond
597+
// reporting status.
598+
returnExitError(exitErr.ExitStatus(),nil)
599+
}
600+
// If the connection drops unexpectedly, we get an
601+
// ExitMissingError but no other error details, so try to at
602+
// least give the user a better message
603+
iferrors.Is(err,&gossh.ExitMissingError{}) {
604+
returnExitError(255,xerrors.New("SSH connection ended unexpectedly"))
605+
}
606+
returnxerrors.Errorf("session ended: %w",err)
581607
}
582-
returnxerrors.Errorf("session ended: %w",err)
583608
}
584-
585609
returnnil
586610
},
587611
}

‎cli/ssh_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,127 @@ func TestSSH_CoderConnect(t *testing.T) {
22002200

22012201
<-cmdDone
22022202
})
2203+
2204+
t.Run("OneShot",func(t*testing.T) {
2205+
t.Parallel()
2206+
2207+
client,workspace,agentToken:=setupWorkspaceForAgent(t)
2208+
inv,root:=clitest.New(t,"ssh",workspace.Name,"echo 'hello world'")
2209+
clitest.SetupConfig(t,client,root)
2210+
2211+
// Capture command output
2212+
output:=new(bytes.Buffer)
2213+
inv.Stdout=output
2214+
2215+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
2216+
defercancel()
2217+
2218+
cmdDone:=tGo(t,func() {
2219+
err:=inv.WithContext(ctx).Run()
2220+
assert.NoError(t,err)
2221+
})
2222+
2223+
_=agenttest.New(t,client.URL,agentToken)
2224+
coderdtest.AwaitWorkspaceAgents(t,client,workspace.ID)
2225+
2226+
<-cmdDone
2227+
2228+
// Verify command output
2229+
assert.Contains(t,output.String(),"hello world")
2230+
})
2231+
2232+
t.Run("OneShotExitCode",func(t*testing.T) {
2233+
t.Parallel()
2234+
2235+
client,workspace,agentToken:=setupWorkspaceForAgent(t)
2236+
2237+
// Setup agent first to avoid race conditions
2238+
_=agenttest.New(t,client.URL,agentToken)
2239+
coderdtest.AwaitWorkspaceAgents(t,client,workspace.ID)
2240+
2241+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
2242+
defercancel()
2243+
2244+
// Test successful exit code
2245+
t.Run("Success",func(t*testing.T) {
2246+
inv,root:=clitest.New(t,"ssh",workspace.Name,"exit 0")
2247+
clitest.SetupConfig(t,client,root)
2248+
2249+
err:=inv.WithContext(ctx).Run()
2250+
assert.NoError(t,err)
2251+
})
2252+
2253+
// Test error exit code
2254+
t.Run("Error",func(t*testing.T) {
2255+
inv,root:=clitest.New(t,"ssh",workspace.Name,"exit 1")
2256+
clitest.SetupConfig(t,client,root)
2257+
2258+
err:=inv.WithContext(ctx).Run()
2259+
assert.Error(t,err)
2260+
varexitErr*ssh.ExitError
2261+
assert.True(t,errors.As(err,&exitErr))
2262+
assert.Equal(t,1,exitErr.ExitStatus())
2263+
})
2264+
})
2265+
2266+
t.Run("OneShotStdio",func(t*testing.T) {
2267+
t.Parallel()
2268+
client,workspace,agentToken:=setupWorkspaceForAgent(t)
2269+
_,_=tGoContext(t,func(ctx context.Context) {
2270+
// Run this async so the SSH command has to wait for
2271+
// the build and agent to connect!
2272+
_=agenttest.New(t,client.URL,agentToken)
2273+
<-ctx.Done()
2274+
})
2275+
2276+
clientOutput,clientInput:=io.Pipe()
2277+
serverOutput,serverInput:=io.Pipe()
2278+
deferfunc() {
2279+
for_,c:=range []io.Closer{clientOutput,clientInput,serverOutput,serverInput} {
2280+
_=c.Close()
2281+
}
2282+
}()
2283+
2284+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
2285+
defercancel()
2286+
2287+
inv,root:=clitest.New(t,"ssh","--stdio",workspace.Name,"echo 'hello stdio'")
2288+
clitest.SetupConfig(t,client,root)
2289+
inv.Stdin=clientOutput
2290+
inv.Stdout=serverInput
2291+
inv.Stderr=io.Discard
2292+
2293+
cmdDone:=tGo(t,func() {
2294+
err:=inv.WithContext(ctx).Run()
2295+
assert.NoError(t,err)
2296+
})
2297+
2298+
conn,channels,requests,err:=ssh.NewClientConn(&testutil.ReaderWriterConn{
2299+
Reader:serverOutput,
2300+
Writer:clientInput,
2301+
},"",&ssh.ClientConfig{
2302+
// #nosec
2303+
HostKeyCallback:ssh.InsecureIgnoreHostKey(),
2304+
})
2305+
require.NoError(t,err)
2306+
deferconn.Close()
2307+
2308+
sshClient:=ssh.NewClient(conn,channels,requests)
2309+
session,err:=sshClient.NewSession()
2310+
require.NoError(t,err)
2311+
defersession.Close()
2312+
2313+
// Capture and verify command output
2314+
output,err:=session.Output("echo 'hello back'")
2315+
require.NoError(t,err)
2316+
assert.Contains(t,string(output),"hello back")
2317+
2318+
err=sshClient.Close()
2319+
require.NoError(t,err)
2320+
_=clientOutput.Close()
2321+
2322+
<-cmdDone
2323+
})
22032324
}
22042325

22052326
typefakeCoderConnectDialerstruct{}

‎cli/testdata/coder_--help.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ SUBCOMMANDS:
4646
show Display details of a workspace's resources and agents
4747
speedtest Run upload and download tests from your machine to a
4848
workspace
49-
ssh Start a shell into a workspace
49+
ssh Start a shell into a workspace or run a command
5050
start Start a workspace
5151
stat Show resource usage for the current workspace.
5252
state Manually manage Terraform state to fix broken workspaces

‎cli/testdata/coder_ssh_--help.golden

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
coder v0.0.0-devel
22

33
USAGE:
4-
coder ssh [flags] <workspace>
4+
coder ssh [flags] <workspace> [command]
55

6-
Start a shell into a workspace
6+
Start a shell into a workspace or run a command
77

88
This command does not have full parity with the standard SSH command. For
99
users who need the full functionality of SSH, create an ssh configuration with
1010
`coder config-ssh`.
11+
12+
- Use `--` to separate and pass flags directly to the command executed via
13+
SSH.:
14+
15+
$ coder ssh <workspace> -- ls -la
1116

1217
OPTIONS:
1318
--disable-autostart bool, $CODER_SSH_DISABLE_AUTOSTART (default: false)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp