Skip to content

Commit

Permalink
internal/task, relui: add posting to Mastodon
Browse files Browse the repository at this point in the history
Very much a copy of the code for Twitter, except that it uses
a 3rd party package to handle posting.  Some of the common code
was moved into a new function.

Also includes an end-to-end test for by-hand use that will send a
Mastodon DM to a specified account.  This test requires access
to the cloud secrets and will skip if it lacks either those
secrets or the command line flag.

Fixes golang/go#65046.

Change-Id: Ie7606242766f36fecd5b15acc3c995c046098079
Reviewed-on: https://go-review.googlesource.com/c/build/+/554375
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
  • Loading branch information
dr2chase committed Jan 22, 2024
1 parent 1d8c01e commit 57d277f
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 100 deletions.
1 change: 1 addition & 0 deletions cmd/relui/deployment-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ spec:
- "[email protected]"
- "[email protected]"
- "--twitter-api-secret=secret:symbolic-datum-552/twitter-api-secret"
- "--mastodon-api-secret=secret:symbolic-datum-552/mastodon-api-secret"
- "--builder-master-key=secret:symbolic-datum-552/builder-master-key"
- "--github-token=secret:symbolic-datum-552/maintner-github-token"
- "--scratch-files-base=gs://golang-release-staging/relui-scratch"
Expand Down
11 changes: 9 additions & 2 deletions cmd/relui/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func main() {
addressListVarFlag(&schedMail.BCC, "schedule-mail-bcc", "The BCC address list to use for the scheduled workflow failure mail.")
var twitterAPI secret.TwitterCredentials
secret.JSONVarFlag(&twitterAPI, "twitter-api-secret", "Twitter API secret to use for workflows involving tweeting.")
var mastodonAPI secret.MastodonCredentials
secret.JSONVarFlag(&mastodonAPI, "mastodon-api-secret", "Mastodon API secret to use for workflows involving posting.")
masterKey := secret.Flag("builder-master-key", "Builder master key")
githubToken := secret.Flag("github-token", "GitHub API token")
https.RegisterFlags(flag.CommandLine)
Expand Down Expand Up @@ -134,13 +136,18 @@ func main() {
gitClient := &task.Git{}
gitClient.UseOAuth2Auth(creds.TokenSource)
mailFunc := task.NewSendGridMailClient(*sendgridAPIKey).SendMail
mastodonClient, err := task.NewMastodonClient(mastodonAPI)
if err != nil {
log.Fatalln(err)
}
commTasks := task.CommunicationTasks{
AnnounceMailTasks: task.AnnounceMailTasks{
SendMail: mailFunc,
AnnounceMailHeader: annMail,
},
TweetTasks: task.TweetTasks{
TwitterClient: task.NewTwitterClient(twitterAPI),
SocialMediaTasks: task.SocialMediaTasks{
TwitterClient: task.NewTwitterClient(twitterAPI),
MastodonClient: mastodonClient,
},
}
dh := relui.NewDefinitionHolder()
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
contrib.go.opencensus.io/exporter/prometheus v0.4.2
contrib.go.opencensus.io/exporter/stackdriver v0.13.5
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf
github.com/McKael/madon/v3 v3.0.0-20230806150951-5ba59b7ca061
github.com/NYTimes/gziphandler v1.1.1
github.com/UserExistsError/conpty v0.1.1
github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527
Expand Down Expand Up @@ -111,6 +112,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ cloud.google.com/go/cloudbuild v1.14.0 h1:YTMxmFra7eIjKFgnyQUxOwWNseNqeO38kGh7th
cloud.google.com/go/cloudbuild v1.14.0/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/container v1.24.0 h1:N51t/cgQJFqDD/W7Mb+IvmAPHrf8AbPx7Bb7aF4lROE=
Expand Down Expand Up @@ -104,6 +105,8 @@ github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvK
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/McKael/madon/v3 v3.0.0-20230806150951-5ba59b7ca061 h1:rIfWpHTqpxWdtMhw/EWb37SXqh1zAS6mVV4u58ym8iU=
github.com/McKael/madon/v3 v3.0.0-20230806150951-5ba59b7ca061/go.mod h1:YOIiFXnBOHdLar2nOtijwnZPHPtZUXt7gHYCNZdKlVE=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
Expand Down Expand Up @@ -468,6 +471,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
Expand Down Expand Up @@ -990,6 +995,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
Expand All @@ -1009,6 +1015,7 @@ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/perf v0.0.0-20230717203022-1ba3a21238c9 h1:HPASJO/sBgVQqFwIsL7A5o5GfTRe30dOhyX94F+4as0=
Expand Down Expand Up @@ -1106,12 +1113,14 @@ golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Expand All @@ -1124,6 +1133,7 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
8 changes: 5 additions & 3 deletions internal/relui/workflows.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,15 +404,17 @@ func addCommTasks(
wd *wf.Definition, build *BuildReleaseTasks, comm task.CommunicationTasks,
kind task.ReleaseKind, published wf.Value[[]task.Published], securitySummary wf.Value[string], securityFixes, coordinators wf.Value[[]string],
) {
okayToAnnounceAndTweet := wf.Action0(wd, "Wait to Announce", build.ApproveAction, wf.After(published))
okayToAnnounce := wf.Action0(wd, "Wait to Announce", build.ApproveAction, wf.After(published))

// Announce that a new Go release has been published.
sentMail := wf.Task4(wd, "mail-announcement", comm.AnnounceRelease, wf.Const(kind), published, securityFixes, coordinators, wf.After(okayToAnnounceAndTweet))
sentMail := wf.Task4(wd, "mail-announcement", comm.AnnounceRelease, wf.Const(kind), published, securityFixes, coordinators, wf.After(okayToAnnounce))
announcementURL := wf.Task1(wd, "await-announcement", comm.AwaitAnnounceMail, sentMail)
tweetURL := wf.Task4(wd, "post-tweet", comm.TweetRelease, wf.Const(kind), published, securitySummary, announcementURL, wf.After(okayToAnnounceAndTweet))
tweetURL := wf.Task4(wd, "post-tweet", comm.TweetRelease, wf.Const(kind), published, securitySummary, announcementURL, wf.After(okayToAnnounce))
mastodonURL := wf.Task4(wd, "post-mastodon", comm.TrumpetRelease, wf.Const(kind), published, securitySummary, announcementURL, wf.After(okayToAnnounce))

wf.Output(wd, "Announcement URL", announcementURL)
wf.Output(wd, "Tweet URL", tweetURL)
wf.Output(wd, "Mastodon URL", mastodonURL)
}

func enableDistpack(major int) bool {
Expand Down
25 changes: 25 additions & 0 deletions internal/secret/gcp_secret_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ const (
// a JSON object that can be unmarshaled into TwitterCredentials.
NameStagingTwitterAPISecret = "staging-" + NameTwitterAPISecret

// NameMastodonAPISecret is the secret name for Mastodon API credentials
// for posting to Hachyderm.io/@golang. The secret value is a JSON
// encoding of the MastodonCredentials.
NameMastodonAPISecret = "mastodon-api-secret"

// NameMacServiceAPIKey is the secret name for the MacService API key.
NameMacServiceAPIKey = "macservice-api-key"
)
Expand All @@ -103,13 +108,33 @@ type TwitterCredentials struct {
AccessTokenSecret string
}

type MastodonCredentials struct {
// Log in to <Instance> as your bot account,
// navigate to Profile -> Development,
// Click on <Application> in the Application column,
// and it will reveal Client Key, Client Secret, and Access Token
Instance string // Instance (e.g. "botsin.space")
Application string // Application name (e.g. ""Go benchmarking bot"")
ClientKey string // Client Key
ClientSecret string // Client secret
AccessToken string // Access token
TestRecipient string // For testing only, ignored by non-test API
}

func (t TwitterCredentials) String() string {
return fmt.Sprintf("{%s (redacted) %s (redacted)}", t.ConsumerKey, t.AccessTokenKey)
}
func (t TwitterCredentials) GoString() string {
return fmt.Sprintf("secret.TwitterCredentials{ConsumerKey:%q ConsumerSecret:(redacted) AccessTokenKey:%q AccessTokenSecret:(redacted)}", t.ConsumerKey, t.AccessTokenKey)
}

func (t MastodonCredentials) String() string {
return fmt.Sprintf("{%s %s (redacted) (redacted) (redacted)}", t.Instance, t.Application)
}
func (t MastodonCredentials) GoString() string {
return fmt.Sprintf("secret.MastodonCredentials{Instance:%q Application:%q ClientKey:(redacted) ClientSecret:(redacted) AccessToken:(redacted)}", t.Instance, t.Application)
}

type secretClient interface {
AccessSecretVersion(ctx context.Context, req *secretmanagerpb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error)
io.Closer
Expand Down
2 changes: 1 addition & 1 deletion internal/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type Published struct {
// CommunicationTasks combines communication tasks together.
type CommunicationTasks struct {
AnnounceMailTasks
TweetTasks
SocialMediaTasks
}

var AwaitDivisor int = 1
Expand Down
Loading

0 comments on commit 57d277f

Please sign in to comment.