-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,468 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
Below is an example of a comprehensive `README.md` for your unified monorepo management tool: | ||
|
||
--- | ||
|
||
```markdown | ||
# Monorepo Manager | ||
|
||
**Monorepo Manager** is a unified command-line tool for managing a Python monorepo that contains multiple standalone packages, each with its own `pyproject.toml`. It consolidates several common tasks—including dependency management, version bumping, remote dependency resolution, test analysis, and project configuration updates—into one robust CLI. | ||
|
||
## Features | ||
|
||
- **Dependency Management** | ||
- **Lock:** Generate a `poetry.lock` file. | ||
- **Install:** Install dependencies with options for extras and development dependencies. | ||
- **Show Freeze:** Display installed packages using `pip freeze`. | ||
|
||
- **Version Management** | ||
- **Version:** Bump (major, minor, patch, finalize) or explicitly set package versions in `pyproject.toml`. | ||
|
||
- **Remote Operations** | ||
- **Remote Fetch:** Fetch the version from a remote GitHub repository’s `pyproject.toml`. | ||
- **Remote Update:** Update a local `pyproject.toml` file with version information from remote Git dependencies. | ||
|
||
- **Test Analysis** | ||
- **Test:** Parse a JSON file with test results, display summary statistics, and evaluate threshold conditions. | ||
|
||
- **Pyproject Operations** | ||
- **Pyproject:** Extract local (path) and Git-based dependencies from a `pyproject.toml` file and optionally update dependency versions. | ||
|
||
## Installation | ||
|
||
```bash | ||
pip install monorepo-manager | ||
``` | ||
|
||
_This installs the `monorepo-manager` CLI (provided via the entry point `monorepo-manager`) into your system PATH._ | ||
|
||
## Usage | ||
|
||
Once installed, you can invoke the CLI using: | ||
|
||
```bash | ||
monorepo-manager --help | ||
``` | ||
|
||
This displays the list of available commands. | ||
|
||
### Command Examples | ||
|
||
#### 1. Lock Dependencies | ||
|
||
Generate a `poetry.lock` file for a package by specifying the directory or file path: | ||
|
||
```bash | ||
# Lock using a directory containing pyproject.toml: | ||
monorepo-manager lock --directory ./packages/package1 | ||
|
||
# Lock using an explicit pyproject.toml file: | ||
monorepo-manager lock --file ./packages/package1/pyproject.toml | ||
``` | ||
|
||
#### 2. Install Dependencies | ||
|
||
Install dependencies with various options: | ||
|
||
```bash | ||
# Basic installation: | ||
monorepo-manager install --directory ./packages/package1 | ||
|
||
# Install using an explicit pyproject.toml file: | ||
monorepo-manager install --file ./packages/package1/pyproject.toml | ||
|
||
# Install including development dependencies: | ||
monorepo-manager install --directory ./packages/package1 --dev | ||
|
||
# Install including extras (e.g., extras named "full"): | ||
monorepo-manager install --directory ./packages/package2 --extras full | ||
|
||
# Install including all extras: | ||
monorepo-manager install --directory ./packages/package2 --all-extras | ||
``` | ||
|
||
#### 3. Version Management | ||
|
||
Bump the version or set it explicitly for a given package: | ||
|
||
```bash | ||
# Bump the patch version (e.g. from 1.2.3.dev1 to 1.2.3.dev2): | ||
monorepo-manager version ./packages/package1/pyproject.toml --bump patch | ||
|
||
# Finalize a development version (remove the ".dev" suffix): | ||
monorepo-manager version ./packages/package1/pyproject.toml --bump finalize | ||
|
||
# Set an explicit version: | ||
monorepo-manager version ./packages/package1/pyproject.toml --set 2.0.0.dev1 | ||
``` | ||
|
||
#### 4. Remote Operations | ||
|
||
Fetch version information from a remote GitHub repository’s `pyproject.toml` and update your local configuration accordingly. | ||
|
||
```bash | ||
# Fetch the remote version: | ||
monorepo-manager remote fetch --git-url https://github.com/YourOrg/YourRepo.git --branch main --subdir "src/" | ||
|
||
# Update a local pyproject.toml with versions resolved from remote dependencies. | ||
# (If --output is omitted, the input file is overwritten.) | ||
monorepo-manager remote update --input ./packages/package1/pyproject.toml --output ./packages/package1/pyproject.updated.toml | ||
``` | ||
|
||
#### 5. Test Analysis | ||
|
||
Analyze test results provided in a JSON file, and enforce percentage thresholds for passed and skipped tests: | ||
|
||
```bash | ||
# Analyze test results without thresholds: | ||
monorepo-manager test test-results.json | ||
|
||
# Analyze test results with thresholds: require that passed tests are greater than 75% and skipped tests are less than 20%: | ||
monorepo-manager test test-results.json --required-passed gt:75 --required-skipped lt:20 | ||
``` | ||
|
||
#### 6. Pyproject Operations | ||
|
||
Operate on the `pyproject.toml` file to extract dependency information and optionally update dependency versions: | ||
|
||
```bash | ||
# Extract local (path) and Git-based dependencies: | ||
monorepo-manager pyproject --pyproject ./packages/package1/pyproject.toml | ||
|
||
# Update local dependency versions to 2.0.0 (updates parent file and, if possible, each dependency's own pyproject.toml): | ||
monorepo-manager pyproject --pyproject ./packages/package1/pyproject.toml --update-version 2.0.0 | ||
``` | ||
|
||
## Development | ||
|
||
### Project Structure | ||
|
||
``` | ||
monorepo_manager/ | ||
├── __init__.py | ||
├── cli.py # Main CLI entry point | ||
├── poetry_ops.py # Poetry operations (lock, install, build, publish, etc.) | ||
├── version_ops.py # Version bumping and setting operations | ||
├── remote_ops.py # Remote Git dependency version fetching/updating | ||
├── test_ops.py # Test result analysis operations | ||
└── pyproject_ops.py # pyproject.toml dependency extraction and updates | ||
pyproject.toml # Package configuration file containing metadata | ||
README.md # This file | ||
``` | ||
|
||
### Running Tests | ||
|
||
For development purposes, you can use your favorite test runner (such as `pytest`) to run tests for the CLI and modules. | ||
|
||
```bash | ||
pytest | ||
``` | ||
|
||
## Contributing | ||
|
||
Contributions are welcome! Feel free to open issues or submit pull requests for improvements or bug fixes. | ||
|
||
## License | ||
|
||
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. | ||
``` | ||
--- | ||
This `README.md` provides a detailed overview, installation instructions, and comprehensive usage examples for each command offered by your CLI tool. Feel free to adjust sections or add any additional details specific to your project needs. |
14 changes: 14 additions & 0 deletions
14
pkgs/tooling/monorepo_manager/monorepo_manager/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# monorepo_manager/__init__.py | ||
|
||
try: | ||
# For Python 3.8 and newer | ||
from importlib.metadata import version, PackageNotFoundError | ||
except ImportError: | ||
# For older Python versions, use the backport | ||
from importlib_metadata import version, PackageNotFoundError | ||
|
||
try: | ||
__version__ = version("monorepo-manager") | ||
except PackageNotFoundError: | ||
# If the package is not installed (for example, during development) | ||
__version__ = "0.0.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
cli.py | ||
This is the main entry point for the monorepo management CLI. | ||
It provides commands to: | ||
- Manage Poetry-based operations (lock, install, show pip-freeze, recursive build, publish) | ||
- Manage version operations (bump or set versions in pyproject.toml) | ||
- Manage remote operations (fetch/update Git dependency versions) | ||
- Analyze test results from a JSON file | ||
- Operate on pyproject.toml files (extract and update dependency versions) | ||
The commands are intentionally named with simple terms (e.g. "lock" instead of "poetry lock", | ||
"install" instead of "poetry install", and "test" instead of "test-analyze"). | ||
""" | ||
|
||
import argparse | ||
import sys | ||
|
||
# Import operations from the local modules. | ||
from monorepo_manager import poetry_ops | ||
from monorepo_manager import version_ops | ||
from monorepo_manager import remote_ops | ||
from monorepo_manager import test_ops | ||
from monorepo_manager import pyproject_ops | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser( | ||
description="A CLI for managing a Python monorepo with multiple standalone packages." | ||
) | ||
subparsers = parser.add_subparsers(dest="command", required=True, help="Available commands") | ||
|
||
# ------------------------------------------------ | ||
# Command: lock | ||
# ------------------------------------------------ | ||
lock_parser = subparsers.add_parser("lock", help="Generate a poetry.lock file") | ||
lock_parser.add_argument("--directory", type=str, help="Directory containing a pyproject.toml") | ||
lock_parser.add_argument("--file", type=str, help="Explicit path to a pyproject.toml file") | ||
|
||
# ------------------------------------------------ | ||
# Command: install | ||
# ------------------------------------------------ | ||
install_parser = subparsers.add_parser("install", help="Install dependencies") | ||
install_parser.add_argument("--directory", type=str, help="Directory containing a pyproject.toml") | ||
install_parser.add_argument("--file", type=str, help="Explicit path to a pyproject.toml file") | ||
install_parser.add_argument("--extras", type=str, help="Extras to include (e.g. 'full')") | ||
install_parser.add_argument("--dev", action="store_true", help="Include dev dependencies") | ||
install_parser.add_argument("--all-extras", action="store_true", help="Include all extras") | ||
|
||
# ------------------------------------------------ | ||
# Command: version | ||
# ------------------------------------------------ | ||
version_parser = subparsers.add_parser("version", help="Bump or set package version") | ||
version_parser.add_argument("pyproject_file", type=str, help="Path to the pyproject.toml file") | ||
vgroup = version_parser.add_mutually_exclusive_group(required=True) | ||
vgroup.add_argument("--bump", choices=["major", "minor", "patch", "finalize"], | ||
help="Bump the version (e.g. patch, major, minor, finalize)") | ||
vgroup.add_argument("--set", dest="set_ver", help="Explicit version to set (e.g. 2.0.0.dev1)") | ||
|
||
# ------------------------------------------------ | ||
# Command: remote | ||
# ------------------------------------------------ | ||
remote_parser = subparsers.add_parser("remote", help="Remote operations for Git dependencies") | ||
remote_subparsers = remote_parser.add_subparsers(dest="remote_cmd", required=True) | ||
|
||
# remote fetch: fetch version from remote GitHub pyproject.toml | ||
fetch_parser = remote_subparsers.add_parser("fetch", help="Fetch version from remote GitHub pyproject.toml") | ||
fetch_parser.add_argument("--git-url", type=str, required=True, help="GitHub repository URL") | ||
fetch_parser.add_argument("--branch", type=str, default="main", help="Branch name (default: main)") | ||
fetch_parser.add_argument("--subdir", type=str, default="", help="Subdirectory where pyproject.toml is located") | ||
|
||
# remote update: update a local pyproject.toml with remote resolved versions. | ||
update_parser = remote_subparsers.add_parser("update", help="Update local pyproject.toml with remote versions") | ||
update_parser.add_argument("--input", required=True, help="Path to the local pyproject.toml") | ||
update_parser.add_argument("--output", help="Optional output file path (defaults to overwriting the input)") | ||
|
||
# ------------------------------------------------ | ||
# Command: test | ||
# ------------------------------------------------ | ||
test_parser = subparsers.add_parser("test", help="Analyze test results from a JSON file") | ||
test_parser.add_argument("file", help="Path to the JSON file with test results") | ||
test_parser.add_argument("--required-passed", type=str, help="Threshold for passed tests (e.g. 'gt:75')") | ||
test_parser.add_argument("--required-skipped", type=str, help="Threshold for skipped tests (e.g. 'lt:20')") | ||
|
||
# ------------------------------------------------ | ||
# Command: pyproject | ||
# ------------------------------------------------ | ||
pyproject_parser = subparsers.add_parser("pyproject", help="Operate on pyproject.toml dependencies") | ||
pyproject_parser.add_argument("--pyproject", required=True, help="Path to the pyproject.toml file") | ||
pyproject_parser.add_argument("--update-version", type=str, help="Update local dependency versions to this version") | ||
|
||
# ------------------------------------------------ | ||
# Dispatch Commands | ||
# ------------------------------------------------ | ||
args = parser.parse_args() | ||
|
||
if args.command == "lock": | ||
poetry_ops.poetry_lock(directory=args.directory, file=args.file) | ||
|
||
elif args.command == "install": | ||
poetry_ops.poetry_install( | ||
directory=args.directory, | ||
file=args.file, | ||
extras=args.extras, | ||
with_dev=args.dev, | ||
all_extras=args.all_extras | ||
) | ||
|
||
elif args.command == "version": | ||
version_ops.bump_or_set_version(args.pyproject_file, bump=args.bump, set_ver=args.set_ver) | ||
|
||
elif args.command == "remote": | ||
if args.remote_cmd == "fetch": | ||
ver = remote_ops.fetch_remote_pyproject_version( | ||
git_url=args.git_url, | ||
branch=args.branch, | ||
subdirectory=args.subdir | ||
) | ||
if ver: | ||
print(f"Fetched remote version: {ver}") | ||
else: | ||
print("Failed to fetch remote version.") | ||
elif args.remote_cmd == "update": | ||
success = remote_ops.update_and_write_pyproject(args.input, args.output) | ||
if not success: | ||
sys.exit(1) | ||
|
||
elif args.command == "test": | ||
test_ops.analyze_test_file( | ||
file_path=args.file, | ||
required_passed=args.required_passed, | ||
required_skipped=args.required_skipped | ||
) | ||
|
||
elif args.command == "pyproject": | ||
print("Extracting dependencies from pyproject.toml ...") | ||
paths = pyproject_ops.extract_path_dependencies(args.pyproject) | ||
if paths: | ||
print("Local (path) dependencies:") | ||
print(", ".join(paths)) | ||
else: | ||
print("No local path dependencies found.") | ||
|
||
git_deps = pyproject_ops.extract_git_dependencies(args.pyproject) | ||
if git_deps: | ||
print("\nGit dependencies:") | ||
for name, details in git_deps.items(): | ||
print(f"{name}: {details}") | ||
else: | ||
print("No Git dependencies found.") | ||
|
||
if args.update_version: | ||
print(f"\nUpdating local dependency versions to {args.update_version} ...") | ||
pyproject_ops.update_dependency_versions(args.pyproject, args.update_version) | ||
|
||
else: | ||
parser.print_help() | ||
sys.exit(1) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.