Contributing Guide
Relevant source files
The following files were used as context for generating this wiki page:This guide provides instructions and best practices for contributing to the Dokku MCP Server project. It covers setting up the development environment, the development workflow, code style, and architectural principles. The project welcomes contributions in the form of code, documentation improvements, bug reports, and feature requests.
Sources: CONTRIBUTING.md:3-5
How to Contribute
There are several ways to contribute to the project's development.
Reporting Bugs
Before submitting a bug, search the existing GitHub Issues to avoid duplicates. When opening a new issue, provide a clear title, a detailed description of the problem, and a code sample or test case that reproduces the issue.
Sources: CONTRIBUTING.md:10-13
Suggesting Enhancements
To suggest an enhancement, open a new issue to discuss the proposed change. Describe the enhancement, its motivation, and the specific use case it addresses.
Sources: CONTRIBUTING.md:15-17
Getting Help with Goose AI
For assistance with development, debugging, or feature implementation, you can tag a GitHub issue or pull request with the :goose label. This will notify Goose AI to provide automated help.
Sources: README.md:65-69
Development Workflow
The project follows a standard feature-branch workflow. All development work should be done in a dedicated branch created from main.
Sources: CONTRIBUTING.md:24-26
1. Environment Setup
A local development environment requires Go, Docker, and Make. The setup process involves cloning the repository and using make targets to install tools and configure git hooks.
Sources: README.md:143-146, CONTRIBUTING.md:21-22
The following diagram illustrates the initial setup flow.
The setup commands are as follows:
# 1. Clone the repository
git clone https://github.com/dokku-mcp/dokku-mcp.git
cd dokku-mcp
# 2. Install Go development tools
make install-tools
# 3. Configure git hooks for code quality checks
make setup-dev
Sources: CONTRIBUTING.md:21-22, README.md:152-155
2. Local Dokku Instance (Optional)
For integration testing and development without a remote Dokku server, you can run a local instance using Docker.
The following commands set up and start the local Dokku container:
# Set up the local Dokku container (run once)
make setup-dokku
# Start the container
make dokku-start
Sources: README.md:122-127
The make setup-dokku command executes the scripts/setup-dokku-local.sh script, which automates several key tasks:
- Starts the Dokku Docker container via
docker compose up -d. - Waits for the Dokku service to become available.
- Generates a dedicated SSH key pair (
.ssh/dokku_mcp_test) for testing. - Adds the public key to the local Dokku instance.
- Creates a
config.yamlfile pre-configured to connect to the local Dokku container.
Sources: scripts/setup-dokku-local.sh:9-88
This diagram shows the components of the local development environment.
Sources: scripts/setup-dokku-local.sh:83-84
3. Code and Tests
Create a feature branch from main for your changes.
git checkout -b feature/your-amazing-feature
Sources: CONTRIBUTING.md:25-26
Write your code, adhering to the project's Architecture & Code Style. Crucially, all new code must be accompanied by tests. You can run the full test suite using:
make test
This command runs all unit and integration tests and generates an HTML coverage report at coverage.html.
Sources: CONTRIBUTING.md:29-30, README.md:166-169
4. Code Quality and Git Hooks
The project uses Git hooks to enforce code quality and style before commits. The make setup-dev command configures core.hooksPath to use the .githooks/ directory.
Sources: CONTRIBUTING.md:43-44, scripts/setup-dev.sh:9-10
The pre-commit hook automatically performs the following actions:
| Action | Description |
|---|---|
| Auto-format | Formats Go code using goimports/gofmt. |
| Static Analysis | Runs go vet to find potential issues. |
| Strong Typing | Enforces rules against interface{}. |
| Quick Tests | Runs tests on modified packages. |
Sources: CONTRIBUTING.md:47-52
This workflow ensures that code committed to the repository meets quality standards.
Sources: CONTRIBUTING.md:46-52
5. Submit a Pull Request
Once your feature is complete and passes all checks, push the branch to your fork and open a pull request against the main branch of the dokku-mcp/dokku-mcp repository. Ensure your PR has a clear description and that all automated status checks pass.
Sources: CONTRIBUTING.md:54-59
Architecture & Code Style
The project follows specific architectural patterns and coding conventions to maintain quality and consistency.
Sources: CONTRIBUTING.md:70-71
Domain-Driven Design (DDD)
The server is structured according to Domain-Driven Design (DDD) principles, separating concerns into distinct layers.
This diagram shows the separation of concerns into Application, Domain, and Infrastructure layers.
Sources: README.md:175-180, PHASE1_IMPLEMENTATION.md:121-125
Plugin-Based Architecture
Functionality is encapsulated within a plugin-based architecture. Each plugin in internal/server-plugins corresponds to a set of Dokku features (e.g., app, core, domain). This modular design is evident in files like internal/server-plugins/app/plugin.go, which implements the ServerPlugin interface to provide app-related resources, tools, and prompts.
Sources: README.md:181-183, internal/server-plugins/app/plugin.go:26-30
Coding Conventions
- Strong Typing: Avoid using
interface{}andanyunless absolutely necessary and justified. Thepre-commithook helps enforce this. - Error Handling: Wrap errors with context using
fmt.Errorfand the%wverb. - Go Conventions: Adhere to standard Go formatting (
gofmt) and static analysis (go vet).
Sources: CONTRIBUTING.md:72-75, PHASE1_IMPLEMENTATION.md:213-214
An example of command validation and error handling can be seen in the Dokku API client:
// internal/dokku-api/client.go:19
func (c *client) ValidateCommand(commandName string, args []string) error {
if commandName == "" {
return fmt.Errorf("command name cannot be empty")
}
// Blacklist first (runtime configuration)
for _, blacklistedPattern := range c.blacklistedCommands {
if strings.Contains(commandName, blacklistedPattern) {
return fmt.Errorf("command is blacklisted (matches pattern '%s'): %s", blacklistedPattern, commandName)
}
}
// ... more validation
return nil
}
Sources: internal/dokku-api/client.go:19-30
Testing
Tests are a critical part of the contribution process and are written using the Ginkgo and Gomega testing frameworks.
Sources: CONTRIBUTING.md:29, internal/dokku-api/ssh_integration_test.go:12-13
Running Tests
The Makefile provides several targets for running tests:
| Command | Description |
|---|---|
make test | Runs all unit and integration tests. |
make check | Runs all code quality checks, including linting and formatting. |
make test-integration-local | Runs integration tests specifically against a local Dokku container. |
Sources: README.md:162-172, CONTRIBUTING.md:35-37
Test Structure Example
Tests are structured in a descriptive, BDD-style format.
// internal/dokku-api/ssh_integration_test.go:15
var _ = Describe("SSH Integration", func() {
var (
logger *slog.Logger
)
BeforeEach(func() {
logger = slog.New(slog.NewTextHandler(GinkgoWriter, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
})
Describe("SSHConfig", func() {
Describe("NewSSHConfigFromServerConfig", func() {
It("should create SSH config from server config parameters", func() {
// ... test logic ...
Expect(err).NotTo(HaveOccurred())
Expect(config.Host()).To(Equal("dokku.com"))
})
})
})
})
Sources: internal/dokku-api/ssh_integration_test.go:15-40
Code Review Checklist
Pull requests are reviewed against the following checklist. Ensure your contribution meets these criteria before submission.
- Does the code have unit tests?
- Is the documentation updated to reflect the changes?
- Is there proper error handling for all new paths?
- Is there proper input validation and sanitization?
- Are logs added for important operations?
- Has performance been considered?
Sources: CONTRIBUTING.md:61-68