Skip to content

Commit 627cbbe

Browse files
authored
feat: (#292) Add conflict command to differentiate versioning
1 parent 33d739f commit 627cbbe

20 files changed

+1388
-106
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@ htmlcov/
5959

6060
# Poetry
6161
poetry.lock
62+
63+
**/.DS_Store
64+
.DS_Store

cli/Makefile

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,73 @@
1-
.PHONY: help install install-dev test test-cov lint clean format check build publish dev run
1+
.PHONY: help setup test test-cov lint clean format check build publish dev nixopus
22

3-
help:
4-
@echo "Available commands:"
3+
help: ## Show available commands
54
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
65

7-
install:
8-
poetry install
6+
setup: ## Setup Python environment and install dependencies
7+
@if command -v poetry >/dev/null 2>&1; then \
8+
echo "Poetry found. Installing dependencies..."; \
9+
poetry install --with dev --quiet; \
10+
echo "Environment ready! Use: make nixopus ARGS=\"command\""; \
11+
else \
12+
echo "Poetry not found. Installing Poetry..."; \
13+
curl -sSL https://install.python-poetry.org | python3 - >/dev/null 2>&1; \
14+
echo "Poetry installed. Please restart your shell or run: source ~/.bashrc (or ~/.zshrc)"; \
15+
echo "Then run 'make setup' again to install dependencies."; \
16+
fi
917

10-
install-dev:
11-
poetry install --with dev --no-root
18+
test: ## Run tests
19+
@poetry run pytest
1220

13-
test:
14-
poetry run pytest
21+
test-cov: ## Run tests with coverage
22+
@poetry run pytest --cov=app --cov-report=term-missing --cov-report=html
1523

16-
test-cov:
17-
poetry run pytest --cov=core --cov=utils --cov-report=term-missing --cov-report=html
24+
lint: ## Run linting
25+
@poetry run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
26+
@poetry run flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
1827

19-
test-watch:
20-
poetry run pytest-watch
28+
format: ## Format code
29+
@poetry run black . --quiet
30+
@poetry run isort . --quiet
2131

22-
lint:
23-
poetry run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
24-
poetry run flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
32+
check: ## Run linting and tests
33+
$(MAKE) lint && $(MAKE) test
2534

26-
format:
27-
poetry run black .
28-
poetry run isort .
35+
clean: ## Clean build artifacts
36+
@rm -rf build/ dist/ *.egg-info/ .pytest_cache/ htmlcov/ .coverage
37+
@find . -type d -name __pycache__ -delete
38+
@find . -type f -name "*.pyc" -delete
2939

30-
check:
31-
$(MAKE) lint
32-
$(MAKE) test
40+
build: ## Build the package
41+
@poetry build
3342

34-
clean:
35-
rm -rf build/
36-
rm -rf dist/
37-
rm -rf *.egg-info/
38-
rm -rf .pytest_cache/
39-
rm -rf htmlcov/
40-
rm -rf .coverage
41-
find . -type d -name __pycache__ -delete
42-
find . -type f -name "*.pyc" -delete
43+
publish: ## Publish to PyPI
44+
@poetry publish
4345

44-
build:
45-
poetry build
46+
dev: ## Activate development shell
47+
@poetry shell
4648

47-
publish:
48-
poetry publish
4949

50-
dev:
51-
poetry shell
50+
# -----------------------------------------------------------------------------
51+
# Nixopus test CLI commands
52+
# -----------------------------------------------------------------------------
53+
nixopus: ## Run nixopus CLI
54+
@if [ -z "$(ARGS)" ]; then \
55+
poetry run nixopus --help; \
56+
else \
57+
poetry run nixopus $(ARGS); \
58+
fi
5259

53-
run:
60+
conflict: ## Run conflict command
61+
@poetry run nixopus conflict $(ARGS)
62+
63+
preflight: ## Run preflight command
64+
@poetry run nixopus preflight $(ARGS)
65+
66+
version: ## Show version
67+
@poetry run nixopus version
68+
69+
run: ## Run nixopus CLI directly
5470
poetry run nixopus
5571

56-
generate-docs:
57-
typer app.main utils docs --output
58-
../docs/cli/cli-reference.md --name
59-
nixopus
72+
generate-docs: ## Generate CLI documentation
73+
typer app.main utils docs --output ../docs/cli/cli-reference.md --name nixopus

cli/app/commands/conflict/__init__.py

Whitespace-only changes.

cli/app/commands/conflict/command.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import typer
2+
from .conflict import ConflictConfig, ConflictService
3+
from .messages import (
4+
conflict_check_help,
5+
error_checking_conflicts,
6+
conflicts_found_warning,
7+
no_conflicts_info,
8+
checking_conflicts_info,
9+
)
10+
from app.utils.logger import Logger
11+
from app.utils.timeout import TimeoutWrapper
12+
13+
conflict_app = typer.Typer(help=conflict_check_help, no_args_is_help=False)
14+
15+
16+
@conflict_app.callback(invoke_without_command=True)
17+
def conflict_callback(
18+
ctx: typer.Context,
19+
config_file: str = typer.Option("helpers/config.prod.yaml", "--config-file", "-c", help="Path to configuration file"),
20+
timeout: int = typer.Option(5, "--timeout", "-t", help="Timeout for tool checks in seconds"),
21+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
22+
output: str = typer.Option("text", "--output", "-o", help="Output format (text/json)"),
23+
) -> None:
24+
"""Check for tool version conflicts"""
25+
if ctx.invoked_subcommand is None:
26+
# Initialize logger once and reuse throughout
27+
logger = Logger(verbose=verbose)
28+
29+
try:
30+
logger.info(checking_conflicts_info)
31+
32+
config = ConflictConfig(
33+
config_file=config_file,
34+
verbose=verbose,
35+
output=output,
36+
)
37+
38+
service = ConflictService(config, logger=logger)
39+
40+
with TimeoutWrapper(timeout):
41+
result = service.check_and_format(output)
42+
# Check if there are any conflicts and exit with appropriate code
43+
results = service.check_conflicts()
44+
conflicts = [r for r in results if r.conflict]
45+
46+
if conflicts:
47+
logger.error(result)
48+
logger.warning(conflicts_found_warning.format(count=len(conflicts)))
49+
raise typer.Exit(1)
50+
else:
51+
logger.success(result)
52+
logger.info(no_conflicts_info)
53+
54+
except TimeoutError as e:
55+
logger.error(str(e))
56+
raise typer.Exit(1)
57+
except Exception as e:
58+
logger.error(error_checking_conflicts.format(error=str(e)))
59+
raise typer.Exit(1)

0 commit comments

Comments
 (0)