From e99dbbb6dff6fef42de0c4bf1bc100ab744ef9b2 Mon Sep 17 00:00:00 2001 From: Joshua Blum Date: Mon, 23 Mar 2026 14:25:03 -0400 Subject: [PATCH] add advertisements to tuxbot --- packaging/linux/tuxbot/bot/chatbot/chatbot.go | 4 +- packaging/linux/tuxbot/bot/common/acl.go | 6 +- packaging/linux/tuxbot/bot/tuxbot/tuxbot.go | 67 +++++++++++++++++-- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/packaging/linux/tuxbot/bot/chatbot/chatbot.go b/packaging/linux/tuxbot/bot/chatbot/chatbot.go index 8081e305365b..51534ace3538 100644 --- a/packaging/linux/tuxbot/bot/chatbot/chatbot.go +++ b/packaging/linux/tuxbot/bot/chatbot/chatbot.go @@ -121,13 +121,13 @@ func (l ChatLogger) VDebug(format string, args ...interface{}) { func (l ChatLogger) Debug(format string, args ...interface{}) { msg := l.msg(format, args...) fmt.Println(msg) - if _, err := l.API.SendMessage(l.DebugChannel, msg); err != nil { + if _, err := l.API.SendMessage(l.DebugChannel, "%s", msg); err != nil { fmt.Printf("unable to SendMessage: %v", err) } } func (l ChatLogger) Info(format string, args ...interface{}) { - if _, err := l.API.SendMessage(l.InfoChannel, l.msg(format, args...)); err != nil { + if _, err := l.API.SendMessage(l.InfoChannel, "%s", l.msg(format, args...)); err != nil { fmt.Printf("unable to SendMessage: %v", err) } if l.InfoChannel.Name != l.DebugChannel.Name || l.InfoChannel.TopicName != l.DebugChannel.TopicName { diff --git a/packaging/linux/tuxbot/bot/common/acl.go b/packaging/linux/tuxbot/bot/common/acl.go index 3e7e72ae4bec..81902dfe0d2a 100644 --- a/packaging/linux/tuxbot/bot/common/acl.go +++ b/packaging/linux/tuxbot/bot/common/acl.go @@ -7,8 +7,10 @@ import ( var self access.Username = "tuxbot" -var tuxbotAdmins = []access.Username{self, "max", "mikem", "modalduality", "cjb", "jzila", - "patrick", "songgao", "strib", "joshblum", "mlsteele"} +var tuxbotAdmins = []access.Username{ + self, "mikem", "modalduality", + "patrick", "songgao", "joshblum", +} func SimpleTuxbotACL(infoChannel chat1.ChatChannel) access.ACL { return access.NewConstantACL(map[chat1.ChatChannel][]access.Username{ diff --git a/packaging/linux/tuxbot/bot/tuxbot/tuxbot.go b/packaging/linux/tuxbot/bot/tuxbot/tuxbot.go index d5a3c4b0dc18..1ca3e62df1dd 100644 --- a/packaging/linux/tuxbot/bot/tuxbot/tuxbot.go +++ b/packaging/linux/tuxbot/bot/tuxbot/tuxbot.go @@ -113,12 +113,12 @@ func (c Tuxbot) Dispatch(msg chat1.MsgSummary, args []string) (err error) { xzCmd := exec.Command("xz") archiveName := fmt.Sprintf("/keybase/team/%s/keybase-%s.tar.xz", c.archiveTeam, revision) - archiveHandle, err := os.OpenFile(archiveName, os.O_RDWR|os.O_CREATE, 0644) + archiveHandle, err := os.OpenFile(archiveName, os.O_RDWR|os.O_CREATE, 0o644) if err != nil { return err } defer archiveHandle.Close() - sigHandle, err := os.OpenFile(archiveName+".sig", os.O_RDWR|os.O_CREATE, 0644) + sigHandle, err := os.OpenFile(archiveName+".sig", os.O_RDWR|os.O_CREATE, 0o644) if err != nil { return err } @@ -228,7 +228,7 @@ func (c Tuxbot) Dispatch(msg chat1.MsgSummary, args []string) (err error) { return } - if _, err := c.API().SendMessage(c.sendChannel, "!build-docker "+strings.Join(args, " ")); err != nil { + if _, err := c.API().SendMessage(c.sendChannel, "%s", "!build-docker "+strings.Join(args, " ")); err != nil { c.Debug("unable to SendMessage: %v", err) } }() @@ -444,7 +444,7 @@ func (c Tuxbot) Dispatch(msg chat1.MsgSummary, args []string) (err error) { } func execToFile(filename string, cmd *exec.Cmd) error { - handle, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0644) + handle, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0o644) if err != nil { return err } @@ -463,6 +463,61 @@ func execToFile(filename string, cmd *exec.Cmd) error { return nil } +func (c Tuxbot) advertisement() kbchat.Advertisement { + commands := []chat1.UserBotCommandInput{ + { + Name: "release", + Description: "Build Linux release packages from HEAD or a specified revision.", + }, + { + Name: "nightly", + Description: "Build nightly Linux packages from HEAD or a specified revision.", + }, + { + Name: "test", + Description: "Build Linux test packages from HEAD or a specified revision.", + }, + { + Name: "archive", + Description: "Create and sign Linux source release artifacts for a revision.", + }, + { + Name: "build-docker", + Description: "Build and push Docker images for HEAD or a specified revision.", + }, + { + Name: "release-docker", + Description: "Promote an existing Docker tag as a release.", + }, + { + Name: "tuxjournal", + Description: "Write the recent tuxbot journal to the archive team folder.", + }, + { + Name: "journal", + Description: "Write the recent system journal to the archive team folder.", + }, + { + Name: "cleanup", + Description: "Run the local cleanup helper on the tuxbot host.", + }, + { + Name: "restartdocker", + Description: "Restart Docker on the tuxbot host.", + }, + } + + return kbchat.Advertisement{ + Alias: c.Name, + Advertisements: []chat1.AdvertiseCommandAPIParam{ + { + Typ: "public", + Commands: commands, + }, + }, + } +} + func main() { err := gotenv.Load(fmt.Sprintf("/keybase/team/%s/.kbfs_autogit/%s/tuxbot.env", os.Getenv("SECRETS_TEAM"), os.Getenv("SECRETS_REPO"))) if err != nil { @@ -510,6 +565,10 @@ func main() { archiveTeam: *infoTeam, } + if _, err := tuxbot.API().AdvertiseCommands(tuxbot.advertisement()); err != nil { + tuxbot.Info("unable to advertise commands: %v", err) + } + if err := chatbot.Listen(tuxbot); err != nil { panic(err) }