feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
|
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
|
|
|
|
|
|
package monitor
|
|
|
|
|
|
|
|
|
|
import (
|
2026-03-29 23:10:19 +00:00
|
|
|
"net/http"
|
|
|
|
|
"net/http/httptest"
|
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
|
|
|
"testing"
|
2026-03-29 23:10:19 +00:00
|
|
|
"time"
|
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
|
|
|
|
2026-03-31 14:54:32 +00:00
|
|
|
"dappco.re/go/agent/pkg/messages"
|
2026-03-29 23:10:19 +00:00
|
|
|
core "dappco.re/go/core"
|
feat(v0.8.0): full AX migration — ServiceRuntime, Actions, quality gates, transport
go-process:
- Register factory, Result lifecycle, 5 named Action handlers
- Start/Run/StartWithOptions/RunWithOptions all return core.Result
- core.ID() replaces fmt.Sprintf, core.As replaces errors.As
core/agent:
- PrepSubsystem + monitor.Subsystem + setup.Service embed ServiceRuntime[T]
- 22 named Actions + agent.completion Task pipeline in OnStartup
- ChannelNotifier removed — all IPC via c.ACTION(messages.X{})
- proc.go: all methods via s.Core().Process(), returns core.Result
- status.go: WriteAtomic + JSONMarshalString
- paths.go: Fs.NewUnrestricted() replaces unsafe.Pointer
- transport.go: ONE net/http file — HTTPGet/HTTPPost/HTTPDo/MCP transport
- All disallowed imports eliminated from source files (13 quality gates)
- String concat eliminated — core.Concat() throughout
- 1:1 _test.go + _example_test.go for every source file
- Reference docs synced from core/go v0.8.0
- RFC-025 updated with net/http, net/url, io/fs quality gates
- lib.go: io/fs eliminated via Data.ListNames, Array[T].Deduplicate
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-26 01:27:46 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestSync_InitSyncTimestamp_Good(t *testing.T) {
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.initSyncTimestamp()
|
|
|
|
|
assert.True(t, mon.lastSyncTimestamp > 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_InitSyncTimestamp_Bad_NoOverwrite(t *testing.T) {
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.lastSyncTimestamp = 42
|
|
|
|
|
mon.initSyncTimestamp()
|
|
|
|
|
assert.Equal(t, int64(42), mon.lastSyncTimestamp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Ugly_NoBrainKey(t *testing.T) {
|
|
|
|
|
t.Setenv("CORE_BRAIN_KEY", "")
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
result := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", result)
|
|
|
|
|
}
|
2026-03-29 23:10:19 +00:00
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Good_NoChanges(t *testing.T) {
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
assert.Equal(t, "/v1/agent/checkin", r.URL.Path)
|
|
|
|
|
resp := CheckinResponse{Timestamp: time.Now().Unix()}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", msg)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 20:37:23 +00:00
|
|
|
func TestSync_SyncRepos_Good_EncodesAgentQuery(t *testing.T) {
|
|
|
|
|
expectedAgent := "test agent+1"
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
assert.Equal(t, "/v1/agent/checkin", r.URL.Path)
|
|
|
|
|
assert.Equal(t, expectedAgent, r.URL.Query().Get("agent"))
|
|
|
|
|
resp := CheckinResponse{Timestamp: time.Now().Unix()}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
t.Setenv("AGENT_NAME", expectedAgent)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", msg)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-29 23:10:19 +00:00
|
|
|
func TestSync_SyncRepos_Bad_APIError(t *testing.T) {
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", msg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Good_UpdatesTimestamp(t *testing.T) {
|
|
|
|
|
newTS := time.Now().Unix() + 1000
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
resp := CheckinResponse{Timestamp: newTS}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.syncRepos()
|
|
|
|
|
|
refactor: AX compliance sweep — replace banned stdlib imports with core primitives
Replaced fmt, strings, sort, os, io, sync, encoding/json, path/filepath,
errors, log, reflect with core.Sprintf, core.E, core.Contains, core.Trim,
core.Split, core.Join, core.JoinPath, slices.Sort, c.Fs(), c.Lock(),
core.JSONMarshal, core.ReadAll and other CoreGO v0.8.0 primitives.
Framework boundary exceptions preserved where stdlib types are required
by external interfaces (Gin, net/http, CGo, Wails, bubbletea).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-13 09:32:00 +01:00
|
|
|
unlock := mon.monitorLock()
|
2026-03-29 23:10:19 +00:00
|
|
|
assert.Equal(t, newTS, mon.lastSyncTimestamp)
|
refactor: AX compliance sweep — replace banned stdlib imports with core primitives
Replaced fmt, strings, sort, os, io, sync, encoding/json, path/filepath,
errors, log, reflect with core.Sprintf, core.E, core.Contains, core.Trim,
core.Split, core.Join, core.JoinPath, slices.Sort, c.Fs(), c.Lock(),
core.JSONMarshal, core.ReadAll and other CoreGO v0.8.0 primitives.
Framework boundary exceptions preserved where stdlib types are required
by external interfaces (Gin, net/http, CGo, Wails, bubbletea).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-13 09:32:00 +01:00
|
|
|
unlock()
|
2026-03-29 23:10:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Good_PullsChangedRepo(t *testing.T) {
|
|
|
|
|
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
|
|
|
|
fs.EnsureDir(remoteDir)
|
|
|
|
|
run(t, remoteDir, "git", "init", "--bare")
|
|
|
|
|
|
|
|
|
|
codeDir := t.TempDir()
|
|
|
|
|
repoDir := core.JoinPath(codeDir, "test-repo")
|
|
|
|
|
run(t, codeDir, "git", "clone", remoteDir, "test-repo")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "main")
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "README.md"), "# test")
|
|
|
|
|
run(t, repoDir, "git", "add", ".")
|
|
|
|
|
run(t, repoDir, "git", "commit", "-m", "init")
|
|
|
|
|
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
|
|
|
|
|
|
|
|
|
clone2Parent := t.TempDir()
|
|
|
|
|
tmpClone := core.JoinPath(clone2Parent, "clone2")
|
|
|
|
|
run(t, clone2Parent, "git", "clone", remoteDir, "clone2")
|
|
|
|
|
run(t, tmpClone, "git", "checkout", "main")
|
|
|
|
|
fs.Write(core.JoinPath(tmpClone, "new.go"), "package main\n")
|
|
|
|
|
run(t, tmpClone, "git", "add", ".")
|
|
|
|
|
run(t, tmpClone, "git", "commit", "-m", "agent work")
|
|
|
|
|
run(t, tmpClone, "git", "push", "origin", "main")
|
|
|
|
|
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
resp := CheckinResponse{
|
|
|
|
|
Changed: []ChangedRepo{{Repo: "test-repo", Branch: "main", SHA: "abc"}},
|
|
|
|
|
Timestamp: time.Now().Unix() + 100,
|
|
|
|
|
}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
t.Setenv("CODE_PATH", codeDir)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Contains(t, msg, "Synced 1 repo(s)")
|
|
|
|
|
assert.Contains(t, msg, "test-repo")
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-31 14:54:32 +00:00
|
|
|
func TestSync_HandleWorkspacePushed_Good_ResetsTrackedRepo(t *testing.T) {
|
|
|
|
|
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
|
|
|
|
fs.EnsureDir(remoteDir)
|
|
|
|
|
run(t, remoteDir, "git", "init", "--bare")
|
|
|
|
|
|
|
|
|
|
codeDir := t.TempDir()
|
|
|
|
|
orgDir := core.JoinPath(codeDir, "core")
|
|
|
|
|
fs.EnsureDir(orgDir)
|
|
|
|
|
repoDir := core.JoinPath(orgDir, "test-repo")
|
|
|
|
|
run(t, orgDir, "git", "clone", remoteDir, "test-repo")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "main")
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "README.md"), "# test")
|
|
|
|
|
run(t, repoDir, "git", "add", ".")
|
|
|
|
|
run(t, repoDir, "git", "commit", "-m", "init")
|
|
|
|
|
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
|
|
|
|
|
|
|
|
|
cloneParent := t.TempDir()
|
|
|
|
|
tmpClone := core.JoinPath(cloneParent, "clone2")
|
|
|
|
|
run(t, cloneParent, "git", "clone", remoteDir, "clone2")
|
|
|
|
|
run(t, tmpClone, "git", "checkout", "main")
|
|
|
|
|
fs.Write(core.JoinPath(tmpClone, "new.go"), "package main\n")
|
|
|
|
|
run(t, tmpClone, "git", "add", ".")
|
|
|
|
|
run(t, tmpClone, "git", "commit", "-m", "agent work")
|
|
|
|
|
run(t, tmpClone, "git", "push", "origin", "main")
|
|
|
|
|
|
|
|
|
|
t.Setenv("CODE_PATH", codeDir)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
|
|
|
|
|
result := mon.HandleIPCEvents(mon.Core(), messages.WorkspacePushed{
|
|
|
|
|
Repo: "test-repo",
|
|
|
|
|
Branch: "main",
|
|
|
|
|
Org: "core",
|
|
|
|
|
})
|
|
|
|
|
assert.True(t, result.OK)
|
|
|
|
|
assert.True(t, fs.Exists(core.JoinPath(repoDir, "new.go")))
|
|
|
|
|
assert.Equal(t, mon.gitOutput(tmpClone, "rev-parse", "HEAD"), mon.gitOutput(repoDir, "rev-parse", "HEAD"))
|
2026-04-02 01:53:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_HandleWorkspacePushed_Good_SwitchesTrackedRepoBranch(t *testing.T) {
|
|
|
|
|
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
|
|
|
|
fs.EnsureDir(remoteDir)
|
|
|
|
|
run(t, remoteDir, "git", "init", "--bare")
|
|
|
|
|
|
|
|
|
|
codeDir := t.TempDir()
|
|
|
|
|
orgDir := core.JoinPath(codeDir, "core")
|
|
|
|
|
fs.EnsureDir(orgDir)
|
|
|
|
|
repoDir := core.JoinPath(orgDir, "test-repo")
|
|
|
|
|
run(t, orgDir, "git", "clone", remoteDir, "test-repo")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "main")
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "README.md"), "# test")
|
|
|
|
|
run(t, repoDir, "git", "add", ".")
|
|
|
|
|
run(t, repoDir, "git", "commit", "-m", "init")
|
|
|
|
|
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "feature/wip")
|
|
|
|
|
|
|
|
|
|
cloneParent := t.TempDir()
|
|
|
|
|
tmpClone := core.JoinPath(cloneParent, "clone2")
|
|
|
|
|
run(t, cloneParent, "git", "clone", remoteDir, "clone2")
|
|
|
|
|
run(t, tmpClone, "git", "checkout", "main")
|
|
|
|
|
fs.Write(core.JoinPath(tmpClone, "new.go"), "package main\n")
|
|
|
|
|
run(t, tmpClone, "git", "add", ".")
|
|
|
|
|
run(t, tmpClone, "git", "commit", "-m", "agent work")
|
|
|
|
|
run(t, tmpClone, "git", "push", "origin", "main")
|
|
|
|
|
|
|
|
|
|
t.Setenv("CODE_PATH", codeDir)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
|
|
|
|
|
result := mon.HandleIPCEvents(mon.Core(), messages.WorkspacePushed{
|
|
|
|
|
Repo: "test-repo",
|
|
|
|
|
Branch: "main",
|
|
|
|
|
Org: "core",
|
|
|
|
|
})
|
|
|
|
|
assert.True(t, result.OK)
|
|
|
|
|
assert.Equal(t, "main", mon.gitOutput(repoDir, "rev-parse", "--abbrev-ref", "HEAD"))
|
|
|
|
|
assert.True(t, fs.Exists(core.JoinPath(repoDir, "new.go")))
|
|
|
|
|
assert.Equal(t, mon.gitOutput(tmpClone, "rev-parse", "HEAD"), mon.gitOutput(repoDir, "rev-parse", "HEAD"))
|
2026-03-31 14:54:32 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-30 16:52:49 +00:00
|
|
|
func TestSync_SyncRepos_Good_NormalisesWindowsRepoPath(t *testing.T) {
|
|
|
|
|
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
|
|
|
|
fs.EnsureDir(remoteDir)
|
|
|
|
|
run(t, remoteDir, "git", "init", "--bare")
|
|
|
|
|
|
|
|
|
|
codeDir := t.TempDir()
|
|
|
|
|
repoDir := core.JoinPath(codeDir, "test-repo")
|
|
|
|
|
run(t, codeDir, "git", "clone", remoteDir, "test-repo")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "main")
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "README.md"), "# test")
|
|
|
|
|
run(t, repoDir, "git", "add", ".")
|
|
|
|
|
run(t, repoDir, "git", "commit", "-m", "init")
|
|
|
|
|
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
|
|
|
|
|
|
|
|
|
clone2Parent := t.TempDir()
|
|
|
|
|
tmpClone := core.JoinPath(clone2Parent, "clone2")
|
|
|
|
|
run(t, clone2Parent, "git", "clone", remoteDir, "clone2")
|
|
|
|
|
run(t, tmpClone, "git", "checkout", "main")
|
|
|
|
|
fs.Write(core.JoinPath(tmpClone, "new.go"), "package main\n")
|
|
|
|
|
run(t, tmpClone, "git", "add", ".")
|
|
|
|
|
run(t, tmpClone, "git", "commit", "-m", "agent work")
|
|
|
|
|
run(t, tmpClone, "git", "push", "origin", "main")
|
|
|
|
|
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
resp := CheckinResponse{
|
|
|
|
|
Changed: []ChangedRepo{{Repo: "core\\test-repo", Branch: "main", SHA: "abc"}},
|
|
|
|
|
Timestamp: time.Now().Unix() + 100,
|
|
|
|
|
}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
t.Setenv("CODE_PATH", codeDir)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Contains(t, msg, "Synced 1 repo(s)")
|
|
|
|
|
assert.Contains(t, msg, "core\\test-repo")
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-29 23:10:19 +00:00
|
|
|
func TestSync_SyncRepos_Good_SkipsDirtyRepo(t *testing.T) {
|
|
|
|
|
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
|
|
|
|
fs.EnsureDir(remoteDir)
|
|
|
|
|
run(t, remoteDir, "git", "init", "--bare")
|
|
|
|
|
|
|
|
|
|
codeDir := t.TempDir()
|
|
|
|
|
repoDir := core.JoinPath(codeDir, "dirty-repo")
|
|
|
|
|
run(t, codeDir, "git", "clone", remoteDir, "dirty-repo")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "main")
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "README.md"), "# test")
|
|
|
|
|
run(t, repoDir, "git", "add", ".")
|
|
|
|
|
run(t, repoDir, "git", "commit", "-m", "init")
|
|
|
|
|
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
|
|
|
|
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "dirty.txt"), "uncommitted")
|
|
|
|
|
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
resp := CheckinResponse{
|
|
|
|
|
Changed: []ChangedRepo{{Repo: "dirty-repo", Branch: "main", SHA: "abc"}},
|
|
|
|
|
Timestamp: time.Now().Unix() + 100,
|
|
|
|
|
}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
t.Setenv("CODE_PATH", codeDir)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", msg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Good_SkipsNonMainBranch(t *testing.T) {
|
|
|
|
|
remoteDir := core.JoinPath(t.TempDir(), "remote")
|
|
|
|
|
fs.EnsureDir(remoteDir)
|
|
|
|
|
run(t, remoteDir, "git", "init", "--bare")
|
|
|
|
|
|
|
|
|
|
codeDir := t.TempDir()
|
|
|
|
|
repoDir := core.JoinPath(codeDir, "feature-repo")
|
|
|
|
|
run(t, codeDir, "git", "clone", remoteDir, "feature-repo")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "main")
|
|
|
|
|
fs.Write(core.JoinPath(repoDir, "README.md"), "# test")
|
|
|
|
|
run(t, repoDir, "git", "add", ".")
|
|
|
|
|
run(t, repoDir, "git", "commit", "-m", "init")
|
|
|
|
|
run(t, repoDir, "git", "push", "-u", "origin", "main")
|
|
|
|
|
run(t, repoDir, "git", "checkout", "-b", "feature/wip")
|
|
|
|
|
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
resp := CheckinResponse{
|
|
|
|
|
Changed: []ChangedRepo{{Repo: "feature-repo", Branch: "main", SHA: "abc"}},
|
|
|
|
|
Timestamp: time.Now().Unix() + 100,
|
|
|
|
|
}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
t.Setenv("CODE_PATH", codeDir)
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.ServiceRuntime = testMon.ServiceRuntime
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", msg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Good_SkipsNonexistentRepo(t *testing.T) {
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
resp := CheckinResponse{
|
|
|
|
|
Changed: []ChangedRepo{{Repo: "nonexistent", Branch: "main", SHA: "abc"}},
|
|
|
|
|
Timestamp: time.Now().Unix() + 100,
|
|
|
|
|
}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
setupAPIEnv(t, srv.URL)
|
|
|
|
|
t.Setenv("CODE_PATH", t.TempDir())
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
msg := mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "", msg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestSync_SyncRepos_Good_UsesEnvBrainKey(t *testing.T) {
|
|
|
|
|
var authHeader string
|
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
authHeader = r.Header.Get("Authorization")
|
|
|
|
|
resp := CheckinResponse{Timestamp: time.Now().Unix()}
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
w.Write([]byte(core.JSONMarshalString(resp)))
|
|
|
|
|
}))
|
|
|
|
|
defer srv.Close()
|
|
|
|
|
|
|
|
|
|
home := t.TempDir()
|
|
|
|
|
t.Setenv("HOME", home)
|
|
|
|
|
t.Setenv("CORE_BRAIN_KEY", "env-key-value")
|
|
|
|
|
t.Setenv("CORE_API_URL", srv.URL)
|
|
|
|
|
t.Setenv("AGENT_NAME", "test-agent")
|
|
|
|
|
|
|
|
|
|
mon := New()
|
|
|
|
|
mon.syncRepos()
|
|
|
|
|
assert.Equal(t, "Bearer env-key-value", authHeader)
|
|
|
|
|
}
|