Monorepo for Tangled tangled.org
5

Configure Feed

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

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 Inputs: nil, 115 }, 116 Repo: &tangled.Pipeline_TriggerRepo{ 117 Knot: "example.com", 118 Did: "did:plc:user123", 119 Repo: sp("my-repo"), 120 RepoDid: sp("did:plc:boltless"), 121 }, 122 } 123 124 step := BuildCloneStep(twf, tr, false) 125 126 // Manual triggers don't have a SHA yet (TODO), so git fetch won't include a SHA 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} 136 137func TestBuildCloneStep_SkipFlag(t *testing.T) { 138 twf := tangled.Pipeline_Workflow{ 139 Clone: &tangled.Pipeline_CloneOpts{ 140 Skip: true, 141 }, 142 } 143 tr := tangled.Pipeline_TriggerMetadata{ 144 Kind: string(workflow.TriggerKindPush), 145 Push: &tangled.Pipeline_PushTriggerData{ 146 NewSha: "abc123", 147 }, 148 Repo: &tangled.Pipeline_TriggerRepo{ 149 Knot: "example.com", 150 Did: "did:plc:user123", 151 Repo: sp("my-repo"), 152 RepoDid: sp("did:plc:boltless"), 153 }, 154 } 155 156 step := BuildCloneStep(twf, tr, false) 157 158 // Empty step when skip is true 159 if step.Name() != "" { 160 t.Error("Expected empty step name when Skip is true") 161 } 162 if len(step.Commands()) != 0 { 163 t.Errorf("Expected no commands when Skip is true, got %d commands", len(step.Commands())) 164 } 165} 166 167func TestBuildCloneStep_DevMode(t *testing.T) { 168 twf := tangled.Pipeline_Workflow{ 169 Clone: &tangled.Pipeline_CloneOpts{ 170 Depth: 1, 171 Skip: false, 172 }, 173 } 174 tr := tangled.Pipeline_TriggerMetadata{ 175 Kind: string(workflow.TriggerKindPush), 176 Push: &tangled.Pipeline_PushTriggerData{ 177 NewSha: "abc123", 178 }, 179 Repo: &tangled.Pipeline_TriggerRepo{ 180 Knot: "localhost:3000", 181 Did: "did:plc:user123", 182 Repo: sp("my-repo"), 183 RepoDid: sp("did:plc:boltless"), 184 }, 185 } 186 187 step := BuildCloneStep(twf, tr, true) 188 189 // In dev mode, should use http:// and replace localhost with host.docker.internal 190 allCmds := strings.Join(step.Commands(), " ") 191 expectedURL := "http://host.docker.internal:3000/did:plc:boltless" 192 if !strings.Contains(allCmds, expectedURL) { 193 t.Errorf("Expected dev mode URL '%s' in commands", expectedURL) 194 } 195} 196 197func TestBuildCloneStep_DepthAndSubmodules(t *testing.T) { 198 twf := tangled.Pipeline_Workflow{ 199 Clone: &tangled.Pipeline_CloneOpts{ 200 Depth: 10, 201 Submodules: true, 202 Skip: false, 203 }, 204 } 205 tr := tangled.Pipeline_TriggerMetadata{ 206 Kind: string(workflow.TriggerKindPush), 207 Push: &tangled.Pipeline_PushTriggerData{ 208 NewSha: "abc123", 209 }, 210 Repo: &tangled.Pipeline_TriggerRepo{ 211 Knot: "example.com", 212 Did: "did:plc:user123", 213 Repo: sp("my-repo"), 214 RepoDid: sp("did:plc:boltless"), 215 }, 216 } 217 218 step := BuildCloneStep(twf, tr, false) 219 220 allCmds := strings.Join(step.Commands(), " ") 221 if !strings.Contains(allCmds, "--depth=10") { 222 t.Error("Commands should contain '--depth=10'") 223 } 224 225 if !strings.Contains(allCmds, "--recurse-submodules=yes") { 226 t.Error("Commands should contain '--recurse-submodules=yes'") 227 } 228} 229 230func TestBuildCloneStep_DefaultDepth(t *testing.T) { 231 twf := tangled.Pipeline_Workflow{ 232 Clone: &tangled.Pipeline_CloneOpts{ 233 Depth: 0, // Default should be 1 234 Skip: false, 235 }, 236 } 237 tr := tangled.Pipeline_TriggerMetadata{ 238 Kind: string(workflow.TriggerKindPush), 239 Push: &tangled.Pipeline_PushTriggerData{ 240 NewSha: "abc123", 241 }, 242 Repo: &tangled.Pipeline_TriggerRepo{ 243 Knot: "example.com", 244 Did: "did:plc:user123", 245 Repo: sp("my-repo"), 246 RepoDid: sp("did:plc:boltless"), 247 }, 248 } 249 250 step := BuildCloneStep(twf, tr, false) 251 252 allCmds := strings.Join(step.Commands(), " ") 253 if !strings.Contains(allCmds, "--depth=1") { 254 t.Error("Commands should default to '--depth=1'") 255 } 256} 257 258func TestBuildCloneStep_NilPushData(t *testing.T) { 259 twf := tangled.Pipeline_Workflow{ 260 Clone: &tangled.Pipeline_CloneOpts{ 261 Depth: 1, 262 Skip: false, 263 }, 264 } 265 tr := tangled.Pipeline_TriggerMetadata{ 266 Kind: string(workflow.TriggerKindPush), 267 Push: nil, // Nil push data should create error step 268 Repo: &tangled.Pipeline_TriggerRepo{ 269 Knot: "example.com", 270 Did: "did:plc:user123", 271 Repo: sp("my-repo"), 272 RepoDid: sp("did:plc:boltless"), 273 }, 274 } 275 276 step := BuildCloneStep(twf, tr, false) 277 278 // Should return an error step 279 if !strings.Contains(step.Name(), "error") { 280 t.Error("Expected error in step name when push data is nil") 281 } 282 283 allCmds := strings.Join(step.Commands(), " ") 284 if !strings.Contains(allCmds, "Failed to get clone info") { 285 t.Error("Commands should contain error message") 286 } 287 if !strings.Contains(allCmds, "exit 1") { 288 t.Error("Commands should exit with error") 289 } 290} 291 292func TestBuildCloneStep_NilPRData(t *testing.T) { 293 twf := tangled.Pipeline_Workflow{ 294 Clone: &tangled.Pipeline_CloneOpts{ 295 Depth: 1, 296 Skip: false, 297 }, 298 } 299 tr := tangled.Pipeline_TriggerMetadata{ 300 Kind: string(workflow.TriggerKindPullRequest), 301 PullRequest: nil, // Nil PR data should create error step 302 Repo: &tangled.Pipeline_TriggerRepo{ 303 Knot: "example.com", 304 Did: "did:plc:user123", 305 Repo: sp("my-repo"), 306 RepoDid: sp("did:plc:boltless"), 307 }, 308 } 309 310 step := BuildCloneStep(twf, tr, false) 311 312 // Should return an error step 313 if !strings.Contains(step.Name(), "error") { 314 t.Error("Expected error in step name when pull request data is nil") 315 } 316 317 allCmds := strings.Join(step.Commands(), " ") 318 if !strings.Contains(allCmds, "Failed to get clone info") { 319 t.Error("Commands should contain error message") 320 } 321} 322 323func TestBuildCloneStep_UnknownTriggerKind(t *testing.T) { 324 twf := tangled.Pipeline_Workflow{ 325 Clone: &tangled.Pipeline_CloneOpts{ 326 Depth: 1, 327 Skip: false, 328 }, 329 } 330 tr := tangled.Pipeline_TriggerMetadata{ 331 Kind: "unknown_trigger", 332 Repo: &tangled.Pipeline_TriggerRepo{ 333 Knot: "example.com", 334 Did: "did:plc:user123", 335 Repo: sp("my-repo"), 336 RepoDid: sp("did:plc:boltless"), 337 }, 338 } 339 340 step := BuildCloneStep(twf, tr, false) 341 342 // Should return an error step 343 if !strings.Contains(step.Name(), "error") { 344 t.Error("Expected error in step name for unknown trigger kind") 345 } 346 347 allCmds := strings.Join(step.Commands(), " ") 348 if !strings.Contains(allCmds, "unknown trigger kind") { 349 t.Error("Commands should contain error message about unknown trigger kind") 350 } 351} 352 353func TestBuildCloneStep_NilCloneOpts(t *testing.T) { 354 twf := tangled.Pipeline_Workflow{ 355 Clone: nil, // Nil clone options should use defaults 356 } 357 tr := tangled.Pipeline_TriggerMetadata{ 358 Kind: string(workflow.TriggerKindPush), 359 Push: &tangled.Pipeline_PushTriggerData{ 360 NewSha: "abc123", 361 }, 362 Repo: &tangled.Pipeline_TriggerRepo{ 363 Knot: "example.com", 364 Did: "did:plc:user123", 365 Repo: sp("my-repo"), 366 RepoDid: sp("did:plc:boltless"), 367 }, 368 } 369 370 step := BuildCloneStep(twf, tr, false) 371 372 // Should still work with default options 373 if step.Kind() != StepKindSystem { 374 t.Errorf("Expected StepKindSystem, got %v", step.Kind()) 375 } 376 377 allCmds := strings.Join(step.Commands(), " ") 378 if !strings.Contains(allCmds, "--depth=1") { 379 t.Error("Commands should default to '--depth=1' when Clone is nil") 380 } 381 if !strings.Contains(allCmds, "git init") { 382 t.Error("Commands should contain 'git init'") 383 } 384}