Monorepo for Tangled tangled.org
1

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / models / clone_test.go
10 kB 388 lines
1package models 2 3import ( 4 "strings" 5 "testing" 6 7 "tangled.org/core/api/tangled" 8 "tangled.org/core/workflow" 9) 10 11func sp(s string) *string { return &s } 12 13func TestBuildCloneStep_PushTrigger(t *testing.T) { 14 twf := tangled.Pipeline_Workflow{ 15 Clone: &tangled.Pipeline_CloneOpts{ 16 Depth: 1, 17 Submodules: false, 18 Skip: false, 19 }, 20 } 21 tr := tangled.Pipeline_TriggerMetadata{ 22 Kind: string(workflow.TriggerKindPush), 23 Push: &tangled.Pipeline_PushTriggerData{ 24 NewSha: "abc123", 25 OldSha: "def456", 26 Ref: "refs/heads/main", 27 }, 28 Repo: &tangled.Pipeline_TriggerRepo{ 29 Knot: "example.com", 30 Did: "did:plc:user123", 31 Repo: sp("my-repo"), 32 RepoDid: sp("did:plc:boltless"), 33 }, 34 } 35 36 step := BuildCloneStep(twf, tr, false) 37 38 if step.Kind() != StepKindSystem { 39 t.Errorf("Expected StepKindSystem, got %v", step.Kind()) 40 } 41 42 if step.Name() != "Clone repository into workspace" { 43 t.Errorf("Expected 'Clone repository into workspace', got '%s'", step.Name()) 44 } 45 46 commands := step.Commands() 47 if len(commands) != 4 { 48 t.Errorf("Expected 4 commands, got %d", len(commands)) 49 } 50 51 // Verify commands contain expected git operations 52 allCmds := strings.Join(commands, " ") 53 if !strings.Contains(allCmds, "git init") { 54 t.Error("Commands should contain 'git init'") 55 } 56 if !strings.Contains(allCmds, "git remote add origin") { 57 t.Error("Commands should contain 'git remote add origin'") 58 } 59 if !strings.Contains(allCmds, "git fetch") { 60 t.Error("Commands should contain 'git fetch'") 61 } 62 if !strings.Contains(allCmds, "abc123") { 63 t.Error("Commands should contain commit SHA") 64 } 65 if !strings.Contains(allCmds, "git checkout FETCH_HEAD") { 66 t.Error("Commands should contain 'git checkout FETCH_HEAD'") 67 } 68 if !strings.Contains(allCmds, "https://example.com/did:plc:boltless") { 69 t.Error("Commands should contain expected repo URL") 70 } 71} 72 73func TestBuildCloneStep_PullRequestTrigger(t *testing.T) { 74 twf := tangled.Pipeline_Workflow{ 75 Clone: &tangled.Pipeline_CloneOpts{ 76 Depth: 1, 77 Skip: false, 78 }, 79 } 80 tr := tangled.Pipeline_TriggerMetadata{ 81 Kind: string(workflow.TriggerKindPullRequest), 82 PullRequest: &tangled.Pipeline_PullRequestTriggerData{ 83 SourceSha: "pr-sha-789", 84 SourceBranch: "feature-branch", 85 TargetBranch: "main", 86 Action: "opened", 87 }, 88 Repo: &tangled.Pipeline_TriggerRepo{ 89 Knot: "example.com", 90 Did: "did:plc:user123", 91 Repo: sp("my-repo"), 92 RepoDid: sp("did:plc:boltless"), 93 }, 94 } 95 96 step := BuildCloneStep(twf, tr, false) 97 98 allCmds := strings.Join(step.Commands(), " ") 99 if !strings.Contains(allCmds, "pr-sha-789") { 100 t.Error("Commands should contain PR commit SHA") 101 } 102} 103 104func TestBuildCloneStep_ManualTrigger(t *testing.T) { 105 twf := tangled.Pipeline_Workflow{ 106 Clone: &tangled.Pipeline_CloneOpts{ 107 Depth: 1, 108 Skip: false, 109 }, 110 } 111 tr := tangled.Pipeline_TriggerMetadata{ 112 Kind: string(workflow.TriggerKindManual), 113 Manual: &tangled.Pipeline_ManualTriggerData{ 114 Sha: "manualsha456", 115 Inputs: nil, 116 }, 117 Repo: &tangled.Pipeline_TriggerRepo{ 118 Knot: "example.com", 119 Did: "did:plc:user123", 120 Repo: sp("my-repo"), 121 RepoDid: sp("did:plc:boltless"), 122 }, 123 } 124 125 step := BuildCloneStep(twf, tr, false) 126 127 allCmds := strings.Join(step.Commands(), " ") 128 // Should still have basic git commands 129 if !strings.Contains(allCmds, "git init") { 130 t.Error("Commands should contain 'git init'") 131 } 132 if !strings.Contains(allCmds, "git fetch") { 133 t.Error("Commands should contain 'git fetch'") 134 } 135 // Manual triggers now carry an explicit SHA, which the fetch targets 136 if !strings.Contains(allCmds, "manualsha456") { 137 t.Error("Commands should contain the manual trigger SHA") 138 } 139} 140 141func TestBuildCloneStep_SkipFlag(t *testing.T) { 142 twf := tangled.Pipeline_Workflow{ 143 Clone: &tangled.Pipeline_CloneOpts{ 144 Skip: true, 145 }, 146 } 147 tr := tangled.Pipeline_TriggerMetadata{ 148 Kind: string(workflow.TriggerKindPush), 149 Push: &tangled.Pipeline_PushTriggerData{ 150 NewSha: "abc123", 151 }, 152 Repo: &tangled.Pipeline_TriggerRepo{ 153 Knot: "example.com", 154 Did: "did:plc:user123", 155 Repo: sp("my-repo"), 156 RepoDid: sp("did:plc:boltless"), 157 }, 158 } 159 160 step := BuildCloneStep(twf, tr, false) 161 162 // Empty step when skip is true 163 if step.Name() != "" { 164 t.Error("Expected empty step name when Skip is true") 165 } 166 if len(step.Commands()) != 0 { 167 t.Errorf("Expected no commands when Skip is true, got %d commands", len(step.Commands())) 168 } 169} 170 171func TestBuildCloneStep_DevMode(t *testing.T) { 172 twf := tangled.Pipeline_Workflow{ 173 Engine: "nixery", 174 Clone: &tangled.Pipeline_CloneOpts{ 175 Depth: 1, 176 Skip: false, 177 }, 178 } 179 tr := tangled.Pipeline_TriggerMetadata{ 180 Kind: string(workflow.TriggerKindPush), 181 Push: &tangled.Pipeline_PushTriggerData{ 182 NewSha: "abc123", 183 }, 184 Repo: &tangled.Pipeline_TriggerRepo{ 185 Knot: "knot.tngl.boltless.dev", 186 Did: "did:plc:user123", 187 Repo: sp("my-repo"), 188 RepoDid: sp("did:plc:boltless"), 189 }, 190 } 191 192 step := BuildCloneStep(twf, tr, true) 193 194 // In dev mode, sslVerify should be disabled 195 allCmds := strings.Join(step.Commands(), " ") 196 if !strings.Contains(allCmds, "git -c http.sslVerify=false fetch") { 197 t.Error("Expected sslVerify to be disabled in dev mode clone commands") 198 } 199} 200 201func TestBuildCloneStep_DepthAndSubmodules(t *testing.T) { 202 twf := tangled.Pipeline_Workflow{ 203 Clone: &tangled.Pipeline_CloneOpts{ 204 Depth: 10, 205 Submodules: true, 206 Skip: false, 207 }, 208 } 209 tr := tangled.Pipeline_TriggerMetadata{ 210 Kind: string(workflow.TriggerKindPush), 211 Push: &tangled.Pipeline_PushTriggerData{ 212 NewSha: "abc123", 213 }, 214 Repo: &tangled.Pipeline_TriggerRepo{ 215 Knot: "example.com", 216 Did: "did:plc:user123", 217 Repo: sp("my-repo"), 218 RepoDid: sp("did:plc:boltless"), 219 }, 220 } 221 222 step := BuildCloneStep(twf, tr, false) 223 224 allCmds := strings.Join(step.Commands(), " ") 225 if !strings.Contains(allCmds, "--depth=10") { 226 t.Error("Commands should contain '--depth=10'") 227 } 228 229 if !strings.Contains(allCmds, "--recurse-submodules=yes") { 230 t.Error("Commands should contain '--recurse-submodules=yes'") 231 } 232} 233 234func TestBuildCloneStep_DefaultDepth(t *testing.T) { 235 twf := tangled.Pipeline_Workflow{ 236 Clone: &tangled.Pipeline_CloneOpts{ 237 Depth: 0, // Default should be 1 238 Skip: false, 239 }, 240 } 241 tr := tangled.Pipeline_TriggerMetadata{ 242 Kind: string(workflow.TriggerKindPush), 243 Push: &tangled.Pipeline_PushTriggerData{ 244 NewSha: "abc123", 245 }, 246 Repo: &tangled.Pipeline_TriggerRepo{ 247 Knot: "example.com", 248 Did: "did:plc:user123", 249 Repo: sp("my-repo"), 250 RepoDid: sp("did:plc:boltless"), 251 }, 252 } 253 254 step := BuildCloneStep(twf, tr, false) 255 256 allCmds := strings.Join(step.Commands(), " ") 257 if !strings.Contains(allCmds, "--depth=1") { 258 t.Error("Commands should default to '--depth=1'") 259 } 260} 261 262func TestBuildCloneStep_NilPushData(t *testing.T) { 263 twf := tangled.Pipeline_Workflow{ 264 Clone: &tangled.Pipeline_CloneOpts{ 265 Depth: 1, 266 Skip: false, 267 }, 268 } 269 tr := tangled.Pipeline_TriggerMetadata{ 270 Kind: string(workflow.TriggerKindPush), 271 Push: nil, // Nil push data should create error step 272 Repo: &tangled.Pipeline_TriggerRepo{ 273 Knot: "example.com", 274 Did: "did:plc:user123", 275 Repo: sp("my-repo"), 276 RepoDid: sp("did:plc:boltless"), 277 }, 278 } 279 280 step := BuildCloneStep(twf, tr, false) 281 282 // Should return an error step 283 if !strings.Contains(step.Name(), "error") { 284 t.Error("Expected error in step name when push data is nil") 285 } 286 287 allCmds := strings.Join(step.Commands(), " ") 288 if !strings.Contains(allCmds, "Failed to get clone info") { 289 t.Error("Commands should contain error message") 290 } 291 if !strings.Contains(allCmds, "exit 1") { 292 t.Error("Commands should exit with error") 293 } 294} 295 296func TestBuildCloneStep_NilPRData(t *testing.T) { 297 twf := tangled.Pipeline_Workflow{ 298 Clone: &tangled.Pipeline_CloneOpts{ 299 Depth: 1, 300 Skip: false, 301 }, 302 } 303 tr := tangled.Pipeline_TriggerMetadata{ 304 Kind: string(workflow.TriggerKindPullRequest), 305 PullRequest: nil, // Nil PR data should create error step 306 Repo: &tangled.Pipeline_TriggerRepo{ 307 Knot: "example.com", 308 Did: "did:plc:user123", 309 Repo: sp("my-repo"), 310 RepoDid: sp("did:plc:boltless"), 311 }, 312 } 313 314 step := BuildCloneStep(twf, tr, false) 315 316 // Should return an error step 317 if !strings.Contains(step.Name(), "error") { 318 t.Error("Expected error in step name when pull request data is nil") 319 } 320 321 allCmds := strings.Join(step.Commands(), " ") 322 if !strings.Contains(allCmds, "Failed to get clone info") { 323 t.Error("Commands should contain error message") 324 } 325} 326 327func TestBuildCloneStep_UnknownTriggerKind(t *testing.T) { 328 twf := tangled.Pipeline_Workflow{ 329 Clone: &tangled.Pipeline_CloneOpts{ 330 Depth: 1, 331 Skip: false, 332 }, 333 } 334 tr := tangled.Pipeline_TriggerMetadata{ 335 Kind: "unknown_trigger", 336 Repo: &tangled.Pipeline_TriggerRepo{ 337 Knot: "example.com", 338 Did: "did:plc:user123", 339 Repo: sp("my-repo"), 340 RepoDid: sp("did:plc:boltless"), 341 }, 342 } 343 344 step := BuildCloneStep(twf, tr, false) 345 346 // Should return an error step 347 if !strings.Contains(step.Name(), "error") { 348 t.Error("Expected error in step name for unknown trigger kind") 349 } 350 351 allCmds := strings.Join(step.Commands(), " ") 352 if !strings.Contains(allCmds, "unknown trigger kind") { 353 t.Error("Commands should contain error message about unknown trigger kind") 354 } 355} 356 357func TestBuildCloneStep_NilCloneOpts(t *testing.T) { 358 twf := tangled.Pipeline_Workflow{ 359 Clone: nil, // Nil clone options should use defaults 360 } 361 tr := tangled.Pipeline_TriggerMetadata{ 362 Kind: string(workflow.TriggerKindPush), 363 Push: &tangled.Pipeline_PushTriggerData{ 364 NewSha: "abc123", 365 }, 366 Repo: &tangled.Pipeline_TriggerRepo{ 367 Knot: "example.com", 368 Did: "did:plc:user123", 369 Repo: sp("my-repo"), 370 RepoDid: sp("did:plc:boltless"), 371 }, 372 } 373 374 step := BuildCloneStep(twf, tr, false) 375 376 // Should still work with default options 377 if step.Kind() != StepKindSystem { 378 t.Errorf("Expected StepKindSystem, got %v", step.Kind()) 379 } 380 381 allCmds := strings.Join(step.Commands(), " ") 382 if !strings.Contains(allCmds, "--depth=1") { 383 t.Error("Commands should default to '--depth=1' when Clone is nil") 384 } 385 if !strings.Contains(allCmds, "git init") { 386 t.Error("Commands should contain 'git init'") 387 } 388}