Skip to content

Commit d362395

Browse files
Merge pull request #3617 from dgoodwin/spotcheck-30d-variants
Reclassify spot-check jobs from 'rare' to 'spotcheck-30d' tier
2 parents 8d299ee + dd2dd31 commit d362395

4 files changed

Lines changed: 396 additions & 115 deletions

File tree

pkg/variantregistry/ocp.go

Lines changed: 104 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,31 @@ ORDER BY j.prowjob_job_name;
260260
dur := time.Since(start)
261261
log.WithField("count", count.Load()).Infof("processed primary job list in %s", dur)
262262

263+
var errs []string
264+
for jobName, variants := range variantsByJob {
265+
if err := validateSpotCheckVariants(jobName, variants); err != nil {
266+
errs = append(errs, err.Error())
267+
}
268+
}
269+
if len(errs) > 0 {
270+
sort.Strings(errs)
271+
return nil, errors.New("variant registry validation failed:\n" + strings.Join(errs, "\n"))
272+
}
273+
263274
return variantsByJob, nil
264275
}
265276

277+
// validateSpotCheckVariants returns an error if a job has JobTier=spotcheck without both
278+
// SpotCheckComponent and SpotCheckCapability defined.
279+
func validateSpotCheckVariants(jobName string, variants map[string]string) error {
280+
if strings.HasPrefix(variants[VariantJobTier], "spotcheck-") {
281+
if variants[VariantSpotCheckComponent] == "" || variants[VariantSpotCheckCapability] == "" {
282+
return fmt.Errorf("job %q has JobTier=%s but is missing SpotCheckComponent or SpotCheckCapability", jobName, variants[VariantJobTier])
283+
}
284+
}
285+
return nil
286+
}
287+
266288
// fileVariantsToIgnore are values in the cluster-data.json that vary by run, and are not consistent for the job itself.
267289
// These are unsuited for variants.
268290
var fileVariantsToIgnore = map[string]bool{
@@ -427,34 +449,36 @@ var (
427449
)
428450

429451
const (
430-
VariantAggregation = "Aggregation" // aggregated or none
431-
VariantArch = "Architecture"
432-
VariantFeatureSet = "FeatureSet" // techpreview / standard
433-
VariantInstaller = "Installer" // ipi / upi / assisted
434-
VariantNetwork = "Network"
435-
VariantNetworkAccess = "NetworkAccess" // disconnected / proxy / standard
436-
VariantNetworkStack = "NetworkStack" // ipv4 / ipv6 / dual
437-
VariantOwner = "Owner" // eng / osd
438-
VariantPlatform = "Platform"
439-
VariantScheduler = "Scheduler" // realtime / standard
440-
VariantSecurityMode = "SecurityMode" // fips / default
441-
VariantSuite = "Suite" // parallel / serial
442-
VariantProcedure = "Procedure" // for jobs that do a specific procedure on the cluster (etcd scaling, cpu partitioning, etc.), and then optionally run conformance
443-
VariantJobTier = "JobTier" // specifies rare, blocking, informing, standard jobs
444-
VariantTopology = "Topology" // ha / single / compact / external
445-
VariantUpgrade = "Upgrade"
446-
VariantContainerRuntime = "ContainerRuntime" // runc / crun
447-
VariantCGroupMode = "CGroupMode" // v2 / v1
448-
VariantRelease = "Release"
449-
VariantReleaseMinor = "ReleaseMinor"
450-
VariantReleaseMajor = "ReleaseMajor"
451-
VariantFromRelease = "FromRelease"
452-
VariantFromReleaseMinor = "FromReleaseMinor"
453-
VariantFromReleaseMajor = "FromReleaseMajor"
454-
VariantLayeredProduct = "LayeredProduct"
455-
VariantOS = "OS"
456-
VariantDefaultValue = "default"
457-
VariantNoValue = "none"
452+
VariantAggregation = "Aggregation" // aggregated or none
453+
VariantArch = "Architecture"
454+
VariantFeatureSet = "FeatureSet" // techpreview / standard
455+
VariantInstaller = "Installer" // ipi / upi / assisted
456+
VariantNetwork = "Network"
457+
VariantNetworkAccess = "NetworkAccess" // disconnected / proxy / standard
458+
VariantNetworkStack = "NetworkStack" // ipv4 / ipv6 / dual
459+
VariantOwner = "Owner" // eng / osd
460+
VariantPlatform = "Platform"
461+
VariantScheduler = "Scheduler" // realtime / standard
462+
VariantSecurityMode = "SecurityMode" // fips / default
463+
VariantSuite = "Suite" // parallel / serial
464+
VariantProcedure = "Procedure" // for jobs that do a specific procedure on the cluster (etcd scaling, cpu partitioning, etc.), and then optionally run conformance
465+
VariantJobTier = "JobTier" // specifies rare, blocking, informing, standard jobs
466+
VariantTopology = "Topology" // ha / single / compact / external
467+
VariantUpgrade = "Upgrade"
468+
VariantContainerRuntime = "ContainerRuntime" // runc / crun
469+
VariantCGroupMode = "CGroupMode" // v2 / v1
470+
VariantRelease = "Release"
471+
VariantReleaseMinor = "ReleaseMinor"
472+
VariantReleaseMajor = "ReleaseMajor"
473+
VariantFromRelease = "FromRelease"
474+
VariantFromReleaseMinor = "FromReleaseMinor"
475+
VariantFromReleaseMajor = "FromReleaseMajor"
476+
VariantLayeredProduct = "LayeredProduct"
477+
VariantOS = "OS"
478+
VariantSpotCheckComponent = "SpotCheckComponent" // component readiness component for spot-check jobs
479+
VariantSpotCheckCapability = "SpotCheckCapability" // component readiness capability for spot-check jobs
480+
VariantDefaultValue = "default"
481+
VariantNoValue = "none"
458482
)
459483

460484
func (v *OCPVariantLoader) IdentifyVariants(jLog logrus.FieldLogger, jobName string) map[string]string {
@@ -480,6 +504,7 @@ func (v *OCPVariantLoader) IdentifyVariants(jLog logrus.FieldLogger, jobName str
480504
setContainerRuntime,
481505
setProcedure,
482506
setOS,
507+
setSpotCheckClassification,
483508
v.setJobTier, // Keep this near last, it relies on other variants like owner
484509
} {
485510
setter(jLog, variants, jobName)
@@ -726,29 +751,69 @@ func (v *OCPVariantLoader) setRelease(logger logrus.FieldLogger, variants map[st
726751
}
727752
}
728753

754+
// setSpotCheckClassification identifies jobs that should be evaluated as spot-check jobs
755+
// in Component Readiness. These jobs run infrequently ("rare" tier historically) and
756+
// must fully pass at least once in the sample window. (with retries if needed)
757+
// They are intended for stable, non-core functionality that does not need in depth
758+
// statistical regression monitoring.
759+
//
760+
// The SpotCheckComponent and SpotCheckCapability variants control where these synthetic
761+
// results appear in the component readiness report.
762+
//
763+
// Be sure to use real Component names from OCPBUGS.
764+
func setSpotCheckClassification(_ logrus.FieldLogger, variants map[string]string, jobName string) {
765+
jobNameLower := strings.ToLower(jobName)
766+
767+
spotCheckPatterns := []struct {
768+
substrings []string
769+
component string
770+
capability string
771+
}{
772+
{[]string{"-cpu-partitioning"}, "Node / Kubelet", "CPU Partitioning"},
773+
{[]string{"-etcd-scaling"}, "Etcd", "Scaling"},
774+
}
775+
776+
for _, p := range spotCheckPatterns {
777+
allMatch := true
778+
for _, sub := range p.substrings {
779+
if !strings.Contains(jobNameLower, sub) {
780+
allMatch = false
781+
break
782+
}
783+
}
784+
if allMatch {
785+
variants[VariantSpotCheckComponent] = p.component
786+
variants[VariantSpotCheckCapability] = p.capability
787+
return
788+
}
789+
}
790+
}
791+
729792
// setJobTier sets the jobTier for a job, with values like this:
730793
//
731-
// blocking: blocking job on payloads, covered by component readiness
732-
// informing: informing job on payloads, covered by component readiness
733-
// standard: should be visible in default views (component readiness, sippy), covered by component readiness
734-
// rare: highly reliable jobs that run at a reduced frequency
735-
// candidate: not covered by component readiness, but may be promoted in the future
736-
// hidden: data should still be synced, but not shown by default
737-
// excluded: data should not be synced, and excluded from all views
794+
// blocking: blocking job on payloads, covered by component readiness
795+
// informing: informing job on payloads, covered by component readiness
796+
// standard: should be visible in default views (component readiness, sippy), covered by component readiness
797+
// spotcheck: jobs evaluated by spot-check analysis (job pass/fail, not junit); views opt in via JobTier include
798+
// candidate: not covered by component readiness, but may be promoted in the future
799+
// hidden: data should still be synced, but not shown by default
800+
// excluded: data should not be synced, and excluded from all views
738801
//
739802
// Note: blocking/informing/standard tiers may be downgraded to candidate by
740803
// adjustJobTierBasedOnView if the job's variants don't match the release-main view.
741804
func (v *OCPVariantLoader) setJobTier(_ logrus.FieldLogger, variants map[string]string, jobName string) {
805+
// Jobs classified as spot-check get the spotcheck-30d tier automatically.
806+
if _, ok := variants[VariantSpotCheckComponent]; ok {
807+
variants[VariantJobTier] = "spotcheck-30d"
808+
return
809+
}
810+
742811
jobNameLower := strings.ToLower(jobName)
743812

744813
jobTierPatterns := []struct {
745814
substrings []string
746815
jobTier string
747816
}{
748-
// Rarely run
749-
{[]string{"-cpu-partitioning"}, "rare"},
750-
{[]string{"-etcd-scaling"}, "rare"},
751-
752817
// QE jobs allowlisted for Component Readiness
753818
{[]string{"-automated-release"}, "standard"},
754819

pkg/variantregistry/ocp_test.go

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,66 @@ func TestVariantSyncer(t *testing.T) {
22042204
VariantOS: "unknown",
22052205
},
22062206
},
2207+
{
2208+
job: "periodic-ci-openshift-release-main-nightly-4.18-e2e-aws-ovn-cpu-partitioning",
2209+
expected: map[string]string{
2210+
VariantRelease: "4.18",
2211+
VariantReleaseMajor: "4",
2212+
VariantReleaseMinor: "18",
2213+
VariantArch: "amd64",
2214+
VariantInstaller: "ipi",
2215+
VariantPlatform: "aws",
2216+
VariantNetwork: "ovn",
2217+
VariantNetworkStack: "ipv4",
2218+
VariantOwner: "eng",
2219+
VariantTopology: "ha",
2220+
VariantSuite: "unknown",
2221+
VariantUpgrade: VariantNoValue,
2222+
VariantProcedure: "cpu-partitioning",
2223+
VariantJobTier: "spotcheck-30d",
2224+
VariantAggregation: VariantNoValue,
2225+
VariantSecurityMode: VariantDefaultValue,
2226+
VariantFeatureSet: VariantDefaultValue,
2227+
VariantNetworkAccess: VariantDefaultValue,
2228+
VariantScheduler: VariantDefaultValue,
2229+
VariantContainerRuntime: "crun",
2230+
VariantCGroupMode: "v2",
2231+
VariantLayeredProduct: VariantNoValue,
2232+
VariantOS: "rhcos9",
2233+
VariantSpotCheckComponent: "Node / Kubelet",
2234+
VariantSpotCheckCapability: "CPU Partitioning",
2235+
},
2236+
},
2237+
{
2238+
job: "periodic-ci-openshift-release-main-nightly-4.18-e2e-gcp-ovn-etcd-scaling",
2239+
expected: map[string]string{
2240+
VariantRelease: "4.18",
2241+
VariantReleaseMajor: "4",
2242+
VariantReleaseMinor: "18",
2243+
VariantArch: "amd64",
2244+
VariantInstaller: "ipi",
2245+
VariantPlatform: "gcp",
2246+
VariantNetwork: "ovn",
2247+
VariantNetworkStack: "ipv4",
2248+
VariantOwner: "eng",
2249+
VariantTopology: "ha",
2250+
VariantSuite: "etcd-scaling",
2251+
VariantUpgrade: VariantNoValue,
2252+
VariantProcedure: "etcd-scaling",
2253+
VariantJobTier: "spotcheck-30d",
2254+
VariantAggregation: VariantNoValue,
2255+
VariantSecurityMode: VariantDefaultValue,
2256+
VariantFeatureSet: VariantDefaultValue,
2257+
VariantNetworkAccess: VariantDefaultValue,
2258+
VariantScheduler: VariantDefaultValue,
2259+
VariantContainerRuntime: "crun",
2260+
VariantCGroupMode: "v2",
2261+
VariantLayeredProduct: VariantNoValue,
2262+
VariantOS: "rhcos9",
2263+
VariantSpotCheckComponent: "Etcd",
2264+
VariantSpotCheckCapability: "Scaling",
2265+
},
2266+
},
22072267
}
22082268
for _, test := range tests {
22092269
t.Run(test.job, func(t *testing.T) {
@@ -2573,16 +2633,16 @@ func TestAdjustJobTierBasedOnView(t *testing.T) {
25732633
expectedTier: "excluded",
25742634
},
25752635
{
2576-
name: "rare job is not adjusted even with non-matching variants",
2636+
name: "spotcheck job is not adjusted even with non-matching variants",
25772637
variants: map[string]string{
25782638
VariantRelease: "4.22",
2579-
VariantJobTier: "rare",
2639+
VariantJobTier: "spotcheck-30d",
25802640
VariantArch: "s390x",
25812641
VariantPlatform: "rosa",
25822642
VariantNetwork: "sdn",
25832643
VariantOwner: "chaos",
25842644
},
2585-
expectedTier: "rare",
2645+
expectedTier: "spotcheck-30d",
25862646
},
25872647
{
25882648
name: "job with no release is not adjusted",

pkg/variantregistry/snapshot.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package variantregistry
22

33
import (
4+
"fmt"
45
"os"
6+
"sort"
57
"strings"
68

79
"github.com/sirupsen/logrus"
@@ -34,6 +36,7 @@ func NewVariantSnapshot(config *v1.SippyConfig, views []crview.View, syntheticRe
3436
func (s *VariantSnapshot) Identify() (JobVariants, error) {
3537
newVariants := map[string]map[string]string{}
3638
variantSyncer := OCPVariantLoader{config: s.config, views: s.views, syntheticReleaseJobOverrides: s.syntheticReleaseJobOverrides}
39+
var errs []string
3740
for _, releaseCfg := range s.config.Releases {
3841
for job := range releaseCfg.Jobs {
3942
if isIgnoredJob(job) {
@@ -42,10 +45,19 @@ func (s *VariantSnapshot) Identify() (JobVariants, error) {
4245
if _, done := newVariants[job]; done {
4346
continue
4447
}
45-
newVariants[job] = variantSyncer.CalculateVariantsForJob(s.log, job, nil)
48+
variants := variantSyncer.CalculateVariantsForJob(s.log, job, nil)
49+
newVariants[job] = variants
50+
if err := validateSpotCheckVariants(job, variants); err != nil {
51+
errs = append(errs, err.Error())
52+
}
4653
}
4754
}
4855

56+
if len(errs) > 0 {
57+
sort.Strings(errs)
58+
return nil, fmt.Errorf("variant registry validation failed:\n%s", strings.Join(errs, "\n"))
59+
}
60+
4961
return newVariants, nil
5062
}
5163

0 commit comments

Comments
 (0)