Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
442d4ce
commit 418632a
Showing
7 changed files
with
691 additions
and
0 deletions.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
cmd/branchingconfigmanagers/generated-release-gating-jobs/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
generated-release-gating-jobs |
14 changes: 14 additions & 0 deletions
14
cmd/branchingconfigmanagers/generated-release-gating-jobs/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Generated release gating jobs manager | ||
This manager attempts to automatize step (2.) of "[Few weeks before branching day](https://docs.google.com/document/d/1Z6ejnDCOCvNv9PWkyNPzVbjuLbDMAAT5GEeDpzb0SMs/edit#heading=h.r9xn02r1cyfn)" phase. | ||
|
||
## Usage | ||
### Options: | ||
- `--current-release` specifies the current OCP version | ||
- `--release-repo` is the absolution path to `openshift/release` repository | ||
|
||
### Example | ||
```sh | ||
$ ./generated-release-gating-jobs \ | ||
--current-release "4.12" \ | ||
--release-repo "/full/path/to/openshift/release/repo" | ||
``` |
84 changes: 84 additions & 0 deletions
84
cmd/branchingconfigmanagers/generated-release-gating-jobs/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"flag" | ||
"fmt" | ||
"path" | ||
"time" | ||
|
||
"github.com/sirupsen/logrus" | ||
|
||
utilerrors "k8s.io/apimachinery/pkg/util/errors" | ||
|
||
"github.com/openshift/ci-tools/pkg/api/ocplifecycle" | ||
"github.com/openshift/ci-tools/pkg/branchcuts/bumper" | ||
cioperatorcfg "github.com/openshift/ci-tools/pkg/config" | ||
) | ||
|
||
const ( | ||
releaseJobsPath = "ci-operator/config/openshift/release" | ||
) | ||
|
||
type options struct { | ||
curOCPVersion string | ||
releaseRepoDir string | ||
logLevel int | ||
newIntervalValue int | ||
} | ||
|
||
func gatherOptions() (*options, error) { | ||
var errs []error | ||
o := &options{} | ||
flag.StringVar(&o.curOCPVersion, "current-release", "", "Current OCP version") | ||
flag.StringVar(&o.releaseRepoDir, "release-repo", "", "Path to 'openshift/release/ folder") | ||
flag.IntVar(&o.newIntervalValue, "interval", 168, "New interval to set") | ||
flag.IntVar(&o.logLevel, "log-level", int(logrus.DebugLevel), "Log level") | ||
flag.Parse() | ||
|
||
if _, err := ocplifecycle.ParseMajorMinor(o.curOCPVersion); o.curOCPVersion != "" && err != nil { | ||
errs = append(errs, fmt.Errorf("error parsing current-release %s", o.curOCPVersion)) | ||
} | ||
|
||
if o.newIntervalValue < 0 { | ||
errs = append(errs, errors.New("error parsing interval: value is not a positive integer")) | ||
} | ||
|
||
if o.releaseRepoDir != "" { | ||
if !path.IsAbs(o.releaseRepoDir) { | ||
errs = append(errs, errors.New("error parsing release repo path: path has to be absolute")) | ||
} | ||
} else { | ||
errs = append(errs, errors.New("error parsing release repo path: path is mandatory")) | ||
} | ||
|
||
return o, utilerrors.NewAggregate(errs) | ||
} | ||
|
||
func main() { | ||
o, err := gatherOptions() | ||
if err != nil { | ||
logrus.WithError(err).Fatal("failed to gather options") | ||
} | ||
|
||
logrus.SetLevel(logrus.Level(o.logLevel)) | ||
logrus.Debugf("using options %+v", o) | ||
|
||
if err := reconcile(time.Now(), o); err != nil { | ||
logrus.WithError(err).Fatal("failed to reconcile the status") | ||
} | ||
logrus.Info("status reconciled") | ||
} | ||
|
||
func reconcile(now time.Time, o *options) error { | ||
logrus.Debugf("using options %+v", o) | ||
releaseJobsDir := path.Join(o.releaseRepoDir, releaseJobsPath) | ||
b, err := bumper.NewGeneratedReleaseGatingJobsBumper(o.curOCPVersion, releaseJobsDir, o.newIntervalValue) | ||
if err != nil { | ||
return fmt.Errorf("new bumper: %w", err) | ||
} | ||
if err := bumper.Bump[*cioperatorcfg.DataWithInfo](b, &bumper.BumpingOptions{}); err != nil { | ||
return fmt.Errorf("bumper: %w", err) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
package bumper | ||
|
||
import ( | ||
"fmt" | ||
"io/fs" | ||
"path" | ||
"path/filepath" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/sirupsen/logrus" | ||
|
||
cioperatorapi "github.com/openshift/ci-tools/pkg/api" | ||
"github.com/openshift/ci-tools/pkg/api/ocplifecycle" | ||
cioperatorcfg "github.com/openshift/ci-tools/pkg/config" | ||
) | ||
|
||
const ( | ||
releaseJobsRegexPatternFormat = `openshift-release-master__(okd|ci|nightly|okd-scos)-%s.*\.yaml` | ||
ocpReleaseEnvVarName = "OCP_VERSION" | ||
) | ||
|
||
type GeneratedReleaseGatingJobsBumper struct { | ||
mm *ocplifecycle.MajorMinor | ||
getFilesRegexp *regexp.Regexp | ||
jobsDir string | ||
newIntervalValue int | ||
} | ||
|
||
var _ Bumper[*cioperatorcfg.DataWithInfo] = &GeneratedReleaseGatingJobsBumper{} | ||
|
||
func NewGeneratedReleaseGatingJobsBumper(ocpVer, jobsDir string, newIntervalValue int) (*GeneratedReleaseGatingJobsBumper, error) { | ||
mm, err := ocplifecycle.ParseMajorMinor(ocpVer) | ||
if err != nil { | ||
return nil, fmt.Errorf("parse release: %w", err) | ||
} | ||
mmRegexp := fmt.Sprintf("%d\\.%d", mm.Major, mm.Minor) | ||
getFilesRegexp := regexp.MustCompile(fmt.Sprintf(releaseJobsRegexPatternFormat, mmRegexp)) | ||
return &GeneratedReleaseGatingJobsBumper{ | ||
mm, | ||
getFilesRegexp, | ||
jobsDir, | ||
newIntervalValue, | ||
}, nil | ||
} | ||
|
||
func (b *GeneratedReleaseGatingJobsBumper) GetFiles() ([]string, error) { | ||
files := make([]string, 0) | ||
err := filepath.Walk(b.jobsDir, func(path string, info fs.FileInfo, err error) error { | ||
if b.getFilesRegexp.Match([]byte(path)) { | ||
files = append(files, path) | ||
} | ||
return nil | ||
}) | ||
return files, err | ||
} | ||
|
||
func (b *GeneratedReleaseGatingJobsBumper) Unmarshall(file string) (*cioperatorcfg.DataWithInfo, error) { | ||
cfgDataByFilename, err := cioperatorcfg.LoadDataByFilename(file) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
filename := path.Base(file) | ||
dataWithInfo, ok := cfgDataByFilename[filename] | ||
if !ok { | ||
logrus.WithError(err).Errorf("failed to get config %s", file) | ||
return nil, fmt.Errorf("can't get data %s", filename) | ||
} | ||
return &dataWithInfo, nil | ||
} | ||
|
||
func (b *GeneratedReleaseGatingJobsBumper) BumpFilename( | ||
filename string, | ||
dataWithInfo *cioperatorcfg.DataWithInfo) (string, error) { | ||
newVariant, err := ReplaceWithNextVersion(dataWithInfo.Info.Metadata.Variant, b.mm.Major) | ||
if err != nil { | ||
return "", err | ||
} | ||
dataWithInfo.Info.Metadata.Variant = newVariant | ||
return dataWithInfo.Info.Metadata.Basename(), nil | ||
} | ||
|
||
/* | ||
Candidate bumping fields: | ||
.base_images.*.name | ||
.releases.*.{release,candidate}.version | ||
.releases.*.prerelease.version_bounds.{lower,upper} | ||
.tests[].steps.test[].env[].default | ||
*/ | ||
func (b *GeneratedReleaseGatingJobsBumper) BumpContent(dataWithInfo *cioperatorcfg.DataWithInfo) (*cioperatorcfg.DataWithInfo, error) { | ||
major := b.mm.Major | ||
config := &dataWithInfo.Configuration | ||
if err := bumpBaseImages(config, major); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := bumpReleases(config, major); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := bumpTests(config, major); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := ReplaceWithNextVersionInPlace(&config.Metadata.Variant, major); err != nil { | ||
return nil, err | ||
} | ||
|
||
if config.Tests != nil { | ||
for i := 0; i < len(config.Tests); i++ { | ||
if config.Tests[i].Interval != nil { | ||
*config.Tests[i].Interval = strconv.Itoa(b.newIntervalValue) + "h" | ||
} | ||
} | ||
} | ||
|
||
return dataWithInfo, nil | ||
} | ||
|
||
func bumpBaseImages(config *cioperatorapi.ReleaseBuildConfiguration, major int) error { | ||
if config.BaseImages == nil { | ||
return nil | ||
} | ||
|
||
bumpedImages := make(map[string]cioperatorapi.ImageStreamTagReference) | ||
for k := range config.BaseImages { | ||
image := config.BaseImages[k] | ||
if err := ReplaceWithNextVersionInPlace(&image.Name, major); err != nil { | ||
return err | ||
} | ||
bumpedImages[k] = image | ||
} | ||
config.BaseImages = bumpedImages | ||
return nil | ||
} | ||
|
||
func bumpReleases(config *cioperatorapi.ReleaseBuildConfiguration, major int) error { | ||
if config.Releases == nil { | ||
return nil | ||
} | ||
|
||
bumpedReleases := make(map[string]cioperatorapi.UnresolvedRelease) | ||
for k := range config.Releases { | ||
release := config.Releases[k] | ||
if release.Release != nil { | ||
if err := ReplaceWithNextVersionInPlace(&release.Release.Version, major); err != nil { | ||
return err | ||
} | ||
} | ||
if release.Candidate != nil { | ||
if err := ReplaceWithNextVersionInPlace(&release.Candidate.Version, major); err != nil { | ||
return err | ||
} | ||
} | ||
if release.Prerelease != nil { | ||
if err := ReplaceWithNextVersionInPlace(&release.Prerelease.VersionBounds.Upper, major); err != nil { | ||
return err | ||
} | ||
if err := ReplaceWithNextVersionInPlace(&release.Prerelease.VersionBounds.Lower, major); err != nil { | ||
return err | ||
} | ||
} | ||
bumpedReleases[k] = release | ||
} | ||
config.Releases = bumpedReleases | ||
return nil | ||
} | ||
|
||
func bumpTests(config *cioperatorapi.ReleaseBuildConfiguration, major int) error { | ||
if config.Tests == nil { | ||
return nil | ||
} | ||
|
||
for i := 0; i < len(config.Tests); i++ { | ||
test := config.Tests[i] | ||
|
||
if test.MultiStageTestConfiguration == nil { | ||
continue | ||
} | ||
|
||
if err := bumpTestSteps(test.MultiStageTestConfiguration.Pre, major); err != nil { | ||
return err | ||
} | ||
if err := bumpTestSteps(test.MultiStageTestConfiguration.Test, major); err != nil { | ||
return err | ||
} | ||
if err := bumpTestSteps(test.MultiStageTestConfiguration.Post, major); err != nil { | ||
return err | ||
} | ||
|
||
if err := ReplaceWithNextVersionInPlace(test.MultiStageTestConfiguration.Workflow, major); err != nil { | ||
return err | ||
} | ||
|
||
config.Tests[i] = test | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func bumpTestSteps(tests []cioperatorapi.TestStep, major int) error { | ||
if tests == nil { | ||
return nil | ||
} | ||
for i := 0; i < len(tests); i++ { | ||
multistageTest := tests[i] | ||
if err := bumpTestStepEnvVars(multistageTest, major); err != nil { | ||
return err | ||
} | ||
tests[i] = multistageTest | ||
} | ||
return nil | ||
} | ||
|
||
func bumpTestStepEnvVars(multistageTest cioperatorapi.TestStep, major int) error { | ||
if multistageTest.LiteralTestStep == nil || multistageTest.LiteralTestStep.Environment == nil { | ||
return nil | ||
} | ||
for i := 0; i < len(multistageTest.Environment); i++ { | ||
env := multistageTest.Environment[i] | ||
if env.Name == ocpReleaseEnvVarName { | ||
if err := ReplaceWithNextVersionInPlace(env.Default, major); err != nil { | ||
return err | ||
} | ||
} | ||
multistageTest.Environment[i] = env | ||
} | ||
return nil | ||
} | ||
|
||
func (b *GeneratedReleaseGatingJobsBumper) Marshall(dataWithInfo *cioperatorcfg.DataWithInfo, bumpedFilename, dir string) error { | ||
absolutePath := path.Join(dir, bumpedFilename) | ||
dirNoOrgRepo := strings.TrimSuffix(absolutePath, dataWithInfo.Info.Metadata.RelativePath()) | ||
if err := dataWithInfo.CommitTo(dirNoOrgRepo); err != nil { | ||
logrus.WithError(err).Errorf("error saving config %s", dirNoOrgRepo) | ||
return fmt.Errorf("commit to %s failed: %w", dirNoOrgRepo, err) | ||
} | ||
return nil | ||
} |
Oops, something went wrong.