Development Guidelines
Relevant source files
The following files were used as context for generating this wiki page:
The Development Guidelines for Kamal provide a structured framework for contributors to maintain code quality, ensure architectural consistency, and follow established workflows for a fork-based maintenance model. These guidelines cover the technical stack, contribution procedures, architectural layers, and specific coding standards required for the project.
Kamal is primarily written in Ruby (v3.2+) and leverages Docker for containerization, SSHKit for remote command execution, and Thor for the Command Line Interface (CLI). Developers must adhere to specific branching strategies and testing protocols to ensure stability across deployments.
Sources: CONTRIBUTING.md:31-33, CLAUDE.md:7-12
Architectural Overview
The Kamal project is organized into functional layers that separate CLI concerns from core logic, command generation, and configuration management.
System Layers
| Layer | Component | Path | Description |
|---|---|---|---|
| Layer 5 | Entry Points | bin/kamal, bin/dash | Identical entry points directing to the Main CLI. |
| Layer 4 | CLI Commands | lib/kamal/cli | Thor-based commands and lifecycle hooks. |
| Layer 3 | Commander | lib/kamal/commander.rb | Singleton managing target resolution. |
| Layer 2 | Commands | lib/kamal/commands | Builders for Docker-specific commands. |
| Layer 1 | Configuration | lib/kamal/configuration | Objects and validation for deploy.yml. |
| Layer 0 | Execution | SSHKit | Core logic for remote shell execution. |
Sources: CLAUDE.md:43-50
Configuration Data Flow
The following diagram illustrates how raw configuration is loaded, processed, and validated within the system:
Sources: lib/kamal/configuration.rb:25-78
Contribution Workflow
Kamal follows a strict fork-maintenance model. While the main branch mirrors the upstream repository, the dash branch contains fork-specific enhancements like proxy load balancing.
Sources: CLAUDE.md:1-5
Branching and Commits
- Feature Branches: Always root feature branches off
dash. - Main Branch: Never commit directly to
main; it is a fast-forward mirror of upstream. - Syncing: Mirror
kamal.gemspecchanges intodash.gemspecafter every upstream sync. - Commit Messages: Should clearly describe what changed and why.
Sources: CLAUDE.md:14-26, CONTRIBUTING.md:28
Pull Request Requirements
Before submitting a Pull Request (PR), developers must ensure:
- Code passes all minitests via
./bin/test. - Changes are focused on a single concern.
- Descriptive variable and function names are used.
- Tests are added for any new functionality or fixes.
- Documentation is updated if necessary.
Sources: CONTRIBUTING.md:14-25
Coding Standards
General Rules
- Ruby Version: Maintain compatibility with Ruby 3.2 through 4.0.
- Linting: Follow
rubocop-rails-omakasestandards. Usebundle exec rubocop --parallelfor linting checks. - Naming: Use alphanumeric characters, hyphens, and underscores for service names.
Sources: CLAUDE.md:11-12, lib/kamal/configuration.rb:271, CLAUDE.md:37
Configuration Validation
The Kamal::Configuration class performs extensive validation during initialization to "fail fast" before any remote connections are established.
- Secret Validation: Secrets are resolved early to prevent mid-deploy failures. This includes registry credentials, builder secrets, and SSL certificates.
- Readiness Gates: Non-proxied roles must have a
healthcheckdefined, or explicitly opt out withhealthcheck: false, to prevent dropped traffic during container rotation. - Proxy Protocol: If
proxy_protocolis enabled,proxy_protocol_allow_ipsshould be defined to avoid unrestricted peer trust.
Sources: lib/kamal/configuration.rb:92-108, lib/kamal/configuration.rb:288-301, lib/kamal/configuration.rb:309-320
Shell Safety and Utilities
Utilities in Kamal::Utils are used to sanitize inputs for shell execution.
- Argumentization: Converts hashes/arrays into escaped shell arguments.
- Sensitivity: Marks values for redaction in logs using
Kamal::Utils::Sensitive. - Escaping: Uses
escape_shell_valueto handle special characters, preventing command injection.
Sources: lib/kamal/utils.rb:10-50, lib/kamal/utils.rb:85-98
Testing Protocols
Testing is divided into Unit tests and Integration tests. Integration tests are critical as they involve real deployments against Docker-in-Docker environments.
Sources: CLAUDE.md:72-80
Test Execution Commands
| Command | Purpose |
|---|---|
bin/test | Runs the full test suite (including integration). |
| `bundle exec ruby -Itest -e 'Dir["test/**/*_test.rb"].grep_v(/integration/).each { | f |
bundle exec rubocop --parallel | Executes linter checks. |
Sources: CLAUDE.md:35-39
Deployment Logic
The deployment process follows a specific sequence managed by Kamal::Cli::Main.
Sources: lib/kamal/cli/main.rb:23-64
Hook Management
Kamal provides lifecycle hooks (pre-deploy, post-deploy, etc.) located in .kamal/hooks. Developers must ensure that legacy traefik hooks are renamed to proxy hooks (e.g., pre-proxy-reboot).
Sources: lib/kamal/configuration.rb:277-285, lib/kamal/cli/main.rb:162-171
Summary
Developers contributing to Kamal must prioritize the "fail fast" philosophy by implementing robust validations in the configuration layer. Adherence to the fork-specific branching rules on the dash branch is mandatory to maintain harmony with upstream updates while supporting extended features like advanced load balancing. All code must be verified through the integrated test suite to ensure that container transitions remain zero-downtime and secure.