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 }