golang.org/x/build@v0.0.0-20240506185731-218518f32b70/internal/task/privx_test.go (about)

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package task
     6  
     7  import (
     8  	"context"
     9  	"net/mail"
    10  	"os"
    11  	"path/filepath"
    12  	"reflect"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"golang.org/x/build/gerrit"
    18  	"golang.org/x/build/internal/workflow"
    19  )
    20  
    21  type privxClient struct {
    22  	GerritClient
    23  
    24  	privRepoDir string
    25  }
    26  
    27  func (c *privxClient) Submitted(ctx context.Context, changeID string, parentCommit string) (string, bool, error) {
    28  	return "123", true, nil
    29  }
    30  
    31  func (c *privxClient) ListProjects(ctx context.Context) ([]string, error) {
    32  	return []string{"net"}, nil
    33  }
    34  
    35  func (c *privxClient) ReadBranchHead(ctx context.Context, project string, branch string) (string, error) {
    36  	return "", nil
    37  }
    38  
    39  func (c *privxClient) ReadFile(ctx context.Context, project string, head string, file string) ([]byte, error) {
    40  	return []byte("module golang.org/x/net\n\ngo 1.24"), nil
    41  }
    42  
    43  func (c *privxClient) ListTags(ctx context.Context, repo string) ([]string, error) {
    44  	return []string{"v1.0.0"}, nil
    45  }
    46  
    47  func (c *privxClient) Tag(ctx context.Context, repo string, tag string, commit string) error {
    48  	return nil
    49  }
    50  
    51  func (c *privxClient) GetChange(ctx context.Context, changeID string, opts ...gerrit.QueryChangesOpt) (*gerrit.ChangeInfo, error) {
    52  	return &gerrit.ChangeInfo{
    53  		Project:         "net",
    54  		Status:          gerrit.ChangeStatusMerged,
    55  		CurrentRevision: "dead",
    56  		Revisions: map[string]gerrit.RevisionInfo{
    57  			"dead": {
    58  				Fetch: map[string]*gerrit.FetchInfo{
    59  					"http": {
    60  						URL: c.privRepoDir,
    61  						Ref: "refs/changes/1234/5",
    62  					},
    63  				},
    64  			},
    65  		},
    66  	}, nil
    67  }
    68  
    69  func TestPrivXPatch(t *testing.T) {
    70  	privRepo := NewFakeRepo(t, "net")
    71  	pubRepo := NewFakeRepo(t, "net")
    72  
    73  	privCommit := privRepo.CommitOnBranch("master", map[string]string{"hi.go": ":)"})
    74  	privRepo.runGit("update-ref", "refs/changes/1234/5", privCommit)
    75  
    76  	if err := os.WriteFile(filepath.Join(pubRepo.dir.dir, ".git/hooks/pre-receive"), []byte(`#!/bin/sh
    77  echo "Resolving deltas: 100% (5/5)"
    78  echo "Waiting for private key checker: 1/1 objects left"
    79  echo "Processing changes: refs: 1, new: 1, done"
    80  echo 
    81  echo "SUCCESS"
    82  echo 
    83  echo "  https://go-review.googlesource.com/c/net/+/558675 net/mail: remove obsolete comment [NEW]"
    84  echo`), 0777); err != nil {
    85  		t.Fatalf("failed to write git pre-receive hook: %s", err)
    86  	}
    87  
    88  	pubBase, _ := strings.CutSuffix(pubRepo.dir.dir, filepath.Base(pubRepo.dir.dir))
    89  
    90  	var announcementHeader MailHeader
    91  	var announcementMessage MailContent
    92  	p := &PrivXPatch{
    93  		Git:           &Git{},
    94  		PrivateGerrit: &privxClient{privRepoDir: privRepo.dir.dir},
    95  		PublicGerrit:  &privxClient{},
    96  
    97  		PublicRepoURL: func(repo string) string {
    98  			return pubBase + "/" + repo
    99  		},
   100  
   101  		ApproveAction: func(*workflow.TaskContext) error { return nil },
   102  		SendMail: func(mh MailHeader, mc MailContent) error {
   103  			announcementHeader, announcementMessage = mh, mc
   104  			return nil
   105  		},
   106  		AnnounceMailHeader: MailHeader{
   107  			From: mail.Address{Address: "hello@google.com"},
   108  			To:   mail.Address{Address: "there@google.com"},
   109  		},
   110  	}
   111  
   112  	wd := p.NewDefinition(&TagXReposTasks{Gerrit: &privxClient{}})
   113  	w, err := workflow.Start(wd, map[string]any{
   114  		"go-internal CL number":              "1234",
   115  		"Reviewer usernames (optional)":      []string{},
   116  		"Repository name":                    filepath.Base(pubRepo.dir.dir),
   117  		"Skip post submit result (optional)": true,
   118  		"CVE":                                "CVE-2024-1234",
   119  		"GitHub issue":                       "https://go.dev/issues/1234",
   120  		"Release note":                       "We fixed a thing.",
   121  		"Acknowledgement":                    "a very nice person",
   122  	})
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
   127  	defer cancel()
   128  	_, err = w.Run(ctx, &verboseListener{t: t})
   129  	if err != nil {
   130  		t.Fatal(err)
   131  	}
   132  
   133  	if !reflect.DeepEqual(announcementHeader, p.AnnounceMailHeader) {
   134  		t.Errorf("unexpected announcement header: got %#v, want %#v", announcementHeader, p.AnnounceMailHeader)
   135  	}
   136  
   137  	expectedSubject := `[security] Vulnerability in golang.org/x/net`
   138  	if announcementMessage.Subject != expectedSubject {
   139  		t.Errorf("unexpected announcement subject: got %q, want %q", announcementMessage.Subject, expectedSubject)
   140  	}
   141  	expectedMessage := `Hello gophers,
   142  
   143  We have tagged version v1.1.0 of golang.org/x/net in order to address a security issue.
   144  
   145  We fixed a thing.
   146  
   147  Thanks to a very nice person for reporting this issue.
   148  
   149  This is CVE-2024-1234 and Go issue https://go.dev/issues/1234.
   150  
   151  Cheers,
   152  Go Security team
   153  `
   154  	if announcementMessage.BodyText != expectedMessage {
   155  		t.Errorf("unexpected announcement plaintext: got: %s\n\nwant: %s\n", announcementMessage.BodyText, expectedMessage)
   156  	}
   157  
   158  	expectedHTML := `<p>Hello gophers,</p>
   159  <p>We have tagged version v1.1.0 of golang.org/x/net in order to address a security issue.</p>
   160  <p>We fixed a thing.</p>
   161  <p>Thanks to a very nice person for reporting this issue.</p>
   162  <p>This is CVE-2024-1234 and Go issue <a href="https://go.dev/issues/1234">https://go.dev/issues/1234</a>.</p>
   163  <p>Cheers,<br>
   164  Go Security team</p>
   165  `
   166  	if announcementMessage.BodyHTML != expectedHTML {
   167  		t.Errorf("unexpected announcement HTML: got: %s\n\nwant: %s\n", announcementMessage.BodyHTML, expectedHTML)
   168  	}
   169  }