@@ -20,6 +20,7 @@ import (
20
20
"context"
21
21
"encoding/json"
22
22
"fmt"
23
+ "io/ioutil"
23
24
"strings"
24
25
25
26
"github.com/blang/semver"
@@ -66,7 +67,11 @@ permissions to your fork of k/sig-release and k-sigs/release-notes.`,
66
67
}
67
68
68
69
type releaseNotesOptions struct {
69
- tag string
70
+ tag string
71
+ draftOrg string
72
+ draftRepo string
73
+ createDraftPR bool
74
+ outputDir string
70
75
}
71
76
72
77
type releaseNotesResult struct {
@@ -85,6 +90,38 @@ func init() {
85
90
"version tag for the notes" ,
86
91
)
87
92
93
+ releaseNotesCmd .PersistentFlags ().StringVarP (
94
+ & releaseNotesOpts .draftOrg ,
95
+ "draft-org" ,
96
+ "" ,
97
+ "" ,
98
+ "a Github organization or user where the Release Notes PR will be created" ,
99
+ )
100
+
101
+ releaseNotesCmd .PersistentFlags ().StringVarP (
102
+ & releaseNotesOpts .draftRepo ,
103
+ "draft-repo" ,
104
+ "" ,
105
+ "" ,
106
+ "the name of a Github repository where the Release Notes PR will be created" ,
107
+ )
108
+
109
+ releaseNotesCmd .PersistentFlags ().BoolVarP (
110
+ & releaseNotesOpts .createDraftPR ,
111
+ "create-draft-pr" ,
112
+ "" ,
113
+ false ,
114
+ "create the Release Notes draft PR. --draft-org and --draft-repo muste be set along with this option" ,
115
+ )
116
+
117
+ releaseNotesCmd .PersistentFlags ().StringVarP (
118
+ & releaseNotesOpts .outputDir ,
119
+ "output-dir" ,
120
+ "o" ,
121
+ "" ,
122
+ "output a copy of the release notes to this directory" ,
123
+ )
124
+
88
125
rootCmd .AddCommand (releaseNotesCmd )
89
126
}
90
127
@@ -113,12 +150,116 @@ func runReleaseNotes() (err error) {
113
150
logrus .Infof ("Using start tag %v" , start )
114
151
logrus .Infof ("Using end tag %v" , tag )
115
152
116
- _ , err = releaseNotesFrom (start )
153
+ if releaseNotesOpts .createDraftPR {
154
+ err = validateDraftPROptions ()
155
+ if err != nil {
156
+ return errors .Wrap (err , "validating PR command line options" )
157
+ }
158
+ }
159
+
160
+ result , err := releaseNotesFrom (start )
117
161
if err != nil {
118
162
return errors .Wrapf (err , "generating release notes" )
119
163
}
120
164
121
- //TODO: implement PR creation for k-sigs/release-notes and k/sig-release
165
+ // Create RN draft PR
166
+ if releaseNotesOpts .createDraftPR {
167
+ err = createDraftPR (tag , result )
168
+ if err != nil {
169
+ return errors .Wrap (err , "Failed to create release notes draft PR" )
170
+ }
171
+ }
172
+
173
+ if releaseNotesOpts .outputDir != "" {
174
+ err = ioutil .WriteFile (releaseNotesOpts .outputDir + "release-notes.json" , []byte (result .json ), 0644 )
175
+ if err != nil {
176
+ return errors .Wrap (err , "writing release notes JSON file" )
177
+ }
178
+
179
+ err = ioutil .WriteFile (releaseNotesOpts .outputDir + "release-notes.md" , []byte (result .json ), 0644 )
180
+ if err != nil {
181
+ return errors .Wrap (err , "writing release notes markdown file" )
182
+ }
183
+ }
184
+
185
+ // TODO: implement PR creation for k-sigs/release-notes
186
+ return nil
187
+ }
188
+
189
+ // validateDraftPROptions checks if we have all needed parameters to create the Release Notes PR
190
+ func validateDraftPROptions () error {
191
+ if releaseNotesOpts .createDraftPR {
192
+ // Check if --draft-org is set
193
+ if releaseNotesOpts .draftOrg == "" {
194
+ return errors .New ("cannot generate Release Notes draft PR without --draft-org" )
195
+ }
196
+
197
+ // Check if --draft-repo is set
198
+ if releaseNotesOpts .draftRepo == "" {
199
+ return errors .New ("cannot generate Release Notes draft PR without --draft-repo" )
200
+ }
201
+ }
202
+ return nil
203
+ }
204
+
205
+ // createDraftPR pushes the release notes draft to the users fork
206
+ func createDraftPR (tag string , result * releaseNotesResult ) error {
207
+ s , err := util .TagStringToSemver (tag )
208
+ if err != nil {
209
+ return errors .Wrapf (err , "no valid tag: %v" , tag )
210
+ }
211
+
212
+ // checkout kubernetes/sig-release
213
+ sigReleaseRepo , err := git .CloneOrOpenGitHubRepo ("" , "kubernetes" , "sig-release" , true )
214
+ if err != nil {
215
+ return errors .Wrap (err , "cloning k/sig-release" )
216
+ }
217
+
218
+ // add the user's fork as a remote
219
+ err = sigReleaseRepo .AddRemote ("userfork" , releaseNotesOpts .draftOrg , releaseNotesOpts .draftRepo )
220
+ if err != nil {
221
+ return errors .Wrap (err , "adding users fork as remote repository" )
222
+ }
223
+
224
+ // verify the branch doesn't already exist on the user's fork
225
+ err = sigReleaseRepo .HasRemoteBranch ("release-notes-draft-" + tag )
226
+ if err == nil {
227
+ return errors .New (fmt .Sprintf ("Remote repo already has a branch named release-notes-draft-%s" , tag ))
228
+ }
229
+
230
+ // checkout the new branch
231
+ err = sigReleaseRepo .Checkout ("-b" , "release-notes-draft-" + tag )
232
+ if err != nil {
233
+ return errors .Wrapf (err , "creating new branch %s" , "release-notes-draft-" + tag )
234
+ }
235
+
236
+ // generate the notes
237
+ targetdir := sigReleaseRepo .Dir () + fmt .Sprintf ("/releases/release-%d.%d" , s .Major , s .Minor )
238
+ logrus .Debugf ("Release notes markdown will be written to %s" , targetdir )
239
+ err = ioutil .WriteFile (targetdir + "/release-notes-draft.md" , []byte (result .markdown ), 0644 )
240
+ if err != nil {
241
+ return errors .Wrapf (err , "writing release notes draft" )
242
+ }
243
+
244
+ // commit the results
245
+ err = sigReleaseRepo .Add (fmt .Sprintf ("releases/release-%d.%d" , s .Major , s .Minor ) + "/release-notes-draft.md" )
246
+ if err != nil {
247
+ return errors .Wrap (err , "adding release notes draft to staging area" )
248
+ }
249
+
250
+ err = sigReleaseRepo .Commit ("Release Notes draft for k/k " + tag )
251
+ if err != nil {
252
+ return errors .Wrapf (err , "Error creating commit in %s/%s" , releaseNotesOpts .draftOrg , releaseNotesOpts .draftRepo )
253
+ }
254
+
255
+ // push to fork
256
+ logrus .Infof ("Pushing release notes draft to %s/%s" , releaseNotesOpts .draftOrg , releaseNotesOpts .draftRepo )
257
+ err = sigReleaseRepo .PushToRemote ("userfork" , "release-notes-draft-" + tag )
258
+ if err != nil {
259
+ return errors .Wrapf (err , "pushing changes to %s/%s" , releaseNotesOpts .draftOrg , releaseNotesOpts .draftRepo )
260
+ }
261
+
262
+ // TODO: Call github API and create PR against k/sig-release
122
263
return nil
123
264
}
124
265
0 commit comments