Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 1 addition & 2 deletions cmd/ci-operator-prowgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -558,11 +558,10 @@ func generateJobBase(name, prefix string, info *prowgenInfo, label jc.ProwgenLab
labels[jc.CanBeRehearsedLabel] = string(jc.Generated)
}

jobPrefix := fmt.Sprintf("%s-ci-%s-%s-%s-", prefix, info.Org, info.Repo, info.Branch)
jobName := info.Info.JobName(prefix, name)
if len(info.Variant) > 0 {
labels[prowJobLabelVariant] = info.Variant
}
jobName := fmt.Sprintf("%s%s", jobPrefix, name)
newTrue := true
dc := &v1.DecorationConfig{SkipCloning: &newTrue}
base := prowconfig.JobBase{
Expand Down
29 changes: 24 additions & 5 deletions cmd/pj-rehearse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,27 @@ func rehearseMain() int {
metrics.RecordChangedCiopConfigs(changedCiopConfigData)
}

refs, chains, workflows, err := load.Registry(filepath.Join(o.releaseRepoPath, config.RegistryPath), false)
if err != nil {
logger.WithError(err).Error("could not load step registry")
return gracefulExit(o.noFail, misconfigurationOutput)
}
graph, err := registry.NewGraph(refs, chains, workflows)
if err != nil {
logger.WithError(err).Error("could not create step registry graph")
return gracefulExit(o.noFail, misconfigurationOutput)
}
changedRegistrySteps, err := config.GetChangedRegistrySteps(o.releaseRepoPath, jobSpec.Refs.BaseSHA, graph)
if err != nil {
logger.WithError(err).Error("could not get step registry differences")
return gracefulExit(o.noFail, misconfigurationOutput)
}
if len(changedRegistrySteps) != 0 {
logger.WithField("registry", changedRegistrySteps).Info("registry steps changed")
// TODO: add metrics for changed registry steps
Comment thread
AlexNPavel marked this conversation as resolved.
Outdated
//metrics.RecordChangedRegistrySteps(changedRegistrySteps)
}

changedTemplates, err := config.GetChangedTemplates(o.releaseRepoPath, jobSpec.Refs.BaseSHA)
if err != nil {
logger.WithError(err).Error("could not get template differences")
Expand Down Expand Up @@ -269,13 +290,11 @@ func rehearseMain() int {
metrics.RecordPresubmitsOpportunity(toRehearseClusterProfiles, "cluster-profile-change")
toRehearse.AddAll(toRehearseClusterProfiles)

refs, chains, workflows, err := load.Registry(filepath.Join(o.releaseRepoPath, config.RegistryPath), false)
if err != nil {
logger.WithError(err).Error("could not load step registry")
return gracefulExit(o.noFail, misconfigurationOutput)
}
resolver := registry.NewResolver(refs, chains, workflows)
jobConfigurer := rehearse.NewJobConfigurer(prConfig.CiOperator, resolver, prNumber, loggers, o.allowVolumes, changedTemplates, changedClusterProfiles, jobSpec.Refs)
presubmitsWithChangedRegistry := rehearse.AddRandomJobsForChangedRegistry(changedRegistrySteps, graph, prConfig.Prow.JobConfig.PresubmitsStatic, filepath.Join(o.releaseRepoPath, diffs.CIOperatorConfigInRepoPath), loggers)
metrics.RecordPresubmitsOpportunity(presubmitsWithChangedRegistry, "registry-change")
toRehearse.AddAll(presubmitsWithChangedRegistry)

presubmitsToRehearse := jobConfigurer.ConfigurePresubmitRehearsals(toRehearse)
periodicsToRehearse := jobConfigurer.ConfigurePeriodicRehearsals(changedPeriodics)
Expand Down
4 changes: 4 additions & 0 deletions pkg/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type Info struct {
RepoPath string
}

func (i *Info) JobName(prefix, name string) string {
return fmt.Sprintf("%s-ci-%s-%s-%s-%s", prefix, i.Org, i.Repo, i.Branch, name)
}

// Basename returns the unique name for this file in the config
func (i *Info) Basename() string {
basename := strings.Join([]string{i.Org, i.Repo, i.Branch}, "-")
Expand Down
45 changes: 44 additions & 1 deletion pkg/config/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import (
"strings"

"github.com/sirupsen/logrus"

pjapi "k8s.io/test-infra/prow/apis/prowjobs/v1"
prowconfig "k8s.io/test-infra/prow/config"
pjdwapi "k8s.io/test-infra/prow/pod-utils/downwardapi"

"github.com/openshift/ci-tools/pkg/registry"
)

const (
Expand Down Expand Up @@ -165,6 +166,48 @@ func GetChangedTemplates(path, baseRev string) ([]ConfigMapSource, error) {
return ret, nil
}

func loadRegistryStep(filename string, graph, changes registry.NodeByName) error {
// if a commands script changed, mark reference as changed
filename = strings.ReplaceAll(filename, "-commands.sh", "-ref.yaml")
name := ""
if strings.HasSuffix(filename, "-ref.yaml") {
name = strings.TrimSuffix(filename, "-ref.yaml")
}
if strings.HasSuffix(filename, "-chain.yaml") {
name = strings.TrimSuffix(filename, "-chain.yaml")
}
if strings.HasSuffix(filename, "-workflow.yaml") {
name = strings.TrimSuffix(filename, "-workflow.yaml")
}
if name == "" {
return fmt.Errorf("invalid step filename: %s", filename)
}
node, ok := graph[name]
if !ok {
return fmt.Errorf("could not find registry component in registry graph: %s", name)
}
changes[name] = node
return nil
}

// GetChangedRegistrySteps identifies all registry components (refs, chains, and workflows) that changed.
func GetChangedRegistrySteps(path, baseRev string, graph registry.NodeByName) (registry.NodeByName, error) {
changes := make(registry.NodeByName)
revChanges, err := getRevChanges(path, RegistryPath, baseRev, true)
if err != nil {
return changes, err
}
for _, c := range revChanges {
if filepath.Ext(c.Filename) == ".yaml" || strings.HasSuffix(c.Filename, "-commands.sh") {
err := loadRegistryStep(filepath.Base(c.Filename), graph, changes)
if err != nil {
return changes, err
}
}
}
return changes, nil
}

func GetChangedClusterProfiles(path, baseRev string) ([]ConfigMapSource, error) {
return getRevChanges(path, ClusterProfilesPath, baseRev, false)
}
Expand Down
121 changes: 121 additions & 0 deletions pkg/rehearse/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package rehearse
import (
"fmt"
"path/filepath"
"reflect"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -32,6 +33,7 @@ import (
prowconfig "k8s.io/test-infra/prow/config"
"k8s.io/test-infra/prow/pjutil"

"github.com/openshift/ci-tools/pkg/api"
"github.com/openshift/ci-tools/pkg/config"
"github.com/openshift/ci-tools/pkg/registry"
)
Expand Down Expand Up @@ -408,6 +410,125 @@ func AddRandomJobsForChangedTemplates(templates []config.ConfigMapSource, toBeRe
return rehearsals
}

func getPresubmitByJobName(presubmits []prowconfig.Presubmit, name string) (prowconfig.Presubmit, error) {
for _, presubmit := range presubmits {
if presubmit.Name == name {
return presubmit, nil
}
}
return prowconfig.Presubmit{}, fmt.Errorf("could not find presubmit with name: %s", name)
}

func getPresubmitForRegistryStep(node registry.Node, configs config.ByFilename, prConfigPresubmits map[string][]prowconfig.Presubmit, addedConfigs []*api.MultiStageTestConfiguration) (map[string][]prowconfig.Presubmit, []*api.MultiStageTestConfiguration, error) {
toTest := make(map[string][]prowconfig.Presubmit)
// get sorted list of configs keys to make the function deterministic
var keys []string
for k := range configs {
keys = append(keys, k)
}
sort.Strings(keys)
for _, key := range keys {
ciopConfig := configs[key]
tests := ciopConfig.Configuration.Tests
repoPresubmits := prConfigPresubmits[ciopConfig.Info.Repo]
for _, test := range tests {
if test.MultiStageTestConfiguration == nil {
continue
}
skip := false
for _, added := range addedConfigs {
if reflect.DeepEqual(test.MultiStageTestConfiguration, added) {
skip = true
break
}
}
if skip {
continue
}
jobName := ciopConfig.Info.JobName("pull", test.As)
Comment thread
AlexNPavel marked this conversation as resolved.
Outdated
// TODO: Handle workflows with overridden fields.
// Workflows can have overridden fields and thus may have overridden the field that made the workflow an ancestor.
// This should be handled to reduce the number of rehearsals being done, but requires much more information than
// the graph alone provides.
if test.MultiStageTestConfiguration.Workflow != nil && node.Type() == registry.Workflow && node.Name() == *test.MultiStageTestConfiguration.Workflow {
presubmit, err := getPresubmitByJobName(repoPresubmits, jobName)
if err != nil {
return toTest, addedConfigs, err
}
addedConfigs = append(addedConfigs, test.MultiStageTestConfiguration)
toTest[ciopConfig.Info.Repo] = append(toTest[ciopConfig.Info.Repo], presubmit)
// continue to check other tests
continue
}
testSteps := append(test.MultiStageTestConfiguration.Pre, append(test.MultiStageTestConfiguration.Test, test.MultiStageTestConfiguration.Post...)...)
for _, testStep := range testSteps {
if testStep.Reference != nil && node.Type() == registry.Reference && node.Name() == *testStep.Reference {
presubmit, err := getPresubmitByJobName(repoPresubmits, jobName)
if err != nil {
return toTest, addedConfigs, err
}
addedConfigs = append(addedConfigs, test.MultiStageTestConfiguration)
toTest[ciopConfig.Info.Repo] = append(toTest[ciopConfig.Info.Repo], presubmit)
// found step; break
break
}
if testStep.Chain != nil && node.Type() == registry.Chain && node.Name() == *testStep.Chain {
presubmit, err := getPresubmitByJobName(repoPresubmits, jobName)
if err != nil {
return toTest, addedConfigs, err
}
addedConfigs = append(addedConfigs, test.MultiStageTestConfiguration)
toTest[ciopConfig.Info.Repo] = append(toTest[ciopConfig.Info.Repo], presubmit)
// found step; break
break
}
}
}
}
return toTest, addedConfigs, nil
}

// expandAncestors takes a graph of changed steps and adds all ancestors of
// the existing steps to the changed steps graph
func expandAncestors(changed, graph registry.NodeByName) {
for _, node := range changed {
for name := range node.AncestorNames() {
changed[name] = graph[name]
}
}
}

func AddRandomJobsForChangedRegistry(regSteps, graph registry.NodeByName, prConfigPresubmits map[string][]prowconfig.Presubmit, configPath string, loggers Loggers) config.Presubmits {
configsByFilename, err := config.LoadConfigByFilename(configPath)
if err != nil {
loggers.Debug.Errorf("Failed to load config by filename in AddRandomJobsForChangedRegistry: %v", err)
}
expandAncestors(regSteps, graph)
rehearsals := make(config.Presubmits)
// get sorted list of regSteps keys to make the function deterministic
var keys []string
for k := range regSteps {
keys = append(keys, k)
}
sort.Strings(keys)
// make list to store MultiStageTestConfigurations that we've already added to the test list
addedConfigs := []*api.MultiStageTestConfiguration{}
for _, key := range keys {
step := regSteps[key]
var presubmitsMap map[string][]prowconfig.Presubmit
presubmitsMap, addedConfigs, err = getPresubmitForRegistryStep(step, configsByFilename, prConfigPresubmits, addedConfigs)
if len(presubmitsMap) == 0 {
// if the code reaches this point, then no config contains the step or the step has already been tested
loggers.Debug.Warnf("No config found containing step: %+v", step)
}
for repo, presubmits := range presubmitsMap {
rehearsals[repo] = append(rehearsals[repo], presubmits...)
continue
}
}
return rehearsals
}

func getClusterTypes(jobs map[string][]prowconfig.Presubmit) []string {
ret := sets.NewString()
for _, jobs := range jobs {
Expand Down