Accepted
We need a Rust-based GitOps promotion tool that:
- Promotes configuration files between environments (e.g., staging → production)
- Supports multiple git repositories with different structures
- Uses git-native features for diff and safety checks
- Excludes certain directories (custom, env, local) from promotion
- Allows flexible file selection via allowlist/denylist patterns
promrail/
├── src/
│ ├── main.rs # CLI entry point
│ ├── cli.rs # clap argument parsing
│ ├── config.rs # YAML config loading
│ ├── error.rs # Error types
│ ├── commands/ # Command implementations
│ ├── git/ # Git operations
│ ├── files/ # File selection
│ └── review/ # Multi-source review artifacts
└── promrail.yaml # Configuration file
Configuration explicitly defines repositories and their environments:
repos:
gitops:
path: ~/gitops
environments:
staging: { path: clusters/staging }
production: { path: clusters/production }Rationale: Different repositories have different structures. Explicit config prevents ambiguity.
- Allowlist-only: Only explicitly allowed patterns are candidates for promotion
- Denylist: Additional exclusions (secrets, test files)
- Protected dirs: Immutable directories (custom, env, local) that are never touched
Rationale: Fail-safe approach. Better to miss a file than accidentally promote secrets.
Uses git2 crate for:
- Repository discovery and validation
- Tree cleanliness checks (
require_clean_tree) - Diff output (colored, unified format)
- Tracked file listing (only consider git-tracked files)
Rationale: Git is the source of truth. Leverage its machinery instead of reimplementing.
Mirrors Python promote script:
--delete: Enable deletion of files in dest that don't exist in source--dest-based: Only delete if parent directory exists in source- Default: delete disabled (safe by default)
Rationale: Compatibility with existing workflow, configurable for different use cases.
prl diff --source <env> --dest <env> [filter...]
prl promote --source <env> --dest <env> [options]
Rationale: Clear separation between preview (diff) and action (promote).
diffis the default safe operationpromoteapplies changes by default; use--confirmfor interactive confirmation--dry-runavailable for additional safety- Clean git tree required before promotion
Rationale: Streamline promotion workflow while maintaining safety options.
Rejected: User requires multi-repo support for different GitOps structures.
Rejected: Explicit config prevents ambiguity and supports varied repo structures.
Rejected: Too destructive. Configurable delete matches Python tool behavior.
Rejected: Rust provides better type safety and git2 bindings.
- Users must create
promrail.yamlconfig before use - Git repository required (no standalone file operations)
- Learning curve for glob patterns in allowlist/denylist
- Compatible with existing Python
promoteworkflow
- Core: CLI, config, error types, git repository handling
- File Selection: allowlist/denylist with globset
- Commands: diff, promote
- Git Features: native diff, notes
- Audit: promotion log
- git2 crate: https://docs.rs/git2/