Skip to content

Contributing to PLift

Thank you for your interest in contributing to PLift! This document provides guidelines and information for contributors.

Quick Start

# Clone the repository
git clone https://github.com/vlebo/plift.git
cd plift

# Copy environment file
cp .env.example .env

# Build and start the stack
./plift build-salt
./plift generate-base
./plift start-base
./plift generate-all
./plift start-stack

Prerequisites

  • Docker and Docker Compose
  • Make
  • Bash shell
  • mkcert (for SSL certificate generation)

Project Structure

plift/
├── Pliftfile                   # Make-based CLI commands
├── plift                       # CLI wrapper script
├── .env.example               # Environment template
├── configs/                    # Configuration (Salt pillars)
│   ├── base/                   # Base container configs
│   ├── services/               # Service definitions
│   │   └── init.sls           # MySQL, Redis, Kafka, etc.
│   ├── tools/                  # Tool definitions
│   │   └── init.sls           # Prometheus, Grafana, etc.
│   ├── apps/                   # Application configs
│   │   ├── init.sls           # App definitions
│   │   └── default/           # Framework defaults
│   ├── databases/              # Database user configs
│   │   ├── mysql/
│   │   └── postgresql/
│   ├── common/                 # Shared configuration
│   └── main/conf              # Active grains configuration
├── salt/                       # Salt Stack states
│   └── actions/generate/       # Config generation logic
│       ├── apps_configs.sls
│       ├── services_configs.sls
│       ├── tools_configs.sls
│       ├── migrations.sls
│       └── templates/          # Jinja2 templates
│           ├── apps/           # App config templates
│           ├── docker/         # Dockerfile templates
│           ├── grafana/        # Grafana provisioning
│           ├── haproxy/        # HAProxy config
│           └── migrations/     # SQL migration templates
├── docker/                     # Container definitions
│   ├── containers/
│   │   └── salt/              # Salt container Dockerfile
│   └── data/                  # Persistent volumes
├── apps/                       # Example applications
│   ├── example_laravel/
│   ├── example_django/
│   ├── example_nodejs/
│   └── example_java/
├── scripts/                    # Utility scripts
│   ├── generate-traffic.sh
│   └── import-grafana-dashboards.sh
├── docs/                       # Documentation
│   ├── architecture.md
│   └── adding-new-app.md
└── generated_configs/          # Auto-generated (gitignored)
    ├── docker/
    ├── haproxy/
    ├── prometheus/
    ├── grafana/
    └── ssl/

Architecture Overview

PLift uses a Salt Stack container to generate all configurations from YAML pillar files:

User Command → Pliftfile → Salt Container → Generated Configs → Docker Compose
     ↓              ↓            ↓                  ↓                ↓
./plift init    Make target   Salt states    docker-compose.yml   Running containers

Key Design Decisions

  1. Configuration as Code: All settings are in YAML pillar files (configs/)
  2. Template-Based Generation: Jinja2 templates produce Docker Compose files, app configs, etc.
  3. Framework Defaults: Each application framework has sensible defaults that can be overridden
  4. Service Isolation: Each service runs in its own container with defined networking
  5. Observability First: Built-in monitoring, logging, and tracing for all applications

How to Add Features

Adding a New Service

  1. Define the service in configs/services/init.sls:

    plift:
      services:
        my_service:
          enabled: true
          docker:
            name: my_service
            image: "my_service:latest"
            port_bindings:
              - "8080:8080"
    

  2. Create template (if needed) in salt/actions/generate/templates/

  3. Update generation logic in salt/actions/generate/services_configs.sls

  4. Regenerate and test:

    ./plift generate c=services
    ./plift start-services
    

Adding a New Application Framework

  1. Add framework defaults to configs/apps/default/init.sls:

    plift:
      frameworks:
        my_framework:
          defaults:
            base_image: "framework:latest"
            app_directory: "/app"
            exposed_port: 8000
    

  2. Create Dockerfile template: salt/actions/generate/templates/docker/dockerfile_my_framework.j2

  3. Create config template: salt/actions/generate/templates/apps/my_framework/env.j2

  4. Update app config generation in salt/actions/generate/apps_configs.sls

  5. Add example app in apps/example_my_framework/

Adding a New Tool

  1. Define the tool in configs/tools/init.sls:

    plift:
      tools:
        my_tool:
          enabled: true
          docker:
            name: my_tool
            image: "my_tool:latest"
          lb:
            enabled: true
            url: "my-tool.{{ LOCAL_DOMAIN }}"
    

  2. Add Grafana datasource (if applicable) in templates

  3. Regenerate and test:

    ./plift generate c=tools
    ./plift start-tools
    

Testing

Manual Testing

# Full stack test
./plift clean
./plift init
./plift status

# Generate test traffic
./plift generate-traffic requests=20

# Check logs
./plift logs c=<container_name>

Testing Configuration Changes

# Regenerate specific configs
./plift generate c=services  # or tools, apps, grafana

# Restart affected containers
./plift stop-services && ./plift start-services

Code Style

Bash Scripts

  • Use #!/bin/bash shebang
  • Quote variables: "${VAR}"
  • Use set -e for error handling where appropriate
  • Add comments for non-obvious logic

YAML Configuration

  • Use 2-space indentation
  • Use lowercase with underscores for keys
  • Group related settings together
  • Add comments for complex configurations

Jinja2 Templates

  • Use meaningful variable names
  • Add whitespace control ({%- and -%}) to avoid extra newlines
  • Comment template logic for clarity

Salt States

  • Use descriptive state IDs
  • Include require statements for dependencies
  • Use pillar data for configuration values

Submitting Changes

Pre-Submission Checklist

  • [ ] Code follows the project's style guidelines
  • [ ] Changes have been tested locally
  • [ ] Documentation has been updated (if applicable)
  • [ ] No sensitive data (passwords, tokens) in commits

Pull Request Guidelines

  1. One feature per PR: Keep changes focused and reviewable
  2. Descriptive title: Summarize what the PR does
  3. Update documentation: If adding features, update README or docs/
  4. Test your changes: Ensure the stack starts and functions correctly

Commit Message Format

<type>: <short description>

<optional longer description>

<optional footer>

Types: - feat: New feature - fix: Bug fix - docs: Documentation changes - refactor: Code refactoring - test: Adding or updating tests - chore: Maintenance tasks

Example:

feat: add MongoDB service support

- Add MongoDB configuration to services/init.sls
- Create Docker Compose template for MongoDB
- Add example configuration in documentation

Getting Help

  • Issues: Open an issue on GitHub for bugs or feature requests
  • Discussions: Use GitHub Discussions for questions and ideas

License

By contributing to PLift, you agree that your contributions will be licensed under the MIT License.