A release branching tool for automating consistent release branching/tagging across many first-party repositories using a single source of truth (BOM).
Maple automates the tedious and error-prone process of creating release branches and tags across multiple repositories. It reads a Bill of Materials (BOM) file, identifies first-party dependencies, and for each repository:
- Clones/fetches the repository
- Checks out the specified version
- Builds and tests the project
- Creates release branch and tag
- Pushes changes to remote
- BOM-driven: Uses JSON BOM files as single source of truth
- Parallel execution: Processes multiple repositories concurrently
- Resume capability: Can resume failed runs from specific repositories
- Dry-run mode: Preview actions without making changes
- Comprehensive reporting: JSON and console output with detailed status
- Pluggable architecture: Extensible parsers and build runners
- Observability: Prometheus metrics and structured logging
Build from source:
git clone https://github.com/your-org/maple-rewrite.git
cd maple-rewrite
./gradlew build- Plan a release (dry-run):
./gradlew run --args="plan --bom bom.json --version 2024.1"- Execute release:
./gradlew run --args="run --bom bom.json --version 2024.1"- Resume failed run:
./gradlew run --args="resume --run-id abc123 --from-repo my-service"{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"components": [
{
"type": "library",
"bom-ref": "com.tableau.modules:my-service:1.0.0",
"group": "com.tableau.modules",
"name": "my-service",
"version": "1.0.0",
"purl": "pkg:maven/com.tableau.modules/my-service@1.0.0"
}
],
"dependencies": [
{
"ref": "com.tableau.modules:my-service:1.0.0",
"dependsOn": ["other-dependency"]
}
]
}Shows what would be done without executing:
maple plan --bom bom.json --version 2024.1Executes the release process:
maple run --bom bom.json --version 2024.1 [--dry-run] [--concurrency 4]Resumes a failed run:
maple resume --run-id <id> --from-repo <repo-name>Manages test fixtures:
maple fixtures init --remote local --count 3 --root /tmp/test-repos
maple fixtures destroy --remote local --root /tmp/test-reposQueries run history:
maple query last-runCreate .maple.yml in your project root:
# Default configuration
workDir: .maple
concurrency: 4
timeout: 15m
firstPartyPrefix: com.tableau
buildCommand: ./gradlew build
branchTemplate: release/{version}
tagTemplate: {version}
# Repository overrides
repos:
my-special-service:
buildCommand: make build
timeout: 30m- Java 21+
- Git
- Docker (optional, for containerized builds)
./gradlew build./gradlew test./gradlew run --args="--help"Maple follows a modular architecture:
- CLI: Command-line interface and argument parsing
- BOM Parser: Parses various BOM formats (JSON, future: Gradle catalogs)
- Orchestrator: Coordinates parallel execution and state management
- Git Driver: Handles git operations (clone, checkout, branch, tag, push)
- Build Runner: Executes build commands with timeout and logging
- State Store: Persists run state for resume capability
- Reporter: Generates JSON and console reports
Enable Prometheus metrics:
export MAPLE_METRICS_ENABLED=true
export MAPLE_METRICS_PORT=9404Enable debug logging:
export MAPLE_DEBUG=true- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Run
./gradlew buildto ensure everything passes - Submit a pull request
[Add your license here]
For issues and questions:
- Create an issue in this repository
- Check the documentation
- Review the design document