Files
kandev/apps/backend/internal/agent/lifecycle/default_scripts.go
T
José Almeida 52b8ee7a85 refactor(scripts): postlude owns worktree-branch checkout
Strip the inline `git checkout -B` block from the Docker and Sprites
default prepare scripts. The kandev-managed postlude
(KandevBranchCheckoutPostlude) is appended unconditionally after every
user prepare script, so keeping the same logic inline made the default
and the postlude two sources of truth that could drift.
2026-05-07 00:33:24 +01:00

165 lines
6.3 KiB
Go

package lifecycle
// DefaultPrepareScript returns the default prepare script for a given executor type string.
func DefaultPrepareScript(executorType string) string {
switch executorType {
case "local":
return defaultLocalPrepareScript
case "worktree":
return defaultWorktreePrepareScript
case "local_docker", "remote_docker":
return defaultDockerPrepareScript
case "sprites":
return defaultSpritesPrepareScript
default:
return ""
}
}
// KandevBranchCheckoutPostlude returns a kandev-managed shell snippet that
// guarantees the session's feature branch is checked out inside the
// workspace, no matter what the user's stored prepare_script does.
//
// Why a postlude instead of just relying on the default script: profiles
// created in the UI snapshot the *then-current* default into their stored
// prepare_script field. When kandev's default is updated to add a new
// kandev-managed step (like the worktree-branch checkout), older profiles
// silently miss it forever. Making the checkout an invariant — appended
// after the user's script — keeps the contract regardless of which default
// the user happens to have stored.
//
// The snippet is wrapped in a subshell + `|| true` so any failure (e.g. the
// user's script never produced /workspace, or the branch is the same as the
// base) is benign and doesn't block agentctl from starting.
//
//nolint:dupword // two `fi` tokens close two distinct shell blocks.
func KandevBranchCheckoutPostlude() string {
return `
# ---- kandev-managed: ensure session feature branch is checked out ----
# Appended automatically after the user's prepare script. Idempotent —
# safe to run even when the user's script already does the checkout.
(
if [ -d "{{workspace.path}}/.git" ] \
&& [ -n "{{worktree.branch}}" ] \
&& [ "{{worktree.branch}}" != "{{repository.branch}}" ]; then
cd "{{workspace.path}}" || exit 0
if git fetch --depth=1 origin "{{worktree.branch}}" 2>/dev/null; then
git checkout -B "{{worktree.branch}}" "origin/{{worktree.branch}}"
elif git rev-parse --verify "{{worktree.branch}}" >/dev/null 2>&1; then
git checkout "{{worktree.branch}}"
else
git checkout -b "{{worktree.branch}}"
fi
fi
) || true
`
}
const defaultLocalPrepareScript = `#!/bin/bash
# Prepare local environment
# Runs before launching the local agent runtime.
# The script executes with working directory set to {{workspace.path}}.
# Use {{repository.path}} when you need the canonical repository root path.
# ---- Repository setup (if configured) ----
{{repository.setup_script}}
`
const defaultWorktreePrepareScript = `#!/bin/bash
# Prepare worktree environment
# Runs after the worktree has already been created/reused by Kandev.
# The script executes with working directory set to {{worktree.path}}.
# Use {{repository.path}} if you need to run commands in the main repository.
# ---- Repository setup (if configured) ----
{{repository.setup_script}}
`
const defaultDockerPrepareScript = `#!/bin/sh
# Prepare Docker container environment (kandev/multi-agent image)
# git, node, and agentctl are already installed in the image
set -eu
# ---- Git identity (optional) ----
{{git.identity_setup}}
# Mounted local remotes and workspaces can be owned by a host UID that does
# not match the container user.
git config --global --add safe.directory '*'
# ---- Configure git/gh for HTTPS auth ----
git config --global url."https://github.com/".insteadOf "git@github.com:"
git config --global url."https://github.com/".insteadOf "ssh://git@github.com/"
# Configure GitHub token for gh CLI and git operations
{{github.auth_setup}}
# ---- Clone repository ----
# The kandev-managed feature-branch checkout is appended as an invariant
# postlude (see KandevBranchCheckoutPostlude) — keep it out of the default
# so old profiles snapshotting this script and the postlude never disagree.
git clone --depth=1 --branch {{repository.branch}} {{repository.clone_url}} {{workspace.path}}
cd {{workspace.path}}
# Strip embedded token from remote URL to avoid persisting credentials in .git/config
git remote set-url origin "$(git remote get-url origin | sed 's|https://[^@]*@github.com/|https://github.com/|')" 2>/dev/null || true
# ---- Repository setup (if configured) ----
{{repository.setup_script}}
`
const defaultSpritesPrepareScript = `#!/bin/bash
# Prepare Sprites.dev cloud sandbox
#
# Pre-installed tools (no need to install):
# git, curl, wget, gh (GitHub CLI), node, python, go,
# build-essential, openssh-client, ca-certificates
set -euo pipefail
# ---- Add SSH host keys (prevent "Host key verification failed") ----
mkdir -p ~/.ssh
ssh-keyscan -t ed25519 github.com gitlab.com bitbucket.org >> ~/.ssh/known_hosts 2>/dev/null
# ---- Configure git/gh for HTTPS auth (token-based, no SSH keys needed) ----
# Rewrite SSH URLs to HTTPS so git clone git@github.com:... works via token auth
git config --global url."https://github.com/".insteadOf "git@github.com:"
git config --global url."https://github.com/".insteadOf "ssh://git@github.com/"
# Configure GitHub token for gh CLI and git operations
# GH_TOKEN is the primary env var for gh CLI authentication
{{github.auth_setup}}
# ---- Install pnpm globally ----
curl -fsSL https://github.com/pnpm/pnpm/releases/download/v10.32.1/pnpm-linux-x64 -o /usr/local/bin/pnpm
chmod +x /usr/local/bin/pnpm
# ---- Git identity ----
{{git.identity_setup}}
# ---- Clone repository ----
# The kandev-managed feature-branch checkout is appended as an invariant
# postlude (see KandevBranchCheckoutPostlude) — keep it out of the default
# so old profiles snapshotting this script and the postlude never disagree.
echo "Cloning {{repository.clone_url}} (branch: {{repository.branch}})..."
git clone --depth=1 --quiet --branch {{repository.branch}} {{repository.clone_url}} {{workspace.path}}
cd {{workspace.path}}
# Strip embedded token from remote URL to avoid persisting credentials in .git/config
git remote set-url origin "$(git remote get-url origin | sed 's|https://[^@]*@github.com/|https://github.com/|')" 2>/dev/null || true
# ---- Repository setup (if configured) ----
{{repository.setup_script}}
# ---- Pre-install agent CLI(s) ----
{{kandev.agents.install}}
# ---- Install and start Kandev agent controller ----
echo "Starting agent controller..."
{{kandev.agentctl.install}}
{{kandev.agentctl.start}}
echo "Prepare complete."
`