Files
dokku-docker-compose/docs/PLUGIN_STYLEGUIDE.md

495 lines
13 KiB
Markdown

# Dokku Plugin Style Guide
This document outlines the best practices and conventions for developing high-quality Dokku plugins, based on the patterns used in popular official plugins like dokku-postgres, dokku-redis, dokku-letsencrypt, and others.
## Plugin Types
Dokku plugins generally fall into three main categories, each with its own patterns and considerations:
### 1. Service Plugins (e.g., dokku-postgres, dokku-redis)
- Manage long-running services (databases, caches, etc.)
- Include full lifecycle management (create, destroy, backup, restore)
- Handle data persistence and migrations
- Support linking to applications
- Examples: PostgreSQL, Redis, MySQL, MongoDB
### 2. Utility Plugins (e.g., dokku-letsencrypt, dokku-http-auth)
- Add specific functionality to Dokku
- Often integrate with external services
- May run on schedules or triggers
- Examples: SSL certificates, authentication, monitoring
### 3. Core Plugins (e.g., dokku-postgres, dokku-redis)
- Provide fundamental infrastructure services
- Often bundled with Dokku
- Handle core functionality like networking, storage, etc.
- Examples: Network, Storage, Scheduler
## Table of Contents
1. [Project Structure](#project-structure)
2. [File Organization](#file-organization)
3. [Code Style](#code-style)
4. [Testing](#testing)
5. [Documentation](#documentation)
6. [Versioning](#versioning)
7. [CI/CD](#cicd)
8. [Common Patterns](#common-patterns)
9. [Best Practices](#best-practices)
## Project Structure
Dokku plugins follow a consistent structure that varies slightly based on the plugin type. Here's a comprehensive directory structure that covers all plugin types:
```
.
├── .github/ # GitHub-specific files
│ ├── workflows/ # GitHub Actions workflows
│ │ ├── ci.yml # Continuous Integration
│ │ └── release.yml # Release automation
│ └── dependabot.yml # Dependency updates
├── docs/ # Documentation
│ ├── README.md # Main documentation
│ ├── commands/ # Command references
│ └── examples/ # Usage examples
├── scripts/ # Utility scripts (optional)
│ └── setup_*.sh # Setup/configuration scripts
├── subcommands/ # Plugin subcommands (one file per subcommand)
│ ├── create # Service creation
│ ├── destroy # Service teardown
│ ├── backup # Data backup
│ └── ... # Other commands
├── tests/ # Test files
│ ├── unit/ # Unit tests
│ ├── integration/ # Integration tests
│ ├── test_helper.bash # Test utilities
│ └── setup.sh # Test setup
├── templates/ # Configuration templates (optional)
│ └── *.conf.sigil # Sigil templates for configs
├── .editorconfig # Editor configuration
├── .gitignore # Git ignore rules
├── Dockerfile # Development container
├── Makefile # Build and test tasks
├── plugin.toml # Plugin metadata
├── commands # Plugin command definitions
├── common-functions # Shared shell functions
├── help-functions # Help text generation
└── README.md # Project overview
```
### Key Files Explained:
1. **plugin.toml**
- Required for all plugins
- Defines plugin metadata and configuration
- Example:
```toml
[plugin]
description = "Postgres service plugin"
version = "1.0.0"
[plugin.config]
# Default configuration values
"docker-options" = "--restart=on-failure:10"
```
2. **commands**
- Defines the main plugin commands
- Maps commands to their implementations
- Example:
```
postgres:create postgres-create
postgres:destroy postgres-destroy
```
3. **subcommands/**
- One file per subcommand
- Naming: `plugin-command` (e.g., `postgres-create`)
- Each file should be executable and include help text
4. **tests/**
- BATS test files
- Mirror the command structure
- Include both unit and integration tests
## File Organization
### Core Files
1. **plugin.toml**
- Contains plugin metadata and configuration
- Defines plugin name, version, and dependencies
- Example:
```toml
[plugin]
description = "Postgres service plugin"
version = "1.15.0"
[plugin.config]
"docker-options" = "--restart=on-failure:10"
```
2. **Makefile**
- Standard build and test targets
- Common targets: `build`, `test`, `lint`, `install`
- Example:
```makefile
.PHONY: test
test:
@bats tests/
```
3. **Dockerfile**
- Defines the development environment
- Includes all necessary build tools and dependencies
### Subcommands
- Each subcommand is a separate file in the `subcommands/` directory
- Naming convention: `subcommands/<command>-<subcommand>`
- Example: `subcommands/service-create`, `subcommands/service-logs`
### Documentation
- Comprehensive README.md with:
- Installation instructions
- Basic usage examples
- Available commands
- Configuration options
- Troubleshooting
## Code Style
### Shell Scripting
- Use `#!/usr/bin/env bash` for portability
- Follow [Google's Shell Style Guide](https://google.github.io/styleguide/shellguide.html)
- Use `local` for function-scoped variables
- Quote all variables to prevent word splitting
- Use `[[` for tests instead of `[`
- Example:
```bash
#!/usr/bin/env bash
set -eo pipefail
my_function() {
local var1="value1"
local var2="value2"
if [[ "$var1" == "$var2" ]]; then
echo "Values are equal"
fi
}
```
### Error Handling
- Use `set -eo pipefail` at the start of scripts
- Provide meaningful error messages
- Use `trap` for cleanup operations
- Example:
```bash
cleanup() {
rm -f "$TEMP_FILE"
}
trap cleanup EXIT
```
## Testing
### Test Structure
- Use [bats-core](https://github.com/bats-core/bats-core) for testing
- Organize tests by functionality
- Follow naming convention: `tests/<feature>_test.bats`
- Example test file:
```bash
#!/usr/bin/env bats
load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load'
setup() {
# Test setup code
}
teardown() {
# Test teardown code
}
@test "service create should succeed" {
run dokku postgres:create test-db
assert_success
assert_output --partial "PostgreSQL container created: test-db"
}
```
### Test Coverage
- Test all subcommands
- Include error cases
- Test edge cases
- Mock external dependencies
- Use test fixtures for complex data
## Documentation
### Command Help
- Include help text for all commands
- Use `dokku <plugin>:help <command>` pattern
- Document all options and arguments
- Example:
```bash
help() {
cat <<EOF
Usage: dokku postgres:create <name> [options]
Create a new PostgreSQL service.
Options:
--config-opt KEY=VALUE Set configuration option
--image IMAGE Use custom Docker image
EOF
}
```
### Man Pages
- Include man pages for complex commands
- Use `ronn` or similar tool to generate man pages from markdown
- Example: `docs/man/dokku-postgres-create.1.ronn`
## Versioning
- Follow [Semantic Versioning](https://semver.org/)
- Update version in `plugin.toml`
- Create GitHub releases with changelog
- Tag releases with `v` prefix (e.g., `v1.0.0`)
## CI/CD
### GitHub Actions
- Run tests on push and pull requests
- Lint shell scripts with ShellCheck
- Build and test on multiple platforms
- Example workflow:
```yaml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: make test
- name: Lint shell scripts
run: shellcheck -x scripts/*
```
### Release Process
1. Update version in `plugin.toml`
2. Update `CHANGELOG.md`
3. Create git tag
4. Push tag to trigger release
5. GitHub Actions will publish the release
## Common Patterns
### Service Management
```bash
# Start service
dokku postgres:start my-db
# Stop service
dokku postgres:stop my-db
# View logs
dokku postgres:logs my-db
```
### Data Management
```bash
# Create backup
dokku postgres:backup my-db
# Restore from backup
dokku postgres:restore my-db < backup.dump
# Export data
dokku postgres:export my-db > data.sql
```
### Linking Services
```bash
# Link service to app
dokku postgres:link my-db my-app
# Unlink service
dokku postgres:unlink my-db my-app
```
## Best Practices
### Core Principles
1. **Idempotency**: All commands should be idempotent (running them multiple times has the same effect as running them once)
2. **Error Handling**:
- Provide clear, actionable error messages
- Include error codes for programmatic handling
- Clean up resources on failure
3. **Documentation**:
- Document all commands with examples
- Keep README and help text up-to-date
- Include troubleshooting guides
### Code Quality
4. **Testing**:
- Maintain high test coverage (aim for 80%+)
- Test edge cases and error conditions
- Include both unit and integration tests
5. **Security**:
- Never log sensitive data
- Validate all inputs
- Follow principle of least privilege
6. **Performance**:
- Optimize for speed and resource usage
- Minimize external command calls
- Cache expensive operations when possible
### Plugin Architecture
7. **Compatibility**:
- Maintain backward compatibility within major versions
- Use feature detection for optional functionality
- Document version requirements
8. **Logging**:
- Use appropriate log levels (DEBUG, INFO, WARN, ERROR)
- Include timestamps and context in logs
- Support structured logging for machine processing
9. **Resource Management**:
- Clean up temporary files and resources
- Handle signals and shutdown gracefully
- Implement timeouts for long-running operations
### Plugin-Specific Guidelines
10. **Service Plugins**:
- Implement full lifecycle management
- Support backup/restore operations
- Handle data persistence and migrations
11. **Utility Plugins**:
- Focus on single responsibility
- Support dry-run mode
- Include validation for all inputs
12. **Core Plugins**:
- Follow established patterns from official plugins
- Document all configuration options
- Include upgrade paths for existing users
### Development Workflow
13. **Version Control**:
- Use semantic versioning
- Create meaningful commit messages
- Use feature branches and pull requests
14. **CI/CD**:
- Automate testing and releases
- Run linters and static analysis
- Generate changelogs automatically
15. **Community**:
- Document contribution guidelines
- Include a code of conduct
- Be responsive to issues and PRs
## Example Plugins
### Service Plugin: dokku-postgres
- **Repository**: [dokku/dokku-postgres](https://github.com/dokku/dokku-postgres)
- **Key Features**:
- Full database lifecycle management
- Backup/restore functionality
- User and permission management
- SSL configuration
- **Notable Patterns**:
- Well-structured subcommands
- Comprehensive test suite
- Detailed documentation
### Utility Plugin: dokku-letsencrypt
- **Repository**: [dokku/dokku-letsencrypt](https://github.com/dokku/dokku-letsencrypt)
- **Key Features**:
- Automatic SSL certificate management
- Certificate renewal
- Nginx configuration
- **Notable Patterns**:
- Cron-based scheduling
- Template-based configuration
- Clean error handling
### Core Plugin: dokku-redis
- **Repository**: [dokku/dokku-redis](https://github.com/dokku/dokku-redis)
- **Key Features**:
- Redis instance management
- Data persistence
- Service linking
- **Notable Patterns**:
- Consistent command structure
- Integration with Dokku networking
- Clear user feedback
## Plugin Development Checklist
When developing a new Dokku plugin, ensure you've covered these aspects:
### Core Functionality
- [ ] Implement all required lifecycle hooks
- [ ] Support all standard commands (create, destroy, info, etc.)
- [ ] Handle errors gracefully
- [ ] Validate all inputs
### User Experience
- [ ] Provide clear help text for all commands
- [ ] Include usage examples
- [ ] Document configuration options
- [ ] Support common environment variables
### Testing
- [ ] Write unit tests for core functions
- [ ] Include integration tests
- [ ] Test error conditions
- [ ] Verify plugin uninstallation
### Documentation
- [ ] Complete README
- [ ] Command reference
- [ ] Installation instructions
- [ ] Upgrade guides
### Deployment
- [ ] CI/CD pipeline
- [ ] Version management
- [ ] Release process
- [ ] Changelog generation
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Update documentation
6. Submit a pull request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.