@@ -17,9 +17,12 @@ limitations under the License.
17
17
package main
18
18
19
19
import (
20
+ "context"
21
+ "encoding/json"
20
22
"fmt"
21
23
"io/ioutil"
22
24
"log"
25
+ "net/http"
23
26
"net/url"
24
27
"os"
25
28
"path/filepath"
@@ -29,6 +32,10 @@ import (
29
32
"text/template"
30
33
"time"
31
34
35
+ "k8s.io/enhancements/api"
36
+
37
+ "github.com/google/go-github/v32/github"
38
+
32
39
yaml "gopkg.in/yaml.v3"
33
40
)
34
41
@@ -55,13 +62,101 @@ const (
55
62
56
63
regexRawGitHubURL = "https://raw.githubusercontent.com/(?P<org>[^/]+)/(?P<repo>[^/]+)/(?P<branch>[^/]+)/(?P<path>.*)"
57
64
regexGitHubURL = "https://github.com/(?P<org>[^/]+)/(?P<repo>[^/]+)/(blob|tree)/(?P<branch>[^/]+)/(?P<path>.*)"
65
+
66
+ // For KEPs automation
67
+ kepURL = "https://storage.googleapis.com/k8s-keps/keps.json"
58
68
)
59
69
60
70
var (
61
71
baseGeneratorDir = ""
62
72
templateDir = "generator"
73
+ releases = Releases {}
74
+ cachedKEPs = []api.Proposal {}
63
75
)
64
76
77
+ // KEP represents an individual KEP holding its metadata information.
78
+ type KEP struct {
79
+ Name string `json:"name"`
80
+ Title string `json:"title"`
81
+ KepNumber string `json:"kepNumber"`
82
+ OwningSig string `json:"owningSig"`
83
+ Stage string `json:"stage"`
84
+ LatestMilestone string `json:"latestMilestone"`
85
+ }
86
+
87
+ type Releases struct {
88
+ Latest string
89
+ LatestMinusOne string
90
+ LatestMinusTwo string
91
+ }
92
+
93
+ // TODO: improve as suggested in https://github.com/kubernetes/community/pull/7038#discussion_r1069456087
94
+ func getLastThreeK8sReleases () (Releases , error ) {
95
+ ctx := context .Background ()
96
+ client := github .NewClient (nil )
97
+
98
+ releases , _ , err := client .Repositories .ListReleases (ctx , "kubernetes" , "kubernetes" , nil )
99
+ if err != nil {
100
+ return Releases {}, err
101
+ }
102
+ var result Releases
103
+ result .Latest = strings .Split (strings .TrimPrefix (* releases [0 ].TagName , "v" ), "." )[0 ] + "." + strings .Split (strings .TrimPrefix (* releases [0 ].TagName , "v" ), "." )[1 ]
104
+ result .LatestMinusOne = strings .Split (strings .TrimPrefix (* releases [1 ].TagName , "v" ), "." )[0 ] + "." + strings .Split (strings .TrimPrefix (* releases [1 ].TagName , "v" ), "." )[1 ]
105
+ result .LatestMinusTwo = strings .Split (strings .TrimPrefix (* releases [2 ].TagName , "v" ), "." )[0 ] + "." + strings .Split (strings .TrimPrefix (* releases [2 ].TagName , "v" ), "." )[1 ]
106
+ return result , nil
107
+ }
108
+
109
+ func getReleases () Releases {
110
+ return releases
111
+ }
112
+
113
+ func fetchKEPs () error {
114
+ url , err := url .Parse (kepURL )
115
+ if err != nil {
116
+ return fmt .Errorf ("Error parsing url: %v" , err )
117
+ }
118
+
119
+ req , err := http .NewRequest ("GET" , url .String (), nil )
120
+ if err != nil {
121
+ return fmt .Errorf ("Error creating request: %v" , err )
122
+ }
123
+
124
+ client := & http.Client {}
125
+ resp , err := client .Do (req )
126
+ if err != nil {
127
+ return fmt .Errorf ("Error fetching KEPs: %v" , err )
128
+ }
129
+ defer resp .Body .Close ()
130
+
131
+ body , err := ioutil .ReadAll (resp .Body )
132
+ if err != nil {
133
+ return fmt .Errorf ("Error reading KEPs body: %v" , err )
134
+ }
135
+
136
+ err = json .Unmarshal (body , & cachedKEPs )
137
+ if err != nil {
138
+ return fmt .Errorf ("Error unmarshalling KEPs: %v" , err )
139
+ }
140
+ return nil
141
+ }
142
+
143
+ func filterKEPs (owningSig string , releases Releases ) (map [api.Stage ][]api.Proposal , error ) {
144
+ kepsByStage := make (map [api.Stage ][]api.Proposal )
145
+ for _ , kep := range cachedKEPs {
146
+ if kep .OwningSIG == owningSig {
147
+ for _ , stage := range api .ValidStages {
148
+ if kep .Stage == stage && (strings .HasSuffix (kep .LatestMilestone , releases .Latest ) ||
149
+ strings .HasSuffix (kep .LatestMilestone , releases .LatestMinusOne ) ||
150
+ strings .HasSuffix (kep .LatestMilestone , releases .LatestMinusTwo )) {
151
+ kepsByStage [stage ] = append (kepsByStage [stage ], kep )
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ return kepsByStage , nil
158
+ }
159
+
65
160
// FoldedString is a string that will be serialized in FoldedStyle by go-yaml
66
161
type FoldedString string
67
162
@@ -169,7 +264,8 @@ type Group struct {
169
264
Leadership LeadershipGroup `yaml:"leadership"`
170
265
Meetings []Meeting
171
266
Contact Contact
172
- Subprojects []Subproject `yaml:",omitempty"`
267
+ Subprojects []Subproject `yaml:",omitempty"`
268
+ KEPs map [string ][]api.Proposal `yaml:",omitempty"`
173
269
}
174
270
175
271
type WGName string
@@ -436,6 +532,8 @@ var funcMap = template.FuncMap{
436
532
"now" : time .Now ,
437
533
"lastYear" : lastYear ,
438
534
"toUpper" : strings .ToUpper ,
535
+ "filterKEPs" : filterKEPs ,
536
+ "getReleases" : getReleases ,
439
537
}
440
538
441
539
// lastYear returns the last year as a string
@@ -456,8 +554,9 @@ func githubURL(url string) string {
456
554
}
457
555
458
556
// orgRepoPath converts either
459
- // - a regular GitHub url of form https://github.com/org/repo/blob/branch/path/to/file
460
- // - a raw GitHub url of form https://raw.githubusercontent.com/org/repo/branch/path/to/file
557
+ // - a regular GitHub url of form https://github.com/org/repo/blob/branch/path/to/file
558
+ // - a raw GitHub url of form https://raw.githubusercontent.com/org/repo/branch/path/to/file
559
+ //
461
560
// to a string of form 'org/repo/path/to/file'
462
561
func orgRepoPath (url string ) string {
463
562
for _ , regex := range []string {regexRawGitHubURL , regexGitHubURL } {
@@ -686,10 +785,22 @@ func writeYaml(data interface{}, path string) error {
686
785
}
687
786
688
787
func main () {
788
+
789
+ // Fetch KEPs and cache them in the keps variable
790
+ err := fetchKEPs ()
791
+ if err != nil {
792
+ log .Fatal (err )
793
+ }
794
+
795
+ releases , err = getLastThreeK8sReleases ()
796
+ if err != nil {
797
+ log .Fatal (err )
798
+ }
799
+
689
800
yamlPath := filepath .Join (baseGeneratorDir , sigsYamlFile )
690
801
var ctx Context
691
802
692
- err : = readYaml (yamlPath , & ctx )
803
+ err = readYaml (yamlPath , & ctx )
693
804
if err != nil {
694
805
log .Fatal (err )
695
806
}
0 commit comments