diff --git a/cmd/schedule-builder/cmd/markdown.go b/cmd/schedule-builder/cmd/markdown.go index f3e40032ac9..adad507f259 100644 --- a/cmd/schedule-builder/cmd/markdown.go +++ b/cmd/schedule-builder/cmd/markdown.go @@ -60,6 +60,51 @@ func parseSchedule(patchSchedule PatchSchedule) string { return scheduleOut } +func parseReleaseSchedule(releaseSchedule ReleaseSchedule) string { + output := []string{} + output = append(output, fmt.Sprintf("# Kubernetes %s\n", releaseSchedule.Releases[0].Version)) + + output = append(output, fmt.Sprintf("#### Links\n")) + for _, link := range releaseSchedule.Releases[0].Links { + output = append(output, fmt.Sprintf("* [%s](%s)\n", link.Text, link.Href)) + } + output = append(output, fmt.Sprintf("#### Tracking docs\n")) + for _, trackingDocs := range releaseSchedule.Releases[0].TrackingDocs { + output = append(output, fmt.Sprintf("* [%s](%s)\n", trackingDocs.Text, trackingDocs.Href)) + } + + output = append(output, fmt.Sprintf("#### Guides\n")) + for _, guide := range releaseSchedule.Releases[0].Guides { + output = append(output, fmt.Sprintf("* [%s](%s)\n", guide.Text, guide.Href)) + } + + output = append(output, fmt.Sprintf("## Timeline\n")) + for _, releaseSchedule := range releaseSchedule.Releases { + tableString := &strings.Builder{} + table := tablewriter.NewWriter(tableString) + table.SetAutoWrapText(false) + table.SetHeader([]string{"**What**", "**Who**", "**When**", "**WEEK**", "**CI Signal**"}) + + for _, timeline := range releaseSchedule.Timeline { + table.Append([]string{strings.TrimSpace(timeline.What), strings.TrimSpace(timeline.Who), strings.TrimSpace(timeline.When), strings.TrimSpace(timeline.Week), strings.TrimSpace(timeline.CISignal), ""}) + + } + + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + table.Render() + + output = append(output, tableString.String()) + } + + scheduleOut := strings.Join(output, "\n") + + logrus.Info("Release Schedule parsed") + println(scheduleOut) + + return scheduleOut +} + func patchReleaseInPreviousList(a string, previousPatches []PreviousPatches) bool { for _, b := range previousPatches { if b.Release == a { diff --git a/cmd/schedule-builder/cmd/model.go b/cmd/schedule-builder/cmd/model.go index eecf4564778..93401ca3436 100644 --- a/cmd/schedule-builder/cmd/model.go +++ b/cmd/schedule-builder/cmd/model.go @@ -38,3 +38,38 @@ type Schedule struct { EndOfLifeDate string `yaml:"endOfLifeDate"` PreviousPatches []PreviousPatches `yaml:"previousPatches"` } + +type ReleaseSchedule struct { + Releases []Release `yaml:"releases"` +} + +type Release struct { + Version string `yaml:"version"` + Links []Link `yaml:"links"` + TrackingDocs []TrackingDoc `yaml:"trackingDocs"` + Guides []Guide `yaml:"guides"` + Timeline []Timeline `yaml:"timeline"` +} + +type Link struct { + Href string `yaml:"href"` + Text string `yaml:"text"` +} + +type TrackingDoc struct { + Href string `yaml:"href"` + Text string `yaml:"text"` +} + +type Guide struct { + Href string `yaml:"href"` + Text string `yaml:"text"` +} + +type Timeline struct { + What string `yaml:"what"` + Who string `yaml:"who"` + When string `yaml:"when"` + Week string `yaml:"week"` + CISignal string `yaml:"ciSignal"` +} diff --git a/cmd/schedule-builder/cmd/root.go b/cmd/schedule-builder/cmd/root.go index 2a328d682a8..dd407792b84 100644 --- a/cmd/schedule-builder/cmd/root.go +++ b/cmd/schedule-builder/cmd/root.go @@ -30,9 +30,9 @@ import ( // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ - Use: "schedule-builder --config-path path/to/schedule.yaml [--output-file ]", + Use: "schedule-builder --config-path path/to/schedule.yaml --type-file /or/[--output-file ]", Short: "schedule-builder generate a humam readable format of the Kubernetes release schedule", - Example: "schedule-builder --config-path /home/user/kubernetes/sig-release/releases/schedule.yaml", + Example: "schedule-builder --config-path /home/user/kubernetes/sig-release/releases/schedule.yaml --type-file patch", SilenceUsage: true, SilenceErrors: true, PersistentPreRunE: initLogging, @@ -45,6 +45,7 @@ type options struct { configPath string outputFile string logLevel string + typeFile string } var opts = &options{} @@ -52,10 +53,12 @@ var opts = &options{} const ( configPathFlag = "config-path" outputFileFlag = "output-file" + typeFileFlag = "type-file" ) var requiredFlags = []string{ configPathFlag, + typeFileFlag, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -88,6 +91,13 @@ func init() { fmt.Sprintf("the logging verbosity, either %s", log.LevelNames()), ) + rootCmd.PersistentFlags().StringVar( + &opts.typeFile, + typeFileFlag, + "patch", + "type of file to be produced - release cycle schedule or patch schedule. To be set to `release` or `patch` and respective yaml needs to be supplied with --config-path", + ) + for _, flag := range requiredFlags { if err := rootCmd.MarkPersistentFlagRequired(flag); err != nil { logrus.Fatal(err) @@ -110,17 +120,34 @@ func run(opts *options) error { return errors.Wrap(err, "failed to read the file") } - var patchSchedule PatchSchedule + var ( + patchSchedule PatchSchedule + releaseSchedule ReleaseSchedule + scheduleOut string + ) logrus.Info("Parsing the schedule...") - err = yaml.UnmarshalStrict(data, &patchSchedule) - if err != nil { - return errors.Wrap(err, "failed to decode the file") - } - logrus.Info("Generating the markdown output...") + if opts.typeFile == "patch" { + err = yaml.UnmarshalStrict(data, &patchSchedule) + if err != nil { + return errors.Wrap(err, "failed to decode the file") + } + + logrus.Info("Generating the markdown output...") + scheduleOut = parseSchedule(patchSchedule) + } else if opts.typeFile == "release" { + + err = yaml.UnmarshalStrict(data, &releaseSchedule) + if err != nil { + return errors.Wrap(err, "failed to decode the file") + } - scheduleOut := parseSchedule(patchSchedule) + logrus.Info("Generating the markdown output...") + scheduleOut = parseReleaseSchedule(releaseSchedule) + } else { + return errors.New("type-file must be either `release` or `patch`") + } if opts.outputFile != "" { logrus.Infof("Saving schedule to a file %s.", opts.outputFile)