qbit_manage/Makefile
bobokun 5a4ddf0112
4.6.0 (#931)
# Requirements Updated
- "humanize==4.13.0"
- "ruff==0.12.11"

# Breaking Changes
- **DEPRECATE `QBT_CONFIG` / `--config-file` OPTION**
- No longer supporting `QBT_CONFIG` / `--config-file`. Instead please
switch over to **`QBT_CONFIG_DIR` / `--config-dir`**.
- `QBT_CONFIG` / `--config-file` option will still work for now but is
now considered legacy and will be removed in a future release.
- **Note**: All yml/yaml files will be treated as valid configuration
files and loaded in the `QBT_CONFIG_DIR` path. Please ensure you
**remove** any old/unused configurations that you don't want to be
loaded prior to using this path.

# Improvements
- Adds docker support for PUID/PGID environment variables
- Dockerfile copies the latest `config.yml.sample` in the config folder
- Add `QBT_HOST` / `--host` option to specify webUI host address (#929
Thanks to @QuixThe2nd)
- WebUI: Quick action settings persist now

# Bug Fixes
- WebUI: Fix loading spinner to be centered in the webUI

**Full Changelog**:
https://github.com/StuffAnThings/qbit_manage/compare/v4.5.5...v4.6.0

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Fabricio Silva <hi@fabricio.dev>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Parsa Yazdani <parsa@yazdani.au>
Co-authored-by: Actionbot <actions@github.com>
2025-08-30 14:54:13 -04:00

344 lines
13 KiB
Makefile

# Define the path to uv
UV_PATH := $(shell which uv 2>/dev/null || echo "")
UV_LOCAL_PATH := $(HOME)/.local/bin/uv
UV_CARGO_PATH := $(HOME)/.cargo/bin/uv
# Check if uv is installed, if not set UV_INSTALL to 1
ifeq ($(UV_PATH),)
ifeq ($(wildcard $(UV_LOCAL_PATH)),)
ifeq ($(wildcard $(UV_CARGO_PATH)),)
UV_INSTALL := 1
else
UV_PATH := $(UV_CARGO_PATH)
endif
else
UV_PATH := $(UV_LOCAL_PATH)
endif
endif
# Define the virtual environment path
VENV := .venv
VENV_ACTIVATE := $(VENV)/bin/activate
VENV_PYTHON := $(VENV)/bin/python
VENV_UV := $(VENV)/bin/uv
VENV_PIP := $(VENV)/bin/pip
VENV_PRE_COMMIT := $(VENV)/bin/pre-commit
VENV_RUFF := $(VENV)/bin/ruff
.PHONY: all
all: venv
.PHONY: install-uv
install-uv:
ifdef UV_INSTALL
@echo "Installing uv..."
@curl -LsSf https://astral.sh/uv/install.sh | sh
@echo "uv installed to $(HOME)/.local/bin/uv"
$(eval UV_PATH := $(HOME)/.local/bin/uv)
endif
.PHONY: venv
venv: install-uv
@echo "Creating virtual environment..."
@$(UV_PATH) venv $(VENV)
@echo "Installing project dependencies from pyproject.toml..."
@$(UV_PATH) pip install --python $(VENV_PYTHON) -e . --config-settings editable_mode=compat
@echo "Removing conflicting console script to avoid PATH conflicts..."
@rm -f $(VENV)/bin/qbit-manage 2>/dev/null || true
@echo "Installing development dependencies..."
@$(UV_PATH) pip install --python $(VENV_PYTHON) pre-commit ruff
@echo "Virtual environment created and dependencies installed."
@echo "✓ Virtual environment ready for development"
@echo "To activate the virtual environment, run: source $(VENV_ACTIVATE)"
.PHONY: sync
sync: venv
@echo "Syncing dependencies from pyproject.toml..."
@$(UV_PATH) pip sync pyproject.toml
.PHONY: test
test: venv
@echo "Running tests..."
@. $(VENV_ACTIVATE) && $(VENV_PYTHON) -m pytest
.PHONY: pre-commit
pre-commit: venv
@echo "Running pre-commit hooks..."
@. $(VENV_ACTIVATE) && $(VENV_PRE_COMMIT) run --all-files
.PHONY: install-hooks
install-hooks: venv
@echo "Installing pre-commit hooks..."
@. $(VENV_ACTIVATE) && $(VENV_PRE_COMMIT) install -f --install-hooks
.PHONY: clean
clean:
@echo "Cleaning up..."
@find -name '*.pyc' -delete
@find -name '__pycache__' -delete
@rm -rf $(VENV)
@rm -rf .pytest_cache
@rm -rf .ruff_cache
@rm -rf dist/
@rm -rf build/
@rm -rf *.egg-info/
@rm -rf web-ui/dist/
@rm -rf web-ui/build/
@rm -rf web-ui/node_modules/
@rm -rf desktop/tauri/src-tauri/target/
@rm -rf desktop/tauri/src-tauri/gen/
@rm -rf desktop/tauri/node_modules/
@echo "Cleanup complete."
.PHONY: lint
lint: venv
@echo "Running linter..."
@. $(VENV_ACTIVATE) && $(VENV_RUFF) check --fix .
.PHONY: format
format: venv
@echo "Running formatter..."
@. $(VENV_ACTIVATE) && $(VENV_RUFF) format .
.PHONY: build
build: venv
@echo "Building package..."
@$(UV_PATH) pip install --python $(VENV_PYTHON) build twine
@. $(VENV_ACTIVATE) && $(VENV_PYTHON) -m build
@echo "Package built successfully. Files in dist/"
.PHONY: check-dist
check-dist: build
@echo "Checking distribution files..."
@. $(VENV_ACTIVATE) && $(VENV_PYTHON) -m twine check dist/*
.PHONY: setup-pypi
setup-pypi:
@echo "Setting up PyPI configuration..."
@if [ -f ~/.pypirc ] && grep -q "password = pypi-" ~/.pypirc 2>/dev/null; then \
echo "✓ ~/.pypirc already exists with API tokens configured"; \
else \
$(MAKE) setup-pypi-interactive; \
fi
.PHONY: setup-pypi-interactive
setup-pypi-interactive:
@echo ""
@echo "This will set up your PyPI credentials for automatic uploads."
@echo "You'll need API tokens from:"
@echo " - Test PyPI: https://test.pypi.org/manage/account/token/"
@echo " - Live PyPI: https://pypi.org/manage/account/token/"
@echo ""
@echo "Creating accounts (if needed):"
@echo " - Test PyPI: https://test.pypi.org/account/register/"
@echo " - Live PyPI: https://pypi.org/account/register/"
@echo ""
@printf "Press Enter to continue or Ctrl+C to cancel..."
@read dummy
@echo ""
@printf "Please enter your Test PyPI API token (starts with 'pypi-'): "
@read testpypi_token; \
echo ""; \
printf "Please enter your PyPI API token (starts with 'pypi-'): "; \
read pypi_token; \
echo ""; \
if [ -z "$$testpypi_token" ] || [ -z "$$pypi_token" ]; then \
echo "❌ Both tokens are required. Setup cancelled."; \
exit 1; \
fi; \
if ! echo "$$testpypi_token" | grep -q "^pypi-" || ! echo "$$pypi_token" | grep -q "^pypi-"; then \
echo "❌ Invalid token format. Tokens should start with 'pypi-'"; \
exit 1; \
fi; \
echo "Creating ~/.pypirc configuration file..."; \
echo "[distutils]" > ~/.pypirc; \
echo "index-servers =" >> ~/.pypirc; \
echo " pypi" >> ~/.pypirc; \
echo " testpypi" >> ~/.pypirc; \
echo "" >> ~/.pypirc; \
echo "[pypi]" >> ~/.pypirc; \
echo "repository = https://upload.pypi.org/legacy/" >> ~/.pypirc; \
echo "username = __token__" >> ~/.pypirc; \
echo "password = $$pypi_token" >> ~/.pypirc; \
echo "" >> ~/.pypirc; \
echo "[testpypi]" >> ~/.pypirc; \
echo "repository = https://test.pypi.org/legacy/" >> ~/.pypirc; \
echo "username = __token__" >> ~/.pypirc; \
echo "password = $$testpypi_token" >> ~/.pypirc; \
chmod 600 ~/.pypirc; \
echo "✓ PyPI configuration saved to ~/.pypirc"; \
echo "✓ You can now use 'make upload-test' and 'make upload-pypi' without entering tokens"
.PHONY: upload-test
upload-test: check-dist
@echo "Uploading to Test PyPI..."
@if [ -z "$$TWINE_PASSWORD_TESTPYPI" ] && ! grep -q "password = pypi-" ~/.pypirc 2>/dev/null; then \
echo ""; \
echo "No API token found. Please either:"; \
echo "1. Set environment variable: export TWINE_PASSWORD_TESTPYPI=your-test-pypi-token"; \
echo "2. Run 'make setup-pypi' and edit ~/.pypirc with your tokens"; \
echo "3. Get token from: https://test.pypi.org/manage/account/token/"; \
exit 1; \
fi
@if [ -n "$$TWINE_PASSWORD_TESTPYPI" ]; then \
echo "Using environment variable for authentication"; \
. $(VENV_ACTIVATE) && TWINE_USERNAME=__token__ TWINE_PASSWORD=$$TWINE_PASSWORD_TESTPYPI $(VENV_PYTHON) -m twine upload --repository testpypi --verbose --skip-existing dist/*; \
else \
echo "Using ~/.pypirc for authentication"; \
. $(VENV_ACTIVATE) && $(VENV_PYTHON) -m twine upload --repository testpypi --verbose --skip-existing dist/*; \
fi
@echo "Upload to Test PyPI complete!"
@echo "Test installation with: pip install --index-url https://test.pypi.org/simple/ qbit-manage"
.PHONY: upload-pypi
upload-pypi: check-dist
@echo "Uploading to PyPI..."
@echo "WARNING: This will upload to the LIVE PyPI repository!"
@if [ -z "$$TWINE_PASSWORD_PYPI" ] && ! grep -q "password = pypi-" ~/.pypirc 2>/dev/null; then \
echo ""; \
echo "No API token found. Please either:"; \
echo "1. Set environment variable: export TWINE_PASSWORD_PYPI=your-pypi-token"; \
echo "2. Run 'make setup-pypi' and edit ~/.pypirc with your tokens"; \
echo "3. Get token from: https://pypi.org/manage/account/token/"; \
exit 1; \
fi
@read -p "Are you sure you want to continue? (y/N): " confirm && [ "$$confirm" = "y" ]
@if [ -n "$$TWINE_PASSWORD_PYPI" ]; then \
echo "Using environment variable for authentication"; \
. $(VENV_ACTIVATE) && TWINE_USERNAME=__token__ TWINE_PASSWORD=$$TWINE_PASSWORD_PYPI $(VENV_PYTHON) -m twine upload --verbose --skip-existing dist/*; \
else \
echo "Using ~/.pypirc for authentication"; \
. $(VENV_ACTIVATE) && $(VENV_PYTHON) -m twine upload --verbose --skip-existing dist/*; \
fi
@echo "Upload to PyPI complete!"
@echo "Package is now available at: https://pypi.org/project/qbit-manage/"
.PHONY: bump-version
bump-version:
@echo "Current version: $$(cat VERSION)"
@echo "Bumping patch version for testing..."
@current_version=$$(cat VERSION | cut -d'-' -f1); \
IFS='.' read -r major minor patch <<< "$$current_version"; \
new_patch=$$((patch + 1)); \
new_version="$$major.$$minor.$$new_patch"; \
echo "$$new_version-dev" > VERSION; \
echo "✓ Version bumped to: $$(cat VERSION)"
@echo "Now you can run: make build && make upload-test"
.PHONY: debug-upload
debug-upload: check-dist
@echo "Debugging upload configuration..."
@echo "Current version: $$(cat VERSION 2>/dev/null || echo 'VERSION file not found')"
@echo ""
@echo "Checking ~/.pypirc configuration:"
@if [ -f ~/.pypirc ]; then \
echo "✓ ~/.pypirc exists"; \
echo "Repositories configured:"; \
grep -E "^\[.*\]" ~/.pypirc || echo "No repositories found"; \
echo ""; \
echo "Test PyPI config:"; \
sed -n '/\[testpypi\]/,/^\[/p' ~/.pypirc | head -n -1 || echo "No testpypi section found"; \
else \
echo "❌ ~/.pypirc not found"; \
fi
@echo ""
@echo "Environment variables:"
@echo "TWINE_USERNAME: $${TWINE_USERNAME:-not set}"
@echo "TWINE_PASSWORD_TESTPYPI: $${TWINE_PASSWORD_TESTPYPI:+set (hidden)}"
@echo "TWINE_PASSWORD_PYPI: $${TWINE_PASSWORD_PYPI:+set (hidden)}"
@echo ""
@echo "Package information:"
@ls -la dist/ 2>/dev/null || echo "No dist/ directory found"
@echo ""
@echo "Common issues and solutions:"
@echo " - File already exists: Run 'make bump-version' to create a new version"
@echo " - Invalid token: Run 'make setup-pypi' to reconfigure"
@echo " - Package name taken: Change name in pyproject.toml"
# UV Tool Installation targets
.PHONY: install
install:
@echo "Installing qbit-manage using uv tool..."
@echo "Cleaning cache and build artifacts to ensure fresh install..."
@rm -rf build/ dist/ *.egg-info/ 2>/dev/null || true
@find . -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true
@$(UV_PATH) cache clean >/dev/null 2>&1 || true
@$(UV_PATH) tool install . --force
@echo "✓ Installation complete!"
@echo "Test with: qbit-manage --version"
.PHONY: uninstall
uninstall:
@echo "Uninstalling qbit-manage..."
@$(UV_PATH) tool uninstall qbit-manage || echo "qbit-manage was not installed"
@echo "✓ Uninstall complete!"
.PHONY: reinstall
reinstall: uninstall install
@echo "✓ Reinstall complete!"
.PHONY: prep-release
prep-release:
@echo "Preparing release..."
@# Step 1: Update uv lock and sync dependencies
@echo "Updating uv lock and syncing dependencies..."
@uv lock --upgrade
@uv sync
@echo "✓ Dependencies updated"
@# Step 2: Strip '-develop*' suffix from VERSION
@current_version=$$(cat VERSION); \
clean_version=$$(echo $$current_version | sed 's/-develop.*$$//'); \
echo "$$clean_version" > VERSION; \
echo "✓ VERSION updated to $$clean_version"
@# Step 3: Check Tauri Rust project builds
@echo "Running cargo check in desktop/tauri/src-tauri..."
@cd desktop/tauri/src-tauri && cargo check
@# Step 4: Prepare CHANGELOG skeleton and bump Full Changelog link
@new_version=$$(cat VERSION); \
major=$$(echo "$$new_version" | cut -d. -f1); \
minor=$$(echo "$$new_version" | cut -d. -f2); \
patch=$$(echo "$$new_version" | cut -d. -f3); \
prev_patch=$$((patch - 1)); \
prev_version="$$major.$$minor.$$prev_patch"; \
updated_deps=$$(git diff master..HEAD -- pyproject.toml | grep '^+' | grep '==' | sed 's/^+//' | sed 's/^ *//' | sed 's/,$$//' | sed 's/^/- /'); \
echo "# Requirements Updated" > CHANGELOG; \
if [ -n "$$updated_deps" ]; then \
echo "$$updated_deps" >> CHANGELOG; \
fi; \
echo "" >> CHANGELOG; \
echo "# New Features" >> CHANGELOG; \
echo "" >> CHANGELOG; \
echo "" >> CHANGELOG; \
echo "# Improvements" >> CHANGELOG; \
echo "" >> CHANGELOG; \
echo "" >> CHANGELOG; \
echo "# Bug Fixes" >> CHANGELOG; \
echo "" >> CHANGELOG; \
echo "" >> CHANGELOG; \
echo "**Full Changelog**: https://github.com/StuffAnThings/qbit_manage/compare/v$$prev_version...v$$new_version" >> CHANGELOG; \
echo "✓ CHANGELOG prepared for release $$new_version"
@echo ""
@echo "REMINDER: Update the CHANGELOG contents with actual improvements and bug fixes before making the release."
.PHONY: help
help:
@echo "Available targets:"
@echo " install - Install qbit-manage using uv tool (overwrites existing)"
@echo " uninstall - Uninstall qbit-manage from uv tools"
@echo " reinstall - Uninstall then install (clean reinstall)"
@echo " venv - Create virtual environment and install dependencies"
@echo " sync - Sync dependencies from pyproject.toml"
@echo " test - Run tests"
@echo " lint - Run linter with fixes"
@echo " format - Run code formatter"
@echo " pre-commit - Run pre-commit hooks"
@echo " build - Build package for distribution"
@echo " check-dist - Check distribution files"
@echo " setup-pypi - Set up PyPI configuration (~/.pypirc)"
@echo " bump-version - Bump patch version for testing uploads"
@echo " prep-release - Strip '-develop*' from VERSION, cargo check, and template CHANGELOG"
@echo " debug-upload - Debug PyPI upload configuration"
@echo " upload-test - Upload to Test PyPI (uses env vars or ~/.pypirc)"
@echo " upload-pypi - Upload to PyPI (LIVE) (uses env vars or ~/.pypirc)"
@echo " clean - Clean up all generated files (venv, dist, build, cache)"
@echo " help - Show this help message"