vitess.io/vitess@v0.16.2/go/tools/releases/releases.go (about)

     1  /*
     2  Copyright 2023 The Vitess Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  // The changelog directory is composed of a README that lists
    20  // and links to all major releases of Vitess. It has one
    21  // sub-directory for each major version. Each sub-directory is
    22  // composed of another README that also lists and links all the
    23  // patch releases of this major release. Those sub-directories
    24  // are composed of one directory per patch release. Finally,
    25  // the patch release directory contains the old files markdown:
    26  // summary, release_notes, changelog.
    27  //
    28  // This tool is solely responsible for generating the READMEs
    29  // and making sure they are up-to-date with the list of major
    30  // and patch releases we have.
    31  
    32  import (
    33  	"log"
    34  	"os"
    35  	"path"
    36  	"sort"
    37  	"strings"
    38  	"text/template"
    39  )
    40  
    41  const (
    42  	rootDir = "./changelog/"
    43  
    44  	rootFileTmpl = `## Releases
    45  
    46  {{- range $r := .SubDirs }}
    47  * [{{ $r.Name }}]({{ $r.Name }})
    48  {{- end -}}
    49  `
    50  
    51  	majorVersionTmpl = `## v{{ .Name }}
    52  
    53  {{- if .Team }}
    54  The dedicated team for this release can be found [here]({{.Team}}).{{ end }}
    55  
    56  {{- range $r := .SubDirs }}
    57  * **[{{ $r.Name }}]({{ $r.Name }})**
    58  {{ if $r.Changelog }}	* [Changelog]({{ $r.Name }}/{{ $r.Changelog }})
    59  {{ end -}}
    60  {{ if $r.ReleaseNotes }}	* [Release Notes]({{ $r.Name }}/{{ $r.ReleaseNotes }})
    61  {{ end -}}
    62  {{- end -}}
    63  `
    64  )
    65  
    66  type dir struct {
    67  	Name         string
    68  	Path         string
    69  	Changelog    string
    70  	ReleaseNotes string
    71  	Team         string
    72  	SubDirs      []dir
    73  }
    74  
    75  func main() {
    76  	rootDir, err := getDirs(dir{Path: rootDir})
    77  	if err != nil {
    78  		log.Fatal(err)
    79  	}
    80  
    81  	err = execReadMeTemplateWithDir(rootDir, rootFileTmpl)
    82  	if err != nil {
    83  		log.Fatal(err)
    84  	}
    85  
    86  	for _, subDir := range rootDir.SubDirs {
    87  		err := execReadMeTemplateWithDir(subDir, majorVersionTmpl)
    88  		if err != nil {
    89  			log.Fatal(err)
    90  		}
    91  	}
    92  }
    93  
    94  func execReadMeTemplateWithDir(d dir, tmpl string) error {
    95  	rootRM, err := os.OpenFile(path.Join(d.Path, "README.md"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0640)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	t := template.Must(template.New("root_readme").Parse(tmpl))
   101  	err = t.ExecuteTemplate(rootRM, "root_readme", d)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	return nil
   106  }
   107  
   108  func getDirs(curDir dir) (dir, error) {
   109  	entries, err := os.ReadDir(curDir.Path)
   110  	if err != nil {
   111  		return dir{}, err
   112  	}
   113  
   114  	for _, entry := range entries {
   115  		if entry.IsDir() {
   116  			subDir, err := getDirs(dir{
   117  				Name: entry.Name(),
   118  				Path: path.Join(curDir.Path, entry.Name()),
   119  			})
   120  			if err != nil {
   121  				return dir{}, err
   122  			}
   123  			curDir.SubDirs = append(curDir.SubDirs, subDir)
   124  			continue
   125  		}
   126  
   127  		switch {
   128  		case strings.Contains(entry.Name(), "changelog.md"):
   129  			curDir.Changelog = entry.Name()
   130  		case strings.Contains(entry.Name(), "release_notes.md"):
   131  			curDir.ReleaseNotes = entry.Name()
   132  		case strings.Contains(entry.Name(), "team.md"):
   133  			curDir.Team = entry.Name()
   134  		}
   135  	}
   136  	sort.Slice(curDir.SubDirs, func(i, j int) bool {
   137  		if len(curDir.SubDirs[i].Name) < len(curDir.SubDirs[j].Name) {
   138  			return false
   139  		}
   140  		return curDir.SubDirs[i].Name > curDir.SubDirs[j].Name
   141  	})
   142  	return curDir, nil
   143  }