in testgrid/pkg/configurator/prow/prow.go [78:246]
func (pac *ProwAwareConfigurator) ApplySingleProwjobAnnotations(c *configpb.Configuration, j prowConfig.JobBase, pj prowapi.ProwJob) error {
tabName := j.Name
testGroupName := j.Name
var repo string
if pj.Spec.Refs != nil {
repo = fmt.Sprintf("%s/%s", pj.Spec.Refs.Org, pj.Spec.Refs.Repo)
}
pc := pac.ProwConfig
dc := pac.DefaultTestgridConfig
mustMakeGroup := j.Annotations[testgridCreateTestGroupAnnotation] == "true"
mustNotMakeGroup := j.Annotations[testgridCreateTestGroupAnnotation] == "false"
dashboards, addToDashboards := j.Annotations[testgridDashboardsAnnotation]
mightMakeGroup := (mustMakeGroup || addToDashboards || pj.Spec.Type != prowapi.PresubmitJob) && !mustNotMakeGroup
var testGroup *configpb.TestGroup
if mightMakeGroup {
if testGroup = config.FindTestGroup(testGroupName, c); testGroup != nil {
if mustMakeGroup {
return fmt.Errorf("test group %q already exists", testGroupName)
}
} else {
var prefix string
if j.DecorationConfig != nil && j.DecorationConfig.GCSConfiguration != nil {
prefix = path.Join(j.DecorationConfig.GCSConfiguration.Bucket, j.DecorationConfig.GCSConfiguration.PathPrefix)
} else if def := pc.Plank.GuessDefaultDecorationConfig(repo, ""); def != nil && def.GCSConfiguration != nil {
prefix = path.Join(def.GCSConfiguration.Bucket, def.GCSConfiguration.PathPrefix)
} else {
return fmt.Errorf("job %s: couldn't figure out a default decoration config", j.Name)
}
testGroup = &configpb.TestGroup{
Name: testGroupName,
GcsPrefix: path.Join(prefix, prowGCS.RootForSpec(&downwardapi.JobSpec{Job: j.Name, Type: pj.Spec.Type})),
}
if dc != nil {
yamlcfg.ReconcileTestGroup(testGroup, dc.DefaultTestGroup)
}
c.TestGroups = append(c.TestGroups, testGroup)
}
} else {
testGroup = config.FindTestGroup(testGroupName, c)
}
if testGroup == nil {
for _, a := range []string{testgridNumColumnsRecentAnnotation, testgridAlertStaleResultsHoursAnnotation,
testgridNumFailuresToAlertAnnotation, testgridDaysOfResultsAnnotation, testgridTabNameAnnotation, testgridEmailAnnotation} {
_, ok := j.Annotations[a]
if ok {
return fmt.Errorf("no testgroup exists for job %q, but annotation %q implies one should exist", j.Name, a)
}
}
// exit early: with no test group, there's nothing else for us to usefully do with the job.
return nil
}
if ncr, ok := j.Annotations[testgridNumColumnsRecentAnnotation]; ok {
ncrInt, err := strconv.ParseInt(ncr, 10, 32)
if err != nil {
return fmt.Errorf("%s value %q is not a valid integer", testgridNumColumnsRecentAnnotation, ncr)
}
testGroup.NumColumnsRecent = int32(ncrInt)
} else if pj.Spec.Type == prowapi.PresubmitJob && testGroup.NumColumnsRecent < minPresubmitNumColumnsRecent {
testGroup.NumColumnsRecent = minPresubmitNumColumnsRecent
}
if srh, ok := j.Annotations[testgridAlertStaleResultsHoursAnnotation]; ok {
srhInt, err := strconv.ParseInt(srh, 10, 32)
if err != nil {
return fmt.Errorf("%s value %q is not a valid integer", testgridAlertStaleResultsHoursAnnotation, srh)
}
testGroup.AlertStaleResultsHours = int32(srhInt)
}
if nfta, ok := j.Annotations[testgridNumFailuresToAlertAnnotation]; ok {
nftaInt, err := strconv.ParseInt(nfta, 10, 32)
if err != nil {
return fmt.Errorf("%s value %q is not a valid integer", testgridNumFailuresToAlertAnnotation, nfta)
}
testGroup.NumFailuresToAlert = int32(nftaInt)
}
if dora, ok := j.Annotations[testgridDaysOfResultsAnnotation]; ok {
doraInt, err := strconv.ParseInt(dora, 10, 32)
if err != nil {
return fmt.Errorf("%s value %q is not a valid integer", testgridDaysOfResultsAnnotation, dora)
}
testGroup.DaysOfResults = int32(doraInt)
}
if stm, ok := j.Annotations[testgridInCellMetric]; ok {
testGroup.ShortTextMetric = stm
}
if dpa, ok := j.Annotations[testGridDisableProwJobAnalysis]; ok {
dpaBool, err := strconv.ParseBool(dpa)
if err != nil {
return fmt.Errorf("%s value %q in not a valid boolean", testGridDisableProwJobAnalysis, dpa)
}
testGroup.DisableProwjobAnalysis = dpaBool
}
if tn, ok := j.Annotations[testgridTabNameAnnotation]; ok {
tabName = tn
}
var baseOptions string
if bo, ok := j.Annotations[testgridBaseOptionsAnnotation]; ok {
baseOptions = bo
}
description := pac.TabDescriptionForProwJob(j)
if addToDashboards {
firstDashboard := true
for _, dashboardName := range strings.Split(dashboards, ",") {
dashboardName = strings.TrimSpace(dashboardName)
d := config.FindDashboard(dashboardName, c)
if d == nil {
return fmt.Errorf("couldn't find dashboard %q for job %q", dashboardName, j.Name)
}
if repo == "" {
if len(j.ExtraRefs) > 0 {
repo = fmt.Sprintf("%s/%s", j.ExtraRefs[0].Org, j.ExtraRefs[0].Repo)
}
}
var codeSearchLinkTemplate, openBugLinkTemplate *configpb.LinkTemplate
if repo != "" {
codeSearchLinkTemplate = &configpb.LinkTemplate{
Url: fmt.Sprintf("https://github.com/%s/compare/<start-custom-0>...<end-custom-0>", repo),
}
openBugLinkTemplate = &configpb.LinkTemplate{
Url: fmt.Sprintf("https://github.com/%s/issues/", repo),
}
}
jobURLPrefix := pac.ProwConfig.Plank.GetJobURLPrefix(&pj)
var openTestLinkTemplate *configpb.LinkTemplate
if jobURLPrefix != "" {
openTestLinkTemplate = &configpb.LinkTemplate{
Url: strings.TrimRight(jobURLPrefix, "/") + "/gs/<gcs_prefix>/<changelist>",
}
}
dt := &configpb.DashboardTab{
Name: tabName,
TestGroupName: testGroupName,
Description: description,
CodeSearchUrlTemplate: codeSearchLinkTemplate,
OpenBugTemplate: openBugLinkTemplate,
OpenTestTemplate: openTestLinkTemplate,
BaseOptions: baseOptions,
}
if firstDashboard {
firstDashboard = false
if emails, ok := j.Annotations[testgridEmailAnnotation]; ok {
dt.AlertOptions = &configpb.DashboardTabAlertOptions{AlertMailToAddresses: emails}
}
}
if dc != nil {
yamlcfg.ReconcileDashboardTab(dt, dc.DefaultDashboardTab)
}
d.DashboardTab = append(d.DashboardTab, dt)
}
}
return nil
}