Skip to content
This repository was archived by the owner on Jun 14, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions cmd/pj-rehearse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,9 @@ func main() {
}

// We can only detect changes if we managed to load both ci-operator config versions
changedCiopConfigs := config.CompoundCiopConfig{}
if masterConfig.CiOperator != nil && prConfig.CiOperator != nil {
changedCiopConfigs := diffs.GetChangedCiopConfigs(masterConfig.CiOperator, prConfig.CiOperator, logger)
for name := range changedCiopConfigs {
logger.WithField("ciop-config", name).Info("Changed ci-operator config")
}
changedCiopConfigs = diffs.GetChangedCiopConfigs(masterConfig.CiOperator, prConfig.CiOperator, logger)
}

// We can only detect changes if we managed to load both CI template versions
Expand Down Expand Up @@ -201,8 +199,10 @@ func main() {
}
loggers := rehearse.Loggers{Job: logger, Debug: debugLogger.WithField(prowgithub.PrLogField, prNumber)}

changedPresubmits := diffs.GetChangedPresubmits(masterConfig.Prow, prConfig.Prow, logger)
rehearsals := rehearse.ConfigureRehearsalJobs(changedPresubmits, prConfig.CiOperator, prNumber, loggers, o.allowVolumes)
toRehearse := diffs.GetChangedPresubmits(masterConfig.Prow, prConfig.Prow, logger)
toRehearse.AddAll(diffs.GetPresubmitsForCiopConfigs(prConfig.Prow, changedCiopConfigs, logger))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, the intention here is to add all the jobs that are using the changed ci-op config?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the jobs that are using some of the changed ci-op configs, there could be more...

AddAll prevents job being present twice, so if a job was already in toRehearse because it was changed directly, it's not added again.


