mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-06-17 01:59:08 +00:00
feat: add midori skeleton, bot scaffolding, CD seeds
This commit is contained in:
parent
7c861b37ca
commit
49d44df231
30 changed files with 854 additions and 123 deletions
41
src/midori/BUILD.bazel
Normal file
41
src/midori/BUILD.bazel
Normal file
|
@ -0,0 +1,41 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_push")
|
||||
|
||||
go_library(
|
||||
name = "midori_lib",
|
||||
srcs = ["midori.go"],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/midori",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//src/common/bot",
|
||||
"//src/common/version",
|
||||
"//src/midori/internal/commands/gh",
|
||||
"//src/midori/internal/commands/tfc",
|
||||
"//src/midori/internal/config",
|
||||
"@com_github_bwmarrin_discordgo//:discordgo",
|
||||
"@com_github_joho_godotenv//autoload",
|
||||
"@io_k8s_klog//:klog",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "midori",
|
||||
embed = [":midori_lib"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_image(
|
||||
name = "image",
|
||||
embed = [":midori_lib"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
container_push(
|
||||
name = "+publish",
|
||||
format = "Docker",
|
||||
image = ":image",
|
||||
registry = "docker.pkg.github.com",
|
||||
repository = "roleypoly/roleypoly/midori",
|
||||
tag = "{STABLE_GIT_BRANCH}",
|
||||
)
|
5
src/midori/README.md
Normal file
5
src/midori/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Midori
|
||||
|
||||
Midori is a GitOps/GitHub Actions/Terraform Cloud helper bot. In it's simplest form, it is a hotline into GitHub Actions and Terraform Cloud to run and act upon the actual pipelines and such.
|
||||
|
||||
This is **not** a public bot for very obvious reasons. You may host it yourself, but it is not a required part of a Roleypoly deployment.
|
16
src/midori/internal/commands/gh/BUILD.bazel
Normal file
16
src/midori/internal/commands/gh/BUILD.bazel
Normal file
|
@ -0,0 +1,16 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "gh",
|
||||
srcs = ["gh.go"],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/midori/internal/commands/gh",
|
||||
visibility = ["//src/midori:__subpackages__"],
|
||||
deps = [
|
||||
"//src/common/bot",
|
||||
"//src/midori/internal/commands/helpers",
|
||||
"//src/midori/internal/config",
|
||||
"@com_github_google_go_github_v32//github:go_default_library",
|
||||
"@com_github_lampjaw_discordclient//:discordclient",
|
||||
"@org_golang_x_oauth2//:oauth2",
|
||||
],
|
||||
)
|
51
src/midori/internal/commands/gh/gh.go
Normal file
51
src/midori/internal/commands/gh/gh.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package gh
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-github/v32/github"
|
||||
"github.com/lampjaw/discordclient"
|
||||
"github.com/roleypoly/roleypoly/src/common/bot"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/commands/helpers"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/config"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
type GitHubCommands struct {
|
||||
ghClient *github.Client
|
||||
}
|
||||
|
||||
func NewGitHubCommands() GitHubCommands {
|
||||
ctx := context.Background()
|
||||
ts := oauth2.StaticTokenSource(
|
||||
&oauth2.Token{AccessToken: config.GitHubToken},
|
||||
)
|
||||
tc := oauth2.NewClient(ctx, ts)
|
||||
ghClient := github.NewClient(tc)
|
||||
|
||||
return GitHubCommands{
|
||||
ghClient: ghClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (ghc GitHubCommands) CommandGroup() bot.CommandGroup {
|
||||
return bot.CommandGroup{
|
||||
{
|
||||
CommandName: "dispatch",
|
||||
Handler: helpers.MustHaveElevatedPermissions(ghc.dispatch),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (ghc GitHubCommands) dispatch(ctx context.Context, message discordclient.Message) {
|
||||
tokens := bot.Tokenize(message)
|
||||
repo, webhookName := tokens[0], tokens[1]
|
||||
payload := json.RawMessage(strings.Join(tokens[2:], " "))
|
||||
|
||||
ghc.ghClient.Repositories.Dispatch(ctx, config.GitHubOrg, repo, github.DispatchRequestOptions{
|
||||
EventType: webhookName,
|
||||
ClientPayload: &payload,
|
||||
})
|
||||
}
|
14
src/midori/internal/commands/helpers/BUILD.bazel
Normal file
14
src/midori/internal/commands/helpers/BUILD.bazel
Normal file
|
@ -0,0 +1,14 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "helpers",
|
||||
srcs = ["permissions.go"],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/midori/internal/commands/helpers",
|
||||
visibility = ["//src/midori:__subpackages__"],
|
||||
deps = [
|
||||
"//src/common",
|
||||
"//src/common/bot",
|
||||
"//src/midori/internal/config",
|
||||
"@com_github_lampjaw_discordclient//:discordclient",
|
||||
],
|
||||
)
|
27
src/midori/internal/commands/helpers/permissions.go
Normal file
27
src/midori/internal/commands/helpers/permissions.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lampjaw/discordclient"
|
||||
"github.com/roleypoly/roleypoly/src/common"
|
||||
"github.com/roleypoly/roleypoly/src/common/bot"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/config"
|
||||
)
|
||||
|
||||
// MustHaveElevatedPermissions ensures a command has either Developer or Root role conditions.
|
||||
func MustHaveElevatedPermissions(next bot.HandlerFunc) bot.HandlerFunc {
|
||||
return func(ctx context.Context, message discordclient.Message) {
|
||||
if common.FindString(message.UserID(), config.RootUsers) || common.FindString(message.UserID(), config.AllowlistedUsers) {
|
||||
next(ctx, message)
|
||||
return
|
||||
}
|
||||
|
||||
NoPermissionsResponse(ctx, message)
|
||||
}
|
||||
}
|
||||
|
||||
// NoPermissionsResponse responds with a simple message that shows why the command failed.
|
||||
func NoPermissionsResponse(ctx context.Context, message discordclient.Message) {
|
||||
bot.ReplyToMessage(ctx, "⛔ You do not have elevated permissions.")
|
||||
}
|
13
src/midori/internal/commands/tfc/BUILD.bazel
Normal file
13
src/midori/internal/commands/tfc/BUILD.bazel
Normal file
|
@ -0,0 +1,13 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "tfc",
|
||||
srcs = ["tfc.go"],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/midori/internal/commands/tfc",
|
||||
visibility = ["//src/midori:__subpackages__"],
|
||||
deps = [
|
||||
"//src/common/bot",
|
||||
"//src/midori/internal/commands/helpers",
|
||||
"@com_github_lampjaw_discordclient//:discordclient",
|
||||
],
|
||||
)
|
25
src/midori/internal/commands/tfc/tfc.go
Normal file
25
src/midori/internal/commands/tfc/tfc.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
package tfc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lampjaw/discordclient"
|
||||
"github.com/roleypoly/roleypoly/src/common/bot"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/commands/helpers"
|
||||
)
|
||||
|
||||
type TerraformCloudCommands struct {
|
||||
}
|
||||
|
||||
func (tfcc TerraformCloudCommands) CommandGroup() bot.CommandGroup {
|
||||
return bot.CommandGroup{
|
||||
{
|
||||
CommandName: "dispatch",
|
||||
Handler: helpers.MustHaveElevatedPermissions(tfcc.dispatch),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (tfcc TerraformCloudCommands) dispatch(ctx context.Context, message discordclient.Message) {
|
||||
bot.ReplyToMessage(ctx, "Ok!")
|
||||
}
|
9
src/midori/internal/config/BUILD.bazel
Normal file
9
src/midori/internal/config/BUILD.bazel
Normal file
|
@ -0,0 +1,9 @@
|
|||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "config",
|
||||
srcs = ["config.go"],
|
||||
importpath = "github.com/roleypoly/roleypoly/src/midori/internal/config",
|
||||
visibility = ["//src/midori:__subpackages__"],
|
||||
deps = ["//src/common"],
|
||||
)
|
15
src/midori/internal/config/config.go
Normal file
15
src/midori/internal/config/config.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/roleypoly/roleypoly/src/common"
|
||||
)
|
||||
|
||||
var (
|
||||
BotToken = common.Getenv("MIDORI_BOT_TOKEN").String()
|
||||
ClientID = common.Getenv("MIDORI_CLIENT_ID").String()
|
||||
AllowlistedUsers = common.Getenv("MIDORI_DEVELOPERS").StringSlice()
|
||||
CommandPrefix = common.Getenv("MIDORI_PREFIX_OVERRIDE", "midori").String()
|
||||
RootUsers = common.Getenv("ROOT_USERS").StringSlice()
|
||||
GitHubOrg = common.Getenv("MIDORI_GITHUB_ORG").String()
|
||||
GitHubToken = common.Getenv("MIDORI_GITHUB_TOKEN").String()
|
||||
)
|
33
src/midori/midori.go
Normal file
33
src/midori/midori.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/bwmarrin/discordgo"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"k8s.io/klog"
|
||||
|
||||
"github.com/roleypoly/roleypoly/src/common/bot"
|
||||
"github.com/roleypoly/roleypoly/src/common/version"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/commands/gh"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/commands/tfc"
|
||||
"github.com/roleypoly/roleypoly/src/midori/internal/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
klog.Info(version.StartupInfo("midori"))
|
||||
|
||||
mux := bot.NewCommandMux(bot.MentionMatcher(config.ClientID))
|
||||
mux.RegisterCommandGroup("gh", gh.GitHubCommands{}.CommandGroup())
|
||||
mux.RegisterCommandGroup("tfc", tfc.TerraformCloudCommands{}.CommandGroup())
|
||||
|
||||
err := bot.ScaffoldBot(bot.BotScaffolding{
|
||||
AllowBots: false,
|
||||
BotToken: config.BotToken,
|
||||
BotClientID: config.ClientID,
|
||||
RootUsers: config.RootUsers,
|
||||
GatewayIntents: discordgo.IntentsGuildMessages,
|
||||
Handler: mux.Handler,
|
||||
})
|
||||
if err != nil {
|
||||
klog.Fatal(err)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue