dodo: Support Sketch agent
Change-Id: I4dcd6aab7d7a2c2e86aaf1ad8d36d30a649ab31d
diff --git a/apps/app-runner/Dockerfile.sketch.latest b/apps/app-runner/Dockerfile.sketch.latest
new file mode 100644
index 0000000..82aba7a
--- /dev/null
+++ b/apps/app-runner/Dockerfile.sketch.latest
@@ -0,0 +1,9 @@
+FROM alpine:3.22.0
+
+ARG TARGETARCH
+
+RUN apk update
+RUN apk add bash curl git nodejs npm
+
+COPY --from=giolekva/sketch:latest /usr/bin/sketch /usr/bin/sketch
+COPY app-runner_${TARGETARCH} /usr/bin/app-runner
diff --git a/apps/app-runner/Makefile b/apps/app-runner/Makefile
index 187ca18..ef1c483 100644
--- a/apps/app-runner/Makefile
+++ b/apps/app-runner/Makefile
@@ -11,6 +11,7 @@
manifest_dest_deno_2_2_0=docker://docker.io/$(repo_name)/app-runner:deno-2.2.0
manifest_dest_nodejs_23_1_0=docker://docker.io/$(repo_name)/app-runner:nodejs-23.1.0
manifest_dest_nodejs_24_0_2=docker://docker.io/$(repo_name)/app-runner:nodejs-24.0.2
+manifest_dest_sketch_latest=docker://docker.io/$(repo_name)/app-runner:sketch-latest
endif
clean:
@@ -166,6 +167,24 @@
$(podman) manifest push $(repo_name)/app-runner:deno-2.2.0 $(manifest_dest_deno_2_2_0)
$(podman) manifest rm $(repo_name)/app-runner:deno-2.2.0
+# Sketch
+
+push_sketch_arm64: clean build_arm64
+ $(podman) build --platform linux/arm64 --tag=$(repo_name)/app-runner:sketch-latest-arm64 -f Dockerfile.sketch.latest $(docker_flags) .
+ $(podman) push $(repo_name)/app-runner:sketch-latest-arm64
+
+push_sketch_amd64: clean build_amd64
+ $(podman) build --platform linux/amd64 --tag=$(repo_name)/app-runner:sketch-latest-amd64 -f Dockerfile.sketch.latest $(docker_flags) .
+ $(podman) push $(repo_name)/app-runner:sketch-latest-amd64
+
+push_sketch:
+ make -C ../../../sketch push
+ make push_sketch_arm64
+ make push_sketch_amd64
+ $(podman) manifest create $(repo_name)/app-runner:sketch-latest $(repo_name)/app-runner:sketch-latest-arm64 $(repo_name)/app-runner:sketch-latest-amd64
+ $(podman) manifest push $(repo_name)/app-runner:sketch-latest $(manifest_dest_sketch_latest)
+ $(podman) manifest rm $(repo_name)/app-runner:sketch-latest
+
# all
-push: push_golang_1_22_0 push_golang_1_20_0 push_hugo push_php_8_2_apache push_nextjs_deno_2_0_0 push_nodejs_23_1_0 push_nodejs_24_0_2 push_deno_2_2_0
+push: push_golang_1_22_0 push_golang_1_20_0 push_hugo push_php_8_2_apache push_nextjs_deno_2_0_0 push_nodejs_23_1_0 push_nodejs_24_0_2 push_deno_2_2_0 push_sketch
diff --git a/apps/app-runner/main.go b/apps/app-runner/main.go
index 96a647e..ebd0ef8 100644
--- a/apps/app-runner/main.go
+++ b/apps/app-runner/main.go
@@ -21,6 +21,7 @@
var port = flag.Int("port", 3000, "Port to listen on")
var appId = flag.String("app-id", "", "Application ID")
var service = flag.String("service", "", "Service name")
+var agentMode = flag.Bool("agent-mode", false, "Sketch agent mode")
var repoAddr = flag.String("repo-addr", "", "Git repository address")
var branch = flag.String("branch", "", "Name of the branch to process")
var rootDir = flag.String("root-dir", "/", "Path to the app code")
@@ -104,8 +105,10 @@
panic(err)
}
}
- if err := os.Mkdir(*appDir, os.ModePerm); err != nil {
- panic(err)
+ if !*agentMode {
+ if err := os.Mkdir(*appDir, os.ModePerm); err != nil {
+ panic(err)
+ }
}
r, err := os.Open(*runCfg)
if err != nil {
@@ -116,7 +119,7 @@
if err := json.NewDecoder(r).Decode(&cmds); err != nil {
panic(err)
}
- s := NewServer(*port, *appId, *service, id, *repoAddr, *branch, *rootDir, signer, *appDir, cmds, self, *managerAddr)
+ s := NewServer(*agentMode, *port, *appId, *service, id, *repoAddr, *branch, *rootDir, signer, *appDir, cmds, self, *managerAddr)
if err := s.Start(); err != nil {
log.Fatal(err)
}
diff --git a/apps/app-runner/server.go b/apps/app-runner/server.go
index 1f7fe01..89f621a 100644
--- a/apps/app-runner/server.go
+++ b/apps/app-runner/server.go
@@ -31,6 +31,7 @@
type Server struct {
l sync.Locker
+ agentMode bool
port int
appId string
service string
@@ -50,9 +51,10 @@
status *Status
}
-func NewServer(port int, appId, service, id, repoAddr, branch, rootDir string, signer ssh.Signer, appDir string, runCommands []Command, self string, manager string) *Server {
+func NewServer(agentMode bool, port int, appId, service, id, repoAddr, branch, rootDir string, signer ssh.Signer, appDir string, runCommands []Command, self string, manager string) *Server {
return &Server{
l: &sync.Mutex{},
+ agentMode: agentMode,
port: port,
ready: false,
appId: appId,
@@ -114,30 +116,80 @@
s.l.Unlock()
}
+type command struct {
+ cmd string
+ env []string
+}
+
func (s *Server) run() error {
- newDir, err := os.MkdirTemp(s.appDir, "code-*")
- if err != nil {
- return err
- }
- commit, err := CloneRepositoryBranch(s.repoAddr, s.branch, s.rootDir, s.signer, newDir)
- if err != nil {
- fmt.Fprintf(s.logs, "!!! dodo: Failed to clone repository\n")
- s.status = &Status{
- Commit: nil,
+ newDir := s.appDir
+ commands := []command{}
+ if !s.agentMode {
+ var err error
+ newDir, err = os.MkdirTemp(s.appDir, "code-*")
+ if err != nil {
+ return err
}
- return err
}
- fmt.Fprintf(s.logs, "!!! dodo: Successfully cloned repository %s\n", commit.Hash)
- s.status = &Status{
- Commit: commit,
- Commands: []CommandStatus{},
+ if s.repoAddr != "" {
+ commit, err := CloneRepositoryBranch(s.repoAddr, s.branch, s.rootDir, s.signer, newDir)
+ if err != nil {
+ fmt.Fprintf(s.logs, "!!! dodo: Failed to clone repository\n")
+ s.status = &Status{
+ Commit: nil,
+ }
+ return err
+ }
+ fmt.Fprintf(s.logs, "!!! dodo: Successfully cloned repository %s\n", commit.Hash)
+ s.status = &Status{
+ Commit: commit,
+ Commands: []CommandStatus{},
+ }
+ } else {
+ s.status = &Status{
+ Commit: nil,
+ Commands: []CommandStatus{},
+ }
}
- commands := []string{}
+ if s.agentMode {
+ if _, err := os.Stat(filepath.Join(newDir, ".git")); err != nil && os.IsNotExist(err) {
+ commands = append(commands, command{cmd: "git config --global user.name dodo"})
+ s.status.Commands = append(s.status.Commands, CommandStatus{
+ Command: commands[len(commands)-1].cmd,
+ State: "waiting",
+ })
+ commands = append(commands, command{cmd: "git config --global user.email dodo@dodo.cloud"})
+ s.status.Commands = append(s.status.Commands, CommandStatus{
+ Command: commands[len(commands)-1].cmd,
+ State: "waiting",
+ })
+ commands = append(commands, command{cmd: "git init ."})
+ s.status.Commands = append(s.status.Commands, CommandStatus{
+ Command: commands[len(commands)-1].cmd,
+ State: "waiting",
+ })
+ commands = append(commands, command{cmd: "echo \"TODO: Describe project\" > README.md"})
+ s.status.Commands = append(s.status.Commands, CommandStatus{
+ Command: commands[len(commands)-1].cmd,
+ State: "waiting",
+ })
+ commands = append(commands, command{cmd: "git add README.md"})
+ s.status.Commands = append(s.status.Commands, CommandStatus{
+ Command: commands[len(commands)-1].cmd,
+ State: "waiting",
+ })
+ commands = append(commands, command{cmd: "git commit -m \"init\""})
+ s.status.Commands = append(s.status.Commands, CommandStatus{
+ Command: commands[len(commands)-1].cmd,
+ State: "waiting",
+ })
+ }
+ }
for _, c := range s.runCommands {
args := []string{c.Bin}
args = append(args, c.Args...)
cmd := strings.Join(args, " ")
- commands = append(commands, cmd)
+ commands = append(commands, command{cmd, c.Env})
s.status.Commands = append(s.status.Commands, CommandStatus{
Command: cmd,
State: "waiting",
@@ -151,8 +203,8 @@
cmd := &exec.Cmd{
Dir: filepath.Join(newDir, s.rootDir),
Path: "/bin/sh",
- Args: []string{"/bin/sh", "-c", c},
- Env: append(os.Environ(), s.runCommands[i].Env...),
+ Args: []string{"/bin/sh", "-c", c.cmd},
+ Env: append(os.Environ(), c.env...),
Stdout: logM,
Stderr: logM,
}
@@ -160,7 +212,7 @@
fmt.Printf("Running: %s\n", c)
fmt.Fprintf(s.logs, "!!! dodo: Running: %s\n", c)
s.status.Commands[i].State = "running"
- if i < len(s.runCommands)-1 {
+ if i < len(commands)-1 {
if err := cmd.Run(); err != nil {
return err
}
@@ -170,7 +222,7 @@
if err := s.kill(); err != nil {
return err
}
- if s.currDir != "" {
+ if s.currDir != "" && !s.agentMode {
if err := os.RemoveAll(s.currDir); err != nil {
return err
}