rehearsals := rehearse.ConfigureRehearsalJobs(toRehearse, prConfig.CiOperator, prNumber, loggers, o.allowVolumes)
if len(rehearsals) == 0 {
logger.Info("no jobs to rehearse have been found")
os.Exit(0)
Expand Down
8 changes: 8 additions & 0 deletions cmd/pj-rehearse/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ func getRehersalsHelper(logger *logrus.Entry, prNumber int) ([]*prowconfig.Presu
candidateConfigPath := filepath.Join(candidatePath, config.ConfigInRepoPath)
candidateJobConfigPath := filepath.Join(candidatePath, config.JobConfigInRepoPath)
candidateCiopConfigPath := filepath.Join(candidatePath, config.CiopConfigInRepoPath)
masterCiopConfigPath := filepath.Join(masterPath, config.CiopConfigInRepoPath)
masterConfigPath := filepath.Join(masterPath, config.ConfigInRepoPath)
masterJobConfigPath := filepath.Join(masterPath, config.JobConfigInRepoPath)

Expand All @@ -146,12 +147,19 @@ func getRehersalsHelper(logger *logrus.Entry, prNumber int) ([]*prowconfig.Presu
if err != nil {
return nil, fmt.Errorf("failed to load ci-operator config: %v", err)
}
ciopMasterConfig, err := config.CompoundLoad(masterCiopConfigPath)
if err != nil {
return nil, fmt.Errorf("failed to load ci-operator config: %v", err)
}

changedPresubmits := diffs.GetChangedPresubmits(prowConfig, prowPRConfig, logger)
if len(changedPresubmits) == 0 {
return nil, fmt.Errorf("Empty changedPresubmits was not expected")
}

changedCiopConfigs := diffs.GetChangedCiopConfigs(ciopMasterConfig, ciopPrConfig, logger)
changedPresubmits.AddAll(diffs.GetPresubmitsForCiopConfigs(prowPRConfig, changedCiopConfigs, logger))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that you needed to do this in the test, too, is smelly

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, that test basically mimics our main().


rehearsals := rehearse.ConfigureRehearsalJobs(changedPresubmits, ciopPrConfig, prNumber, rehearse.Loggers{Job: logger, Debug: logger}, false)
return rehearsals, nil
}
36 changes: 36 additions & 0 deletions pkg/config/jobs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package config

import (
prowconfig "k8s.io/test-infra/prow/config"
)

type Presubmits map[string][]prowconfig.Presubmit

// AddAll adds all jobs from a different instance.
// The method assumes two jobs with a matching name for the same repository
// are identical, so so if a presubmit with a given name already exists, it
// is kept as is.
func (p Presubmits) AddAll(jobs Presubmits) {
for repo := range jobs {
if _, ok := p[repo]; !ok {
p[repo] = []prowconfig.Presubmit{}
}

for _, sourceJob := range jobs[repo] {
p.Add(repo, sourceJob)
}
}
}

// Add a presubmit for a given repo.
// The method assumes two jobs with a matching name are identical, so if
// a presubmit with a given name already exists, it is kept as is.
func (p Presubmits) Add(repo string, job prowconfig.Presubmit) {
for _, destJob := range p[repo] {
if destJob.Name == job.Name {
return
}
}

p[repo] = append(p[repo], job)
}
118 changes: 118 additions & 0 deletions pkg/config/jobs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package config

import (
"k8s.io/apimachinery/pkg/util/diff"
"reflect"
"testing"

prowconfig "k8s.io/test-infra/prow/config"
)

func TestPresubmitsAddAll(t *testing.T) {
testCases := []struct {
description string
source Presubmits
destination Presubmits
expected Presubmits
}{{
description: "merge empty structure into empty structure",
}, {
description: "merge empty structure into non-empty structure",
source: Presubmits{},
destination: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "destination-job-for-org-repo"}},
}},
expected: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "destination-job-for-org-repo"}},
}},
}, {
description: "merge non-empty structure into empty structure",
source: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "source-job-for-org-repo"}},
}},
destination: Presubmits{},
expected: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "source-job-for-org-repo"}},
}},
}, {
description: "merge different jobs for a single repo, result should have both",
source: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "source-job-for-org-repo"}},
}},
destination: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "destination-job-for-org-repo"}}}},
expected: Presubmits{"org/repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "destination-job-for-org-repo"}},
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "source-job-for-org-repo"}},
}},
}, {
description: "merge jobs for different repos, result should have both",
source: Presubmits{"org/source-repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "source-job-for-org-source-repo"}},
}},
destination: Presubmits{"org/destination-repo": {
prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "destination-job-for-org-destination-repo"}}}},
expected: Presubmits{
"org/source-repo": {prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "source-job-for-org-source-repo"}}},
"org/destination-repo": {prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "destination-job-for-org-destination-repo"}}},
},
}, {
description: "merge jobs with same name for a single repo, result has the one originally in destination",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we need unique names to work this might be better as an error, but meh

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It cannot be an error. In rehearse, when both ci-operator config and a presubmit that uses it change, we'll want to rehearse the same job for two reasons, so it ends up being returned by two different "what jobs do we need to rehearse" methods, and those results need to be merged.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah

source: Presubmits{"org/repo": {
prowconfig.Presubmit{
JobBase: prowconfig.JobBase{Name: "same-job-for-org-repo"},
AlwaysRun: true,
},
}},
destination: Presubmits{"org/repo": {
prowconfig.Presubmit{
JobBase: prowconfig.JobBase{Name: "same-job-for-org-repo"},
AlwaysRun: false,
}}},
expected: Presubmits{"org/repo": {
prowconfig.Presubmit{
JobBase: prowconfig.JobBase{Name: "same-job-for-org-repo"},
AlwaysRun: false,
},
}},
},
}

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
tc.destination.AddAll(tc.source)

if !reflect.DeepEqual(tc.destination, tc.expected) {
t.Errorf("Presubmits differ from expected after AddAll:\n%s", diff.ObjectDiff(tc.expected, tc.destination))
}
})
}
}

func TestPresubmitsAdd(t *testing.T) {
testCases := []struct {
description string
presubmits Presubmits
repo string
job prowconfig.Presubmit
expected Presubmits
}{{
description: "add job to new repo",
presubmits: Presubmits{},
repo: "org/repo",
job: prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "job-for-org-repo"}},
expected: Presubmits{"org/repo": {prowconfig.Presubmit{JobBase: prowconfig.JobBase{Name: "job-for-org-repo"}}}},
},
}

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
tc.presubmits.Add(tc.repo, tc.job)

