github.com/xgoffin/jenkins-library@v1.154.0/cmd/artifactPrepareVersion_test.go (about) 1 package cmd 2 3 import ( 4 "fmt" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/SAP/jenkins-library/pkg/mock" 10 "github.com/SAP/jenkins-library/pkg/orchestrator" 11 "github.com/SAP/jenkins-library/pkg/telemetry" 12 "github.com/SAP/jenkins-library/pkg/versioning" 13 14 "github.com/ghodss/yaml" 15 "github.com/stretchr/testify/assert" 16 "helm.sh/helm/v3/pkg/chart" 17 18 "github.com/go-git/go-git/v5" 19 gitConfig "github.com/go-git/go-git/v5/config" 20 "github.com/go-git/go-git/v5/plumbing" 21 "github.com/go-git/go-git/v5/plumbing/object" 22 gitHttp "github.com/go-git/go-git/v5/plumbing/transport/http" 23 "github.com/go-git/go-git/v5/plumbing/transport/ssh" 24 ) 25 26 type artifactVersioningMock struct { 27 originalVersion string 28 newVersion string 29 getVersionError string 30 setVersionError string 31 initCalled bool 32 versioningScheme string 33 coordinates versioning.Coordinates 34 coordinatesError error 35 } 36 37 func (a *artifactVersioningMock) VersioningScheme() string { 38 return a.versioningScheme 39 } 40 41 func (a *artifactVersioningMock) GetVersion() (string, error) { 42 if len(a.getVersionError) > 0 { 43 return "", fmt.Errorf(a.getVersionError) 44 } 45 return a.originalVersion, nil 46 } 47 48 func (a *artifactVersioningMock) SetVersion(version string) error { 49 if len(a.setVersionError) > 0 { 50 return fmt.Errorf(a.setVersionError) 51 } 52 a.newVersion = version 53 return nil 54 } 55 56 func (a *artifactVersioningMock) GetCoordinates() (versioning.Coordinates, error) { 57 if a.coordinatesError != nil { 58 return versioning.Coordinates{}, a.coordinatesError 59 } 60 return a.coordinates, nil 61 } 62 63 type gitRepositoryMock struct { 64 createRemoteConfigs []*gitConfig.RemoteConfig 65 createRemoteCalls int 66 createRemoteError []string 67 deleteRemoteNames []string 68 deleteRemoteCalls int 69 deleteRemoteError []string 70 pushCalled bool 71 pushOptions *git.PushOptions 72 pushError string 73 remote *git.Remote 74 remoteError string 75 revision string 76 revisionHash plumbing.Hash 77 revisionError string 78 tag string 79 tagHash plumbing.Hash 80 tagError string 81 worktree *git.Worktree 82 worktreeError string 83 commitObjectHash string 84 } 85 86 func (r *gitRepositoryMock) CommitObject(hash plumbing.Hash) (*object.Commit, error) { 87 r.commitObjectHash = hash.String() 88 return &object.Commit{Hash: hash, Message: "Test commit message"}, nil 89 } 90 91 func (r *gitRepositoryMock) CreateTag(name string, hash plumbing.Hash, opts *git.CreateTagOptions) (*plumbing.Reference, error) { 92 if len(r.tagError) > 0 { 93 return nil, fmt.Errorf(r.tagError) 94 } 95 r.tag = name 96 r.tagHash = hash 97 return nil, nil 98 } 99 100 func (r *gitRepositoryMock) CreateRemote(config *gitConfig.RemoteConfig) (*git.Remote, error) { 101 r.createRemoteCalls++ 102 if len(r.createRemoteError) >= r.createRemoteCalls && len(r.createRemoteError[r.createRemoteCalls-1]) > 0 { 103 return nil, fmt.Errorf(r.createRemoteError[r.createRemoteCalls-1]) 104 } 105 r.createRemoteConfigs = append(r.createRemoteConfigs, config) 106 return nil, nil 107 } 108 109 func (r *gitRepositoryMock) DeleteRemote(name string) error { 110 r.deleteRemoteCalls++ 111 if len(r.deleteRemoteError) >= r.deleteRemoteCalls && len(r.deleteRemoteError[r.deleteRemoteCalls-1]) > 0 { 112 return fmt.Errorf(r.deleteRemoteError[r.deleteRemoteCalls-1]) 113 } 114 r.deleteRemoteNames = append(r.deleteRemoteNames, name) 115 return nil 116 } 117 118 func (r *gitRepositoryMock) Push(o *git.PushOptions) error { 119 if len(r.pushError) > 0 { 120 return fmt.Errorf(r.pushError) 121 } 122 r.pushCalled = true 123 r.pushOptions = o 124 return nil 125 } 126 127 func (r *gitRepositoryMock) Remote(name string) (*git.Remote, error) { 128 if len(r.remoteError) > 0 { 129 return &git.Remote{}, fmt.Errorf(r.remoteError) 130 } 131 return r.remote, nil 132 } 133 134 func (r *gitRepositoryMock) ResolveRevision(rev plumbing.Revision) (*plumbing.Hash, error) { 135 if len(r.revisionError) > 0 { 136 return nil, fmt.Errorf(r.revisionError) 137 } 138 r.revision = rev.String() 139 return &r.revisionHash, nil 140 } 141 142 func (r *gitRepositoryMock) Worktree() (*git.Worktree, error) { 143 if len(r.worktreeError) > 0 { 144 return nil, fmt.Errorf(r.worktreeError) 145 } 146 return r.worktree, nil 147 } 148 149 type gitWorktreeMock struct { 150 checkoutError string 151 checkoutOpts *git.CheckoutOptions 152 commitHash plumbing.Hash 153 commitMsg string 154 commitOpts *git.CommitOptions 155 commitError string 156 } 157 158 func (w *gitWorktreeMock) Checkout(opts *git.CheckoutOptions) error { 159 if len(w.checkoutError) > 0 { 160 return fmt.Errorf(w.checkoutError) 161 } 162 w.checkoutOpts = opts 163 return nil 164 } 165 func (w *gitWorktreeMock) Commit(msg string, opts *git.CommitOptions) (plumbing.Hash, error) { 166 if len(w.commitError) > 0 { 167 return plumbing.Hash{}, fmt.Errorf(w.commitError) 168 } 169 w.commitMsg = msg 170 w.commitOpts = opts 171 return w.commitHash, nil 172 } 173 174 type artifactPrepareVersionMockUtils struct { 175 *mock.ExecMockRunner 176 *mock.FilesMock 177 } 178 179 func newArtifactPrepareVersionMockUtils() *artifactPrepareVersionMockUtils { 180 utils := artifactPrepareVersionMockUtils{ 181 ExecMockRunner: &mock.ExecMockRunner{}, 182 FilesMock: &mock.FilesMock{}, 183 } 184 return &utils 185 } 186 187 func (a *artifactPrepareVersionMockUtils) DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error { 188 // so far no dedicated logic required for testing 189 return nil 190 } 191 192 func (a *artifactPrepareVersionMockUtils) NewOrchestratorSpecificConfigProvider() (orchestrator.OrchestratorSpecificConfigProviding, error) { 193 return &orchestrator.UnknownOrchestratorConfigProvider{}, nil 194 } 195 196 func TestRunArtifactPrepareVersion(t *testing.T) { 197 198 t.Run("success case - cloud", func(t *testing.T) { 199 200 config := artifactPrepareVersionOptions{ 201 BuildTool: "maven", 202 IncludeCommitID: true, 203 Password: "****", 204 TagPrefix: "v", 205 Username: "testUser", 206 VersioningType: "cloud", 207 } 208 telemetryData := telemetry.CustomData{} 209 210 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 211 212 versioningMock := artifactVersioningMock{ 213 originalVersion: "1.2.3", 214 versioningScheme: "maven", 215 } 216 217 utils := newArtifactPrepareVersionMockUtils() 218 219 worktree := gitWorktreeMock{ 220 commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}), 221 } 222 223 conf := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"https://my.test.server"}} 224 225 repo := gitRepositoryMock{ 226 revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}), 227 remote: git.NewRemote(nil, &conf), 228 } 229 230 err := runArtifactPrepareVersion(&config, &telemetryData, &cpe, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 231 232 assert.NoError(t, err) 233 234 assert.Contains(t, versioningMock.newVersion, "1.2.3") 235 assert.Contains(t, versioningMock.newVersion, fmt.Sprintf("_%v", repo.revisionHash.String())) 236 237 assert.Equal(t, "HEAD", repo.revision) 238 assert.Contains(t, repo.tag, "v1.2.3") 239 assert.Equal(t, &git.CheckoutOptions{Hash: repo.revisionHash, Keep: true}, worktree.checkoutOpts) 240 assert.True(t, repo.pushCalled) 241 242 assert.Contains(t, cpe.artifactVersion, "1.2.3") 243 assert.Contains(t, cpe.originalArtifactVersion, "1.2.3") 244 assert.Equal(t, worktree.commitHash.String(), cpe.git.commitID) 245 assert.Equal(t, "Test commit message", cpe.git.commitMessage) 246 247 assert.Equal(t, telemetry.CustomData{Custom1Label: "buildTool", Custom1: "maven", Custom2Label: "filePath", Custom2: ""}, telemetryData) 248 }) 249 250 t.Run("success case - cloud_noTag", func(t *testing.T) { 251 252 config := artifactPrepareVersionOptions{ 253 BuildTool: "maven", 254 IncludeCommitID: true, 255 Password: "****", 256 TagPrefix: "v", 257 Username: "testUser", 258 VersioningType: "cloud_noTag", 259 } 260 telemetryData := telemetry.CustomData{} 261 262 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 263 264 versioningMock := artifactVersioningMock{ 265 originalVersion: "1.2.3", 266 versioningScheme: "maven", 267 } 268 269 utils := newArtifactPrepareVersionMockUtils() 270 271 worktree := gitWorktreeMock{ 272 commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}), 273 } 274 275 conf := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"https://my.test.server"}} 276 277 repo := gitRepositoryMock{ 278 revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}), 279 remote: git.NewRemote(nil, &conf), 280 } 281 282 err := runArtifactPrepareVersion(&config, &telemetryData, &cpe, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 283 284 assert.NoError(t, err) 285 286 assert.False(t, repo.pushCalled) 287 assert.Contains(t, cpe.artifactVersion, "1.2.3") 288 assert.Contains(t, cpe.originalArtifactVersion, "1.2.3") 289 assert.Equal(t, repo.revisionHash.String(), cpe.git.commitID) 290 }) 291 292 t.Run("success case - compatibility", func(t *testing.T) { 293 config := artifactPrepareVersionOptions{ 294 BuildTool: "maven", 295 VersioningType: "cloud", 296 VersioningTemplate: "${version}", 297 } 298 299 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 300 301 versioningMock := artifactVersioningMock{ 302 originalVersion: "1.2.3", 303 versioningScheme: "maven", 304 } 305 306 worktree := gitWorktreeMock{} 307 repo := gitRepositoryMock{} 308 309 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 310 311 assert.NoError(t, err) 312 assert.Equal(t, "1.2.3", cpe.artifactVersion) 313 }) 314 315 t.Run("success case - library", func(t *testing.T) { 316 config := artifactPrepareVersionOptions{ 317 BuildTool: "maven", 318 VersioningType: "library", 319 } 320 321 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 322 323 versioningMock := artifactVersioningMock{ 324 originalVersion: "1.2.3", 325 versioningScheme: "maven", 326 } 327 328 worktree := gitWorktreeMock{ 329 commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}), 330 } 331 repo := gitRepositoryMock{ 332 revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}), 333 } 334 335 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 336 337 assert.NoError(t, err) 338 assert.Equal(t, "1.2.3", cpe.artifactVersion) 339 assert.Equal(t, repo.revisionHash.String(), cpe.git.commitID) 340 }) 341 342 t.Run("success case - coordinates", func(t *testing.T) { 343 config := artifactPrepareVersionOptions{ 344 BuildTool: "maven", 345 VersioningType: "library", 346 FetchCoordinates: true, 347 } 348 349 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 350 351 versioningMock := artifactVersioningMock{ 352 originalVersion: "1.2.3", 353 versioningScheme: "maven", 354 coordinates: versioning.Coordinates{GroupID: "my.testGroup", ArtifactID: "testArtifact", Packaging: "testPackaging"}, 355 } 356 357 worktree := gitWorktreeMock{ 358 commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}), 359 } 360 repo := gitRepositoryMock{ 361 revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}), 362 } 363 364 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, nil, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 365 366 assert.NoError(t, err) 367 assert.Equal(t, "testArtifact", cpe.artifactID) 368 assert.Equal(t, "my.testGroup", cpe.groupID) 369 assert.Equal(t, "testPackaging", cpe.packaging) 370 }) 371 372 t.Run("error - failed to retrieve version", func(t *testing.T) { 373 config := artifactPrepareVersionOptions{} 374 375 versioningMock := artifactVersioningMock{ 376 getVersionError: "getVersion error", 377 } 378 379 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, nil, nil) 380 assert.EqualError(t, err, "failed to retrieve version: getVersion error") 381 382 }) 383 384 t.Run("error - failed to retrieve git commit ID", func(t *testing.T) { 385 config := artifactPrepareVersionOptions{} 386 387 versioningMock := artifactVersioningMock{ 388 originalVersion: "1.2.3", 389 versioningScheme: "maven", 390 } 391 392 repo := gitRepositoryMock{revisionError: "revision error"} 393 394 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, nil, &versioningMock, nil, &repo, nil) 395 assert.EqualError(t, err, "failed to retrieve git commit ID: revision error") 396 }) 397 398 t.Run("error - versioning template", func(t *testing.T) { 399 config := artifactPrepareVersionOptions{ 400 VersioningType: "cloud", 401 } 402 403 versioningMock := artifactVersioningMock{ 404 originalVersion: "1.2.3", 405 versioningScheme: "notSupported", 406 } 407 408 utils := newArtifactPrepareVersionMockUtils() 409 410 repo := gitRepositoryMock{} 411 412 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &artifactPrepareVersionCommonPipelineEnvironment{}, &versioningMock, utils, &repo, nil) 413 assert.Contains(t, fmt.Sprint(err), "failed to get versioning template for scheme 'notSupported'") 414 }) 415 416 t.Run("error - failed to retrieve git worktree", func(t *testing.T) { 417 config := artifactPrepareVersionOptions{ 418 VersioningType: "cloud", 419 } 420 421 versioningMock := artifactVersioningMock{ 422 originalVersion: "1.2.3", 423 versioningScheme: "maven", 424 } 425 426 utils := newArtifactPrepareVersionMockUtils() 427 428 repo := gitRepositoryMock{} 429 430 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &artifactPrepareVersionCommonPipelineEnvironment{}, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return nil, fmt.Errorf("worktree error") }) 431 assert.EqualError(t, err, "failed to retrieve git worktree: worktree error") 432 }) 433 434 t.Run("error - failed to initialize git worktree: ", func(t *testing.T) { 435 config := artifactPrepareVersionOptions{ 436 VersioningType: "cloud", 437 } 438 439 versioningMock := artifactVersioningMock{ 440 originalVersion: "1.2.3", 441 versioningScheme: "maven", 442 } 443 444 utils := newArtifactPrepareVersionMockUtils() 445 446 worktree := gitWorktreeMock{checkoutError: "checkout error"} 447 repo := gitRepositoryMock{} 448 449 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &artifactPrepareVersionCommonPipelineEnvironment{}, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 450 assert.EqualError(t, err, "failed to initialize worktree: checkout error") 451 }) 452 453 t.Run("error - failed to set version", func(t *testing.T) { 454 config := artifactPrepareVersionOptions{ 455 VersioningType: "cloud", 456 } 457 458 versioningMock := artifactVersioningMock{ 459 originalVersion: "1.2.3", 460 setVersionError: "setVersion error", 461 versioningScheme: "maven", 462 } 463 464 utils := newArtifactPrepareVersionMockUtils() 465 466 worktree := gitWorktreeMock{} 467 repo := gitRepositoryMock{} 468 469 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &artifactPrepareVersionCommonPipelineEnvironment{}, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 470 assert.EqualError(t, err, "failed to write version: setVersion error") 471 }) 472 473 t.Run("error - failed to push changes", func(t *testing.T) { 474 config := artifactPrepareVersionOptions{ 475 VersioningType: "cloud", 476 } 477 478 versioningMock := artifactVersioningMock{ 479 originalVersion: "1.2.3", 480 versioningScheme: "maven", 481 } 482 483 utils := newArtifactPrepareVersionMockUtils() 484 485 worktree := gitWorktreeMock{} 486 repo := gitRepositoryMock{} 487 488 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &artifactPrepareVersionCommonPipelineEnvironment{}, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 489 assert.Contains(t, fmt.Sprint(err), "failed to push changes for version '1.2.3") 490 }) 491 492 t.Run("error - failed to get coordinates", func(t *testing.T) { 493 config := artifactPrepareVersionOptions{ 494 BuildTool: "maven", 495 VersioningType: "library", 496 FetchCoordinates: true, 497 } 498 499 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 500 501 versioningMock := artifactVersioningMock{ 502 originalVersion: "1.2.3", 503 versioningScheme: "maven", 504 coordinatesError: fmt.Errorf("coordinatesError"), 505 } 506 507 utils := newArtifactPrepareVersionMockUtils() 508 509 worktree := gitWorktreeMock{ 510 commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}), 511 } 512 repo := gitRepositoryMock{ 513 revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}), 514 } 515 516 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 517 518 assert.EqualError(t, err, "failed to get coordinates: coordinatesError") 519 }) 520 521 t.Run("warning - failed to get coordinates", func(t *testing.T) { 522 config := artifactPrepareVersionOptions{ 523 BuildTool: "maven", 524 VersioningType: "library", 525 FetchCoordinates: false, 526 } 527 528 cpe := artifactPrepareVersionCommonPipelineEnvironment{} 529 530 versioningMock := artifactVersioningMock{ 531 originalVersion: "1.2.3", 532 versioningScheme: "maven", 533 coordinatesError: fmt.Errorf("coordinatesError"), 534 } 535 536 utils := newArtifactPrepareVersionMockUtils() 537 538 worktree := gitWorktreeMock{ 539 commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{2, 3, 4}), 540 } 541 repo := gitRepositoryMock{ 542 revisionHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}), 543 } 544 545 err := runArtifactPrepareVersion(&config, &telemetry.CustomData{}, &cpe, &versioningMock, utils, &repo, func(r gitRepository) (gitWorktree, error) { return &worktree, nil }) 546 547 assert.NoError(t, err) 548 }) 549 } 550 551 func TestVersioningTemplate(t *testing.T) { 552 tt := []struct { 553 scheme string 554 expected string 555 expectedErr string 556 }{ 557 {scheme: "maven", expected: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}_{{.CommitID}}{{end}}{{end}}"}, 558 {scheme: "semver2", expected: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}"}, 559 {scheme: "pep440", expected: "{{.Version}}{{if .Timestamp}}.{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}"}, 560 {scheme: "notSupported", expected: "", expectedErr: "versioning scheme 'notSupported' not supported"}, 561 } 562 563 for _, test := range tt { 564 scheme, err := versioningTemplate(test.scheme) 565 assert.Equal(t, test.expected, scheme) 566 if len(test.expectedErr) == 0 { 567 assert.NoError(t, err) 568 } else { 569 assert.EqualError(t, err, test.expectedErr) 570 } 571 } 572 } 573 574 func TestCalculateNewVersion(t *testing.T) { 575 576 currentVersion := "1.2.3" 577 testTime := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) 578 579 commitID := plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3}).String() 580 581 tt := []struct { 582 versioningTemplate string 583 includeCommitID bool 584 shortCommitID bool 585 unixTimestamp bool 586 expected string 587 expectedErr string 588 }{ 589 {versioningTemplate: "", expectedErr: "failed calculate version, new version is ''"}, 590 {versioningTemplate: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", expected: "1.2.3-20200101000000"}, 591 {versioningTemplate: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", includeCommitID: true, expected: "1.2.3-20200101000000+428ecf70bc22df0ba3dcf194b5ce53e769abab07"}, 592 {versioningTemplate: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", includeCommitID: true, shortCommitID: true, expected: "1.2.3-20200101000000+428ecf7"}, 593 {versioningTemplate: "{{.Version}}{{if .Timestamp}}-{{.Timestamp}}{{if .CommitID}}+{{.CommitID}}{{end}}{{end}}", includeCommitID: true, unixTimestamp: true, expected: "1.2.3-1577836800+428ecf70bc22df0ba3dcf194b5ce53e769abab07"}, 594 } 595 596 for _, test := range tt { 597 version, err := calculateNewVersion(test.versioningTemplate, currentVersion, commitID, test.includeCommitID, test.shortCommitID, test.unixTimestamp, testTime) 598 assert.Equal(t, test.expected, version) 599 if len(test.expectedErr) == 0 { 600 assert.NoError(t, err) 601 } else { 602 assert.EqualError(t, err, test.expectedErr) 603 } 604 } 605 } 606 607 func TestPushChanges(t *testing.T) { 608 609 newVersion := "1.2.3" 610 testTime := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) 611 612 conf := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"https://my.test.server"}} 613 remote := git.NewRemote(nil, &conf) 614 615 t.Run("success - username/password", func(t *testing.T) { 616 config := artifactPrepareVersionOptions{Username: "testUser", Password: "****", CommitUserName: "Project Piper"} 617 repo := gitRepositoryMock{remote: remote} 618 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 619 620 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 621 assert.NoError(t, err) 622 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 623 assert.Equal(t, "update version 1.2.3", worktree.commitMsg) 624 assert.Equal(t, &git.CommitOptions{All: true, Author: &object.Signature{Name: "Project Piper", When: testTime}}, worktree.commitOpts) 625 assert.Equal(t, "1.2.3", repo.tag) 626 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", repo.tagHash.String()) 627 assert.Equal(t, &git.PushOptions{RefSpecs: []gitConfig.RefSpec{"refs/tags/1.2.3:refs/tags/1.2.3"}, Auth: &gitHttp.BasicAuth{Username: config.Username, Password: config.Password}}, repo.pushOptions) 628 }) 629 630 t.Run("success - ssh fallback", func(t *testing.T) { 631 config := artifactPrepareVersionOptions{CommitUserName: "Project Piper"} 632 repo := gitRepositoryMock{remote: remote} 633 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 634 635 originalSSHAgentAuth := sshAgentAuth 636 sshAgentAuth = func(u string) (*ssh.PublicKeysCallback, error) { return &ssh.PublicKeysCallback{}, nil } 637 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 638 sshAgentAuth = originalSSHAgentAuth 639 640 assert.NoError(t, err) 641 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 642 assert.Equal(t, "update version 1.2.3", worktree.commitMsg) 643 assert.Equal(t, &git.CommitOptions{All: true, Author: &object.Signature{Name: "Project Piper", When: testTime}}, worktree.commitOpts) 644 assert.Equal(t, "1.2.3", repo.tag) 645 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", repo.tagHash.String()) 646 assert.Equal(t, &git.PushOptions{RefSpecs: []gitConfig.RefSpec{"refs/tags/1.2.3:refs/tags/1.2.3"}, Auth: &ssh.PublicKeysCallback{}}, repo.pushOptions) 647 }) 648 649 t.Run("success - ssh", func(t *testing.T) { 650 confSSH := gitConfig.RemoteConfig{Name: "origin", URLs: []string{"git@my.test.server"}} 651 remoteSSH := git.NewRemote(nil, &confSSH) 652 653 config := artifactPrepareVersionOptions{} 654 repo := gitRepositoryMock{remote: remoteSSH} 655 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 656 657 originalSSHAgentAuth := sshAgentAuth 658 sshAgentAuth = func(u string) (*ssh.PublicKeysCallback, error) { return &ssh.PublicKeysCallback{}, nil } 659 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 660 sshAgentAuth = originalSSHAgentAuth 661 662 assert.NoError(t, err) 663 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 664 assert.Equal(t, &git.PushOptions{RefSpecs: []gitConfig.RefSpec{"refs/tags/1.2.3:refs/tags/1.2.3"}, Auth: &ssh.PublicKeysCallback{}}, repo.pushOptions) 665 }) 666 667 t.Run("error - commit", func(t *testing.T) { 668 config := artifactPrepareVersionOptions{} 669 repo := gitRepositoryMock{} 670 worktree := gitWorktreeMock{commitError: "commit error", commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 671 672 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 673 assert.Equal(t, "0000000000000000000000000000000000000000", commitID) 674 assert.EqualError(t, err, "failed to commit new version: commit error") 675 }) 676 677 t.Run("error - create tag", func(t *testing.T) { 678 config := artifactPrepareVersionOptions{} 679 repo := gitRepositoryMock{tagError: "tag error"} 680 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 681 682 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 683 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 684 assert.EqualError(t, err, "tag error") 685 }) 686 687 t.Run("error - no remote url", func(t *testing.T) { 688 config := artifactPrepareVersionOptions{} 689 repo := gitRepositoryMock{} 690 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 691 692 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 693 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 694 assert.EqualError(t, err, "no remote url maintained") 695 }) 696 697 t.Run("error - ssh fallback", func(t *testing.T) { 698 699 config := artifactPrepareVersionOptions{} 700 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 701 702 sshSuccess := func(u string) (*ssh.PublicKeysCallback, error) { return nil, nil } 703 sshFailure := func(u string) (*ssh.PublicKeysCallback, error) { return nil, fmt.Errorf("ssh error") } 704 705 tt := []struct { 706 repo gitRepositoryMock 707 sshAgentAuth func(string) (*ssh.PublicKeysCallback, error) 708 expectedError string 709 }{ 710 {repo: gitRepositoryMock{remote: remote, deleteRemoteError: []string{"delete error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to update remote origin - remove: delete error"}, 711 {repo: gitRepositoryMock{remote: remote, createRemoteError: []string{"update error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to update remote origin - create: update error"}, 712 {repo: gitRepositoryMock{remote: remote}, sshAgentAuth: sshFailure, expectedError: "failed to retrieve ssh authentication: ssh error"}, 713 {repo: gitRepositoryMock{remote: remote, deleteRemoteError: []string{"", "delete error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to restore remote origin - remove: delete error"}, 714 {repo: gitRepositoryMock{remote: remote, createRemoteError: []string{"", "update error"}}, sshAgentAuth: sshSuccess, expectedError: "failed to restore remote origin - create: update error"}, 715 } 716 717 originalSSHAgentAuth := sshAgentAuth 718 719 for _, test := range tt { 720 sshAgentAuth = test.sshAgentAuth 721 commitID, err := pushChanges(&config, newVersion, &test.repo, &worktree, testTime) 722 sshAgentAuth = originalSSHAgentAuth 723 724 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 725 assert.EqualError(t, err, test.expectedError) 726 } 727 }) 728 729 t.Run("error - push", func(t *testing.T) { 730 config := artifactPrepareVersionOptions{Username: "testUser", Password: "****"} 731 repo := gitRepositoryMock{remote: remote, pushError: "push error"} 732 worktree := gitWorktreeMock{commitHash: plumbing.ComputeHash(plumbing.CommitObject, []byte{1, 2, 3})} 733 734 commitID, err := pushChanges(&config, newVersion, &repo, &worktree, testTime) 735 assert.Equal(t, "428ecf70bc22df0ba3dcf194b5ce53e769abab07", commitID) 736 assert.EqualError(t, err, "push error") 737 }) 738 } 739 740 func TestTemplateCompatibility(t *testing.T) { 741 tt := []struct { 742 groovy string 743 versioningType string 744 timestamp bool 745 commitID bool 746 }{ 747 {groovy: `${version}`, versioningType: "library", timestamp: false, commitID: false}, 748 {groovy: `${version}-${timestamp}`, versioningType: "cloud", timestamp: true, commitID: false}, 749 {groovy: `${version}-${timestamp}${commitId?"_"+commitId:""`, versioningType: "cloud", timestamp: true, commitID: true}, 750 } 751 752 for _, test := range tt { 753 versioningType, timestamp, commitID := templateCompatibility(test.groovy) 754 assert.Equal(t, test.versioningType, versioningType) 755 assert.Equal(t, test.timestamp, timestamp) 756 assert.Equal(t, test.commitID, commitID) 757 } 758 } 759 760 func TestConvertHTTPToSSHURL(t *testing.T) { 761 tt := []struct { 762 httpURL string 763 expected string 764 }{ 765 {httpURL: "https://my.test.server/owner/repo.git", expected: "git@my.test.server:owner/repo.git"}, 766 } 767 768 for _, test := range tt { 769 assert.Equal(t, test.expected, convertHTTPToSSHURL(test.httpURL)) 770 } 771 } 772 773 func TestPropagateVersion(t *testing.T) { 774 t.Parallel() 775 776 gitCommitID := "theGitCommitId" 777 testTime := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) //20200101000000 778 779 t.Run("success case", func(t *testing.T) { 780 config := artifactPrepareVersionOptions{ 781 VersioningType: "cloud", 782 AdditionalTargetTools: []string{"helm"}, 783 } 784 785 chartMetadata := chart.Metadata{Version: "1.2.3"} 786 content, err := yaml.Marshal(chartMetadata) 787 assert.NoError(t, err) 788 789 utils := newArtifactPrepareVersionMockUtils() 790 utils.AddFile("myChart/Chart.yaml", content) 791 artifactOpts := versioning.Options{} 792 793 err = propagateVersion(&config, utils, &artifactOpts, "1.2.4", gitCommitID, testTime) 794 assert.NoError(t, err) 795 }) 796 797 t.Run("success case - dedicated build descriptors", func(t *testing.T) { 798 config := artifactPrepareVersionOptions{ 799 VersioningType: "cloud", 800 AdditionalTargetTools: []string{"helm"}, 801 AdditionalTargetDescriptors: []string{"myChart/Chart.yaml"}, 802 } 803 804 chartMetadata := chart.Metadata{Version: "1.2.3"} 805 content, err := yaml.Marshal(chartMetadata) 806 assert.NoError(t, err) 807 808 utils := newArtifactPrepareVersionMockUtils() 809 utils.AddFile("myChart/Chart.yaml", content) 810 artifactOpts := versioning.Options{} 811 812 err = propagateVersion(&config, utils, &artifactOpts, "1.2.4", gitCommitID, testTime) 813 assert.NoError(t, err) 814 }) 815 816 t.Run("success case - noop", func(t *testing.T) { 817 config := artifactPrepareVersionOptions{} 818 utils := newArtifactPrepareVersionMockUtils() 819 artifactOpts := versioning.Options{} 820 821 err := propagateVersion(&config, utils, &artifactOpts, "1.2.4", gitCommitID, testTime) 822 assert.NoError(t, err) 823 }) 824 825 t.Run("error case - wrong config", func(t *testing.T) { 826 config := artifactPrepareVersionOptions{ 827 AdditionalTargetDescriptors: []string{"pom.xml"}, 828 AdditionalTargetTools: []string{"maven", "helm"}, 829 } 830 utils := newArtifactPrepareVersionMockUtils() 831 artifactOpts := versioning.Options{} 832 833 err := propagateVersion(&config, utils, &artifactOpts, "1.2.4", gitCommitID, testTime) 834 assert.EqualError(t, err, "additionalTargetDescriptors cannot have a different number of entries than additionalTargetTools") 835 }) 836 837 t.Run("error case - wrong target tool", func(t *testing.T) { 838 config := artifactPrepareVersionOptions{ 839 AdditionalTargetTools: []string{"notKnown"}, 840 } 841 utils := newArtifactPrepareVersionMockUtils() 842 artifactOpts := versioning.Options{} 843 844 err := propagateVersion(&config, utils, &artifactOpts, "1.2.4", gitCommitID, testTime) 845 assert.Contains(t, fmt.Sprint(err), "failed to retrieve artifact") 846 }) 847 }