@@ -8,7 +8,9 @@ package main
8
8
import (
9
9
"context"
10
10
"fmt"
11
+ "net/url"
11
12
"os"
13
+ "strings"
12
14
"time"
13
15
14
16
"github.com/cockroachdb/cockroach/pkg/cmd/bazci/githubpost/issues"
@@ -35,6 +37,7 @@ type GithubPoster interface {
35
37
// githubIssues struct implements GithubPoster
36
38
type githubIssues struct {
37
39
disable bool
40
+ dryRun bool
38
41
issuePoster func (context.Context , issues.Logger , issues.IssueFormatter , issues.PostRequest ,
39
42
* issues.Options ) (* issues.TestFailureIssue , error )
40
43
teamLoader func () (team.Map , error )
@@ -327,6 +330,10 @@ func (g *githubIssues) MaybePost(
327
330
message string ,
328
331
params map [string ]string ,
329
332
) (* issues.TestFailureIssue , error ) {
333
+ if g .dryRun {
334
+ return nil , g .dryRunPost (t , issueInfo , l , message , params )
335
+ }
336
+
330
337
skipReason := g .shouldPost (t )
331
338
if skipReason != "" {
332
339
l .Printf ("skipping GitHub issue posting (%s)" , skipReason )
@@ -352,3 +359,75 @@ func (g *githubIssues) MaybePost(
352
359
opts ,
353
360
)
354
361
}
362
+
363
+ // dryRunPost simulates posting an issue to GitHub by rendering
364
+ // the issue and logging a clickable link.
365
+ func (g * githubIssues ) dryRunPost (
366
+ t * testImpl ,
367
+ issueInfo * githubIssueInfo ,
368
+ l * logger.Logger ,
369
+ message string ,
370
+ params map [string ]string ,
371
+ ) error {
372
+ postRequest , err := g .createPostRequest (
373
+ t .Name (), t .start , t .end , t .spec , t .failures (),
374
+ message ,
375
+ roachtestutil .UsingRuntimeAssertions (t ), t .goCoverEnabled , params , issueInfo ,
376
+ )
377
+ if err != nil {
378
+ return err
379
+ }
380
+ _ , url , err := formatPostRequest (postRequest )
381
+ if err != nil {
382
+ return err
383
+ }
384
+ l .Printf ("GitHub issue posting in dry-run mode:\n %s" , url )
385
+ return nil
386
+ }
387
+
388
+ // formatPostRequest returns a string representation of the rendered PostRequest
389
+ // as well as a link that can be followed to open the issue in Github. The rendered
390
+ // PostRequest also includes the labels that would be applied to the issue as part
391
+ // of the body.
392
+ func formatPostRequest (req issues.PostRequest ) (string , string , error ) {
393
+ data := issues.TemplateData {
394
+ PostRequest : req ,
395
+ Parameters : req .ExtraParams ,
396
+ CondensedMessage : issues .CondensedMessage (req .Message ),
397
+ Branch : "test_branch" ,
398
+ Commit : "test_SHA" ,
399
+ PackageNameShort : strings .TrimPrefix (req .PackageName , issues .CockroachPkgPrefix ),
400
+ }
401
+
402
+ formatter := issues .UnitTestFormatter
403
+ r := & issues.Renderer {}
404
+ if err := formatter .Body (r , data ); err != nil {
405
+ return "" , "" , err
406
+ }
407
+
408
+ var post strings.Builder
409
+ post .WriteString (r .String ())
410
+
411
+ // Github labels are normally not part of the rendered issue body, but we want to
412
+ // still test that they are correctly set so append them here.
413
+ post .WriteString ("\n ------\n Labels:\n " )
414
+ for _ , label := range req .Labels {
415
+ post .WriteString (fmt .Sprintf ("- <code>%s</code>\n " , label ))
416
+ }
417
+
418
+ u , err := url .Parse ("https://github.com/cockroachdb/cockroach/issues/new" )
419
+ if err != nil {
420
+ return "" , "" , err
421
+ }
422
+ q := u .Query ()
423
+ q .Add ("title" , formatter .Title (data ))
424
+ q .Add ("body" , post .String ())
425
+ // Adding a template parameter is required to be able to view the rendered
426
+ // template on GitHub, otherwise it just takes you to the template selection
427
+ // page.
428
+ q .Add ("template" , "none" )
429
+ u .RawQuery = q .Encode ()
430
+ post .WriteString (fmt .Sprintf ("Rendered:\n %s" , u .String ()))
431
+
432
+ return post .String (), u .String (), nil
433
+ }
0 commit comments