Smyklot
GitHub App for automated PR approvals and merges based on CODEOWNERS
Overview
Smyklot is a GitHub App that automates pull request approvals and merges by validating permissions against your repository's CODEOWNERS file. Simply comment on a PR with commands or add emoji reactions, and Smyklot handles the rest.
Features
- CODEOWNERS-based permissions - Only repository owners defined in
.github/CODEOWNERS can approve/merge
- Multiple command formats - Supports slash commands (
/approve), mentions (@smyklot approve), and bare commands (lgtm, merge)
- Merge method control - Explicit
squash and rebase commands with intelligent fallback for merge
- Reaction-based commands - Use π to approve, π to merge, or β€οΈ to cleanup
- Cleanup command - Remove all bot reactions, approvals, and comments with a single command
- Approval deduplication - Prevents duplicate approvals with smart reaction handling
- Flexible configuration - Configure via
SMYKLOT_CONFIG JSON, individual variables, or environment variables
- Emoji feedback - Get instant visual confirmation with β
(success), β (error), or β οΈ (warning)
- Comment edit/delete handling - Reacts to command edits and removes reactions when commands are deleted
- Reaction removal tracking - Automatically removes approvals/merges when reactions are removed
- Multi-command support - Execute multiple commands in a single comment
- Security-first design - Follows GitHub Actions best practices with minimal permissions
- Zero external dependencies - Runs entirely on GitHub Actions
- TDD implementation - 130+ passing tests
Quick Start
Prerequisites
- GitHub repository with Actions enabled
.github/CODEOWNERS file in your repository
Installation
Option 1: GitHub App (Recommended)
-
Install the Smyklot GitHub App on your repository
-
Create .github/CODEOWNERS:
* @username
-
Comment on PRs with commands or add reactions
Option 2: Manual Workflow
Copy the workflow file to your repository:
cp .github/workflows/pr-commands.yml your-repo/.github/workflows/
Usage
Smyklot responds to these commands in PR comments:
| Command |
Aliases |
Format |
Description |
approve |
lgtm, accept |
/approve, @smyklot approve, approve |
Approve the pull request |
merge |
- |
/merge, @smyklot merge, merge |
Merge the pull request (with fallback) |
squash |
- |
/squash, @smyklot squash, squash |
Squash merge the pull request |
rebase |
- |
/rebase, @smyklot rebase, rebase |
Rebase merge the pull request |
unapprove |
- |
/unapprove, @smyklot unapprove |
Remove approval |
cleanup |
- |
/cleanup, @smyklot cleanup, cleanup |
Remove all bot reactions, approvals, and comments |
help |
- |
/help, @smyklot help |
Show help information |
Command Formats:
- Slash commands:
/approve, /merge, /squash, /rebase, /unapprove, /cleanup, /help
- Mention commands:
@smyklot approve, @smyklot merge, @smyklot squash, @smyklot rebase, @smyklot unapprove, @smyklot cleanup
- Bare commands:
approve, accept, lgtm, merge, squash, rebase, cleanup (exact match only)
All commands are case-insensitive.
Reaction Commands
| Reaction |
Action |
| π |
Approve the pull request |
| π |
Merge the pull request |
| β€οΈ |
Cleanup (remove all bot reactions, approvals, and comments) |
Note: Removing a reaction will automatically undo the corresponding action (remove approval/merge labels).
Multiple Commands
You can use multiple non-contradicting commands in a single comment:
/approve
/merge
or
lgtm merge
Commands will be executed in order: approve first, then merge.
Examples
Approving a PR
Any of these will approve the PR:
/approve
@smyklot approve
lgtm
Or simply add a π reaction to any comment.
Merging a PR
Merge with default method (with fallback to squash/rebase if merge commits disallowed):
/merge
Or add a π reaction to any comment.
Squash Merging
/squash
Rebase Merging
/rebase
Removing Approval
/unapprove
Or remove your π reaction.
Cleanup
Remove all bot reactions, approvals, and comments:
/cleanup
Or add a β€οΈ reaction to any comment.
Note: Cleanup cannot be combined with other commands.
Configuration
CODEOWNERS Setup
Create .github/CODEOWNERS in your repository:
# Global owners can approve/merge any PR
* @username1 @username2
Currently only global owners (* pattern) are supported. Path-specific owners will be added in Phase 2.
Bot Configuration
Smyklot can be configured via repository variables (Settings β Secrets and variables β Actions β Variables).
Configuration Precedence: CLI flags > Environment variables > Repository variables > Defaults
Option 1: Full JSON Configuration (Recommended)
Set a SMYKLOT_CONFIG repository variable with your complete configuration:
{
"quiet_success": false,
"quiet_reactions": false,
"allowed_commands": ["approve", "merge"],
"command_aliases": {
"ok": "approve",
"ship": "merge"
},
"command_prefix": "/",
"disable_mentions": false,
"disable_bare_commands": false,
"disable_unapprove": false,
"disable_reactions": false,
"disable_deleted_comments": false
}
Option 2: Individual Variables
Configure individual settings via repository variables or environment variables with SMYKLOT_ prefix:
| Variable |
Type |
Default |
Description |
SMYKLOT_QUIET_SUCCESS |
boolean |
false |
Disable success feedback comments |
SMYKLOT_QUIET_REACTIONS |
boolean |
false |
Disable reaction-based approval/merge comments |
SMYKLOT_ALLOWED_COMMANDS |
list |
all |
Limit which commands are allowed |
SMYKLOT_COMMAND_ALIASES |
map |
default |
Define custom command aliases |
SMYKLOT_COMMAND_PREFIX |
string |
/ |
Custom command prefix |
SMYKLOT_DISABLE_MENTIONS |
boolean |
false |
Disable mention commands |
SMYKLOT_DISABLE_BARE_COMMANDS |
boolean |
false |
Disable bare commands |
SMYKLOT_DISABLE_UNAPPROVE |
boolean |
false |
Disable unapprove command |
SMYKLOT_DISABLE_REACTIONS |
boolean |
false |
Disable reaction-based approvals/merges |
SMYKLOT_DISABLE_DELETED_COMMENTS |
boolean |
false |
Disable handling of deleted comments |
Configuration Examples
Example 1: Quiet Mode
Only show emoji reactions, no success comments:
# In workflow or as repository variable
env:
SMYKLOT_QUIET_SUCCESS: "true"
Result: User sees only β
reaction, no "PR Approved" comment.
Example 2: Custom Prefix
Use ! instead of / for commands:
env:
SMYKLOT_COMMAND_PREFIX: "!"
Users can now use !approve and !merge.
Example 3: Command Aliases
Create shortcuts for commands:
env:
SMYKLOT_COMMAND_ALIASES: '{"app":"approve","a":"approve","m":"merge"}'
Users can use /app, /a, or /m as shortcuts.
Example 4: Reactions Only
Disable comment-based commands, only allow reactions:
{
"disable_mentions": true,
"disable_bare_commands": true,
"command_prefix": "disabled"
}
Only π and π reactions will work.
Example 5: Disable Reaction Tracking
Don't remove approvals/merges when reactions are removed:
env:
SMYKLOT_DISABLE_DELETED_COMMENTS: "true"
Architecture
How It Works
- User comments a command or adds a reaction on a PR
- GitHub triggers
issue_comment webhook
pr-commands.yml workflow starts
- Smyklot:
- Parses the command (supports slash, mention, and bare formats)
- Or processes reactions (π for approve, π for merge, β€οΈ for cleanup)
- Validates command combinations (cleanup cannot be combined with others)
- Checks for duplicate approvals (prevents re-approving)
- Fetches
.github/CODEOWNERS via GitHub API
- Checks user permissions
- Calls GitHub API to approve/merge/cleanup
- For merge: tries specified method or falls back (merge β squash β rebase)
- Posts reactions and feedback
- On comment edit/delete or reaction removal, updates accordingly
Permission System
Phase 1 (Current):
- Only global owners (
* @username) are supported
- Global owners can approve/merge any PR
- Reaction-based approvals/merges with tracking
Phase 2 (Planned):
- Path-specific ownership patterns
- Scoped permissions based on changed files
- Team support (
@org/team-name)
- Self-approval prevention
Security
- All inputs passed via environment variables
- No shell interpolation of user data
- Actions pinned by commit digest
- Minimal workflow permissions (contents: read, pull-requests: write)
- Token-based authentication via GitHub App
- CODEOWNERS file fetched via API (no repository checkout)
Development
Requirements
- Go 1.25+
- mise for tool management
- Task for task automation
Setup
# Clone repository
git clone https://github.com/bartsmykla/smyklot.git
cd smyklot
# Install tools
mise install
# Download dependencies
go mod download
# Run tests
task test
Project Structure
smyklot/
βββ cmd/
β βββ github-action/ # GitHub Actions entrypoint
βββ pkg/
β βββ commands/ # Command parser (slash, mention, bare)
β βββ config/ # Configuration management (Viper)
β βββ feedback/ # User feedback system (reactions, comments)
β βββ github/ # GitHub API client
β βββ permissions/ # CODEOWNERS parser & permission checker
βββ .github/workflows/ # GitHub Actions workflows
βββ .goreleaser.yml # GoReleaser config for releases
βββ .mise.toml # Tool versions
βββ Dockerfile # Docker image for GitHub Actions
βββ Taskfile.yaml # Task automation
βββ go.mod # Go module definition
Available Tasks
task # Show available tasks
task test # Run all tests with coverage
task test:unit # Run unit tests only
task lint # Run all linters
task build # Build binaries
task clean # Clean build artifacts
Testing
All tests use Ginkgo/Gomega BDD framework:
# Run all tests
task test
# Run specific package
ginkgo -r pkg/commands/
# Watch mode for TDD
ginkgo watch -r
Current test coverage: 130+ tests passing
- 52+ command parser tests
- 12 CODEOWNERS parser tests
- 30 permission checker tests
- 30 feedback system tests
- 18+ GitHub client tests
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feat/amazing-feature)
- Write tests first (TDD)
- Implement the feature
- Ensure all checks pass:
task lint && task test
- Commit with conventional commits (
feat:, fix:, docs:, etc.)
- Push to your fork
- Open a pull request
Roadmap
Phase 1: GitHub Actions Bot β
- Command parser (slash, mention, bare)
- Multi-command support
- Merge method commands (merge, squash, rebase)
- Merge method fallback (merge β squash β rebase)
- Cleanup command (remove all bot reactions, approvals, comments)
- Approval deduplication (prevent duplicate approvals)
- Reaction-based approvals/merges/cleanup (π, π, β€οΈ)
- Reaction removal tracking
- Comment edit/delete handling
- CODEOWNERS parser (global owners)
- Permission checker
- GitHub API client
- Feedback system (emoji + comments)
- Configuration system (Viper)
- GitHub Actions workflows
- Docker-based GitHub Action
- Documentation
Phase 2: Enhanced Permissions (Planned)
- Path-specific ownership patterns
- Scoped approval requirements based on changed files
- Team support in CODEOWNERS (
@org/team-name)
- Self-approval prevention
- Required approvals count
Phase 3: Kubernetes Deployment (Future)
- HTTP webhook server
- Persistent service deployment
- Scalable architecture
- Prometheus metrics
- Helm chart
Phase 4: Discord Integration (Future)
- Discord bot
- Unified command system
- Cross-platform notifications
- Status synchronization
License
MIT License - see LICENSE for details
Acknowledgments
Built with:
Made with β€οΈ by @bartsmykla