summaryrefslogtreecommitdiff
path: root/generator/app.go
diff options
context:
space:
mode:
authorPriyanka Saggu <priyankasaggu11929@gmail.com>2023-01-20 10:51:45 +0000
committerPriyanka Saggu <priyankasaggu11929@gmail.com>2023-01-21 11:28:23 +0000
commita0bf20abbb1a8c9f83a3bf7e78aab09710af84a4 (patch)
treef17fbc3ca73a8e4936facdb7840af4a63d02c9ae /generator/app.go
parentd78fbdc3e04da54ac938755dd78972593403d8cf (diff)
auto generate list of subprojects & working-groups from annual report year
Diffstat (limited to 'generator/app.go')
-rw-r--r--generator/app.go278
1 files changed, 252 insertions, 26 deletions
diff --git a/generator/app.go b/generator/app.go
index 6d631343..09986697 100644
--- a/generator/app.go
+++ b/generator/app.go
@@ -20,6 +20,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "io"
"io/ioutil"
"log"
"net/http"
@@ -28,6 +29,7 @@ import (
"path/filepath"
"regexp"
"sort"
+ "strconv"
"strings"
"text/template"
"time"
@@ -36,6 +38,10 @@ import (
"github.com/google/go-github/v32/github"
+ "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing"
+ "github.com/go-git/go-git/v5/storage/memory"
+
yaml "gopkg.in/yaml.v3"
)
@@ -65,25 +71,23 @@ const (
// For KEPs automation
kepURL = "https://storage.googleapis.com/k8s-keps/keps.json"
+ // For Subprojects automation
+ communityRepoURL = "https://github.com/kubernetes/community.git"
+ localRepoPath = "."
)
var (
- baseGeneratorDir = ""
- templateDir = "generator"
- releases = Releases{}
- cachedKEPs = []api.Proposal{}
+ baseGeneratorDir = ""
+ templateDir = "generator"
+ releases = Releases{}
+ cachedKEPs = []api.Proposal{}
+ repo = &git.Repository{}
+ annualReportYear = time.Time{}
+ currentYear = time.Time{}
+ commitFromAnnualReportYear = &plumbing.Hash{}
+ commitFromCurrentYear = &plumbing.Hash{}
)
-// KEP represents an individual KEP holding its metadata information.
-type KEP struct {
- Name string `json:"name"`
- Title string `json:"title"`
- KepNumber string `json:"kepNumber"`
- OwningSig string `json:"owningSig"`
- Stage string `json:"stage"`
- LatestMilestone string `json:"latestMilestone"`
-}
-
type Releases struct {
Latest string
LatestMinusOne string
@@ -524,16 +528,18 @@ func getExistingContent(path string, fileFormat string) (string, error) {
}
var funcMap = template.FuncMap{
- "tzUrlEncode": tzURLEncode,
- "trimSpace": strings.TrimSpace,
- "trimSuffix": strings.TrimSuffix,
- "githubURL": githubURL,
- "orgRepoPath": orgRepoPath,
- "now": time.Now,
- "lastYear": lastYear,
- "toUpper": strings.ToUpper,
- "filterKEPs": filterKEPs,
- "getReleases": getReleases,
+ "tzUrlEncode": tzURLEncode,
+ "trimSpace": strings.TrimSpace,
+ "trimSuffix": strings.TrimSuffix,
+ "githubURL": githubURL,
+ "orgRepoPath": orgRepoPath,
+ "now": time.Now,
+ "lastYear": lastYear,
+ "toUpper": strings.ToUpper,
+ "filterKEPs": filterKEPs,
+ "getReleases": getReleases,
+ "getCategorizedSubprojects": getCategorizedSubprojects,
+ "getCategorizedWorkingGroups": getCategorizedWorkingGroups,
}
// lastYear returns the last year as a string
@@ -784,10 +790,230 @@ func writeYaml(data interface{}, path string) error {
return enc.Encode(data)
}
+// get the first commit on a given date
+func getCommitByDate(repo *git.Repository, date time.Time) (*plumbing.Hash, error) {
+ // Get the commit iterator
+ iterator, err := repo.Log(&git.LogOptions{Order: git.LogOrderCommitterTime})
+ if err != nil {
+ return nil, err
+ }
+
+ // Iterate through the commits
+ var commit *plumbing.Hash
+ for {
+ // Get the next commit
+ c, err := iterator.Next()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return nil, err
+ }
+
+ // Check if the commit date is less than or equal to the specified date
+ if c.Committer.When.Before(date) || c.Committer.When.Equal(date) {
+ commit = &c.Hash
+ break
+ }
+ }
+
+ return commit, nil
+}
+
+// get the "sigs.yaml" file from a given commit
+func getFileFromCommit(repo *git.Repository, commit *plumbing.Hash, filename string) ([]byte, error) {
+ // Get the commit object
+ obj, err := repo.CommitObject(*commit)
+ if err != nil {
+ return nil, err
+ }
+
+ // Get the commit tree
+ tree, err := obj.Tree()
+ if err != nil {
+ return nil, err
+ }
+
+ // Get the file from the tree
+ entry, err := tree.FindEntry(filename)
+ if err != nil {
+ return nil, err
+ }
+
+ // Get the file content
+ file, err := repo.BlobObject(entry.Hash)
+ if err != nil {
+ return nil, err
+ }
+
+ reader, err := file.Reader()
+ if err != nil {
+ return nil, err
+ }
+ defer reader.Close()
+
+ content, err := ioutil.ReadAll(reader)
+ if err != nil {
+ return nil, err
+ }
+
+ return content, nil
+}
+
+func getSigsYamlFromCommit(repo *git.Repository, commitFromAnnualReportYear, commitFromCurrentYear plumbing.Hash) (Context, Context, error) {
+ var annualReportYearSigs, currentYearSigs Context
+
+ annualReportYearSigFile, err := getFileFromCommit(repo, &commitFromAnnualReportYear, sigsYamlFile)
+ if err != nil {
+ return Context{}, Context{}, err
+ }
+ err = yaml.Unmarshal([]byte(annualReportYearSigFile), &annualReportYearSigs)
+ if err != nil {
+ return Context{}, Context{}, err
+ }
+
+ currentYearSigFile, err := getFileFromCommit(repo, &commitFromCurrentYear, sigsYamlFile)
+ if err != nil {
+ return Context{}, Context{}, err
+ }
+ err = yaml.Unmarshal([]byte(currentYearSigFile), &currentYearSigs)
+ if err != nil {
+ return Context{}, Context{}, err
+ }
+
+ return annualReportYearSigs, currentYearSigs, nil
+}
+
+func contains(strlist []string, val string) bool {
+ for _, str := range strlist {
+ if str == val {
+ return true
+ }
+ }
+ return false
+}
+
+func getCategorizedSubprojects(dir string) (map[string][]string, error) {
+ subprojectsMap := make(map[string][]string)
+ // set for the subprojects in the annual year
+ annualSubprojects := make(map[string]bool)
+
+ annualReportYearSigs, currentYearSigs, err := getSigsYamlFromCommit(repo, *commitFromAnnualReportYear, *commitFromCurrentYear)
+ if err != nil {
+ return nil, err
+ }
+
+ // iterate over sigs from the annual report year (say 2022)
+ for _, sig1 := range annualReportYearSigs.Sigs {
+ if sig1.Dir != dir {
+ continue
+ }
+ for _, sub1 := range sig1.Subprojects {
+ annualSubprojects[sub1.Name] = true
+ }
+ }
+
+ // iterate over sigs from the current year (say 2023)
+ for _, sig2 := range currentYearSigs.Sigs {
+ if sig2.Dir != dir {
+ continue
+ }
+ for _, sub2 := range sig2.Subprojects {
+ if annualSubprojects[sub2.Name] {
+ subprojectsMap["Continuing"] = append(subprojectsMap["Continuing"], sub2.Name)
+ delete(annualSubprojects, sub2.Name)
+ } else {
+ subprojectsMap["New"] = append(subprojectsMap["New"], sub2.Name)
+ }
+ }
+ }
+
+ for sub := range annualSubprojects {
+ subprojectsMap["Retired"] = append(subprojectsMap["Retired"], sub)
+ }
+
+ return subprojectsMap, nil
+}
+
+func getCategorizedWorkingGroups(dir string) (map[string][]string, error) {
+ workingGroupsMap := make(map[string][]string)
+
+ // set for the working groups in the annual year
+ annualWGs := make(map[string]bool)
+ annualReportYearSigs, currentYearSigs, err := getSigsYamlFromCommit(repo, *commitFromAnnualReportYear, *commitFromCurrentYear)
+ if err != nil {
+ return nil, err
+ }
+
+ annualReportYearSigs.Complete()
+ annualReportYearSigs.Sort()
+ currentYearSigs.Complete()
+ currentYearSigs.Sort()
+
+ // iterate over the ReportingWGs from the annual report year (say 2022)
+ for _, sig := range annualReportYearSigs.Sigs {
+ if sig.Dir != dir {
+ continue
+ }
+ for _, wg := range sig.ReportingWGs {
+ annualWGs[string(wg)] = true
+ }
+ }
+
+ // iterate over the ReportingWGs from the current year (say 2023)
+ for _, sig := range currentYearSigs.Sigs {
+ if sig.Dir != dir {
+ continue
+ }
+ for _, newWG := range sig.ReportingWGs {
+ if _, ok := annualWGs[string(newWG)]; !ok {
+ workingGroupsMap["New"] = append(workingGroupsMap["New"], string(newWG))
+ } else {
+ workingGroupsMap["Continuing"] = append(workingGroupsMap["Continuing"], string(newWG))
+ delete(annualWGs, string(newWG))
+ }
+ }
+ }
+
+ for wg := range annualWGs {
+ workingGroupsMap["Retired"] = append(workingGroupsMap["Retired"], string(wg))
+ }
+
+ return workingGroupsMap, nil
+}
+
func main() {
+ // prep for automated listing of subprojects in the annual report
+ intLastYear, err := strconv.Atoi(lastYear())
+ if err != nil {
+ log.Fatal(err)
+ }
+ annualReportYear = time.Date(intLastYear, time.January, 1, 0, 0, 0, 0, time.UTC)
+ currentYear = time.Date(intLastYear+1, time.January, 1, 0, 0, 0, 0, time.UTC)
+
+ repo, err = git.PlainOpen(localRepoPath)
+ if err != nil {
+ if err == git.ErrRepositoryNotExists {
+ repo, err = git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
+ URL: communityRepoURL,
+ })
+ } else {
+ log.Fatal(err)
+ }
+ }
+
+ commitFromAnnualReportYear, err = getCommitByDate(repo, annualReportYear)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ commitFromCurrentYear, err = getCommitByDate(repo, currentYear)
+ if err != nil {
+ log.Fatal(err)
+ }
- // Fetch KEPs and cache them in the keps variable
- err := fetchKEPs()
+ // fetch KEPs and cache them in the keps variable
+ err = fetchKEPs()
if err != nil {
log.Fatal(err)
}