feat: add coder exp sync list command (#26443)

Add a new subcommand to list all registered sync units and their current
statuses. This provides a quick overview of the dependency coordination
state in a workspace without needing to query each unit individually.

The command supports both table (default) and JSON output formats.

```
$ coder exp sync list
UNIT    STATUS     READY
unit-a  started    true
unit-b  completed  true
unit-c  pending    false

$ coder exp sync list --output json
[
  {
    "unit_name": "my-unit",
    "status": "started",
    "is_ready": true
  }
]
```

When no units are registered, the command prints `No units registered`.

<details><summary>Changes across layers</summary>

- `agent/unit`: add `Manager.ListUnits()` method
- `agent/agentsocket/proto`: add `SyncList` RPC, bump API to v1.2
- `agent/agentsocket`: add service and client implementations
- `cli`: add `sync_list.go` command, register in `sync.go`
- Tests: three golden-file test cases (empty list, multiple units, JSON)

</details>

> Generated by Coder Agents on behalf of @SasSwart

---------

Co-authored-by: Cian Johnston <cian@coder.com>
This commit is contained in:
Sas Swart
2026-06-17 13:01:57 +02:00
committed by GitHub
co-authored by Cian Johnston
parent 74a7ad0929
commit 7d95153bf4
18 changed files with 553 additions and 39 deletions
+23
View File
@@ -175,6 +175,29 @@ func (s *DRPCAgentSocketService) SyncStatus(_ context.Context, req *proto.SyncSt
}, nil
}
// SyncList returns all registered units and their current statuses.
func (s *DRPCAgentSocketService) SyncList(_ context.Context, _ *proto.SyncListRequest) (*proto.SyncListResponse, error) {
if s.unitManager == nil {
return nil, xerrors.Errorf("cannot list units: %w", ErrUnitManagerNotAvailable)
}
units := s.unitManager.ListUnits()
var unitInfos []*proto.UnitInfo
for _, u := range units {
isReady, err := s.unitManager.IsReady(u.ID())
if err != nil {
return nil, xerrors.Errorf("cannot check readiness for unit %q: %w", u.ID(), err)
}
unitInfos = append(unitInfos, &proto.UnitInfo{
Unit: string(u.ID()),
Status: string(u.Status()),
IsReady: isReady,
})
}
return &proto.SyncListResponse{Units: unitInfos}, nil
}
// UpdateAppStatus forwards an app status update to coderd via the
// agent API. Returns an error if the agent is not connected.
func (s *DRPCAgentSocketService) UpdateAppStatus(ctx context.Context, req *agentproto.UpdateAppStatusRequest) (*agentproto.UpdateAppStatusResponse, error) {