Skip to content

Commit 1264b91

Browse files
dmitshurgopherbot
authored andcommitted
cmd/relui: join announcement mail and tweet tasks in one workflow
Now that both workflows and their tasks are ready, we can combine them into one workflow. Keep the old separate ones a bit longer, until we get some experience using the new ones. This removes the need to manually copy the AnnouncementURL output from the the mail workflow into the tweet workflow, since a unified workflow can do that automatically for us. Fixes golang/go#47406. Change-Id: Ie929e5ee2927e74547c1ef4cccc370874420559c Reviewed-on: https://go-review.googlesource.com/c/build/+/413534 Reviewed-by: Alex Rakoczy <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Dmitri Shuralyov <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Run-TryBot: Dmitri Shuralyov <[email protected]>
1 parent e6724bd commit 1264b91

File tree

3 files changed

+187
-14
lines changed

3 files changed

+187
-14
lines changed

cmd/relui/main.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ func main() {
108108
}
109109
dh := relui.NewDefinitionHolder()
110110
relui.RegisterMailDLCLDefinition(dh, versionTasks)
111-
relui.RegisterAnnounceDefinitions(dh, annMail)
112-
relui.RegisterTweetDefinitions(dh, extCfg)
111+
relui.RegisterCommunicationDefinitions(dh, annMail, extCfg)
112+
relui.RegisterAnnounceMailOnlyDefinitions(dh, annMail)
113+
relui.RegisterTweetOnlyDefinitions(dh, extCfg)
113114
userPassAuth := buildlet.UserPass{
114115
Username: "user-relui",
115116
Password: key(*masterKey, "user-relui"),

internal/relui/workflows.go

Lines changed: 169 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,171 @@ For example:
100100
h.RegisterDefinition("mail-dl-cl", wd)
101101
}
102102