if !reflect.DeepEqual(tc.expected, tc.presubmits) {
t.Errorf("Presubmits differ from expected after Add:\n%s", diff.ObjectDiff(tc.expected, tc.presubmits))
}
})
}

}
2 changes: 2 additions & 0 deletions pkg/config/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const (
CiopConfigInRepoPath = "ci-operator/config"
// TemplatesPath is the path of the templates from release repo
TemplatesPath = "ci-operator/templates"
// Name of the configmap that stores all ci-operator configs
CiOperatorConfigsCMName = "ci-operator-configs"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true -- we are sharded. See the ConfigMapName() method on the config.Info struct

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm aware of that, I want to tackle that tomorrow. IMHO it's worth a separate PR. I only moved this constant, not created it. Rehearse is a little broken after the sharding anyways.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in #104

)

// ReleaseRepoConfig contains all configuration present in release repo (usually openshift/release)
Expand Down
37 changes: 32 additions & 5 deletions pkg/diffs/diffs.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func GetChangedCiopConfigs(masterConfig, prConfig config.CompoundCiopConfig, log
}

// GetChangedPresubmits returns a mapping of repo to presubmits to execute.
func GetChangedPresubmits(prowMasterConfig, prowPRConfig *prowconfig.Config, logger *logrus.Entry) map[string][]prowconfig.Presubmit {
ret := make(map[string][]prowconfig.Presubmit)
func GetChangedPresubmits(prowMasterConfig, prowPRConfig *prowconfig.Config, logger *logrus.Entry) config.Presubmits {
ret := config.Presubmits{}

masterJobs := getJobsByRepoAndName(prowMasterConfig.JobConfig.Presubmits)
for repo, jobs := range prowPRConfig.JobConfig.Presubmits {
Expand All @@ -77,14 +77,14 @@ func GetChangedPresubmits(prowMasterConfig, prowPRConfig *prowconfig.Config, log
if masterJob.Agent != job.Agent {
logFields[logDiffs] = convertToReadableDiff(masterJob.Agent, job.Agent, objectAgent)
logger.WithFields(logFields).Info(chosenJob)
ret[repo] = append(ret[repo], job)
ret.Add(repo, job)
continue
}

if !equality.Semantic.DeepEqual(masterJob.Spec, job.Spec) {
logFields[logDiffs] = convertToReadableDiff(masterJob.Spec, job.Spec, objectSpec)
logger.WithFields(logFields).Info(chosenJob)
ret[repo] = append(ret[repo], job)
ret.Add(repo, job)
}
}
}
Expand All @@ -96,7 +96,7 @@ func GetChangedPresubmits(prowMasterConfig, prowPRConfig *prowconfig.Config, log
// and compare the same key and index of the other map of slices,
// we convert them as `repo-> jobName-> Presubmit` to be able to
// access any specific elements of the Presubmits without the need to iterate in slices.
func getJobsByRepoAndName(presubmits map[string][]prowconfig.Presubmit) map[string]map[string]prowconfig.Presubmit {
func getJobsByRepoAndName(presubmits config.Presubmits) map[string]map[string]prowconfig.Presubmit {
jobsByRepo := make(map[string]map[string]prowconfig.Presubmit)

for repo, preSubmitList := range presubmits {
Expand Down Expand Up @@ -150,3 +150,30 @@ func GetChangedTemplates(masterTemplates, prTemplates map[string]*templateapi.Te
}
return changedTemplates
}

func GetPresubmitsForCiopConfigs(prowConfig *prowconfig.Config, ciopConfigs config.CompoundCiopConfig, logger *logrus.Entry) config.Presubmits {
ret := config.Presubmits{}

for repo, jobs := range prowConfig.JobConfig.Presubmits {
for _, job := range jobs {
if job.Agent != string(pjapi.KubernetesAgent) {
continue
}
for _, env := range job.Spec.Containers[0].Env {
if env.ValueFrom == nil {
continue
}
if env.ValueFrom.ConfigMapKeyRef == nil {
continue
}
if env.ValueFrom.ConfigMapKeyRef.Name == config.CiOperatorConfigsCMName {
if _, ok := ciopConfigs[env.ValueFrom.ConfigMapKeyRef.Key]; ok {
ret.Add(repo, job)
}
}
}
}
}

return ret
}
Loading