Initial commit: Add documentation and move to docs/ directory
This commit is contained in:
494
docs/PLUGIN_STYLEGUIDE.md
Normal file
494
docs/PLUGIN_STYLEGUIDE.md
Normal file
@@ -0,0 +1,494 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user