diff options
Diffstat (limited to 'generator')
| -rw-r--r-- | generator/app.go | 171 |
1 files changed, 118 insertions, 53 deletions
diff --git a/generator/app.go b/generator/app.go index 82b3799b..543e3a9a 100644 --- a/generator/app.go +++ b/generator/app.go @@ -52,11 +52,23 @@ var ( templateDir = "generator" ) +// FoldedString is a string that will be serialized in FoldedStyle by go-yaml +type FoldedString string + +// MarshalYAML customizes how FoldedStrings will be serialized by go-yaml +func (x FoldedString) MarshalYAML() (interface{}, error) { + return &yaml.Node{ + Kind: yaml.ScalarNode, + Style: yaml.FoldedStyle, + Value: string(x), + }, nil +} + // Person represents an individual person holding a role in a group. type Person struct { + GitHub string Name string Company string - GitHub string } // Meeting represents a regular meeting for a group. @@ -66,53 +78,53 @@ type Meeting struct { Time string TZ string Frequency string - URL string - ArchiveURL string `yaml:"archive_url"` - RecordingsURL string `yaml:"recordings_url"` + URL string `yaml:",omitempty"` + ArchiveURL string `yaml:"archive_url,omitempty"` + RecordingsURL string `yaml:"recordings_url,omitempty"` } // Contact represents the various contact points for a group. type Contact struct { - Slack string - MailingList string `yaml:"mailing_list"` - PrivateMailingList string `yaml:"private_mailing_list"` - GithubTeams []GithubTeams `yaml:"teams"` + Slack string `yaml:",omitempty"` + MailingList string `yaml:"mailing_list,omitempty"` + PrivateMailingList string `yaml:"private_mailing_list,omitempty"` + GithubTeams []GithubTeam `yaml:"teams,omitempty"` } -// GithubTeams represents a specific Github Team. -type GithubTeams struct { +// GithubTeam represents a specific Github Team. +type GithubTeam struct { Name string - Description string + Description string `yaml:",omitempty"` } // Subproject represents a specific subproject owned by the group type Subproject struct { Name string - Description string - Contact *Contact + Description string `yaml:",omitempty"` + Contact *Contact `yaml:",omitempty"` Owners []string - Meetings []Meeting + Meetings []Meeting `yaml:",omitempty"` } // LeadershipGroup represents the different groups of leaders within a group type LeadershipGroup struct { Chairs []Person - TechnicalLeads []Person `yaml:"tech_leads"` - EmeritusLeads []Person `yaml:"emeritus_leads"` + TechnicalLeads []Person `yaml:"tech_leads,omitempty"` + EmeritusLeads []Person `yaml:"emeritus_leads,omitempty"` } // Group represents either a Special Interest Group (SIG) or a Working Group (WG) type Group struct { - Name string Dir string - MissionStatement string `yaml:"mission_statement,omitempty"` - CharterLink string `yaml:"charter_link,omitempty"` + Name string + MissionStatement FoldedString `yaml:"mission_statement,omitempty"` + CharterLink string `yaml:"charter_link,omitempty"` + StakeholderSIGs []string `yaml:"stakeholder_sigs,omitempty"` Label string Leadership LeadershipGroup `yaml:"leadership"` Meetings []Meeting Contact Contact - Subprojects []Subproject - StakeholderSIGs []string `yaml:"stakeholder_sigs,omitempty"` + Subprojects []Subproject `yaml:",omitempty"` } // DirName returns the directory that a group's documentation will be @@ -130,6 +142,57 @@ type Context struct { Committees []Group } +// PrefixToGroupMap returns a map of prefix to groups, useful for iteration over all groups +func (c *Context) PrefixToGroupMap() map[string][]Group { + return map[string][]Group{ + "sig": c.Sigs, + "wg": c.WorkingGroups, + "ug": c.UserGroups, + "committee": c.Committees, + } +} + +// Sort sorts all lists within the Context struct +func (c *Context) Sort() { + for _, groups := range c.PrefixToGroupMap() { + sort.Slice(groups, func(i, j int) bool { + return groups[i].Dir < groups[j].Dir + }) + for _, group := range groups { + sort.Strings(group.StakeholderSIGs) + for _, people := range [][]Person{ + group.Leadership.Chairs, + group.Leadership.TechnicalLeads, + group.Leadership.EmeritusLeads} { + sort.Slice(people, func(i, j int) bool { + // This ensure OWNERS / OWNERS_ALIAS files are ordered by github + return people[i].GitHub < people[j].GitHub + }) + } + sort.Slice(group.Meetings, func(i, j int) bool { + return group.Meetings[i].Description < group.Meetings[j].Description + }) + sort.Slice(group.Contact.GithubTeams, func(i, j int) bool { + return group.Contact.GithubTeams[i].Name < group.Contact.GithubTeams[j].Name + }) + sort.Slice(group.Subprojects, func(i, j int) bool { + return group.Subprojects[i].Name < group.Subprojects[j].Name + }) + for _, subproject := range group.Subprojects { + if subproject.Contact != nil { + sort.Slice(subproject.Contact.GithubTeams, func(i, j int) bool { + return subproject.Contact.GithubTeams[i].Name < subproject.Contact.GithubTeams[j].Name + }) + } + sort.Strings(subproject.Owners) + sort.Slice(subproject.Meetings, func(i, j int) bool { + return subproject.Meetings[i].Description < subproject.Meetings[j].Description + }) + } + } + } +} + func pathExists(path string) bool { _, err := os.Stat(path) return err == nil @@ -182,14 +245,14 @@ func getExistingContent(path string, fileFormat string) (string, error) { } var funcMap = template.FuncMap{ - "tzUrlEncode": tzUrlEncode, + "tzUrlEncode": tzURLEncode, "trimSpace": strings.TrimSpace, } // tzUrlEncode returns a url encoded string without the + shortcut. This is // required as the timezone conversion site we are using doesn't recognize + as // a valid url escape character. -func tzUrlEncode(tz string) string { +func tzURLEncode(tz string) string { return strings.Replace(url.QueryEscape(tz), "+", "%20", -1) } @@ -289,52 +352,54 @@ func createGroupReadme(groups []Group, prefix string) error { return nil } -func main() { - yamlData, err := ioutil.ReadFile(filepath.Join(baseGeneratorDir, sigsYamlFile)) +// readSigsYaml decodes yaml stored in a file at path into the +// specified yaml.Node +func readYaml(path string, data interface{}) error { + file, err := os.Open(path) if err != nil { - log.Fatal(err) + return err } + defer file.Close() + decoder := yaml.NewDecoder(file) + decoder.KnownFields(true) + return decoder.Decode(data) +} - var ctx Context - err = yaml.Unmarshal(yamlData, &ctx) +// writeSigsYaml writes the specified data to a file at path +// indent is set to 2 spaces +func writeYaml(data interface{}, path string) error { + file, err := os.Create(path) if err != nil { - log.Fatal(err) + return err } + defer file.Close() + enc := yaml.NewEncoder(file) + enc.SetIndent(2) + return enc.Encode(data) +} - sort.Slice(ctx.Sigs, func(i, j int) bool { - return strings.ToLower(ctx.Sigs[i].Name) <= strings.ToLower(ctx.Sigs[j].Name) - }) - - sort.Slice(ctx.WorkingGroups, func(i, j int) bool { - return strings.ToLower(ctx.WorkingGroups[i].Name) <= strings.ToLower(ctx.WorkingGroups[j].Name) - }) - - sort.Slice(ctx.UserGroups, func(i, j int) bool { - return strings.ToLower(ctx.UserGroups[i].Name) <= strings.ToLower(ctx.UserGroups[j].Name) - }) - - sort.Slice(ctx.Committees, func(i, j int) bool { - return strings.ToLower(ctx.Committees[i].Name) <= strings.ToLower(ctx.Committees[j].Name) - }) +func main() { + yamlPath := filepath.Join(baseGeneratorDir, sigsYamlFile) + var ctx Context - err = createGroupReadme(ctx.Sigs, "sig") + err := readYaml(yamlPath, &ctx) if err != nil { log.Fatal(err) } - err = createGroupReadme(ctx.WorkingGroups, "wg") - if err != nil { - log.Fatal(err) - } + ctx.Sort() - err = createGroupReadme(ctx.UserGroups, "ug") + // Write the Context struct back to yaml to enforce formatting + err = writeYaml(&ctx, yamlPath) if err != nil { log.Fatal(err) } - err = createGroupReadme(ctx.Committees, "committee") - if err != nil { - log.Fatal(err) + for prefix, groups := range ctx.PrefixToGroupMap() { + err = createGroupReadme(groups, prefix) + if err != nil { + log.Fatal(err) + } } fmt.Println("Generating sig-list.md") |
