169 lines
4.9 KiB
Go
169 lines
4.9 KiB
Go
package scriptengine
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// RepositoryProvider returns git-related placeholders from metadata and environment.
|
|
// Parameters:
|
|
// - metadata: executor create request metadata (contains "repository_path", "base_branch", etc.)
|
|
// - env: environment variables (contains "GITHUB_TOKEN", etc.)
|
|
// - repoURLResolver: resolves a local repo path to its remote URL (e.g., `git remote get-url origin`)
|
|
// - tokenInjector: injects auth token into a clone URL
|
|
func RepositoryProvider(
|
|
metadata map[string]any,
|
|
env map[string]string,
|
|
repoURLResolver func(string) (string, error),
|
|
tokenInjector func(string, map[string]string) string,
|
|
) PlaceholderProvider {
|
|
return func() map[string]string {
|
|
vars := make(map[string]string)
|
|
|
|
repoPath := getMetaString(metadata, "repository_path")
|
|
if repoPath != "" {
|
|
vars["repository.path"] = repoPath
|
|
vars["repository.name"] = repoNameFromPath(repoPath)
|
|
}
|
|
|
|
branch := getMetaString(metadata, "base_branch")
|
|
if branch == "" {
|
|
branch = getMetaString(metadata, "repository_branch")
|
|
}
|
|
vars["repository.branch"] = branch
|
|
|
|
setupScript := getMetaString(metadata, "repository_setup_script")
|
|
vars["repository.setup_script"] = setupScript
|
|
|
|
// Clone URL: prefer explicit metadata, fall back to resolving from local repo
|
|
cloneURL := getMetaString(metadata, "repository_clone_url")
|
|
if cloneURL == "" && repoPath != "" && repoURLResolver != nil {
|
|
if remoteURL, err := repoURLResolver(repoPath); err == nil && remoteURL != "" {
|
|
vars["repository.ssh_url"] = remoteURL
|
|
cloneURL = remoteURL
|
|
}
|
|
}
|
|
if cloneURL != "" {
|
|
vars["repository.clone_url"] = injectToken(cloneURL, env, tokenInjector)
|
|
}
|
|
|
|
return vars
|
|
}
|
|
}
|
|
|
|
// AgentctlProvider returns kandev agentctl-related placeholders.
|
|
func AgentctlProvider(agentctlPort int, workspacePath string) PlaceholderProvider {
|
|
return func() map[string]string {
|
|
portStr := fmt.Sprintf("%d", agentctlPort)
|
|
return map[string]string{
|
|
"kandev.agentctl.port": portStr,
|
|
"kandev.agentctl.install": "chmod +x /usr/local/bin/agentctl",
|
|
"kandev.agentctl.start": fmt.Sprintf(
|
|
"nohup agentctl --port %s --workdir %s > /tmp/agentctl.log 2>&1 &\nsleep 1",
|
|
portStr, workspacePath,
|
|
),
|
|
}
|
|
}
|
|
}
|
|
|
|
// WorkspaceProvider returns workspace path placeholder.
|
|
func WorkspaceProvider(workspacePath string) PlaceholderProvider {
|
|
return func() map[string]string {
|
|
return map[string]string{
|
|
"workspace.path": workspacePath,
|
|
}
|
|
}
|
|
}
|
|
|
|
// WorktreeProvider returns placeholders that describe the selected worktree context.
|
|
func WorktreeProvider(basePath, path, id, branch, baseBranch string) PlaceholderProvider {
|
|
return func() map[string]string {
|
|
return map[string]string{
|
|
"worktree.base_path": basePath,
|
|
"worktree.path": path,
|
|
"worktree.id": id,
|
|
"worktree.branch": branch,
|
|
"worktree.base_branch": baseBranch,
|
|
}
|
|
}
|
|
}
|
|
|
|
// GitIdentityProvider returns placeholders for git identity setup in remote executors.
|
|
func GitIdentityProvider(metadata map[string]any) PlaceholderProvider {
|
|
return func() map[string]string {
|
|
name := getMetaString(metadata, "git_user_name")
|
|
email := getMetaString(metadata, "git_user_email")
|
|
|
|
vars := map[string]string{
|
|
"git.user_name": name,
|
|
"git.user_email": email,
|
|
"git.identity_setup": "",
|
|
}
|
|
if name == "" || email == "" {
|
|
return vars
|
|
}
|
|
|
|
lines := []string{
|
|
fmt.Sprintf("git config --global user.name '%s'", shellSingleQuote(name)),
|
|
fmt.Sprintf("git config --global user.email '%s'", shellSingleQuote(email)),
|
|
}
|
|
vars["git.identity_setup"] = strings.Join(lines, "\n")
|
|
return vars
|
|
}
|
|
}
|
|
|
|
// injectToken applies token injection to a URL if an injector is provided.
|
|
func injectToken(url string, env map[string]string, injector func(string, map[string]string) string) string {
|
|
if injector != nil {
|
|
return injector(url, env)
|
|
}
|
|
return url
|
|
}
|
|
|
|
// getMetaString extracts a string value from a metadata map.
|
|
func getMetaString(metadata map[string]any, key string) string {
|
|
if metadata == nil {
|
|
return ""
|
|
}
|
|
if v, ok := metadata[key].(string); ok {
|
|
return v
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// repoNameFromPath extracts the repository name from a file path.
|
|
func repoNameFromPath(repoPath string) string {
|
|
if repoPath == "" {
|
|
return ""
|
|
}
|
|
// Find last path component
|
|
for i := len(repoPath) - 1; i >= 0; i-- {
|
|
if repoPath[i] == '/' {
|
|
return repoPath[i+1:]
|
|
}
|
|
}
|
|
return repoPath
|
|
}
|
|
|
|
// AgentInstallProvider returns a placeholder with combined install scripts for multiple agents.
|
|
func AgentInstallProvider(installScripts []string) PlaceholderProvider {
|
|
return func() map[string]string {
|
|
seen := map[string]bool{}
|
|
var lines []string
|
|
for _, s := range installScripts {
|
|
s = strings.TrimSpace(s)
|
|
if s != "" && !seen[s] {
|
|
seen[s] = true
|
|
lines = append(lines, s)
|
|
}
|
|
}
|
|
return map[string]string{
|
|
"kandev.agents.install": strings.Join(lines, "\n"),
|
|
}
|
|
}
|
|
}
|
|
|
|
func shellSingleQuote(value string) string {
|
|
return strings.ReplaceAll(value, "'", `'"'"'`)
|
|
}
|