github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/activity_test.go (about)

     1  // +build unit
     2  
     3  package kube_test
     4  
     5  import (
     6  	"fmt"
     7  	"strconv"
     8  	"testing"
     9  	"time"
    10  
    11  	jenkinsio_v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1"
    12  	v1 "github.com/jenkins-x/jx-api/pkg/apis/jenkins.io/v1"
    13  	jxfake "github.com/jenkins-x/jx-api/pkg/client/clientset/versioned/fake"
    14  	"github.com/jenkins-x/jx/v2/pkg/cmd/testhelpers"
    15  	"github.com/jenkins-x/jx/v2/pkg/gits"
    16  	appsv1 "k8s.io/api/apps/v1"
    17  	k8s_v1 "k8s.io/api/core/v1"
    18  
    19  	typev1 "github.com/jenkins-x/jx-api/pkg/client/clientset/versioned/typed/jenkins.io/v1"
    20  	"github.com/jenkins-x/jx/v2/pkg/cmd/clients"
    21  	"github.com/jenkins-x/jx/v2/pkg/cmd/opts"
    22  	"github.com/jenkins-x/jx/v2/pkg/kube"
    23  	"github.com/stretchr/testify/assert"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	kube_mocks "k8s.io/client-go/kubernetes/fake"
    26  )
    27  
    28  func TestGenerateBuildNumber(t *testing.T) {
    29  	commonOpts := opts.NewCommonOptionsWithFactory(clients.NewFactory())
    30  	options := &commonOpts
    31  	testhelpers.ConfigureTestOptions(options, options.Git(), options.Helm())
    32  
    33  	jxClient, ns, err := options.JXClientAndDevNamespace()
    34  	assert.NoError(t, err, "Creating JX client")
    35  	if err != nil {
    36  		return
    37  	}
    38  
    39  	activities := jxClient.JenkinsV1().PipelineActivities(ns)
    40  
    41  	org := "jstrachan"
    42  	repo := "cheese"
    43  	branch := "master"
    44  
    45  	results := []string{}
    46  	expected := []string{}
    47  	for i := 1; i < 4; i++ {
    48  		buildNumberText := strconv.Itoa(i)
    49  		pID := kube.NewPipelineID(repo, org, branch)
    50  		pipelines := getPipelines(activities)
    51  		build, activity, err := kube.GenerateBuildNumber(activities, pipelines, pID)
    52  		if assert.NoError(t, err, "GenerateBuildNumber %d", i) {
    53  			if assert.NotNil(t, activity, "No PipelineActivity returned!") {
    54  				results = append(results, build)
    55  				assert.Equal(t, buildNumberText, activity.Spec.Build, "Build number for PipelineActivity %s", activity.Name)
    56  			}
    57  		}
    58  		expected = append(expected, buildNumberText)
    59  	}
    60  	assert.Equal(t, expected, results, "generated build numbers")
    61  }
    62  
    63  func getPipelines(activities typev1.PipelineActivityInterface) []*v1.PipelineActivity {
    64  	pipelineList, _ := activities.List(metav1.ListOptions{})
    65  	pipelines := []*v1.PipelineActivity{}
    66  	for _, pipeline := range pipelineList.Items {
    67  		copy := pipeline
    68  		pipelines = append(pipelines, &copy)
    69  	}
    70  	return pipelines
    71  }
    72  
    73  func TestCreateOrUpdateActivities(t *testing.T) {
    74  	t.Parallel()
    75  
    76  	nsObj := &k8s_v1.Namespace{
    77  		ObjectMeta: metav1.ObjectMeta{
    78  			Name:      "jx-testing",
    79  			Namespace: "testing_ns",
    80  		},
    81  	}
    82  
    83  	secret := &k8s_v1.Secret{}
    84  	mockKubeClient := kube_mocks.NewSimpleClientset(nsObj, secret)
    85  
    86  	ingressConfig := &k8s_v1.ConfigMap{
    87  		ObjectMeta: metav1.ObjectMeta{
    88  			Name: kube.ConfigMapIngressConfig,
    89  		},
    90  		Data: map[string]string{"key1": "value1", "domain": "test-domain", "config.yml": ""},
    91  	}
    92  
    93  	mockKubeClient.CoreV1().ConfigMaps(nsObj.Namespace).Create(ingressConfig)
    94  	mockTektonDeployment := &appsv1.Deployment{
    95  		ObjectMeta: metav1.ObjectMeta{
    96  			Name: kube.DeploymentTektonController,
    97  		},
    98  	}
    99  	mockKubeClient.AppsV1().Deployments(nsObj.Namespace).Create(mockTektonDeployment)
   100  	jxClient := jxfake.NewSimpleClientset()
   101  
   102  	const (
   103  		expectedName         = "demo-2"
   104  		expectedBuild        = "2"
   105  		expectedEnvironment  = "staging"
   106  		expectedOrganisation = "test-org"
   107  	)
   108  	expectedPipeline := expectedOrganisation + "/" + expectedName + "/master"
   109  
   110  	key := kube.PipelineActivityKey{
   111  		Name:     expectedName,
   112  		Pipeline: expectedPipeline,
   113  		Build:    expectedBuild,
   114  		GitInfo: &gits.GitRepository{
   115  			Name:         expectedName,
   116  			Organisation: expectedOrganisation,
   117  			URL:          "https://github.com/" + expectedOrganisation + "/" + expectedName,
   118  		},
   119  	}
   120  
   121  	for i := 1; i < 3; i++ {
   122  		a, _, err := key.GetOrCreate(jxClient, nsObj.Namespace)
   123  		assert.Nil(t, err)
   124  		assert.Equal(t, expectedName, a.Name)
   125  		spec := &a.Spec
   126  		assert.Equal(t, expectedPipeline, spec.Pipeline)
   127  		assert.Equal(t, expectedBuild, spec.Build)
   128  	}
   129  
   130  	// lazy add a PromotePullRequest
   131  	promoteKey := kube.PromoteStepActivityKey{
   132  		PipelineActivityKey: key,
   133  		Environment:         expectedEnvironment,
   134  	}
   135  
   136  	promotePullRequestStarted := func(a *v1.PipelineActivity, s *v1.PipelineActivityStep, ps *v1.PromoteActivityStep, p *v1.PromotePullRequestStep) error {
   137  		assert.NotNil(t, a)
   138  		assert.NotNil(t, p)
   139  		if p.StartedTimestamp == nil {
   140  			p.StartedTimestamp = &metav1.Time{
   141  				Time: time.Now(),
   142  			}
   143  		}
   144  		return nil
   145  	}
   146  
   147  	err := promoteKey.OnPromotePullRequest(mockKubeClient, jxClient, nsObj.Namespace, promotePullRequestStarted)
   148  	assert.Nil(t, err)
   149  
   150  	promoteStarted := func(a *v1.PipelineActivity, s *v1.PipelineActivityStep, ps *v1.PromoteActivityStep, p *v1.PromoteUpdateStep) error {
   151  		assert.NotNil(t, a)
   152  		assert.NotNil(t, p)
   153  		kube.CompletePromotionUpdate(a, s, ps, p)
   154  		return nil
   155  	}
   156  
   157  	err = promoteKey.OnPromoteUpdate(mockKubeClient, jxClient, nsObj.Namespace, promoteStarted)
   158  	assert.Nil(t, err)
   159  
   160  	// lets validate that we added a PromotePullRequest step
   161  	a, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Get(expectedName, metav1.GetOptions{})
   162  	assert.NotNil(t, a, "should have a PipelineActivity for %s", expectedName)
   163  	steps := a.Spec.Steps
   164  	assert.Equal(t, 2, len(steps), "Should have 2 steps!")
   165  	step := a.Spec.Steps[0]
   166  	stage := step.Stage
   167  	assert.NotNil(t, stage, "step 0 should have a Stage")
   168  	assert.Equal(t, v1.ActivityStepKindTypeStage, step.Kind, "step - kind")
   169  	assert.Equal(t, v1.ActivityStatusTypeSucceeded, stage.Status, "step 0 Stage status")
   170  	assert.NotNil(t, stage.StartedTimestamp, "stage should have a StartedTimestamp")
   171  	assert.NotNil(t, stage.CompletedTimestamp, "stage should have a CompletedTimestamp")
   172  
   173  	step = a.Spec.Steps[1]
   174  	promote := step.Promote
   175  	assert.NotNil(t, promote, "step 1 should have a Promote")
   176  	assert.Equal(t, v1.ActivityStepKindTypePromote, step.Kind, "step 1 kind")
   177  
   178  	pullRequestStep := promote.PullRequest
   179  	assert.NotNil(t, pullRequestStep, "Promote should have a PullRequest")
   180  	assert.NotNil(t, pullRequestStep.StartedTimestamp, "Promote should have a PullRequest.StartedTimestamp")
   181  	assert.NotNil(t, pullRequestStep.CompletedTimestamp, "Promote should not have a PullRequest.CompletedTimestamp")
   182  
   183  	updateStep := promote.Update
   184  	assert.NotNil(t, updateStep, "Promote should have an Update")
   185  	assert.NotNil(t, updateStep.StartedTimestamp, "Promote should have a Update.StartedTimestamp")
   186  	assert.NotNil(t, updateStep.CompletedTimestamp, "Promote should have a Update.CompletedTimestamp")
   187  
   188  	assert.NotNil(t, promote.StartedTimestamp, "promote should have a StartedTimestamp")
   189  	assert.NotNil(t, promote.CompletedTimestamp, "promote should have a CompletedTimestamp")
   190  
   191  	assert.Equal(t, v1.ActivityStatusTypeSucceeded, pullRequestStep.Status, "pullRequestStep status")
   192  	assert.Equal(t, v1.ActivityStatusTypeSucceeded, updateStep.Status, "updateStep status")
   193  	assert.Equal(t, v1.ActivityStatusTypeSucceeded, promote.Status, "promote status")
   194  	assert.Equal(t, v1.ActivityStatusTypeSucceeded, a.Spec.Status, "activity status")
   195  
   196  	//tests.Debugf("Has Promote %#v\n", promote)
   197  }
   198  
   199  func TestCreateOrUpdateActivityForBatchBuild(t *testing.T) {
   200  	t.Parallel()
   201  
   202  	nsObj := &k8s_v1.Namespace{
   203  		ObjectMeta: metav1.ObjectMeta{
   204  			Name:      "jx-testing",
   205  			Namespace: "testing_ns",
   206  		},
   207  	}
   208  
   209  	jxClient := jxfake.NewSimpleClientset()
   210  
   211  	const (
   212  		expectedName         = "demo-2"
   213  		expectedBuild        = "2"
   214  		expectedOrganisation = "test-org"
   215  	)
   216  	expectedPipeline := expectedOrganisation + "/" + expectedName + "/master"
   217  
   218  	key := kube.PipelineActivityKey{
   219  		Name:     expectedName,
   220  		Pipeline: expectedPipeline,
   221  		Build:    expectedBuild,
   222  		GitInfo: &gits.GitRepository{
   223  			Name:         expectedName,
   224  			Organisation: expectedOrganisation,
   225  			URL:          "https://github.com/" + expectedOrganisation + "/" + expectedName,
   226  		},
   227  		PullRefs: map[string]string{
   228  			"1": "sha1",
   229  			"2": "sha2",
   230  		},
   231  	}
   232  
   233  	_, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Create(&v1.PipelineActivity{
   234  		ObjectMeta: metav1.ObjectMeta{
   235  			Name: "PA0",
   236  			Labels: map[string]string{
   237  				"lastCommitSha": "sha1",
   238  				"branch":        "PR-1",
   239  			},
   240  		},
   241  		Spec: v1.PipelineActivitySpec{
   242  			Build: "1",
   243  		},
   244  	})
   245  	assert.NoError(t, err)
   246  
   247  	// lets create a build PA for the same PR but with a different SHA so we can check we discard it later
   248  	_, err = jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Create(&v1.PipelineActivity{
   249  		ObjectMeta: metav1.ObjectMeta{
   250  			Name: "PA0-2",
   251  			Labels: map[string]string{
   252  				"lastCommitSha": "sha3",
   253  				"branch":        "PR-1",
   254  			},
   255  		},
   256  		Spec: v1.PipelineActivitySpec{
   257  			Build: "5",
   258  		},
   259  	})
   260  	assert.NoError(t, err)
   261  
   262  	//lets create a few "builds" for PR-2 with the same SHA so we can check if we choose the right one
   263  	for i := 1; i < 4; i++ {
   264  		_, err = jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Create(&v1.PipelineActivity{
   265  			ObjectMeta: metav1.ObjectMeta{
   266  				Name: fmt.Sprintf("PA%d", i),
   267  				Labels: map[string]string{
   268  					"lastCommitSha": "sha2",
   269  					"branch":        "PR-2",
   270  				},
   271  			},
   272  			Spec: v1.PipelineActivitySpec{
   273  				Build: strconv.Itoa(i),
   274  			},
   275  		})
   276  		assert.NoError(t, err)
   277  	}
   278  
   279  	a, _, err := key.GetOrCreate(jxClient, nsObj.Namespace)
   280  	assert.Nil(t, err)
   281  	assert.Equal(t, expectedName, a.Name)
   282  	spec := &a.Spec
   283  	assert.Equal(t, expectedPipeline, spec.Pipeline)
   284  	assert.Equal(t, expectedBuild, spec.Build)
   285  
   286  	pa1, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Get("PA0", metav1.GetOptions{})
   287  	assert.NoError(t, err)
   288  
   289  	pa3, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Get("PA3", metav1.GetOptions{})
   290  	assert.NoError(t, err)
   291  
   292  	assert.Len(t, a.Spec.BatchPipelineActivity.ComprisingPulLRequests, 2, "There should be %d PRs information in the ComprisingPullRequests property", 2)
   293  	exists := false
   294  	for _, i := range a.Spec.BatchPipelineActivity.ComprisingPulLRequests {
   295  		if i.PullRequestNumber == "PR-1" {
   296  			assert.NotEqual(t, "5", i.LastBuildNumberForCommit)
   297  		}
   298  		if i.PullRequestNumber == "PR-2" {
   299  			exists = true
   300  			assert.Equal(t, "3", i.LastBuildNumberForCommit)
   301  			assert.Equal(t, "sha2", i.LastBuildSHA)
   302  		}
   303  	}
   304  	assert.True(t, exists, "There should be a Pull Request called PR-2 within the ComprisingPullRequests property")
   305  	assert.Equal(t, expectedBuild, pa1.Spec.BatchPipelineActivity.BatchBuildNumber, "The batch build number that is going to merge this PR should be %s", expectedBuild)
   306  	assert.Equal(t, expectedBuild, pa3.Spec.BatchPipelineActivity.BatchBuildNumber, "The batch build number that is going to merge this PR should be %s", expectedBuild)
   307  }
   308  
   309  func TestCreateOrUpdateActivityForBatchBuildWithoutExistingActivities(t *testing.T) {
   310  	t.Parallel()
   311  
   312  	nsObj := &k8s_v1.Namespace{
   313  		ObjectMeta: metav1.ObjectMeta{
   314  			Name:      "jx-testing",
   315  			Namespace: "testing_ns",
   316  		},
   317  	}
   318  
   319  	jxClient := jxfake.NewSimpleClientset()
   320  
   321  	const (
   322  		expectedName         = "demo-2"
   323  		expectedBuild        = "2"
   324  		expectedOrganisation = "test-org"
   325  	)
   326  	expectedPipeline := expectedOrganisation + "/" + expectedName + "/master"
   327  
   328  	key := kube.PipelineActivityKey{
   329  		Name:     expectedName,
   330  		Pipeline: expectedPipeline,
   331  		Build:    expectedBuild,
   332  		GitInfo: &gits.GitRepository{
   333  			Name:         expectedName,
   334  			Organisation: expectedOrganisation,
   335  			URL:          "https://github.com/" + expectedOrganisation + "/" + expectedName,
   336  		},
   337  		PullRefs: map[string]string{
   338  			"1": "sha1",
   339  			"2": "sha2",
   340  		},
   341  	}
   342  
   343  	//lets create a few "builds" for PR-2 with the same SHA so we can check if we choose the right one
   344  	for i := 1; i < 4; i++ {
   345  		_, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Create(&v1.PipelineActivity{
   346  			ObjectMeta: metav1.ObjectMeta{
   347  				Name: fmt.Sprintf("PA%d", i),
   348  				Labels: map[string]string{
   349  					"lastCommitSha": "sha2",
   350  					"branch":        "PR-2",
   351  				},
   352  			},
   353  			Spec: v1.PipelineActivitySpec{
   354  				Build: strconv.Itoa(i),
   355  			},
   356  		})
   357  		assert.NoError(t, err)
   358  	}
   359  
   360  	a, _, err := key.GetOrCreate(jxClient, nsObj.Namespace)
   361  	assert.Nil(t, err)
   362  	assert.Equal(t, expectedName, a.Name)
   363  	spec := &a.Spec
   364  	assert.Equal(t, expectedPipeline, spec.Pipeline)
   365  	assert.Equal(t, expectedBuild, spec.Build)
   366  
   367  	pa3, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Get("PA3", metav1.GetOptions{})
   368  	assert.NoError(t, err)
   369  
   370  	assert.Len(t, a.Spec.BatchPipelineActivity.ComprisingPulLRequests, 1, "There should be %d PRs information in the ComprisingPullRequests property", 1)
   371  	exists := false
   372  	for _, i := range a.Spec.BatchPipelineActivity.ComprisingPulLRequests {
   373  		if i.PullRequestNumber == "PR-2" {
   374  			exists = true
   375  			assert.Equal(t, "3", i.LastBuildNumberForCommit)
   376  		}
   377  	}
   378  	assert.True(t, exists, "There should be a Pull Request called PR-2 within the ComprisingPullRequests property")
   379  	assert.Equal(t, expectedBuild, pa3.Spec.BatchPipelineActivity.BatchBuildNumber, "The batch build number that is going to merge this PR should be %s", expectedBuild)
   380  }
   381  
   382  func TestCreateOrUpdatePRActivityWithLastCommitSHA(t *testing.T) {
   383  	t.Parallel()
   384  
   385  	nsObj := &k8s_v1.Namespace{
   386  		ObjectMeta: metav1.ObjectMeta{
   387  			Name:      "jx-testing",
   388  			Namespace: "testing_ns",
   389  		},
   390  	}
   391  
   392  	jxClient := jxfake.NewSimpleClientset()
   393  
   394  	const (
   395  		expectedName         = "demo-2"
   396  		expectedBuild        = "2"
   397  		expectedOrganisation = "test-org"
   398  	)
   399  	expectedPipeline := expectedOrganisation + "/" + expectedName + "/master"
   400  
   401  	key := kube.PipelineActivityKey{
   402  		Name:     expectedName,
   403  		Pipeline: expectedPipeline,
   404  		Build:    expectedBuild,
   405  		GitInfo: &gits.GitRepository{
   406  			Name:         expectedName,
   407  			Organisation: expectedOrganisation,
   408  			URL:          "https://github.com/" + expectedOrganisation + "/" + expectedName,
   409  		},
   410  		PullRefs: map[string]string{
   411  			"1": "sha1",
   412  		},
   413  	}
   414  
   415  	a, _, err := key.GetOrCreate(jxClient, nsObj.Namespace)
   416  	assert.Nil(t, err)
   417  	assert.Equal(t, expectedName, a.Name)
   418  	spec := &a.Spec
   419  	assert.Equal(t, expectedPipeline, spec.Pipeline)
   420  	assert.Equal(t, expectedBuild, spec.Build)
   421  
   422  	assert.Equal(t, "sha1", a.ObjectMeta.Labels[v1.LabelLastCommitSha])
   423  }
   424  
   425  func TestBatchReconciliationWithTwoPRBuildExecutions(t *testing.T) {
   426  	t.Parallel()
   427  
   428  	nsObj := &k8s_v1.Namespace{
   429  		ObjectMeta: metav1.ObjectMeta{
   430  			Name:      "jx-testing",
   431  			Namespace: "testing_ns",
   432  		},
   433  	}
   434  
   435  	jxClient := jxfake.NewSimpleClientset()
   436  
   437  	const (
   438  		expectedName         = "demo-2"
   439  		expectedBuild        = "2"
   440  		expectedOrganisation = "test-org"
   441  		expectedBatchBuild   = "1"
   442  	)
   443  
   444  	prPAName := fmt.Sprintf("%s-%s-pr1-1", expectedOrganisation, expectedName)
   445  	pr1PA := &v1.PipelineActivity{
   446  		ObjectMeta: metav1.ObjectMeta{
   447  			Name: prPAName,
   448  			Labels: map[string]string{
   449  				v1.LabelBranch:        "PR-1",
   450  				v1.LabelLastCommitSha: "sha1",
   451  				v1.LabelBuild:         "1",
   452  			},
   453  		},
   454  		Spec: v1.PipelineActivitySpec{
   455  			GitOwner:      expectedOrganisation,
   456  			GitRepository: expectedName,
   457  			Build:         "1",
   458  			BatchPipelineActivity: v1.BatchPipelineActivity{
   459  				BatchBuildNumber: expectedBatchBuild,
   460  			},
   461  		},
   462  	}
   463  
   464  	_, err := jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Create(pr1PA)
   465  	assert.NoError(t, err)
   466  
   467  	batchPAName := fmt.Sprintf("%s-%s-batch-1", expectedOrganisation, expectedName)
   468  	batchPA := &v1.PipelineActivity{
   469  		ObjectMeta: metav1.ObjectMeta{
   470  			Name: batchPAName,
   471  			Labels: map[string]string{
   472  				v1.LabelBranch:        "batch",
   473  				v1.LabelLastCommitSha: "testSha",
   474  				v1.LabelBuild:         expectedBatchBuild,
   475  			},
   476  		},
   477  		Spec: v1.PipelineActivitySpec{
   478  			GitOwner:      expectedOrganisation,
   479  			GitRepository: expectedName,
   480  			Build:         expectedBatchBuild,
   481  			BatchPipelineActivity: v1.BatchPipelineActivity{
   482  				ComprisingPulLRequests: []v1.PullRequestInfo{
   483  					{PullRequestNumber: "PR-1", LastBuildNumberForCommit: "1"},
   484  				},
   485  			},
   486  		},
   487  	}
   488  
   489  	_, err = jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Create(batchPA)
   490  	assert.NoError(t, err)
   491  
   492  	expectedPipeline := expectedOrganisation + "/" + expectedName + "/PR-1"
   493  	key := kube.PipelineActivityKey{
   494  		Name:     expectedName,
   495  		Pipeline: expectedPipeline,
   496  		Build:    expectedBuild,
   497  		GitInfo: &gits.GitRepository{
   498  			Name:         expectedName,
   499  			Organisation: expectedOrganisation,
   500  			URL:          "https://github.com/" + expectedOrganisation + "/" + expectedName,
   501  		},
   502  		PullRefs: map[string]string{
   503  			expectedBuild: "sha1",
   504  		},
   505  	}
   506  
   507  	a, _, err := key.GetOrCreate(jxClient, nsObj.Namespace)
   508  	assert.Nil(t, err)
   509  	assert.Equal(t, expectedBatchBuild, a.Spec.BatchPipelineActivity.BatchBuildNumber, "The batch build in the BatchPipeline of the PR should be 1")
   510  
   511  	o := metav1.GetOptions{}
   512  	batchPA, err = jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Get(batchPAName, o)
   513  	assert.Equal(t, expectedBuild, batchPA.Spec.BatchPipelineActivity.ComprisingPulLRequests[0].LastBuildNumberForCommit, "The build number for the comprising PR should be 2")
   514  
   515  	pr1PA, err = jxClient.JenkinsV1().PipelineActivities(nsObj.Namespace).Get(prPAName, o)
   516  	assert.Empty(t, pr1PA.Spec.BatchPipelineActivity.BatchBuildNumber, "The batch build number for the second PR should be empty")
   517  
   518  	assert.Equal(t, expectedBatchBuild, a.Spec.BatchPipelineActivity.BatchBuildNumber, "The batch build number for the second execution of the PR should be 1")
   519  }
   520  
   521  func TestCreatePipelineDetails(t *testing.T) {
   522  	expectedGitOwner := "jstrachan"
   523  	expectedGitRepo := "myapp"
   524  	expectedBranch := "master"
   525  	expectedPipeline := expectedGitOwner + "/" + expectedGitRepo + "/" + expectedBranch
   526  	expectedBuild := "3"
   527  	expectedContext := "release"
   528  
   529  	pipelines := []*v1.PipelineActivity{
   530  		{
   531  			ObjectMeta: metav1.ObjectMeta{
   532  				Name: "a1",
   533  			},
   534  			Spec: v1.PipelineActivitySpec{
   535  				Pipeline: expectedPipeline,
   536  				Build:    expectedBuild,
   537  			},
   538  		},
   539  		{
   540  			ObjectMeta: metav1.ObjectMeta{
   541  				Name: "a2",
   542  			},
   543  			Spec: v1.PipelineActivitySpec{
   544  				GitOwner:      expectedGitOwner,
   545  				GitRepository: expectedGitRepo,
   546  				Build:         expectedBuild,
   547  				Context:       expectedContext,
   548  			},
   549  		},
   550  	}
   551  	for _, pipeline := range pipelines {
   552  		d1 := kube.CreatePipelineDetails(pipeline)
   553  		name := pipeline.Name
   554  		if assert.NotNil(t, d1, "%s did not create a PipelineDetails", name) {
   555  			assert.Equal(t, expectedGitOwner, d1.GitOwner, "%s GitOwner", name)
   556  			assert.Equal(t, expectedGitRepo, d1.GitRepository, "%s GitRepository", name)
   557  			assert.Equal(t, expectedBranch, d1.BranchName, "%s BranchName", name)
   558  			assert.Equal(t, expectedPipeline, d1.Pipeline, "%s Pipeline", name)
   559  			assert.Equal(t, expectedBuild, d1.Build, "%s Build", name)
   560  			if pipeline.Spec.Context != "" {
   561  				assert.Equal(t, expectedContext, d1.Context, "%s Context", name)
   562  			}
   563  		}
   564  	}
   565  }
   566  
   567  func TestPipelineID(t *testing.T) {
   568  	t.Parallel()
   569  
   570  	// A simple ID.
   571  	pID := kube.NewPipelineID("o1", "r1", "b1")
   572  	validatePipelineID(t, pID, "o1/r1/b1", "o1-r1-b1")
   573  
   574  	// Upper case allowed in our ID, but not in the K8S 'name'.
   575  	pID = kube.NewPipelineID("OwNeR1", "rEpO1", "BrAnCh1")
   576  	validatePipelineID(t, pID, "OwNeR1/rEpO1/BrAnCh1", "owner1-repo1-branch1")
   577  
   578  	//Punctuation other than '-' and '.' not allowed in K8S 'name'. Note that this isn't currently handled by the
   579  	//system - the illegal characters are not yet encoded & will be rejected by K8S.
   580  	pID = kube.NewPipelineID("O/N!R@1", "therepo", "thebranch")
   581  	validatePipelineID(t, pID, "O/N!R@1/therepo/thebranch", "o-n!r@1-therepo-thebranch")
   582  }
   583  
   584  func TestSortActivities(t *testing.T) {
   585  	t.Parallel()
   586  	date1 := metav1.Date(2009, time.September, 10, 23, 0, 0, 0, time.UTC)
   587  	date2 := metav1.Date(2009, time.October, 10, 23, 0, 0, 0, time.UTC)
   588  	date3 := metav1.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
   589  	date4 := metav1.Date(2009, time.December, 10, 23, 0, 0, 0, time.UTC)
   590  
   591  	activities := []jenkinsio_v1.PipelineActivity{
   592  		{
   593  			ObjectMeta: metav1.ObjectMeta{
   594  				Name: "a1",
   595  			},
   596  			Spec: v1.PipelineActivitySpec{
   597  				StartedTimestamp: &date3,
   598  			},
   599  		},
   600  		{
   601  			ObjectMeta: metav1.ObjectMeta{
   602  				Name: "a2",
   603  			},
   604  			Spec: v1.PipelineActivitySpec{
   605  				StartedTimestamp: &date2,
   606  			},
   607  		},
   608  		{
   609  			ObjectMeta: metav1.ObjectMeta{
   610  				Name: "a3",
   611  			},
   612  			Spec: v1.PipelineActivitySpec{
   613  				StartedTimestamp: &date1,
   614  			},
   615  		},
   616  		{
   617  			ObjectMeta: metav1.ObjectMeta{
   618  				Name: "a4",
   619  			},
   620  			Spec: v1.PipelineActivitySpec{
   621  				StartedTimestamp: &date4,
   622  			},
   623  		},
   624  	}
   625  
   626  	kube.SortActivities(activities)
   627  
   628  	assert.Equal(t, "a3", activities[0].Name, "Activity 0")
   629  	assert.Equal(t, "a2", activities[1].Name, "Activity 1")
   630  	assert.Equal(t, "a1", activities[2].Name, "Activity 2")
   631  	assert.Equal(t, "a4", activities[3].Name, "Activity 3")
   632  }
   633  
   634  func TestSortActivitiesWithPendingCases(t *testing.T) {
   635  	t.Parallel()
   636  	date1 := metav1.Date(2009, time.September, 10, 23, 0, 0, 0, time.UTC)
   637  	date2 := metav1.Date(2009, time.October, 10, 23, 0, 0, 0, time.UTC)
   638  	date3 := metav1.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
   639  
   640  	activities := []jenkinsio_v1.PipelineActivity{
   641  		{
   642  			ObjectMeta: metav1.ObjectMeta{
   643  				Name: "a1",
   644  			},
   645  			Spec: v1.PipelineActivitySpec{
   646  				StartedTimestamp: &date3,
   647  			},
   648  		},
   649  		{
   650  			ObjectMeta: metav1.ObjectMeta{
   651  				Name: "a2",
   652  			},
   653  			Spec: v1.PipelineActivitySpec{
   654  				StartedTimestamp: &date2,
   655  			},
   656  		},
   657  		{
   658  			ObjectMeta: metav1.ObjectMeta{
   659  				Name: "a3",
   660  			},
   661  			Spec: v1.PipelineActivitySpec{
   662  				StartedTimestamp: &date1,
   663  			},
   664  		},
   665  		{
   666  			ObjectMeta: metav1.ObjectMeta{
   667  				Name: "p",
   668  			},
   669  			Spec: v1.PipelineActivitySpec{
   670  				StartedTimestamp: nil,
   671  			},
   672  		},
   673  	}
   674  
   675  	kube.SortActivities(activities)
   676  
   677  	assert.Equal(t, "a3", activities[0].Name, "Activity 0")
   678  	assert.Equal(t, "a2", activities[1].Name, "Activity 1")
   679  	assert.Equal(t, "a1", activities[2].Name, "Activity 2")
   680  	assert.Equal(t, "p", activities[3].Name, "Activity 3")
   681  }
   682  
   683  func validatePipelineID(t *testing.T, pID kube.PipelineID, expectedID string, expectedName string) {
   684  	assert.Equal(t, expectedID, pID.ID)
   685  	assert.Equal(t, expectedName, pID.Name)
   686  }