103-
// RegisterAnnounceDefinitions registers workflow definitions involving announcing
103+
// RegisterCommunicationDefinitions registers workflow definitions
104+
// involving mailing announcements and posting tweets onto h.
105+
func RegisterCommunicationDefinitions(h *DefinitionHolder, tasks task.AnnounceMailTasks, e task.ExternalConfig) {
106+
version := workflow.Parameter{
107+
Name: "Version",
108+
Doc: `Version is the Go version that has been released.
109+
110+
The version string must use the same format as Go tags.`,
111+
}
112+
securitySummary := workflow.Parameter{
113+
Name: "Security Summary (optional)",
114+
Doc: `Security Summary is an optional sentence describing security fixes included in this release.
115+
116+
It shows up in the release tweet.
117+
118+
The empty string means there are no security fixes to highlight.
119+
120+
Past examples:
121+
• "Includes a security fix for crypto/tls (CVE-2021-34558)."
122+
• "Includes a security fix for the Wasm port (CVE-2021-38297)."
123+
• "Includes security fixes for encoding/pem (CVE-2022-24675), crypto/elliptic (CVE-2022-28327), crypto/x509 (CVE-2022-27536)."`,
124+
}
125+
securityFixes := workflow.Parameter{
126+
Name: "Security Fixes (optional)",
127+
ParameterType: workflow.SliceLong,
128+
Doc: `Security Fixes is a list of descriptions, one for each distinct security fix included in this release, in Markdown format.
129+
130+
It shows up in the announcement mail.
131+
132+
The empty list means there are no security fixes included.
133+
134+
Past examples:
135+
• "encoding/pem: fix stack overflow in Decode
136+
137+
A large (more than 5 MB) PEM input can cause a stack overflow in Decode,
138+
leading the program to crash.
139+
140+
Thanks to Juho Nurminen of Mattermost who reported the error.
141+
142+
This is CVE-2022-24675 and Go issue https://go.dev/issue/51853."
143+
• "crypto/elliptic: tolerate all oversized scalars in generic P-256
144+
145+
A crafted scalar input longer than 32 bytes can cause P256().ScalarMult
146+
or P256().ScalarBaseMult to panic. Indirect uses through crypto/ecdsa and
147+
crypto/tls are unaffected. amd64, arm64, ppc64le, and s390x are unaffected.
148+
149+
This was discovered thanks to a Project Wycheproof test vector.
150+
151+
This is CVE-2022-28327 and Go issue https://go.dev/issue/52075."`,
152+
Example: `encoding/pem: fix stack overflow in Decode
153+
154+
A large (more than 5 MB) PEM input can cause a stack overflow in Decode,
155+
leading the program to crash.
156+
157+
Thanks to Juho Nurminen of Mattermost who reported the error.
158+
159+
This is CVE-2022-24675 and Go issue https://go.dev/issue/51853.`,
160+
}
161+
names := workflow.Parameter{
162+
Name: "Names (optional)",
163+
ParameterType: workflow.SliceShort,
164+
Doc: `Names is an optional list of release coordinator names to include in the sign-off message.
165+
166+
It shows up in the announcement mail.`,
167+
}
168+
169+
{
170+
wd := workflow.New()
171+
172+
minorVersion := version
173+
minorVersion.Example = "go1.18.2"
174+
v1 := wd.Parameter(minorVersion)
175+
v2 := wd.Parameter(workflow.Parameter{
176+
Name: "Secondary Version",
177+
Doc: `Secondary Version is an older Go version that was also released.`,
178+
Example: "go1.17.10",
179+
})
180+
securitySummary := wd.Parameter(securitySummary)
181+
securityFixes := wd.Parameter(securityFixes)
182+
names := wd.Parameter(names)
183+
184+
sentMail := wd.Task("mail-announcement", func(ctx *workflow.TaskContext, v1, v2 string, sec, names []string) (task.SentMail, error) {
185+
return tasks.AnnounceMinorRelease(ctx, task.ReleaseAnnouncement{Version: v1, SecondaryVersion: v2, Security: sec, Names: names})
186+
}, v1, v2, securityFixes, names)
187+
announcementURL := wd.Task("await-announcement", tasks.AwaitAnnounceMail, sentMail)
188+
tweetURL := wd.Task("post-tweet", func(ctx *workflow.TaskContext, v1, v2, sec, ann string) (string, error) {
189+
return task.TweetMinorRelease(ctx, task.ReleaseTweet{Version: v1, SecondaryVersion: v2, Security: sec, Announcement: ann}, e)
190+
}, v1, v2, securitySummary, announcementURL)
191+
192+
wd.Output("AnnouncementURL", announcementURL)
193+
wd.Output("TweetURL", tweetURL)
194+
195+
h.RegisterDefinition("announce-and-tweet-minor", wd)
196+
}
197+
{
198+
wd := workflow.New()
199+
200+
betaVersion := version
201+
betaVersion.Example = "go1.19beta1"
202+
v := wd.Parameter(betaVersion)
203+
names := wd.Parameter(names)
204+
205+
sentMail := wd.Task("mail-announcement", func(ctx *workflow.TaskContext, v string, names []string) (task.SentMail, error) {
206+
return tasks.AnnounceBetaRelease(ctx, task.ReleaseAnnouncement{Version: v, Names: names})
207+
}, v, names)
208+
announcementURL := wd.Task("await-announcement", tasks.AwaitAnnounceMail, sentMail)
209+
tweetURL := wd.Task("post-tweet", func(ctx *workflow.TaskContext, v, ann string) (string, error) {
210+
return task.TweetBetaRelease(ctx, task.ReleaseTweet{Version: v, Announcement: ann}, e)
211+
}, v, announcementURL)
212+
213+
wd.Output("AnnouncementURL", announcementURL)
214+
wd.Output("TweetURL", tweetURL)
215+
216+
h.RegisterDefinition("announce-and-tweet-beta", wd)
217+
}
218+
{
219+
wd := workflow.New()
220+
221+
rcVersion := version
222+
rcVersion.Example = "go1.19rc1"
223+
v := wd.Parameter(rcVersion)
224+
names := wd.Parameter(names)
225+
226+
sentMail := wd.Task("mail-announcement", func(ctx *workflow.TaskContext, v string, names []string) (task.SentMail, error) {
227+
return tasks.AnnounceRCRelease(ctx, task.ReleaseAnnouncement{Version: v, Names: names})
228+
}, v, names)
229+
announcementURL := wd.Task("await-announcement", tasks.AwaitAnnounceMail, sentMail)
230+
tweetURL := wd.Task("post-tweet", func(ctx *workflow.TaskContext, v, ann string) (string, error) {
231+
return task.TweetRCRelease(ctx, task.ReleaseTweet{Version: v, Announcement: ann}, e)
232+
}, v, announcementURL)
233+
234+
wd.Output("AnnouncementURL", announcementURL)
235+
wd.Output("TweetURL", tweetURL)
236+
237+
h.RegisterDefinition("announce-and-tweet-rc", wd)
238+
}
239+
{
240+
wd := workflow.New()
241+
242+
majorVersion := version
243+
majorVersion.Example = "go1.19"
244+
v := wd.Parameter(majorVersion)
245+
names := wd.Parameter(names)
246+
247+
sentMail := wd.Task("mail-announcement", func(ctx *workflow.TaskContext, v string, names []string) (task.SentMail, error) {
248+
return tasks.AnnounceMajorRelease(ctx, task.ReleaseAnnouncement{Version: v, Names: names})
249+
}, v, names)
250+
announcementURL := wd.Task("await-announcement", tasks.AwaitAnnounceMail, sentMail)
251+
tweetURL := wd.Task("post-tweet", func(ctx *workflow.TaskContext, v string) (string, error) {
252+
return task.TweetMajorRelease(ctx, task.ReleaseTweet{Version: v}, e)
253+
}, v)
254+
255+
wd.Output("AnnouncementURL", announcementURL)
256+
wd.Output("TweetURL", tweetURL)
257+
258+
h.RegisterDefinition("announce-and-tweet-major", wd)
259+
}
260+
}
261+
262+
// RegisterAnnounceMailOnlyDefinitions registers workflow definitions involving announcing
104263
// onto h.
105-
func RegisterAnnounceDefinitions(h *DefinitionHolder, tasks task.AnnounceMailTasks) {
264+
//
265+
// This is superseded by RegisterCommunicationDefinitions and will be removed
266+
// after some time, when we confirm there's no need for separate workflows.
267+
func RegisterAnnounceMailOnlyDefinitions(h *DefinitionHolder, tasks task.AnnounceMailTasks) {
106268
version := workflow.Parameter{
107269
Name: "Version",
108270
Doc: `Version is the Go version that has been released.
@@ -202,9 +364,12 @@ This is CVE-2022-24675 and Go issue https://go.dev/issue/51853.`,
202364
}
203365
}
204366

205-
// RegisterTweetDefinitions registers workflow definitions involving tweeting
367+
// RegisterTweetOnlyDefinitions registers workflow definitions involving tweeting
206368
// onto h, using e for the external service configuration.
207-
func RegisterTweetDefinitions(h *DefinitionHolder, e task.ExternalConfig) {
369+
//
370+
// This is superseded by RegisterCommunicationDefinitions and will be removed
371+
// after some time, when we confirm there's no need for separate workflows.
372+
func RegisterTweetOnlyDefinitions(h *DefinitionHolder, e task.ExternalConfig) {
208373
version := workflow.Parameter{
209374
Name: "Version",
210375
Doc: `Version is the Go version that has been released.

internal/task/announce.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,20 +127,27 @@ func (t AnnounceMailTasks) announceRelease(ctx *workflow.TaskContext, r ReleaseA
127127
return SentMail{}, err
128128
}
129129
if log := ctx.Logger; log != nil {
130-
log.Printf("announcement subject: %s\n", m.Subject)
131-
log.Printf("\nannouncement body HTML:\n%s", m.BodyHTML)
132-
log.Printf("\nannouncement body text:\n%s", m.BodyText)
130+
log.Printf("announcement subject: %s\n\n", m.Subject)
131+
log.Printf("announcement body HTML:\n%s\n", m.BodyHTML)
132+
log.Printf("announcement body text:\n%s", m.BodyText)
133133
}
134134

135-
// Confirm that this announcement doesn't already exist.
135+
// Before sending, check to see if this announcement already exists.
136136
if threadURL, err := findGoogleGroupsThread(ctx, m.Subject); err != nil {
137137
// Proceeding would risk sending a duplicate email, so error out instead.
138138
return SentMail{}, fmt.Errorf("stopping early due to error checking for an existing Google Groups thread: %v", err)
139139
} else if threadURL != "" {
140-
// TODO(go.dev/issue/47406): Once this task is a part of a larger workflow (which may need
141-
// to tolerate resuming, restarting, and so on), the case of the matching subject already
142-
// being there should become considered as "success, keep going" rather than "error, stop".
143-
return SentMail{}, fmt.Errorf("a Google Groups thread with matching subject %q already exists at %q, stopping", m.Subject, threadURL)
140+
// This should never happen since this task runs once per release.
141+
// It can happen under unusual circumstances, for example if the task crashes after
142+
// mailing but before completion, or if parts of the release workflow are restarted,
143+
// or if a human mails the announcement email manually out of band.
144+
//
145+
// So if we see that the email exists, consider it as "task completed successfully"
146+
// and pretend we were the ones that sent it, so the high level workflow can keep going.
147+
if log := ctx.Logger; log != nil {
148+
log.Printf("a Google Groups thread with matching subject %q already exists at %q, so we'll consider that as it being sent successfully", m.Subject, threadURL)
149+
}
150+
return SentMail{m.Subject}, nil
144151
}
145152

146153
// Send the announcement email to the destination mailing lists.

0 commit comments

Comments
 (0)