948743600e
Tier 1 of the post-review cleanup. Each item is independently safe; bundling because they're all small, mechanical, and lint-passing. - fix(clone): unify injectTokenIntoURL across Docker and Sprites — Sprites used to ignore GH_TOKEN entirely (a user with only GH_TOKEN set got 401 on Sprites clone but worked on Docker). Promote one `injectGitHubTokenIntoCloneURL` helper, accept both env vars (GITHUB_TOKEN wins, matching Docker), and use the documented `https://x-access-token:T@github.com/` form on both surfaces. - fix(executor-popover): swap the <span tabIndex role="button"> trigger for <Button variant="ghost"> so Enter/Space activation, focus rings on Safari, and disabled semantics come for free. - test(docker): rewrite TestDockerStopInstance_PreservesSessionDirOnPlainStop to drive the real DockerExecutor.StopInstance path with ContainerID="" (skips the docker daemon, exercises the kandev-side cleanup branch). Previous version only iterated shouldRunExecutorCleanup strings — would pass even if StopInstance always cleaned up. Now table-driven over preserve+destructive reasons with on-disk asserts. - refactor(orchestrator): drop dead `_ = arg` parameters from persist* helpers (persistResumeState, persistModelSwitchState, persistLaunchState). Brings signatures from 9→6 args, under the funlen lint cap. - refactor(orchestrator): collapse byte-identical isContainerizedExecutor ≡ isCloneBasedExecutorType predicate into one. - refactor(lifecycle): drop dead getMetadataBool, FileUploader.RunCommand, expandMountSource {home} arm (no production agent ships {home} in Mounts; codex_acp_test asserts it), dockerTaskBranch one-line wrapper.
85 lines
2.2 KiB
Go
85 lines
2.2 KiB
Go
package lifecycle
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/kandev/kandev/internal/agent/remoteauth"
|
|
"github.com/kandev/kandev/internal/common/logger"
|
|
)
|
|
|
|
// FileUploader abstracts writing files to a remote environment. Used by
|
|
// UploadCredentialFiles to seed agent auth files into the kandev-managed
|
|
// per-container session dir (local) or sprite (remote).
|
|
type FileUploader interface {
|
|
WriteFile(ctx context.Context, path string, data []byte, mode os.FileMode) error
|
|
}
|
|
|
|
// UploadCredentialFiles reads local credential files and uploads them to the remote environment.
|
|
func UploadCredentialFiles(
|
|
ctx context.Context,
|
|
uploader FileUploader,
|
|
methods []remoteauth.Method,
|
|
targetHomeDir string,
|
|
log *logger.Logger,
|
|
) error {
|
|
if len(methods) == 0 {
|
|
return nil
|
|
}
|
|
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get home directory: %w", err)
|
|
}
|
|
|
|
for _, method := range methods {
|
|
if method.Type != "files" {
|
|
continue
|
|
}
|
|
|
|
for _, relPath := range method.SourceFiles {
|
|
srcPath := filepath.Join(home, relPath)
|
|
data, readErr := os.ReadFile(srcPath)
|
|
if readErr != nil {
|
|
log.Warn("credential source file not found, skipping",
|
|
zap.String("method_id", method.MethodID),
|
|
zap.String("path", srcPath))
|
|
continue
|
|
}
|
|
|
|
targetPath := filepath.Join(targetHomeDir, method.TargetRelDir, filepath.Base(relPath))
|
|
if err := uploader.WriteFile(ctx, targetPath, data, 0o644); err != nil {
|
|
return fmt.Errorf("failed to upload %s: %w", targetPath, err)
|
|
}
|
|
log.Debug("uploaded credential file",
|
|
zap.String("method_id", method.MethodID),
|
|
zap.String("target", targetPath))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DetectGHToken runs `gh auth token` locally and returns the GitHub OAuth token.
|
|
func DetectGHToken() (string, error) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
cmd := exec.CommandContext(ctx, "gh", "auth", "token")
|
|
out, err := cmd.Output()
|
|
if err != nil {
|
|
return "", fmt.Errorf("gh auth token failed: %w", err)
|
|
}
|
|
token := strings.TrimSpace(string(out))
|
|
if token == "" {
|
|
return "", fmt.Errorf("gh auth token returned empty")
|
|
}
|
|
return token, nil
|
|
}
|