- Add make agents-sync-package and release-check parity gate - Add tests/test_packaged_agents_parity.py; sync packaged agents with agents/ - Update install docs (HELLO_WORLD, CLI_CHEAT_SHEET, AGENT_DISTRIBUTION) - Expand PACKAGE_RELEASE.md secrets setup and pre-tag checklist - Add flake8 to Gitea CI; CHANGELOG Unreleased for v1.2.0 - Expand INTEGRATION_PATTERNS activity-core handoff checklist
1102 lines
44 KiB
Makefile
1102 lines
44 KiB
Makefile
# Makefile for Kaizen Agentic development tasks
|
||
|
||
.PHONY: help setup-complete setup-structure setup-python setup-tools setup-docs setup-tests setup-verify ensure-project-structure install-dev install-local install-global standards-check standards-fix standards-test test test-all build clean lint format venv-status agents-list agents-update agents-validate agents-status agents-sync-package agents-install-cli release-check release-prepare release-test release-publish publish-gitea package-check release-finalize release-rollback
|
||
|
||
# Variables
|
||
VENV = .venv
|
||
VENV_PYTHON = $(VENV)/bin/python
|
||
VENV_PIP = $(VENV)/bin/pip
|
||
GITEA_PACKAGE_OWNER ?= coulomb
|
||
GITEA_PYPI_REPOSITORY_URL ?= https://gitea.coulomb.social/api/packages/$(GITEA_PACKAGE_OWNER)/pypi
|
||
GITEA_PYPI_SIMPLE_URL ?= https://gitea.coulomb.social/api/packages/$(GITEA_PACKAGE_OWNER)/pypi/simple/
|
||
|
||
# Default target
|
||
help:
|
||
@echo "Kaizen Agentic Development Commands"
|
||
@echo "==================================="
|
||
@echo ""
|
||
@echo "Environment Status:"
|
||
@$(MAKE) --no-print-directory venv-status
|
||
@echo ""
|
||
@echo "Setup & Installation:"
|
||
@echo " setup-complete - Complete repository setup from stub (PythonVibes)"
|
||
@echo " setup-structure - Create directory structure and basic files"
|
||
@echo " setup-python - Configure Python package structure"
|
||
@echo " setup-tools - Install and configure development tools"
|
||
@echo " setup-docs - Generate documentation framework"
|
||
@echo " setup-tests - Create testing infrastructure"
|
||
@echo " setup-verify - Verify complete setup functionality"
|
||
@echo " install-dev - Install package in development mode"
|
||
@echo " install-local - Install from locally built package (test PyPI installation)"
|
||
@echo " install-global - Install globally from locally built package"
|
||
@echo " venv-status - Check if venv is active"
|
||
@echo ""
|
||
@echo "Standards Compliance:"
|
||
@echo " standards-check - Check repository against PythonVibes standards"
|
||
@echo " standards-fix - Fix any standards violations found"
|
||
@echo " standards-test - Run repository standards compliance tests"
|
||
@echo ""
|
||
@echo "Agent Management:"
|
||
@echo " agents-list - List installed agents"
|
||
@echo " agents-update - Update agents to latest versions"
|
||
@echo " agents-validate - Validate agent definitions"
|
||
@echo " agents-status - Show agent status and project info"
|
||
@echo " agents-sync-package - Sync agents/ into packaged data/agents/ (DRY_RUN=1 to preview)"
|
||
@echo " agents-install-cli - Install kaizen-agentic CLI tool"
|
||
@echo ""
|
||
@echo "Release Management:"
|
||
@echo " release-check - Validate release readiness (tests, linting, version consistency)"
|
||
@echo " release-prepare - Prepare release (update versions, build packages)"
|
||
@echo " package-check - Build and validate wheel/sdist with twine"
|
||
@echo " publish-gitea - Publish dist/* to Coulomb Gitea PyPI registry"
|
||
@echo " release-test - Test publication workflow using TestPyPI"
|
||
@echo " release-publish - Publish to production PyPI (pypi.org)"
|
||
@echo " release-finalize - Post-release tasks (tags, GitHub release, documentation)"
|
||
@echo " release-rollback - Emergency rollback procedures"
|
||
@echo ""
|
||
@echo "Development:"
|
||
@echo " test - Run unit tests only (fast)"
|
||
@echo " test-all - Run comprehensive test suite (tests + standards + quality)"
|
||
@echo " build - Build the package"
|
||
@echo " lint - Run code linting"
|
||
@echo " format - Format code with black"
|
||
@echo " clean - Clean build artifacts and cache"
|
||
@echo ""
|
||
@echo "Examples:"
|
||
@echo " make setup-complete # Set up new repository"
|
||
@echo " make test-all # Run full test suite"
|
||
@echo " make standards-check # Audit repository compliance"
|
||
@echo " make agents-status # Check installed agents"
|
||
|
||
# Virtual environment status check
|
||
venv-status:
|
||
@if [ -d "$(VENV)" ]; then \
|
||
echo "✅ Virtual environment: Active (.venv)"; \
|
||
echo " Python: $$($(VENV_PYTHON) --version 2>/dev/null || echo 'Not found')"; \
|
||
echo " Location: $$(pwd)/$(VENV)"; \
|
||
else \
|
||
echo "❌ Virtual environment: Not found"; \
|
||
echo " Run 'make setup-complete' to create it"; \
|
||
fi
|
||
|
||
# Create virtual environment
|
||
$(VENV)/bin/activate:
|
||
@echo "🔧 Creating virtual environment..."
|
||
python3 -m venv $(VENV)
|
||
@echo "✅ Virtual environment created at $(VENV)"
|
||
|
||
# Install package in development mode
|
||
install-dev: $(VENV)/bin/activate
|
||
@echo "📦 Installing package in development mode..."
|
||
@$(VENV_PIP) install --upgrade pip
|
||
@$(VENV_PIP) install -e .
|
||
@echo "✅ Package installed in development mode"
|
||
|
||
# Install from locally built package (test PyPI installation)
|
||
install-local: $(VENV)/bin/activate
|
||
@echo "📦 Installing from locally built package..."
|
||
@if [ ! -d "dist" ] || [ -z "$$(ls dist/*.whl 2>/dev/null)" ]; then \
|
||
echo "❌ No wheel package found in dist/"; \
|
||
echo " Run 'make build' or 'make release-prepare' first"; \
|
||
exit 1; \
|
||
fi; \
|
||
WHEEL_FILE=$$(ls dist/*.whl | head -1); \
|
||
VERSION=$$(basename "$$WHEEL_FILE" | sed 's/kaizen_agentic-\(.*\)-py3.*/\1/'); \
|
||
echo " Installing kaizen-agentic v$$VERSION from local wheel..."; \
|
||
$(VENV_PIP) install --upgrade pip; \
|
||
$(VENV_PIP) uninstall -y kaizen-agentic 2>/dev/null || true; \
|
||
$(VENV_PIP) install "$$WHEEL_FILE" --force-reinstall; \
|
||
echo ""; \
|
||
echo "✅ Local package installed successfully!"; \
|
||
echo " Version: $$VERSION"; \
|
||
echo " Package contents:"; \
|
||
$(VENV_PIP) show kaizen-agentic; \
|
||
echo ""; \
|
||
echo "🧪 Testing installation..."; \
|
||
if $(VENV_PYTHON) -c "import kaizen_agentic; print(f'✅ Import successful: kaizen_agentic v{kaizen_agentic.__version__}')" 2>/dev/null; then \
|
||
echo " ✅ Package import test passed"; \
|
||
else \
|
||
echo " ❌ Package import test failed"; \
|
||
$(VENV_PYTHON) -c "import kaizen_agentic" 2>&1 || true; \
|
||
fi; \
|
||
if $(VENV)/bin/kaizen-agentic --version 2>/dev/null; then \
|
||
echo " ✅ CLI command test passed"; \
|
||
else \
|
||
echo " ❌ CLI command test failed"; \
|
||
$(VENV)/bin/kaizen-agentic --version 2>&1 || true; \
|
||
fi; \
|
||
if $(VENV)/bin/kaizen-agentic list 2>/dev/null | head -5; then \
|
||
echo " ✅ CLI functionality test passed"; \
|
||
else \
|
||
echo " ❌ CLI functionality test failed"; \
|
||
fi; \
|
||
echo ""; \
|
||
echo "💡 Usage:"; \
|
||
echo " source $(VENV)/bin/activate"; \
|
||
echo " kaizen-agentic --help"
|
||
|
||
# Install globally from locally built package
|
||
install-global:
|
||
@echo "🌍 Installing kaizen-agentic globally from local package..."
|
||
@if [ ! -d "dist" ] || [ -z "$$(ls dist/*.whl 2>/dev/null)" ]; then \
|
||
echo "❌ No wheel package found in dist/"; \
|
||
echo " Run 'python3 -m build' first to create the package"; \
|
||
echo " Or run 'make release-prepare' for full build"; \
|
||
exit 1; \
|
||
fi; \
|
||
WHEEL_FILE=$$(ls dist/*.whl | head -1); \
|
||
VERSION=$$(basename "$$WHEEL_FILE" | sed 's/kaizen_agentic-\(.*\)-py3.*/\1/'); \
|
||
echo " Installing kaizen-agentic v$$VERSION globally..."; \
|
||
echo ""; \
|
||
echo "🔧 Trying installation methods in order:"; \
|
||
echo ""; \
|
||
if command -v pipx >/dev/null 2>&1; then \
|
||
echo " 📦 Method 1: Using pipx (recommended)..."; \
|
||
pipx uninstall kaizen-agentic 2>/dev/null || true; \
|
||
pipx install "$$WHEEL_FILE" && \
|
||
echo " ✅ Installed via pipx" && \
|
||
INSTALL_SUCCESS=1; \
|
||
else \
|
||
echo " ⚠️ pipx not found, trying pip --user..."; \
|
||
INSTALL_SUCCESS=0; \
|
||
fi; \
|
||
if [ "$$INSTALL_SUCCESS" != "1" ]; then \
|
||
echo " 📦 Method 2: Using pip --user..."; \
|
||
python3 -m pip uninstall -y kaizen-agentic 2>/dev/null || true; \
|
||
if python3 -m pip install --user "$$WHEEL_FILE" --force-reinstall 2>/dev/null; then \
|
||
echo " ✅ Installed via pip --user"; \
|
||
INSTALL_SUCCESS=1; \
|
||
else \
|
||
echo " ⚠️ pip --user failed, trying with --break-system-packages..."; \
|
||
fi; \
|
||
fi; \
|
||
if [ "$$INSTALL_SUCCESS" != "1" ]; then \
|
||
echo " 📦 Method 3: Using pip --break-system-packages..."; \
|
||
python3 -m pip install --user "$$WHEEL_FILE" --force-reinstall --break-system-packages && \
|
||
echo " ✅ Installed via pip with system override" && \
|
||
INSTALL_SUCCESS=1; \
|
||
fi; \
|
||
echo ""; \
|
||
if [ "$$INSTALL_SUCCESS" = "1" ]; then \
|
||
echo "✅ Global installation completed!"; \
|
||
echo " Version: $$VERSION"; \
|
||
echo ""; \
|
||
echo "🧪 Testing global installation..."; \
|
||
if command -v kaizen-agentic >/dev/null 2>&1; then \
|
||
echo " ✅ CLI command available globally"; \
|
||
kaizen-agentic --version; \
|
||
else \
|
||
echo " ⚠️ CLI not in PATH. Add to your PATH:"; \
|
||
if command -v pipx >/dev/null 2>&1; then \
|
||
echo " export PATH=\"$$HOME/.local/bin:$$PATH\""; \
|
||
else \
|
||
echo " export PATH=\"$$HOME/.local/bin:$$PATH\""; \
|
||
fi; \
|
||
echo " Add this to your ~/.bashrc or ~/.zshrc for persistence"; \
|
||
fi; \
|
||
echo ""; \
|
||
echo "💡 Usage:"; \
|
||
echo " kaizen-agentic --help # Available from any directory"; \
|
||
echo " cd /any/other/project && kaizen-agentic list"; \
|
||
else \
|
||
echo "❌ Global installation failed!"; \
|
||
echo " Manual installation options:"; \
|
||
echo " 1. Install pipx: python3 -m pip install --user pipx"; \
|
||
echo " 2. Or use: python3 -m pip install --user $$WHEEL_FILE --break-system-packages"; \
|
||
exit 1; \
|
||
fi
|
||
|
||
# Ensure proper Python project structure exists
|
||
ensure-project-structure:
|
||
@echo "🔍 Ensuring proper Python project structure..."
|
||
@if [ ! -f "pyproject.toml" ] && [ ! -f "setup.py" ]; then \
|
||
echo "❌ No pyproject.toml or setup.py found!"; \
|
||
echo " Creating minimal pyproject.toml..."; \
|
||
echo '[build-system]' > pyproject.toml; \
|
||
echo 'requires = ["setuptools>=64", "wheel"]' >> pyproject.toml; \
|
||
echo 'build-backend = "setuptools.build_meta"' >> pyproject.toml; \
|
||
echo '' >> pyproject.toml; \
|
||
echo '[project]' >> pyproject.toml; \
|
||
echo 'name = "kaizen-agentic"' >> pyproject.toml; \
|
||
echo 'version = "0.1.0"' >> pyproject.toml; \
|
||
echo 'description = "AI agent development framework"' >> pyproject.toml; \
|
||
echo 'requires-python = ">=3.8"' >> pyproject.toml; \
|
||
echo 'dependencies = []' >> pyproject.toml; \
|
||
echo '' >> pyproject.toml; \
|
||
echo '[tool.setuptools.packages.find]' >> pyproject.toml; \
|
||
echo 'where = ["src"]' >> pyproject.toml; \
|
||
echo '' >> pyproject.toml; \
|
||
echo '[tool.setuptools.package-dir]' >> pyproject.toml; \
|
||
echo '"" = "src"' >> pyproject.toml; \
|
||
echo '' >> pyproject.toml; \
|
||
echo '[tool.black]' >> pyproject.toml; \
|
||
echo 'line-length = 88' >> pyproject.toml; \
|
||
echo '' >> pyproject.toml; \
|
||
echo '[tool.flake8]' >> pyproject.toml; \
|
||
echo 'max-line-length = 100' >> pyproject.toml; \
|
||
echo '' >> pyproject.toml; \
|
||
echo '[tool.pytest.ini_options]' >> pyproject.toml; \
|
||
echo 'testpaths = ["tests"]' >> pyproject.toml; \
|
||
echo 'python_files = ["test_*.py"]' >> pyproject.toml; \
|
||
echo 'python_classes = ["Test*"]' >> pyproject.toml; \
|
||
echo 'python_functions = ["test_*"]' >> pyproject.toml; \
|
||
echo "✅ Created pyproject.toml with basic configuration"; \
|
||
else \
|
||
echo "✅ Project configuration file found"; \
|
||
fi
|
||
@if [ ! -d "src" ]; then \
|
||
echo " Creating src/ directory structure..."; \
|
||
mkdir -p src; \
|
||
echo "✅ Created src/ directory"; \
|
||
fi
|
||
|
||
# Complete setup with development dependencies
|
||
setup-complete: setup-structure setup-python setup-tools setup-docs setup-tests setup-verify
|
||
@echo "✅ Complete repository setup from stub finished!"
|
||
@echo ""
|
||
@echo "🎯 Repository now follows PythonVibes best practices:"
|
||
@echo " • Proper src/ layout with package structure"
|
||
@echo " • Development tools configured (black, flake8, mypy, pytest)"
|
||
@echo " • Essential documentation files created"
|
||
@echo " • Testing infrastructure established"
|
||
@echo " • Virtual environment and dependencies installed"
|
||
@echo ""
|
||
@echo "🚀 Next steps:"
|
||
@echo " 1. Activate virtual environment: source $(VENV)/bin/activate"
|
||
@echo " 2. Run tests: make test"
|
||
@echo " 3. Check code quality: make lint"
|
||
@echo " 4. Format code: make format"
|
||
|
||
# Create directory structure and basic files
|
||
setup-structure:
|
||
@echo "📁 Creating directory structure and basic files..."
|
||
@mkdir -p src docs tests .github/workflows
|
||
@if [ ! -f ".gitignore" ]; then \
|
||
echo "Creating .gitignore..."; \
|
||
echo "# Python" > .gitignore; \
|
||
echo "__pycache__/" >> .gitignore; \
|
||
echo "*.py[cod]" >> .gitignore; \
|
||
echo "*$$.py.class" >> .gitignore; \
|
||
echo "*.so" >> .gitignore; \
|
||
echo ".Python" >> .gitignore; \
|
||
echo "build/" >> .gitignore; \
|
||
echo "develop-eggs/" >> .gitignore; \
|
||
echo "dist/" >> .gitignore; \
|
||
echo "downloads/" >> .gitignore; \
|
||
echo "eggs/" >> .gitignore; \
|
||
echo ".eggs/" >> .gitignore; \
|
||
echo "lib/" >> .gitignore; \
|
||
echo "lib64/" >> .gitignore; \
|
||
echo "parts/" >> .gitignore; \
|
||
echo "sdist/" >> .gitignore; \
|
||
echo "var/" >> .gitignore; \
|
||
echo "wheels/" >> .gitignore; \
|
||
echo "*.egg-info/" >> .gitignore; \
|
||
echo ".installed.cfg" >> .gitignore; \
|
||
echo "*.egg" >> .gitignore; \
|
||
echo "MANIFEST" >> .gitignore; \
|
||
echo "" >> .gitignore; \
|
||
echo "# Virtual environments" >> .gitignore; \
|
||
echo ".env" >> .gitignore; \
|
||
echo ".venv" >> .gitignore; \
|
||
echo "env/" >> .gitignore; \
|
||
echo "venv/" >> .gitignore; \
|
||
echo "ENV/" >> .gitignore; \
|
||
echo "env.bak/" >> .gitignore; \
|
||
echo "venv.bak/" >> .gitignore; \
|
||
echo "" >> .gitignore; \
|
||
echo "# IDEs" >> .gitignore; \
|
||
echo ".vscode/" >> .gitignore; \
|
||
echo ".idea/" >> .gitignore; \
|
||
echo "*.swp" >> .gitignore; \
|
||
echo "*.swo" >> .gitignore; \
|
||
echo "*~" >> .gitignore; \
|
||
echo "" >> .gitignore; \
|
||
echo "# Testing" >> .gitignore; \
|
||
echo ".pytest_cache/" >> .gitignore; \
|
||
echo ".coverage" >> .gitignore; \
|
||
echo "htmlcov/" >> .gitignore; \
|
||
echo ".tox/" >> .gitignore; \
|
||
fi
|
||
@if [ ! -f "LICENSE" ]; then \
|
||
echo "Creating MIT LICENSE..."; \
|
||
echo "MIT License" > LICENSE; \
|
||
echo "" >> LICENSE; \
|
||
echo "Copyright (c) $$(date +%Y) Project Name" >> LICENSE; \
|
||
echo "" >> LICENSE; \
|
||
echo "Permission is hereby granted, free of charge, to any person obtaining a copy" >> LICENSE; \
|
||
echo "of this software and associated documentation files (the \"Software\"), to deal" >> LICENSE; \
|
||
echo "in the Software without restriction, including without limitation the rights" >> LICENSE; \
|
||
echo "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell" >> LICENSE; \
|
||
echo "copies of the Software, and to permit persons to whom the Software is" >> LICENSE; \
|
||
echo "furnished to do so, subject to the following conditions:" >> LICENSE; \
|
||
echo "" >> LICENSE; \
|
||
echo "The above copyright notice and this permission notice shall be included in all" >> LICENSE; \
|
||
echo "copies or substantial portions of the Software." >> LICENSE; \
|
||
echo "" >> LICENSE; \
|
||
echo "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR" >> LICENSE; \
|
||
echo "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY," >> LICENSE; \
|
||
echo "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE" >> LICENSE; \
|
||
echo "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER" >> LICENSE; \
|
||
echo "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM," >> LICENSE; \
|
||
echo "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE" >> LICENSE; \
|
||
echo "SOFTWARE." >> LICENSE; \
|
||
fi
|
||
@echo "✅ Directory structure and basic files created"
|
||
|
||
# Configure Python package structure
|
||
setup-python: setup-structure ensure-project-structure
|
||
@echo "🐍 Configuring Python package structure..."
|
||
@if [ ! -d "src" ]; then mkdir -p src; fi
|
||
@# Determine package name from pyproject.toml or use default
|
||
@PACKAGE_NAME=$$(grep '^name = ' pyproject.toml 2>/dev/null | sed 's/name = "\(.*\)"/\1/' | tr '-' '_' || echo "project_name"); \
|
||
if [ ! -d "src/$$PACKAGE_NAME" ]; then \
|
||
echo "Creating src/$$PACKAGE_NAME package..."; \
|
||
mkdir -p "src/$$PACKAGE_NAME"; \
|
||
echo '"""Package initialization for '"$$PACKAGE_NAME"'."""' > "src/$$PACKAGE_NAME/__init__.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/__init__.py"; \
|
||
echo "__version__ = \"0.1.0\"" >> "src/$$PACKAGE_NAME/__init__.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/__init__.py"; \
|
||
echo "# Example core module" > "src/$$PACKAGE_NAME/core.py"; \
|
||
echo '"""Core functionality."""' >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "from typing import Optional" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "class ExampleClass:" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo ' """Example class demonstrating proper structure."""' >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo " def __init__(self, name: str, value: Optional[int] = None) -> None:" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo ' """Initialize instance."""' >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo " self.name = name" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo " self.value = value or 0" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo "" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo " def process(self, input_data: str) -> str:" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo ' """Process input data."""' >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo " if not input_data.strip():" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo ' raise ValueError("Input data cannot be empty")' >> "src/$$PACKAGE_NAME/core.py"; \
|
||
echo " return f\"{self.name}: {input_data} (value: {self.value})\"" >> "src/$$PACKAGE_NAME/core.py"; \
|
||
fi
|
||
@echo "✅ Python package structure configured"
|
||
|
||
# Install and configure development tools
|
||
setup-tools: $(VENV)/bin/activate
|
||
@echo "🔧 Installing and configuring development tools..."
|
||
@$(VENV_PYTHON) -m pip install --upgrade pip
|
||
@$(VENV_PYTHON) -m pip install pytest black flake8 mypy
|
||
@echo "✅ Development tools installed and configured"
|
||
|
||
# Generate documentation framework
|
||
setup-docs: setup-structure
|
||
@echo "📚 Generating documentation framework..."
|
||
@if [ ! -f "README.md" ]; then \
|
||
echo "Creating README.md..."; \
|
||
PACKAGE_NAME=$$(grep '^name = ' pyproject.toml 2>/dev/null | sed 's/name = "\(.*\)"/\1/' || echo "Project Name"); \
|
||
echo "# $$PACKAGE_NAME" > README.md; \
|
||
echo "" >> README.md; \
|
||
echo "A Python project following PythonVibes best practices." >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "## Installation" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "\`\`\`bash" >> README.md; \
|
||
echo "# Clone the repository" >> README.md; \
|
||
echo "git clone <repository-url>" >> README.md; \
|
||
echo "cd $$PACKAGE_NAME" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "# Set up development environment" >> README.md; \
|
||
echo "make setup-complete" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "# Activate virtual environment" >> README.md; \
|
||
echo "source .venv/bin/activate" >> README.md; \
|
||
echo "\`\`\`" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "## Development" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "\`\`\`bash" >> README.md; \
|
||
echo "# Run tests" >> README.md; \
|
||
echo "make test" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "# Check code quality" >> README.md; \
|
||
echo "make lint" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "# Format code" >> README.md; \
|
||
echo "make format" >> README.md; \
|
||
echo "\`\`\`" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "## License" >> README.md; \
|
||
echo "" >> README.md; \
|
||
echo "MIT License - see LICENSE file for details." >> README.md; \
|
||
fi
|
||
@echo "✅ Documentation framework generated"
|
||
|
||
# Create testing infrastructure
|
||
setup-tests: setup-python
|
||
@echo "🧪 Creating testing infrastructure..."
|
||
@if [ ! -d "tests" ]; then mkdir -p tests; fi
|
||
@if [ ! -f "tests/__init__.py" ]; then \
|
||
echo "Creating tests/__init__.py..."; \
|
||
echo '"""Test package initialization."""' > tests/__init__.py; \
|
||
fi
|
||
@PACKAGE_NAME=$$(grep '^name = ' pyproject.toml 2>/dev/null | sed 's/name = "\(.*\)"/\1/' | tr '-' '_' || echo "project_name"); \
|
||
if [ ! -f "tests/test_core.py" ]; then \
|
||
echo "Creating tests/test_core.py..."; \
|
||
echo '"""Tests for core functionality."""' > tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo "import pytest" >> tests/test_core.py; \
|
||
echo "from $$PACKAGE_NAME.core import ExampleClass" >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo "class TestExampleClass:" >> tests/test_core.py; \
|
||
echo ' """Test cases for ExampleClass."""' >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo " def test_initialization(self):" >> tests/test_core.py; \
|
||
echo ' """Test ExampleClass initialization."""' >> tests/test_core.py; \
|
||
echo ' obj = ExampleClass("test")' >> tests/test_core.py; \
|
||
echo ' assert obj.name == "test"' >> tests/test_core.py; \
|
||
echo " assert obj.value == 0" >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo " def test_initialization_with_value(self):" >> tests/test_core.py; \
|
||
echo ' """Test ExampleClass initialization with value."""' >> tests/test_core.py; \
|
||
echo ' obj = ExampleClass("test", 42)' >> tests/test_core.py; \
|
||
echo ' assert obj.name == "test"' >> tests/test_core.py; \
|
||
echo " assert obj.value == 42" >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo " def test_process_valid_input(self):" >> tests/test_core.py; \
|
||
echo ' """Test process method with valid input."""' >> tests/test_core.py; \
|
||
echo ' obj = ExampleClass("test", 42)' >> tests/test_core.py; \
|
||
echo ' result = obj.process("hello")' >> tests/test_core.py; \
|
||
echo ' assert result == "test: hello (value: 42)"' >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo " def test_process_empty_input(self):" >> tests/test_core.py; \
|
||
echo ' """Test process method with empty input."""' >> tests/test_core.py; \
|
||
echo ' obj = ExampleClass("test")' >> tests/test_core.py; \
|
||
echo " with pytest.raises(ValueError, match=\"Input data cannot be empty\"):" >> tests/test_core.py; \
|
||
echo ' obj.process("")' >> tests/test_core.py; \
|
||
echo "" >> tests/test_core.py; \
|
||
echo " with pytest.raises(ValueError, match=\"Input data cannot be empty\"):" >> tests/test_core.py; \
|
||
echo ' obj.process(" ")' >> tests/test_core.py; \
|
||
fi
|
||
@echo "✅ Testing infrastructure created"
|
||
|
||
# Verify complete setup functionality
|
||
setup-verify: $(VENV)/bin/activate
|
||
@echo "🔍 Verifying complete setup functionality..."
|
||
@echo " • Checking virtual environment..."
|
||
@if [ -f "$(VENV)/bin/python" ]; then \
|
||
echo " ✅ Virtual environment active"; \
|
||
else \
|
||
echo " ❌ Virtual environment not found"; \
|
||
exit 1; \
|
||
fi
|
||
@echo " • Checking package structure..."
|
||
@PACKAGE_NAME=$$(grep '^name = ' pyproject.toml 2>/dev/null | sed 's/name = "\(.*\)"/\1/' | tr '-' '_' || echo "project_name"); \
|
||
if [ -f "src/$$PACKAGE_NAME/__init__.py" ] && [ -f "src/$$PACKAGE_NAME/core.py" ]; then \
|
||
echo " ✅ Package structure correct"; \
|
||
else \
|
||
echo " ❌ Package structure incomplete"; \
|
||
exit 1; \
|
||
fi
|
||
@echo " • Checking development tools..."
|
||
@if $(VENV_PYTHON) -c "import pytest, black, flake8, mypy" 2>/dev/null; then \
|
||
echo " ✅ Development tools installed"; \
|
||
else \
|
||
echo " ❌ Development tools missing"; \
|
||
exit 1; \
|
||
fi
|
||
@echo " • Running tests..."
|
||
@if $(VENV_PYTHON) -m pytest tests/ -v --tb=short; then \
|
||
echo " ✅ Tests pass"; \
|
||
else \
|
||
echo " ❌ Tests failing"; \
|
||
exit 1; \
|
||
fi
|
||
@echo " • Checking code quality..."
|
||
@if $(VENV_PYTHON) -m flake8 src/ --max-line-length=100 --show-source; then \
|
||
echo " ✅ Code quality checks pass"; \
|
||
else \
|
||
echo " ❌ Code quality issues found"; \
|
||
exit 1; \
|
||
fi
|
||
@echo "✅ Setup verification complete! Repository ready for development."
|
||
|
||
# ============================================================================
|
||
# Development Targets
|
||
# ============================================================================
|
||
|
||
# Run tests (unit tests only - fast)
|
||
test: $(VENV)/bin/activate
|
||
@echo "🧪 Running unit tests..."
|
||
@if [ -f $(VENV)/bin/pytest ]; then \
|
||
PYTHONPATH=. $(VENV)/bin/pytest tests/ -v; \
|
||
else \
|
||
PYTHONPATH=. $(VENV_PYTHON) -m pytest tests/ -v 2>/dev/null || \
|
||
PYTHONPATH=. $(VENV_PYTHON) -m unittest discover tests/ -v; \
|
||
fi
|
||
|
||
# Run comprehensive test suite (tests + standards + quality)
|
||
test-all: standards-test test lint
|
||
@echo "🎯 Running comprehensive test suite..."
|
||
@$(MAKE) --no-print-directory test
|
||
@echo ""
|
||
@echo "✅ All tests completed successfully!"
|
||
@echo " • Unit tests: PASSED"
|
||
@echo " • Standards compliance: PASSED"
|
||
@echo " • Code quality: PASSED"
|
||
|
||
# Build the package
|
||
build: $(VENV)/bin/activate
|
||
@echo "🏗️ Building package..."
|
||
@$(VENV_PYTHON) -m build
|
||
@echo "✅ Package built successfully"
|
||
|
||
# Run code linting
|
||
lint: $(VENV)/bin/activate
|
||
@echo "🔍 Running linting..."
|
||
@if $(VENV_PYTHON) -c "import flake8" 2>/dev/null; then \
|
||
$(VENV_PYTHON) -m flake8 src/ --max-line-length=100 --show-source; \
|
||
echo "✅ Linting completed"; \
|
||
else \
|
||
echo "⚠️ flake8 not installed. Run 'make setup-tools' first."; \
|
||
fi
|
||
|
||
# Format code with black
|
||
format: $(VENV)/bin/activate
|
||
@echo "🎨 Formatting code with black..."
|
||
@if $(VENV_PYTHON) -c "import black" 2>/dev/null; then \
|
||
$(VENV_PYTHON) -m black src/ tests/; \
|
||
echo "✅ Code formatting completed"; \
|
||
else \
|
||
echo "⚠️ black not installed. Run 'make setup-tools' first."; \
|
||
fi
|
||
|
||
# Clean build artifacts and cache
|
||
clean:
|
||
@echo "🧹 Cleaning build artifacts and cache..."
|
||
@rm -rf build/ dist/ *.egg-info/ .pytest_cache/ __pycache__/ .coverage htmlcov/
|
||
@rm -rf agents_backup_*/
|
||
@find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
|
||
@find . -type f -name "*.pyc" -delete 2>/dev/null || true
|
||
@find . -type f -name "*.pyo" -delete 2>/dev/null || true
|
||
@echo "✅ Cleanup completed"
|
||
|
||
# Install pre-commit hooks (WP-0001 T02)
|
||
pre-commit-install: $(VENV)/bin/activate
|
||
@echo "🔧 Installing pre-commit hooks..."
|
||
@$(VENV_PIP) install pre-commit
|
||
@$(VENV)/bin/pre-commit install
|
||
@echo "✅ pre-commit installed — run 'pre-commit run --all-files' to verify"
|
||
|
||
# ============================================================================
|
||
# Standards Compliance Targets
|
||
# ============================================================================
|
||
|
||
# Check repository against PythonVibes standards (read-only analysis)
|
||
standards-check:
|
||
@echo "🔍 Checking repository against PythonVibes standards..."
|
||
@echo ""
|
||
@echo "📋 Repository Structure Analysis:"
|
||
@echo "================================"
|
||
@ISSUES=0; \
|
||
echo " • Project Configuration:"; \
|
||
if [ -f "pyproject.toml" ]; then \
|
||
echo " ✅ pyproject.toml exists"; \
|
||
if grep -q '^\[build-system\]' pyproject.toml && grep -q '^name = ' pyproject.toml; then \
|
||
echo " ✅ pyproject.toml properly configured"; \
|
||
else \
|
||
echo " ⚠️ pyproject.toml missing required sections"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
else \
|
||
echo " ❌ pyproject.toml missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo ""; \
|
||
echo " • Directory Structure:"; \
|
||
if [ -d "src" ]; then \
|
||
echo " ✅ src/ directory exists"; \
|
||
PACKAGE_NAME=$$(grep '^name = ' pyproject.toml 2>/dev/null | sed 's/name = "\(.*\)"/\1/' | tr '-' '_' || echo ""); \
|
||
if [ -n "$$PACKAGE_NAME" ] && [ -d "src/$$PACKAGE_NAME" ]; then \
|
||
echo " ✅ Package directory src/$$PACKAGE_NAME exists"; \
|
||
if [ -f "src/$$PACKAGE_NAME/__init__.py" ]; then \
|
||
echo " ✅ Package __init__.py exists"; \
|
||
else \
|
||
echo " ❌ Package __init__.py missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
else \
|
||
echo " ❌ Package directory missing or misnamed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
else \
|
||
echo " ❌ src/ directory missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if [ -d "tests" ]; then \
|
||
echo " ✅ tests/ directory exists"; \
|
||
if [ -f "tests/__init__.py" ]; then \
|
||
echo " ✅ tests/__init__.py exists"; \
|
||
else \
|
||
echo " ⚠️ tests/__init__.py missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
else \
|
||
echo " ❌ tests/ directory missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if [ -d "docs" ]; then \
|
||
echo " ✅ docs/ directory exists"; \
|
||
else \
|
||
echo " ⚠️ docs/ directory missing"; \
|
||
fi; \
|
||
echo ""; \
|
||
echo " • Essential Files:"; \
|
||
for file in README.md LICENSE .gitignore; do \
|
||
if [ -f "$$file" ]; then \
|
||
echo " ✅ $$file exists"; \
|
||
else \
|
||
echo " ❌ $$file missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
done; \
|
||
echo ""; \
|
||
echo " • Development Tools:"; \
|
||
if [ -f "$(VENV)/bin/python" ]; then \
|
||
echo " ✅ Virtual environment active"; \
|
||
if $(VENV_PYTHON) -c "import pytest" 2>/dev/null; then \
|
||
echo " ✅ pytest installed"; \
|
||
else \
|
||
echo " ❌ pytest not installed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if $(VENV_PYTHON) -c "import black" 2>/dev/null; then \
|
||
echo " ✅ black installed"; \
|
||
else \
|
||
echo " ❌ black not installed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if $(VENV_PYTHON) -c "import flake8" 2>/dev/null; then \
|
||
echo " ✅ flake8 installed"; \
|
||
else \
|
||
echo " ❌ flake8 not installed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
else \
|
||
echo " ❌ Virtual environment not found"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo ""; \
|
||
echo " • Code Quality:"; \
|
||
if [ -d "src" ] && [ -f "$(VENV)/bin/python" ]; then \
|
||
if $(VENV_PYTHON) -m flake8 src/ --max-line-length=100 --show-source >/dev/null 2>&1; then \
|
||
echo " ✅ Code passes flake8 checks"; \
|
||
else \
|
||
echo " ⚠️ Code has flake8 violations"; \
|
||
fi; \
|
||
if [ -d "tests" ] && $(VENV_PYTHON) -m pytest tests/ --tb=no -q >/dev/null 2>&1; then \
|
||
echo " ✅ Tests pass"; \
|
||
else \
|
||
echo " ⚠️ Tests failing or missing"; \
|
||
fi; \
|
||
fi; \
|
||
echo ""; \
|
||
echo "📊 Standards Compliance Summary:"; \
|
||
echo "==============================="; \
|
||
if [ $$ISSUES -eq 0 ]; then \
|
||
echo "🎉 Repository fully complies with PythonVibes standards!"; \
|
||
echo " All essential components are properly configured."; \
|
||
elif [ $$ISSUES -le 3 ]; then \
|
||
echo "⚠️ Repository mostly complies with minor issues ($$ISSUES violations)"; \
|
||
echo " Run 'make standards-fix' to address these issues."; \
|
||
else \
|
||
echo "❌ Repository has significant standards violations ($$ISSUES issues)"; \
|
||
echo " Run 'make standards-fix' to bring repository up to standards."; \
|
||
fi; \
|
||
echo ""; \
|
||
echo "💡 Next steps:"; \
|
||
echo " • Run 'make standards-fix' to automatically fix issues"; \
|
||
echo " • Use agent-setupRepository.md for manual guidance"; \
|
||
echo " • Check individual components with specific setup-* targets"
|
||
|
||
# Fix standards violations (idempotent setup)
|
||
standards-fix: setup-complete
|
||
@echo "🔧 Fixed any standards violations found."
|
||
@echo " Repository now complies with PythonVibes standards."
|
||
@echo ""
|
||
@echo "🔍 Run 'make standards-check' to verify compliance."
|
||
|
||
# Run repository standards compliance tests
|
||
standards-test: $(VENV)/bin/activate
|
||
@echo "🔍 Running repository standards compliance tests..."
|
||
@echo ""
|
||
@ISSUES=0; \
|
||
echo "📋 Testing Repository Standards:"; \
|
||
echo "==============================="; \
|
||
echo " • Project Configuration:"; \
|
||
if [ -f "pyproject.toml" ]; then \
|
||
if grep -q '^\[build-system\]' pyproject.toml && grep -q '^name = ' pyproject.toml; then \
|
||
echo " ✅ pyproject.toml properly configured"; \
|
||
else \
|
||
echo " ❌ pyproject.toml missing required sections"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
else \
|
||
echo " ❌ pyproject.toml missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Directory Structure:"; \
|
||
if [ -d "src" ]; then \
|
||
echo " ✅ src/ directory exists"; \
|
||
else \
|
||
echo " ❌ src/ directory missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if [ -d "tests" ]; then \
|
||
echo " ✅ tests/ directory exists"; \
|
||
else \
|
||
echo " ❌ tests/ directory missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Essential Files:"; \
|
||
for file in README.md LICENSE .gitignore; do \
|
||
if [ -f "$$file" ]; then \
|
||
echo " ✅ $$file exists"; \
|
||
else \
|
||
echo " ❌ $$file missing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
done; \
|
||
echo " • Development Tools:"; \
|
||
if $(VENV_PYTHON) -c "import pytest" 2>/dev/null; then \
|
||
echo " ✅ pytest installed"; \
|
||
else \
|
||
echo " ❌ pytest not installed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if $(VENV_PYTHON) -c "import black" 2>/dev/null; then \
|
||
echo " ✅ black installed"; \
|
||
else \
|
||
echo " ❌ black not installed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
if $(VENV_PYTHON) -c "import flake8" 2>/dev/null; then \
|
||
echo " ✅ flake8 installed"; \
|
||
else \
|
||
echo " ❌ flake8 not installed"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo ""; \
|
||
if [ $$ISSUES -eq 0 ]; then \
|
||
echo "✅ Repository standards compliance: PASSED"; \
|
||
else \
|
||
echo "❌ Repository standards compliance: FAILED ($$ISSUES violations)"; \
|
||
echo " Run 'make standards-fix' to resolve issues."; \
|
||
exit 1; \
|
||
fi
|
||
|
||
# ============================================================================
|
||
# Agent Management Targets
|
||
# ============================================================================
|
||
|
||
# List installed agents
|
||
agents-list:
|
||
@echo "🤖 Installed agents:"
|
||
@if [ -d "agents" ]; then \
|
||
ls agents/ 2>/dev/null | grep agent- | sed 's/agent-//g' | sed 's/.md//g' | sort || echo "No agents installed"; \
|
||
else \
|
||
echo "No agents directory found"; \
|
||
fi
|
||
|
||
# Update installed agents to latest versions
|
||
agents-update: $(VENV)/bin/activate
|
||
@echo "🔄 Updating agents..."
|
||
@if command -v kaizen-agentic >/dev/null 2>&1; then \
|
||
kaizen-agentic update; \
|
||
else \
|
||
echo "⚠️ kaizen-agentic CLI not found."; \
|
||
echo " Dev install: make agents-install-cli (or pip install -e .)"; \
|
||
echo " Registry: see docs/PACKAGE_RELEASE.md"; \
|
||
fi
|
||
|
||
# Validate installed agents
|
||
agents-validate:
|
||
@echo "✅ Validating agents..."
|
||
@if command -v kaizen-agentic >/dev/null 2>&1; then \
|
||
kaizen-agentic validate; \
|
||
else \
|
||
echo "⚠️ kaizen-agentic CLI not found."; \
|
||
echo " Dev install: make agents-install-cli (or pip install -e .)"; \
|
||
echo " Registry: see docs/PACKAGE_RELEASE.md"; \
|
||
fi
|
||
|
||
# Show agent status and project information
|
||
agents-status:
|
||
@echo "📊 Agent status:"
|
||
@if command -v kaizen-agentic >/dev/null 2>&1; then \
|
||
kaizen-agentic status; \
|
||
else \
|
||
echo "⚠️ kaizen-agentic CLI not found."; \
|
||
echo " Dev install: make agents-install-cli (or pip install -e .)"; \
|
||
echo " Registry: see docs/PACKAGE_RELEASE.md"; \
|
||
echo ""; \
|
||
echo "Manual agent check:"; \
|
||
if [ -d "agents" ]; then \
|
||
echo "Agents directory exists with $$(ls agents/ | wc -l) files"; \
|
||
else \
|
||
echo "No agents directory found"; \
|
||
fi; \
|
||
fi
|
||
|
||
# Sync canonical agents/ into packaged wheel data
|
||
AGENTS_SRC_DIR = agents
|
||
AGENTS_PKG_DIR = src/kaizen_agentic/data/agents
|
||
|
||
agents-sync-package:
|
||
@echo "📦 Syncing packaged agents from $(AGENTS_SRC_DIR)/ ..."
|
||
@mkdir -p $(AGENTS_PKG_DIR); \
|
||
SYNCED=0; \
|
||
for f in $(AGENTS_SRC_DIR)/agent-*.md; do \
|
||
dest="$(AGENTS_PKG_DIR)/$$(basename $$f)"; \
|
||
if [ -n "$(DRY_RUN)" ]; then \
|
||
if [ -f "$$dest" ] && cmp -s "$$f" "$$dest"; then \
|
||
echo " = $$(basename $$f) (unchanged)"; \
|
||
else \
|
||
echo " → $$(basename $$f)"; \
|
||
fi; \
|
||
else \
|
||
cp "$$f" "$$dest"; \
|
||
echo " ✓ $$(basename $$f)"; \
|
||
SYNCED=$$((SYNCED + 1)); \
|
||
fi; \
|
||
done; \
|
||
if [ -z "$(DRY_RUN)" ]; then \
|
||
echo "✅ Synced $$SYNCED file(s) to $(AGENTS_PKG_DIR)/"; \
|
||
else \
|
||
echo "ℹ️ DRY_RUN preview only — no files copied"; \
|
||
fi
|
||
|
||
# Install agent distribution CLI
|
||
agents-install-cli: $(VENV)/bin/activate
|
||
@echo "📦 Installing Kaizen Agentic CLI..."
|
||
@$(VENV_PIP) install --upgrade pip
|
||
@$(VENV_PIP) install -e .
|
||
@echo "✅ CLI installed. Use 'kaizen-agentic --help' for usage."
|
||
@echo "💡 Activate virtual environment with: source $(VENV)/bin/activate"
|
||
|
||
# ============================================================================
|
||
# Release Management Targets
|
||
# ============================================================================
|
||
|
||
# Validate release readiness (tests, linting, version consistency)
|
||
release-check: $(VENV)/bin/activate
|
||
@echo "🔍 Validating release readiness..."
|
||
@echo ""
|
||
@ISSUES=0; \
|
||
echo "📋 Release Readiness Checklist:"; \
|
||
echo "==============================="; \
|
||
echo " • Version Consistency:"; \
|
||
CHANGELOG_VERSION=$$(grep '^## \[' CHANGELOG.md | grep -v "Unreleased" | head -1 | sed 's/## \[\(.*\)\].*/\1/' || echo ""); \
|
||
PYPROJECT_VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/' || echo ""); \
|
||
if [ "$$CHANGELOG_VERSION" = "$$PYPROJECT_VERSION" ] && [ -n "$$CHANGELOG_VERSION" ]; then \
|
||
echo " ✅ Versions consistent: $$CHANGELOG_VERSION"; \
|
||
else \
|
||
echo " ❌ Version mismatch: CHANGELOG.md='$$CHANGELOG_VERSION', pyproject.toml='$$PYPROJECT_VERSION'"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Code Quality:"; \
|
||
if $(VENV_PYTHON) -m flake8 src/ --max-line-length=100 >/dev/null 2>&1; then \
|
||
echo " ✅ Code passes linting"; \
|
||
else \
|
||
echo " ❌ Code has linting violations"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Test Suite:"; \
|
||
if $(VENV_PYTHON) -m pytest tests/ --tb=no -q >/dev/null 2>&1; then \
|
||
echo " ✅ All tests pass"; \
|
||
else \
|
||
echo " ❌ Tests failing"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Documentation:"; \
|
||
if [ -f "README.md" ] && [ -f "CHANGELOG.md" ] && [ -f "docs/GETTING_STARTED.md" ]; then \
|
||
echo " ✅ Core documentation exists"; \
|
||
else \
|
||
echo " ❌ Missing core documentation files"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Build System:"; \
|
||
if [ -f "pyproject.toml" ] && grep -q '^\[build-system\]' pyproject.toml; then \
|
||
echo " ✅ Build configuration present"; \
|
||
else \
|
||
echo " ❌ Build system not configured"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo " • Packaged Agent Parity:"; \
|
||
PARITY_OK=1; \
|
||
for f in agents/agent-*.md; do \
|
||
dest="src/kaizen_agentic/data/agents/$$(basename $$f)"; \
|
||
if [ ! -f "$$dest" ] || ! cmp -s "$$f" "$$dest"; then \
|
||
PARITY_OK=0; \
|
||
break; \
|
||
fi; \
|
||
done; \
|
||
if [ $$PARITY_OK -eq 1 ] && ls agents/agent-*.md >/dev/null 2>&1; then \
|
||
echo " ✅ agents/ matches data/agents/"; \
|
||
else \
|
||
echo " ❌ Packaged agents drift from agents/ — run: make agents-sync-package"; \
|
||
ISSUES=$$((ISSUES + 1)); \
|
||
fi; \
|
||
echo ""; \
|
||
if [ $$ISSUES -eq 0 ]; then \
|
||
echo "✅ Release readiness: PASSED"; \
|
||
echo " Ready for release preparation."; \
|
||
else \
|
||
echo "❌ Release readiness: FAILED ($$ISSUES issues)"; \
|
||
echo " Fix issues before proceeding with release."; \
|
||
exit 1; \
|
||
fi
|
||
|
||
# Prepare release (update versions, build packages)
|
||
release-prepare: release-check clean
|
||
@echo "🏗️ Preparing release..."
|
||
@echo ""
|
||
@VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \
|
||
echo "📦 Building packages for version $$VERSION..."; \
|
||
$(VENV_PYTHON) -c "import build" 2>/dev/null || $(VENV_PIP) install build; \
|
||
$(VENV_PYTHON) -m build; \
|
||
echo ""; \
|
||
echo "✅ Release preparation completed:"; \
|
||
echo " • Version: $$VERSION"; \
|
||
echo " • Packages built in dist/"; \
|
||
ls -la dist/ | grep "$$VERSION" || echo " • Package files:"; ls -la dist/; \
|
||
echo ""; \
|
||
echo "💡 Next steps:"; \
|
||
echo " • Run 'make publish-gitea' for Coulomb Gitea PyPI"; \
|
||
echo " • Run 'make release-test' to test publication on TestPyPI"; \
|
||
echo " • Run 'make release-publish' for pypi.org (when configured)"
|
||
|
||
# Build and validate distributions
|
||
package-check: release-prepare
|
||
$(VENV_PYTHON) -c "import twine" 2>/dev/null || $(VENV_PIP) install twine
|
||
$(VENV_PYTHON) -m twine check dist/*
|
||
|
||
# Publish to Coulomb Gitea PyPI registry
|
||
publish-gitea: package-check
|
||
ifndef TWINE_USERNAME
|
||
$(error TWINE_USERNAME is required (e.g. export TWINE_USERNAME=<gitea-user>))
|
||
endif
|
||
ifndef TWINE_PASSWORD
|
||
$(error TWINE_PASSWORD is required (e.g. export TWINE_PASSWORD=$$GITEA_API_TOKEN))
|
||
endif
|
||
$(VENV_PYTHON) -m twine upload --repository-url "$(GITEA_PYPI_REPOSITORY_URL)" dist/*
|
||
|
||
# Test publication workflow using TestPyPI
|
||
release-test: release-prepare
|
||
@echo "🧪 Testing publication workflow with TestPyPI..."
|
||
@echo ""
|
||
@VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \
|
||
echo "🚀 Uploading to TestPyPI (version $$VERSION)..."; \
|
||
$(VENV_PYTHON) -c "import twine" 2>/dev/null || $(VENV_PIP) install twine; \
|
||
echo ""; \
|
||
echo "⚠️ Manual Step Required:"; \
|
||
echo " Run the following command to upload to TestPyPI:"; \
|
||
echo " $(VENV_PYTHON) -m twine upload --repository testpypi dist/*"; \
|
||
echo ""; \
|
||
echo " Then test installation:"; \
|
||
echo " pip install --index-url https://test.pypi.org/simple/ kaizen-agentic==$$VERSION"; \
|
||
echo ""; \
|
||
echo "💡 Configure TestPyPI credentials:"; \
|
||
echo " • Create account at https://test.pypi.org/"; \
|
||
echo " • Generate API token"; \
|
||
echo " • Store in ~/.pypirc or use keyring"
|
||
|
||
# Publish to production PyPI
|
||
release-publish: release-check
|
||
@echo "🚀 Publishing to production PyPI..."
|
||
@echo ""
|
||
@VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \
|
||
echo "⚠️ PRODUCTION RELEASE WARNING ⚠️"; \
|
||
echo " About to publish version $$VERSION to PyPI"; \
|
||
echo " This action cannot be undone!"; \
|
||
echo ""; \
|
||
echo "📋 Pre-flight checklist:"; \
|
||
echo " ✅ All tests pass"; \
|
||
echo " ✅ Documentation updated"; \
|
||
echo " ✅ Version tagged in git"; \
|
||
echo " ✅ TestPyPI upload tested"; \
|
||
echo ""; \
|
||
$(VENV_PYTHON) -c "import twine" 2>/dev/null || $(VENV_PIP) install twine; \
|
||
echo "⚠️ Manual Step Required:"; \
|
||
echo " Run the following command to publish:"; \
|
||
echo " $(VENV_PYTHON) -m twine upload dist/*"; \
|
||
echo ""; \
|
||
echo "💡 Configure PyPI credentials:"; \
|
||
echo " • Create account at https://pypi.org/"; \
|
||
echo " • Generate API token"; \
|
||
echo " • Store in ~/.pypirc or use keyring"
|
||
|
||
# Post-release tasks (tags, GitHub release, documentation)
|
||
release-finalize: $(VENV)/bin/activate
|
||
@echo "🏁 Finalizing release..."
|
||
@echo ""
|
||
@VERSION=$$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/'); \
|
||
echo "📝 Post-release tasks for version $$VERSION:"; \
|
||
echo ""; \
|
||
echo " • Git Tagging:"; \
|
||
if git tag -l | grep -q "^v$$VERSION$$"; then \
|
||
echo " ✅ Tag v$$VERSION already exists"; \
|
||
else \
|
||
echo " 📌 Creating git tag v$$VERSION..."; \
|
||
git tag -a "v$$VERSION" -m "Release version $$VERSION"; \
|
||
echo " ✅ Tag created"; \
|
||
fi; \
|
||
echo ""; \
|
||
echo " • GitHub Release:"; \
|
||
echo " 💡 Manual steps required:"; \
|
||
echo " 1. Push tags: git push origin v$$VERSION"; \
|
||
echo " 2. Create GitHub release at:"; \
|
||
echo " https://github.com/kaizen-agentic/kaizen-agentic/releases/new"; \
|
||
echo " 3. Upload dist/ files as release assets"; \
|
||
echo ""; \
|
||
echo " • Documentation:"; \
|
||
echo " 💡 Verify installation instructions work:"; \
|
||
echo " pip install kaizen-agentic==$$VERSION --extra-index-url <gitea-pypi-simple>"; \
|
||
echo " See docs/PACKAGE_RELEASE.md"; \
|
||
echo ""; \
|
||
echo "✅ Release finalization checklist provided"; \
|
||
echo " Complete manual steps above to finish release process"
|
||
|
||
# Emergency rollback procedures
|
||
release-rollback: $(VENV)/bin/activate
|
||
@echo "🚨 Emergency release rollback procedures..."
|
||
@echo ""
|
||
@echo "⚠️ ROLLBACK PROCEDURES ⚠️"; \
|
||
echo "================================"; \
|
||
echo ""; \
|
||
echo "📋 Available rollback options:"; \
|
||
echo ""; \
|
||
echo " 1. PyPI Package Yanking:"; \
|
||
echo " • Cannot delete published packages"; \
|
||
echo " • Can 'yank' versions to prevent new installs"; \
|
||
echo " • Use PyPI web interface or twine"; \
|
||
echo ""; \
|
||
echo " 2. Git Rollback:"; \
|
||
echo " • Revert commits: git revert <commit-hash>"; \
|
||
echo " • Delete tags: git tag -d v<version>"; \
|
||
echo " • Force push (if no external users)"; \
|
||
echo ""; \
|
||
echo " 3. Documentation Updates:"; \
|
||
echo " • Update CHANGELOG.md with rollback notice"; \
|
||
echo " • Add deprecation warnings"; \
|
||
echo " • Publish corrected documentation"; \
|
||
echo ""; \
|
||
echo " 4. Emergency Release:"; \
|
||
echo " • Increment patch version"; \
|
||
echo " • Fix critical issues"; \
|
||
echo " • Fast-track through release process"; \
|
||
echo ""; \
|
||
echo "💡 Prevention for next time:"; \
|
||
echo " • Always test with TestPyPI first"; \
|
||
echo " • Use staging/preview environments"; \
|
||
echo " • Implement automated quality gates"; \
|
||
echo " • Consider pre-release versions for testing"
|