Skip to content

Commit

Permalink
Merge pull request #729 from blakebarnett/update_slack_bot_to_fix_app…
Browse files Browse the repository at this point in the history
…rovals

Update to slack-go/slack v0.12.2
  • Loading branch information
rusenask authored Aug 9, 2023
2 parents bea3fb3 + e57f78d commit da5cfa1
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 74 deletions.
2 changes: 1 addition & 1 deletion bot/slack/approvals.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"

"github.com/keel-hq/keel/types"
"github.com/nlopes/slack"
"github.com/slack-go/slack"
)

// Request - request approval
Expand Down
95 changes: 42 additions & 53 deletions bot/slack/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"strings"
"time"

"github.com/nlopes/slack"
"github.com/slack-go/slack"

"github.com/keel-hq/keel/bot"
"github.com/keel-hq/keel/constants"
Expand All @@ -19,12 +19,6 @@ import (
log "github.com/sirupsen/logrus"
)

// SlackImplementer - implementes slack HTTP functionality, used to
// send messages with attachments
type SlackImplementer interface {
PostMessage(channelID string, options ...slack.MsgOption) (string, string, error)
}

// Bot - main slack bot container
type Bot struct {
id string // bot id
Expand All @@ -37,8 +31,6 @@ type Bot struct {
slackClient *slack.Client
slackRTM *slack.RTM

slackHTTPClient SlackImplementer

approvalsChannel string // slack approvals channel name

ctx context.Context
Expand All @@ -54,20 +46,21 @@ func (b *Bot) Configure(approvalsRespCh chan *bot.ApprovalResponse, botMessagesC
if os.Getenv(constants.EnvSlackToken) != "" {

b.name = "keel"
if bootName := os.Getenv(constants.EnvSlackBotName); bootName != "" {
b.name = bootName
if botName := os.Getenv(constants.EnvSlackBotName); botName != "" {
b.name = botName
}

token := os.Getenv(constants.EnvSlackToken)
client := slack.New(token)

debug, _ := strconv.ParseBool(os.Getenv("DEBUG"))
client := slack.New(token, slack.OptionDebug(debug))

b.approvalsChannel = "general"
if channel := os.Getenv(constants.EnvSlackApprovalsChannel); channel != "" {
b.approvalsChannel = strings.TrimPrefix(channel, "#")
}

b.slackClient = client
b.slackHTTPClient = client
b.approvalsRespCh = approvalsRespCh
b.botMessagesChannel = botMessagesChannel

Expand Down Expand Up @@ -114,42 +107,38 @@ func (b *Bot) startInternal() error {
b.slackRTM = b.slackClient.NewRTM()

go b.slackRTM.ManageConnection()
for {
select {
case <-b.ctx.Done():
return nil

case msg := <-b.slackRTM.IncomingEvents:
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
// Ignore hello
case *slack.ConnectedEvent:
// nothing to do
case *slack.MessageEvent:
b.handleMessage(ev)
case *slack.PresenceChangeEvent:
// nothing to do
case *slack.RTMError:
log.Errorf("Error: %s", ev.Error())
case *slack.InvalidAuthEvent:
log.Error("Invalid credentials")
return fmt.Errorf("invalid credentials")

default:

// Ignore other events..
// fmt.Printf("Unexpected: %v\n", msg.Data)
}

for msg := range b.slackRTM.IncomingEvents {
switch ev := msg.Data.(type) {
case *slack.HelloEvent:
// Ignore hello
case *slack.ConnectedEvent:
// nothing to do
case *slack.MessageEvent:
b.handleMessage(ev)
case *slack.PresenceChangeEvent:
// nothing to do
case *slack.RTMError:
log.Errorf("Error: %s", ev.Error())
case *slack.InvalidAuthEvent:
log.Error("Invalid credentials")
return fmt.Errorf("invalid credentials")

default:

// Ignore other events..
// fmt.Printf("Unexpected: %v\n", msg.Data)
}
}
return fmt.Errorf("No more events?")
}

func (b *Bot) postMessage(title, message, color string, fields []slack.AttachmentField) error {
params := slack.NewPostMessageParameters()
params.Username = b.name
params.IconURL = b.getBotUserIconURL()

attachements := []slack.Attachment{
attachments := []slack.Attachment{
{
Fallback: message,
Color: color,
Expand All @@ -162,9 +151,9 @@ func (b *Bot) postMessage(title, message, color string, fields []slack.Attachmen
var mgsOpts []slack.MsgOption

mgsOpts = append(mgsOpts, slack.MsgOptionPostMessageParameters(params))
mgsOpts = append(mgsOpts, slack.MsgOptionAttachments(attachements...))
mgsOpts = append(mgsOpts, slack.MsgOptionAttachments(attachments...))

_, _, err := b.slackHTTPClient.PostMessage(b.approvalsChannel, mgsOpts...)
_, _, err := b.slackClient.PostMessage(b.approvalsChannel, mgsOpts...)
if err != nil {
log.WithFields(log.Fields{
"error": err,
Expand All @@ -177,26 +166,26 @@ func (b *Bot) postMessage(title, message, color string, fields []slack.Attachmen
// checking if message was received in approvals channel
func (b *Bot) isApprovalsChannel(event *slack.MessageEvent) bool {

channel, err := b.slackClient.GetChannelInfo(event.Channel)
channel, err := b.slackClient.GetConversationInfo(&slack.GetConversationInfoInput{ChannelID: event.Channel})
if err != nil {
// looking for private channel
conv, err := b.slackRTM.GetConversationInfo(event.Channel, true)
if err != nil {
log.Errorf("couldn't find amongst private conversations: %s", err)
} else if conv.Name == b.approvalsChannel {
return true
if channel != (&slack.Channel{}) && channel != nil {
if channel.GroupConversation.Name == b.approvalsChannel &&
channel.GroupConversation.Conversation.IsPrivate {
return true
} else {
log.Errorf("couldn't find amongst private conversations: %s", err)
}
}

log.WithError(err).Errorf("channel with ID %s could not be retrieved", event.Channel)
return false
}

log.Debugf("checking if approvals channel: %s==%s", channel.Name, b.approvalsChannel)
if channel.Name == b.approvalsChannel {
log.Debugf("checking if approvals channel: %s==%s", channel.GroupConversation.Name, b.approvalsChannel)
if channel.GroupConversation.Name == b.approvalsChannel {
return true
}

log.Debugf("message was received not on approvals channel (%s)", channel.Name)
log.Debugf("message was received not on approvals channel (%s)", channel.GroupConversation.Name)

return false
}
Expand Down
13 changes: 6 additions & 7 deletions bot/slack/slack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"path/filepath"
"time"

"github.com/nlopes/slack"
"github.com/slack-go/slack"

"github.com/keel-hq/keel/extension/approval"
"github.com/keel-hq/keel/pkg/store/sql"
Expand All @@ -31,15 +31,14 @@ var approvalsRespCh chan *b.ApprovalResponse

func New(name, token, channel string,
k8sImplementer kubernetes.Implementer,
approvalsManager approvals.Manager, fi SlackImplementer) *Bot {
approvalsManager approvals.Manager) *Bot {

approvalsRespCh = make(chan *b.ApprovalResponse)
botMessagesChannel = make(chan *b.BotMessage)

slack := &Bot{}
b.RegisterBot(name, slack)
b.Run(k8sImplementer, approvalsManager)
slack.slackHTTPClient = fi
return slack
}

Expand Down Expand Up @@ -125,7 +124,7 @@ func TestBotRequest(t *testing.T) {
Store: store,
})

New("keel", token, "approvals", f8s, am, fi)
New("keel", token, "approvals", f8s, am)
defer b.Stop()

time.Sleep(1 * time.Second)
Expand Down Expand Up @@ -172,7 +171,7 @@ func TestProcessApprovedResponse(t *testing.T) {
Store: store,
})

New("keel", token, "approvals", f8s, am, fi)
New("keel", token, "approvals", f8s, am)
defer b.Stop()

time.Sleep(1 * time.Second)
Expand Down Expand Up @@ -239,7 +238,7 @@ func TestProcessApprovalReply(t *testing.T) {
t.Fatalf("unexpected error while creating : %s", err)
}

bot := New("keel", token, "approvals", f8s, am, fi)
bot := New("keel", token, "approvals", f8s, am)
defer b.Stop()

time.Sleep(1 * time.Second)
Expand Down Expand Up @@ -309,7 +308,7 @@ func TestProcessRejectedReply(t *testing.T) {
t.Fatalf("unexpected error while creating : %s", err)
}

bot := New("keel", "random", "approvals", f8s, am, fi)
bot := New("keel", "random", "approvals", f8s, am)
defer b.Stop()

collector := approval.New()
Expand Down
2 changes: 1 addition & 1 deletion extension/notification/slack/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"strings"
"time"

"github.com/nlopes/slack"
"github.com/slack-go/slack"

"github.com/keel-hq/keel/constants"
"github.com/keel-hq/keel/extension/notification"
Expand Down
11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ require (
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/jinzhu/gorm v1.9.16
github.com/nlopes/slack v0.6.0
github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc2
github.com/prometheus/client_golang v1.14.0
github.com/rusenask/cron v1.1.0
github.com/rusenask/docker-registry-client v0.0.0-20200210164146-049272422097
github.com/ryanuber/go-glob v1.0.0
github.com/sirupsen/logrus v1.9.0
github.com/slack-go/slack v0.12.2
github.com/stretchr/testify v1.8.2
github.com/tbruyelle/hipchat-go v0.0.0-20170717082847-35aebc99209a
github.com/urfave/negroni v1.0.0
Expand Down Expand Up @@ -122,7 +123,6 @@ require (
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmoiron/sqlx v1.3.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.11.13 // indirect
Expand All @@ -132,8 +132,8 @@ require (
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
Expand All @@ -153,6 +153,7 @@ require (
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rubenv/sql-migrate v1.3.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
Expand All @@ -168,7 +169,7 @@ require (
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
Expand Down
21 changes: 14 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=
Expand Down Expand Up @@ -336,7 +338,6 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
Expand Down Expand Up @@ -466,11 +467,13 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
Expand Down Expand Up @@ -522,8 +525,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/nelsam/hel/v2 v2.3.2/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w=
github.com/nelsam/hel/v2 v2.3.3/go.mod h1:1ZTGfU2PFTOd5mx22i5O0Lc2GY933lQ2wb/ggy+rL3w=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA=
github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
Expand Down Expand Up @@ -585,6 +586,9 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
Expand Down Expand Up @@ -616,6 +620,8 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ=
github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
Expand Down Expand Up @@ -908,8 +914,9 @@ golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
Expand Down

0 comments on commit da5cfa1

Please sign in to comment.