-
Notifications
You must be signed in to change notification settings - Fork 6
Add initial Otto bot #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces the initial implementation of Otto bot, setting up the core infrastructure including configuration, HTTP server, telemetry, database, module/event handling, and test utilities.
- Added core application functionality with modular design
- Integrated OpenTelemetry for metrics, tracing, and logging
- Provided test helpers and example configuration for easier development and testing
Reviewed Changes
Copilot reviewed 25 out of 28 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| otto/internal/testing.go | Test helpers for initializing the app, database, and repository |
| otto/internal/telemetry.go | OpenTelemetry integration for metrics, traces, and log bridging |
| otto/internal/server.go | HTTP webhook server implementation with signature verification |
| otto/internal/repository.go | SQLite repository implementation and transaction support |
| otto/internal/modules_test.go | Unit tests for module registration and event dispatching |
| otto/internal/modules.go | Module interface definitions and global module registry |
| otto/internal/middleware_test.go | Placeholder for removed command middleware tests |
| otto/internal/middleware.go | Placeholder for removed command middleware |
| otto/internal/error.go | Application error handling and logging mechanism |
| otto/internal/db.go | Shared SQLite database connection setup |
| otto/internal/config.go | YAML configuration loading, validation, and defaults |
| otto/internal/commands_test.go | Tests for slash command parsing utility |
| otto/internal/commands.go | Slash command parsing and tracing utilities; minor iteration bug present |
| otto/internal/app.go | Main application struct, initialization, and shutdown logic |
| otto/config.example.yaml | Example configuration file |
| otto/cmd/otto/main.go | Application entrypoint and graceful shutdown logic |
| otto/README.md | Project documentation and overview |
Files not reviewed (3)
- otto/Dockerfile: Language not supported
- otto/Makefile: Language not supported
- otto/go.mod: Language not supported
Comments suppressed due to low confidence (2)
otto/internal/commands.go:20
- The function strings.SplitSeq is not part of the standard library; replace it with strings.Split to correctly split the string.
lines := strings.SplitSeq(body, "\n")
otto/internal/commands.go:21
- The for loop iterates over indices rather than values; use 'for _, line := range lines {' to correctly iterate over each line.
for line := range lines {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be not under otto/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, it likely should ignore the .env file no matter where it's placed, but setting it's path here will only exclude it in the otto/ dir. Which may be the spot Austin's using locally, but someone is bound to put it somewhere else eventually. .env files are notorious exposers of secrets :D
| cache-dependency-path: otto/go.sum | ||
|
|
||
| - name: Install dependencies | ||
| run: go mod download |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't go test -v ./... automatically download the dependencies? Is it necessary to pre-download step?
| --mount=type=cache,target=/root/.cache/go-build \ | ||
| cd ./otto && go build -o /out/otto ./cmd/otto | ||
|
|
||
| FROM debian:bullseye-slim |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since otto (love the name) is a go app, any objections to converting the second stage to a scratch container? It'll be lighter than bullseye-slim & more security, especially since all we need is the binary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want 1000 of these stickers, just saying :)
|
|
||
| import ( | ||
| "context" | ||
| "log/slog" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a personal preference thing: using zap instead of slog. Both are supported by the log bridge though.
edit: I just got to the point of looking at the instrumentation code, so nevermind on the secondary statement I made previously.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a couple helpers I've found useful that could be added here, like licensing, gci, imports, osv-scanner, and formatting. I'm happy to add them on a next pass unless you want to now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does goreleaser do that stuff? I was thinking of switching to it anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK, not directly. It supports hooks though which can hook into the makefile. It's good to have this stuff in local dev. If locked to 1.24 of go it can be incorporated into the tools directive, else, the older pattern can easily be followed (which I haven't migrated to the new pattern yet).
Tools the OTel collector finds useful are: (and i echo)
## OTEL Collector Specific ones
_ "github.com/daixiang0/gci"
_ "github.com/google/addlicense"
_ "golang.org/x/tools/cmd/goimports"
_ "golang.org/x/vuln/cmd/govulncheck"
_ "gotest.tools/gotestsum"
_ "mvdan.cc/gofumpt"
## Other
_ "github.com/google/osv-scanner/v2/cmd/osv-scanner"
)Happy to submit a PR if you want me to add some of this.
| web_hook_secret: "your_web_hook_secret" | ||
| port: "8080" | ||
| db_path: "data.db" | ||
| github_token: "" # GitHub personal access token for API requests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of a PAT, we should use oidc through gh app auth (i have a otel collector extension i wrote as reference, pretty easy to implement).
Also, can we separate the normal config from the secret configuration here to ensure better security around the token / webhook secret on the next pass?
| return | ||
| case <-ticker.C: | ||
| if err := o.CheckUnacknowledgedTasks(); err != nil { | ||
| slog.Error("Error checking unacknowledged tasks", "error", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: there's inconsistency in the casing of log messages. Some start upper, others don't.
|
I've fixed the issues identified in the PR review:
All tests are now passing. |
|
I've addressed several of the PR comments:
The remaining suggestions about the Docker image, workflow improvements, and configuration can be addressed in future PRs. |
|
claude forgot to actually commit those changes so i guess they'll be in a different PR |
Not yet complete, but I wanted to get the initial work pushed.