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

Commitf528eb3

Browse files
feat(agent/agentcontainers): auto detect dev containers
1 parent0cdcf89 commitf528eb3

File tree

4 files changed

+102
-9
lines changed

4 files changed

+102
-9
lines changed

‎agent/agent.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1168,7 +1168,7 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
11681168
// return existing devcontainers but actual container detection
11691169
// and creation will be deferred.
11701170
a.containerAPI.Init(
1171-
agentcontainers.WithManifestInfo(manifest.OwnerName,manifest.WorkspaceName,manifest.AgentName),
1171+
agentcontainers.WithManifestInfo(manifest.OwnerName,manifest.WorkspaceName,manifest.AgentName,manifest.Directory),
11721172
agentcontainers.WithDevcontainers(manifest.Devcontainers,manifest.Scripts),
11731173
agentcontainers.WithSubAgentClient(agentcontainers.NewSubAgentClientFromAPI(a.logger,aAPI)),
11741174
)

‎agent/agentcontainers/api.go‎

Lines changed: 94 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"io/fs"
89
"maps"
910
"net/http"
1011
"os"
@@ -21,6 +22,7 @@ import (
2122
"github.com/fsnotify/fsnotify"
2223
"github.com/go-chi/chi/v5"
2324
"github.com/google/uuid"
25+
"github.com/spf13/afero"
2426
"golang.org/x/xerrors"
2527

2628
"cdr.dev/slog"
@@ -60,6 +62,7 @@ type API struct {
6062
updateInterval time.Duration// Interval for periodic container updates.
6163
logger slog.Logger
6264
watcher watcher.Watcher
65+
fs afero.Fs
6366
execer agentexec.Execer
6467
commandEnvCommandEnv
6568
ccliContainerCLI
@@ -71,9 +74,10 @@ type API struct {
7174
subAgentURLstring
7275
subAgentEnv []string
7376

74-
ownerNamestring
75-
workspaceNamestring
76-
parentAgentstring
77+
ownerNamestring
78+
workspaceNamestring
79+
parentAgentstring
80+
agentDirectorystring
7781

7882
mu sync.RWMutex// Protects the following fields.
7983
initDonechanstruct{}// Closed by Init.
@@ -192,11 +196,12 @@ func WithSubAgentEnv(env ...string) Option {
192196

193197
// WithManifestInfo sets the owner name, and workspace name
194198
// for the sub-agent.
195-
funcWithManifestInfo(owner,workspace,parentAgentstring)Option {
199+
funcWithManifestInfo(owner,workspace,parentAgent,agentDirectorystring)Option {
196200
returnfunc(api*API) {
197201
api.ownerName=owner
198202
api.workspaceName=workspace
199203
api.parentAgent=parentAgent
204+
api.agentDirectory=agentDirectory
200205
}
201206
}
202207

@@ -261,6 +266,13 @@ func WithWatcher(w watcher.Watcher) Option {
261266
}
262267
}
263268

269+
// WithFileSystem sets the file system used for discovering projects.
270+
funcWithFileSystem(fs afero.Fs)Option {
271+
returnfunc(api*API) {
272+
api.fs=fs
273+
}
274+
}
275+
264276
// ScriptLogger is an interface for sending devcontainer logs to the
265277
// controlplane.
266278
typeScriptLoggerinterface {
@@ -331,6 +343,9 @@ func NewAPI(logger slog.Logger, options ...Option) *API {
331343
api.watcher=watcher.NewNoop()
332344
}
333345
}
346+
ifapi.fs==nil {
347+
api.fs=afero.NewOsFs()
348+
}
334349
ifapi.subAgentClient.Load()==nil {
335350
varcSubAgentClient=noopSubAgentClient{}
336351
api.subAgentClient.Store(&c)
@@ -375,10 +390,85 @@ func (api *API) Start() {
375390
api.watcherDone=make(chanstruct{})
376391
api.updaterDone=make(chanstruct{})
377392

393+
gofunc() {
394+
iferr:=api.discoverDevcontainerProjects();err!=nil {
395+
api.logger.Error(api.ctx,"discovering dev container projects",slog.Error(err))
396+
}
397+
}()
398+
378399
goapi.watcherLoop()
379400
goapi.updaterLoop()
380401
}
381402

403+
func (api*API)discoverDevcontainerProjects()error {
404+
isGitProject,err:=afero.DirExists(api.fs,filepath.Join(api.agentDirectory,"/.git"))
405+
iferr!=nil {
406+
returnxerrors.Errorf(".git dir exists: %w",err)
407+
}
408+
409+
// If the agent directory is a git project, we'll search
410+
// the project for any `.devcontainer/devcontainer.json`
411+
// files.
412+
ifisGitProject {
413+
returnapi.discoverDevcontainersInProject(api.agentDirectory)
414+
}
415+
416+
// The agent directory is _not_ a git project, so we'll
417+
// search the top level of the agent directory for any
418+
// git projects, and search those.
419+
entries,err:=afero.ReadDir(api.fs,api.agentDirectory)
420+
iferr!=nil {
421+
returnxerrors.Errorf("read agent directory: %w",err)
422+
}
423+
424+
for_,entry:=rangeentries {
425+
if!entry.IsDir() {
426+
continue
427+
}
428+
429+
isGitProject,err=afero.DirExists(api.fs,filepath.Join(api.agentDirectory,entry.Name(),".git"))
430+
iferr!=nil {
431+
returnxerrors.Errorf(".git dir exists: %w",err)
432+
}
433+
434+
// If this directory is a git project, we'll search
435+
// it for any `.devcontainer/devcontainer.json` files.
436+
ifisGitProject {
437+
iferr:=api.discoverDevcontainersInProject(filepath.Join(api.agentDirectory,entry.Name()));err!=nil {
438+
returnerr
439+
}
440+
}
441+
}
442+
443+
returnnil
444+
}
445+
446+
func (api*API)discoverDevcontainersInProject(projectPathstring)error {
447+
returnafero.Walk(api.fs,projectPath,func(pathstring,info fs.FileInfo,errerror)error {
448+
ifstrings.HasSuffix(path,".devcontainer/devcontainer.json") {
449+
workspaceFolder:=strings.TrimSuffix(path,".devcontainer/devcontainer.json")
450+
451+
api.mu.Lock()
452+
if_,found:=api.knownDevcontainers[workspaceFolder];!found {
453+
dc:= codersdk.WorkspaceAgentDevcontainer{
454+
ID:uuid.New(),
455+
Name:"",// Updated later based on container state.
456+
WorkspaceFolder:workspaceFolder,
457+
ConfigPath:path,
458+
Status:"",// Updated later based on container state.
459+
Dirty:false,// Updated later based on config file changes.
460+
Container:nil,
461+
}
462+
463+
api.knownDevcontainers[workspaceFolder]=dc
464+
}
465+
api.mu.Unlock()
466+
}
467+
468+
returnnil
469+
})
470+
}
471+
382472
func (api*API)watcherLoop() {
383473
deferclose(api.watcherDone)
384474
deferapi.logger.Debug(api.ctx,"watcher loop stopped")

‎agent/agentcontainers/api_test.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,7 @@ func TestAPI(t *testing.T) {
16781678
agentcontainers.WithSubAgentClient(fakeSAC),
16791679
agentcontainers.WithSubAgentURL("test-subagent-url"),
16801680
agentcontainers.WithDevcontainerCLI(fakeDCCLI),
1681-
agentcontainers.WithManifestInfo("test-user","test-workspace","test-parent-agent"),
1681+
agentcontainers.WithManifestInfo("test-user","test-workspace","test-parent-agent","/parent-agent"),
16821682
)
16831683
api.Start()
16841684
apiClose:=func() {
@@ -2662,7 +2662,7 @@ func TestAPI(t *testing.T) {
26622662
agentcontainers.WithSubAgentClient(fSAC),
26632663
agentcontainers.WithSubAgentURL("test-subagent-url"),
26642664
agentcontainers.WithWatcher(watcher.NewNoop()),
2665-
agentcontainers.WithManifestInfo("test-user","test-workspace","test-parent-agent"),
2665+
agentcontainers.WithManifestInfo("test-user","test-workspace","test-parent-agent","/parent-agent"),
26662666
)
26672667
api.Start()
26682668
deferapi.Close()

‎site/src/modules/resources/AgentDevcontainerCard.tsx‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
181181

182182
constappsClasses="flex flex-wrap gap-4 empty:hidden md:justify-start";
183183

184+
console.log(devcontainer);
185+
184186
return(
185187
<Stack
186188
key={devcontainer.id}
@@ -218,7 +220,8 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
218220
text-sm font-semibold text-content-primary
219221
md:overflow-visible"
220222
>
221-
{subAgent?.name??devcontainer.name}
223+
{subAgent?.name??
224+
(devcontainer.name||devcontainer.config_path)}
222225
{devcontainer.container&&(
223226
<spanclassName="text-content-tertiary">
224227
{" "}
@@ -253,7 +256,7 @@ export const AgentDevcontainerCard: FC<AgentDevcontainerCardProps> = ({
253256
disabled={devcontainer.status==="starting"}
254257
>
255258
<Spinnerloading={devcontainer.status==="starting"}/>
256-
Rebuild
259+
{devcontainer.container===undefined ?<>Start</> :<>Rebuild</>}
257260
</Button>
258261

259262
{showDevcontainerControls&&displayApps.includes("ssh_helper")&&(

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp