forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
at master 3.8 kB view raw
1package models 2 3import ( 4 "fmt" 5 "strings" 6 7 "tangled.org/core/api/tangled" 8 "tangled.org/core/workflow" 9) 10 11type CloneStep struct { 12 name string 13 kind StepKind 14 commands []string 15} 16 17func (s CloneStep) Name() string { 18 return s.name 19} 20 21func (s CloneStep) Commands() []string { 22 return s.commands 23} 24 25func (s CloneStep) Command() string { 26 return strings.Join(s.commands, "\n") 27} 28 29func (s CloneStep) Kind() StepKind { 30 return s.kind 31} 32 33// BuildCloneStep generates git clone commands. 34// The caller must ensure the current working directory is set to the desired 35// workspace directory before executing these commands. 36// 37// The generated commands are: 38// - git init 39// - git remote add origin <url> 40// - git fetch --depth=<d> --recurse-submodules=<yes|no> <sha> 41// - git checkout FETCH_HEAD 42// 43// Supports all trigger types (push, PR, manual) and clone options. 44func BuildCloneStep(twf tangled.Pipeline_Workflow, tr tangled.Pipeline_TriggerMetadata, dev bool) CloneStep { 45 if twf.Clone != nil && twf.Clone.Skip { 46 return CloneStep{} 47 } 48 49 commitSHA, err := extractCommitSHA(tr) 50 if err != nil { 51 return CloneStep{ 52 kind: StepKindSystem, 53 name: "Clone repository into workspace (error)", 54 commands: []string{fmt.Sprintf("echo 'Failed to get clone info: %s' && exit 1", err.Error())}, 55 } 56 } 57 58 repoURL := BuildRepoURL(tr.Repo, dev) 59 60 var cloneOpts tangled.Pipeline_CloneOpts 61 if twf.Clone != nil { 62 cloneOpts = *twf.Clone 63 } 64 fetchArgs := buildFetchArgs(cloneOpts, commitSHA) 65 66 return CloneStep{ 67 kind: StepKindSystem, 68 name: "Clone repository into workspace", 69 commands: []string{ 70 "git init", 71 fmt.Sprintf("git remote add origin %s", repoURL), 72 fmt.Sprintf("git fetch %s", strings.Join(fetchArgs, " ")), 73 "git checkout FETCH_HEAD", 74 }, 75 } 76} 77 78// extractCommitSHA extracts the commit SHA from trigger metadata based on trigger type 79func extractCommitSHA(tr tangled.Pipeline_TriggerMetadata) (string, error) { 80 switch workflow.TriggerKind(tr.Kind) { 81 case workflow.TriggerKindPush: 82 if tr.Push == nil { 83 return "", fmt.Errorf("push trigger metadata is nil") 84 } 85 return tr.Push.NewSha, nil 86 87 case workflow.TriggerKindPullRequest: 88 if tr.PullRequest == nil { 89 return "", fmt.Errorf("pull request trigger metadata is nil") 90 } 91 return tr.PullRequest.SourceSha, nil 92 93 case workflow.TriggerKindManual: 94 // Manual triggers don't have an explicit SHA in the metadata 95 // For now, return empty string - could be enhanced to fetch from default branch 96 // TODO: Implement manual trigger SHA resolution (fetch default branch HEAD) 97 return "", nil 98 99 default: 100 return "", fmt.Errorf("unknown trigger kind: %s", tr.Kind) 101 } 102} 103 104// BuildRepoURL constructs the repository URL from repo metadata. 105func BuildRepoURL(repo *tangled.Pipeline_TriggerRepo, devMode bool) string { 106 if repo == nil { 107 return "" 108 } 109 110 scheme := "https://" 111 if devMode { 112 scheme = "http://" 113 } 114 115 // Get host from knot 116 host := repo.Knot 117 118 // In dev mode, replace localhost with host.docker.internal for Docker networking 119 if devMode && strings.Contains(host, "localhost") { 120 host = strings.ReplaceAll(host, "localhost", "host.docker.internal") 121 } 122 123 // Build URL: {scheme}{knot}/{did}/{repo} 124 return fmt.Sprintf("%s%s/%s/%s", scheme, host, repo.Did, repo.Repo) 125} 126 127// buildFetchArgs constructs the arguments for git fetch based on clone options 128func buildFetchArgs(clone tangled.Pipeline_CloneOpts, sha string) []string { 129 args := []string{} 130 131 // Set fetch depth (default to 1 for shallow clone) 132 depth := clone.Depth 133 if depth == 0 { 134 depth = 1 135 } 136 args = append(args, fmt.Sprintf("--depth=%d", depth)) 137 138 // Add submodules if requested 139 if clone.Submodules { 140 args = append(args, "--recurse-submodules=yes") 141 } 142 143 // Add remote and SHA 144 args = append(args, "origin") 145 if sha != "" { 146 args = append(args, sha) 147 } 148 149 return args 150}