-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
148 lines (123 loc) · 3.95 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package main
import (
"flag"
"fmt"
"log"
"math/rand"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/adjust/michaelbot/auth"
"github.com/adjust/michaelbot/bot"
"github.com/adjust/michaelbot/dashboard"
"github.com/adjust/michaelbot/deploy"
"github.com/adjust/michaelbot/server"
"github.com/adjust/michaelbot/slack"
)
const (
DefaultHost = "0.0.0.0"
DefaultPort = 8081
)
var (
binPath = os.Args[0]
version = "n/a"
buildDate = "n/a"
buildRev = "n/a"
buildGoVersion = "n/a"
builder = "n/a"
args struct {
host string
port int
printVersion bool
}
)
func init() {
flag.BoolVar(&args.printVersion, "version", false, "Print version and exit")
flag.StringVar(&args.host, "h", DefaultHost, "Host or address to listen on")
flag.IntVar(&args.port, "p", DefaultPort, "Port to listen on")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options]\n\nOptions:\n", binPath)
flag.PrintDefaults()
}
}
func printVersion() {
fmt.Printf("%s v%s (rev %s)\n", binPath, version, buildRev)
fmt.Printf("Built with %s on %s by %s\n\n", buildGoVersion, buildDate, builder)
fmt.Println("Found a bug? Got an idea? Open an issue on https://github.com/adjust/michaelbot\nContributions are welcome!")
os.Exit(0)
}
func main() {
flag.Parse()
if args.printVersion {
printVersion()
}
slackToken := os.Getenv("SLACK_TOKEN")
if slackToken == "" {
log.Fatal("Missing SLACK_TOKEN env variable")
}
log.SetOutput(os.Stderr)
log.SetFlags(5)
githubToken := os.Getenv("GITHUB_TOKEN")
if githubToken == "" {
log.Printf("GITHUB_TOKEN env variable not set, only public PRs details will be displayed in deploy announcements")
}
var (
slackBot *bot.Bot
deployDashboard *dashboard.Dashboard
)
if boltDBPath := os.Getenv("BOLTDB_PATH"); boltDBPath != "" {
log.Printf("writing deploy history into a BoltDB in %s", boltDBPath)
store, err := deploy.NewBoltDBStore(boltDBPath)
if err != nil {
log.Fatalf("failed to open deploy DB: %s", err)
}
deployDashboard = dashboard.New(store)
slackBot = bot.New(slackToken, githubToken, store)
} else {
log.Println("BOLTDB_PATH env variable not set, keeping deploy history in memory")
store := deploy.NewInMemoryStore()
deployDashboard = dashboard.New(store)
slackBot = bot.New(slackToken, githubToken, store)
}
if slackWebAPIToken := os.Getenv("SLACK_WEBAPI_TOKEN"); slackWebAPIToken != "" {
api := slack.NewWebAPI(slackWebAPIToken, nil)
// Update channel topic to reflect current deploy status
slackBot.AddDeployEventHandler(bot.NewSlackTopicManager(api))
// Send direct messages to users mentioned in deploy subject
slackBot.AddDeployEventHandler(bot.NewSlackIMNotifier(api, 2*time.Hour))
} else {
log.Printf("SLACK_WEBAPI_TOKEN env variable not set, channel topic notifications are disabled")
}
tokenSource := auth.RandomTokenSource{Src: rand.NewSource(time.Now().UnixNano())}
authenticator := auth.NewOneTimeTokenAuthenticator(&tokenSource)
authSecret := os.Getenv("HISTORY_AUTH_SECRET")
if authSecret == "" {
authSecret = tokenSource.Generate(128)
log.Printf("HISTORY_AUTH_SECRET is not set, using randomly generated %q", authSecret)
}
slackBot.SetDashboardAuth(authenticator)
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, req *http.Request) {
if req.Method != "GET" {
http.NotFound(w, req)
return
}
fmt.Fprintf(w, "Michaelbot is running!")
})
mux.Handle("/deploy", slackBot)
mux.Handle("/", auth.TokenAuthenticationMiddleware(auth.ChannelAuthorizerMiddleware(deployDashboard, []byte(authSecret)), authenticator, []byte(authSecret)))
srv := server.New(args.host, args.port)
if err := srv.Start(mux); err != nil {
log.Fatal(err)
}
log.Printf("Michael Buffer v%s is listening on %s", version, srv.Addr)
signals := make(chan os.Signal)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
select {
case <-signals:
log.Println("signal received, shutting down...")
srv.Shutdown()
}
}