Slice 1: build green, MVP core flow

- New agentlib module (gitutil + deployer with NewGo / NewPHP) replaces
  agent-micro/internal so both agents can share it (Go's internal/ rule
  was blocking agent-gateway from importing agent-micro's packages).
- Migrate agents from legacy github.com/docker/docker/client to the
  current github.com/moby/moby/client v0.5.0 / moby/moby/api v1.55.0.
- Fix compile errors in the original committed code: missing
  gorilla/websocket import in control-plane/internal/ws/handlers.go,
  unaliased dockerclient reference, wrong SQLite driver name
  (sqlite3 -> sqlite), Dialer.Dial 3-return-value mismatch.
- scripts/build.sh: Go 1.23 -> 1.24, apk add git, safe.directory for
  bind-mounted host tree, chmod inside container (host can't chmod
  files owned by container root).
- README and REQUIREMENTS updated to reflect the actual architecture
  (Go + SQLite, no Spring Boot, moby SDK, per-deploy no image build)
  with a per-feature status checklist at the end of REQUIREMENTS.
This commit is contained in:
opencode
2026-06-24 01:43:43 +00:00
parent 7c1013e083
commit 2bc3ff73a2
18 changed files with 3218 additions and 321 deletions
+13 -11
View File
@@ -1,6 +1,6 @@
// Command agent-micro runs on the microservices VM (172.18.136.92). It
// maintains a WebSocket to the control plane, accepts deploy/stop commands,
// and runs the build+container pipeline locally.
// maintains a WebSocket to the control plane, accepts deploy/stop frames,
// and runs the build+container pipeline locally for Go microservices.
package main
import (
@@ -13,17 +13,17 @@ import (
"sync"
"time"
"github.com/docker/docker/client"
docker "github.com/moby/moby/client"
"github.com/gorilla/websocket"
"github.com/sdp/agent-micro/internal/deployer"
"github.com/sdp/agent-micro/internal/gitutil"
"github.com/sdp/agentlib/deployer"
"github.com/sdp/agentlib/gitutil"
"github.com/sdp/protocol"
)
// ponytail: hand-curated from REQUIREMENTS.md. Real version reads a yaml
// config file. Adding a new service = one line.
var repos = map[string]string{
// ponytail: hand-curated from REQUIREMENTS.md. Real version reads a yaml
// config file. Adding a new service = one line.
"account": "/home/user/AppGolang/account",
"payment": "/home/user/AppGolang/payment",
"user": "/home/user/AppGolang/user",
@@ -35,7 +35,7 @@ func main() {
nodeID := flag.String("node", envOr("SDP_NODE_ID", "micro"), "node id sent in WS query")
flag.Parse()
cli, err := client.NewClientWithOpts(client.FromEnv)
cli, err := docker.NewClientWithOpts(docker.FromEnv)
if err != nil {
log.Fatalf("docker client: %v", err)
}
@@ -69,7 +69,8 @@ func main() {
func dial(u *url.URL) (*websocket.Conn, error) {
log.Printf("connecting to %s", u)
return websocket.DefaultDialer.Dial(u.String(), nil)
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
return c, err
}
// writer pumps outbound events to whichever conn is current. If conn is
@@ -93,7 +94,7 @@ type runState struct {
cancel context.CancelFunc
}
func readLoop(c *websocket.Conn, cli *dockerclient.Client, out chan<- []byte, mu *sync.Mutex, connPtr **websocket.Conn) {
func readLoop(c *websocket.Conn, cli *docker.Client, out chan<- []byte, mu *sync.Mutex, connPtr **websocket.Conn) {
inflight := map[string]*runState{}
for {
_, raw, err := c.ReadMessage()
@@ -107,6 +108,7 @@ func readLoop(c *websocket.Conn, cli *dockerclient.Client, out chan<- []byte, mu
_ = c.Close()
return
}
// Inbound frame: {op, data, id}. Op is the verb. data is op-specific.
var frame struct {
Op string `json:"op"`
Data protocol.DeployRequest `json:"data"`
@@ -128,7 +130,7 @@ func readLoop(c *websocket.Conn, cli *dockerclient.Client, out chan<- []byte, mu
})
continue
}
d := deployer.New(cli, frame.Data.DeploymentID,
d := deployer.NewGo(cli, frame.Data.DeploymentID,
frame.Data.Repository, repoPath,
frame.Data.Branch, frame.Data.Env,
gitutil.Creds{Username: frame.Data.Username, Password: frame.Data.Password},