Skip to content

v0.19.0 - Major Release: Runtime Modernization & Enhanced Operations#360

Draft
Xieyt wants to merge 400 commits into
mainfrom
develop
Draft

v0.19.0 - Major Release: Runtime Modernization & Enhanced Operations#360
Xieyt wants to merge 400 commits into
mainfrom
develop

Conversation

@Xieyt

@Xieyt Xieyt commented Feb 12, 2026

Copy link
Copy Markdown
Collaborator

This is a major release with significant improvements to CLI UX, SSL management, architecture refactoring, and Python/Node runtime modernization.

Breaking Changes

  • Migration Window: v0.19.0 only supports migrations from v0.18.0+. Users on older versions must upgrade to v0.18.0 first.
  • Runtime Change: Switched from pyenv/nvm to uv/fnm for Python and Node management
  • SSL Provider: Replaced certbot with acme.sh for SSL certificate management
  • Docker Images: Updated to v0.19.0 images with UV and FNM support

Changes

CLI/UX Improvements

  • InquirerPy Integration: Replaced Rich prompts with InquirerPy for better interactive experience
  • Interactive Bench Selection: Auto-detect and select bench when not specified
  • Progress Spinners: Added visual feedback for long-running operations
  • TTY Detection: Automatic fallback for non-TTY environments (CI/CD friendly)
  • Cleaner Output: Reduced verbosity with context-aware logging
  • Better Error Messages: Improved error handling and user-friendly messages

Architecture & Configuration

  • Alias Domains: Support for multiple domain aliases per bench
    • Primary domain + multiple aliases
    • Automatic SSL certificate handling for aliases
  • Upload Size Limits: Configurable upload size limits for bench sites (nginx)
  • Unique Database Names: Auto-generated unique database names to prevent conflicts
  • Docker Restart Policies: Configurable restart policies for containers
  • Removed oh-my-zsh: Switched to system-wide bash configuration for simpler setup
  • Private and Public App Cloning:
    • Clone multiple apps simultaneously for faster setup
    • Supports private repo
    • Monorepo support

SSL Management Overhaul

  • Standalone SSL Management: Complete SSL certificate lifecycle management independent of bench operations
  • CNAME Delegation Support: Issue certificates for external domains using CNAME validation
  • acme.sh Passthrough: Direct access to acme.sh advanced operations via fm ssl acme-sh
  • Force Renewal & Dry-run: Enhanced SSL renewal with --force and --dry-run options
  • Improved Validation: Better CNAME/DNS validation with clearer error messages
  • Removed Email Requirement: Let's Encrypt operations no longer require email (optional)

Unit test and Integration tests

  • Comprehensive SSL manager tests
  • Migration flow integration tests
  • Contextual logging tests
  • Output manager unit tests
  • Docker compose tests

🎯 CLI Changes

Check each command example by running fm <command> --help for more info

Removed Options

  • --frappe-branch → Use --apps frappe:version-15 instead
  • --ssl, --letsencrypt-email, --letsencrypt-preferred-challenge → Use fm ssl add after creation
  • fm ssl delete command → Use fm ssl remove instead

New Options

fm create
  • --apps, -a - Install apps (repeatable): --apps frappe:v16 --apps erpnext:v16
  • --environment, -e - Environment type: dev or prod
  • --python - Python version: --python 3.11
  • --node - Node version: --node 20
  • --restart - Docker restart policy
fm update
  • --upload-limit - Set max file upload size: --upload-limit 500M
  • --python / --node - Update runtime versions
  • --add-alias / --remove-alias - Manage domain aliases
fm shell
  • -c, --command - Execute command and exit: fm shell mybench -c "bench version"
  • --bench-console - Open Frappe IPython console
  • Supports heredoc/piped input and passthrough syntax
fm restart
  • --web, --workers, --redis, --nginx - Target specific services
  • --container - Restart entire container
  • --supervisor - Restart supervisor processes (faster)
  • --force - Force immediate restart
fm logs
  • --service - Filter by service: --service nginx
  • --follow, -f - Follow logs in real-time
fm delete
  • --yes, -y - Skip confirmation
  • --delete-db-from-global-db - Control database deletion
fm ssl (New Subcommands)
  • add - Issue certificates with --challenge, --dry-run, --cname, --standalone
  • renew - Renew certificates with --force, --dry-run, --all
  • remove - Remove certificates
  • list / info - View certificates
  • acme-sh - Direct acme.sh passthrough

Examples:

fm ssl add mybench.localhost
fm ssl add example.com --cname --standalone
fm ssl renew mybench.localhost --force
fm ssl acme-sh -- --list

Global Flags

  • --verbose, -v - Show detailed output (INFO level)
  • --log-level - Set log level: debug|info|warning|error
  • --non-interactive, -n - Disable prompts (CI/CD mode)
  • --version, -V - Show version

Output Control:

# Default: Quiet (warnings/errors only)
fm create mybench

# Verbose: Show operation details
fm create mybench --verbose

# Debug: Show everything
fm create mybench --log-level debug

Migration Guide

  • Now divided into two infra and each bench migration.
  • Infra migrations runs by invocation of any subcommand like fm migrate, fm start etc
  • Each bench migation is opt in, you will have to manually run fm migrate <benchname>

Upgrading from v0.18.0

# Backup your benches first
fm services backup-database

# Upgrade FM
uv tool upgrade frappe-manager
# or
pipx upgrade frappe-manager

# Migrate infra
fm migrate

# Migrate bench `mybench`
fm migrate mybench

Important Notes

  • Migration creates backups automatically
  • Runtime rebuild may take 5-10 minutes per bench
  • SSL certificates are preserved and migrated
  • Database data is not affected

Full Changelog

For detailed commit history, see: v0.18.0...v0.19.0

Xieyt added 30 commits February 3, 2026 12:49
- Add --non-interactive flag to app_callback()
- Set interactive mode on global output handler
- Store flag in ctx.obj for commands
- 16/16 CLI tests passing

Phase 2 of non-interactive mode implementation.
- update.py: add --yes flag for confirmation prompt
- ngrok.py: add --save-token/--no-save-token flag
- callbacks.py: error in non-interactive mode for bench selection
- exceptions.py: add NonInteractiveError with suggestions

All commands now use required_flag parameter for helpful errors.
Phase 3 of non-interactive mode implementation.
- Add required_flag to 3 migration prompts in app_callback
- Add required_flag to SSL certificate removal prompts
- Both bench and external SSL removal now show helpful errors

Completes Phase 3 of non-interactive mode implementation.
All prompts now provide flag suggestions in non-interactive mode.
The error() method requires an exception parameter to properly
handle and display errors. This was causing a TypeError when
update checks failed in non-interactive mode.
- Add is_interactive() checks to start(), change_head(), update_head(), stop()
- Spinners and status updates now only show in interactive mode
- Data output (print, error, warning) still appears in both modes
- Fixes issue where 'fm -n list' showed spinner animations
- Update tests to simulate interactive mode for spinner delegation tests

Non-interactive mode is for automation/CI - status indicators are
unnecessary and can interfere with output parsing.
BREAKING CHANGE: DisplayManager functionality moved to RichOutputHandler

Architecture:
- Inline all DisplayManager methods into RichOutputHandler (self-contained)
- RichOutputHandler now owns stdout, stderr, spinner, live (no delegation)
- Fix interactive mode to check both --non-interactive flag AND TTY
- Update logger to get console/live from global output handler
- Remove DisplayManager as separate class (now thin proxy for compatibility)
- Remove deprecation warnings (user requested)
- Fix recursion bug in richprint proxy (_richprint_instance)

Benefits:
- Single source of truth for Rich rendering
- Proper non-interactive mode handling (spinners suppressed correctly)
- No more singleton state issues
- Each RichOutputHandler instance is independent
- Eliminated import cycle risks

Implementation:
- frappe_manager/output_manager/rich_output.py (567 lines)
  * Inlined start(), stop(), print(), error(), warning(), change_head(), update_head()
  * Direct ownership of stdout, stderr, spinner, live (Rich components)
  * Thread safety via _lock (threading.RLock)
  * _is_interactive property checks both flag and TTY
- frappe_manager/logger/log.py
  * LiveAwareRichHandler gets console/live from global output handler
  * Changed from richprint.stderr to output.stderr
- frappe_manager/display_manager/DisplayManager.py (62 lines)
  * Thin proxy to global handler (backward compatibility)
  * Fixed richprint recursion with _richprint_instance
  * No deprecation warnings

Tests:
- Rewrite test_rich_output.py (25 tests, all passing)
  * Tests direct implementation instead of delegation
  * Tests _is_interactive behavior (flag + TTY)
  * Tests thread safety (_lock attribute)
- Update test_stream_separation.py (11 tests, all passing)
  * Uses RichOutputHandler directly (not DisplayManager)
  * Changed _richprint.stdout to stdout
- Delete test_deprecation_warnings.py (no longer needed)

Results:
- All 228 tests passing (142 output_manager + 86 logger)
- Non-interactive mode works correctly (spinners suppressed)
- Backward compatibility maintained (richprint import works)
- No import cycles, clean architecture
BREAKING CHANGE: DisplayManager and richprint imports no longer available

All DisplayManager functionality has been fully inlined into RichOutputHandler.
The backward compatibility proxy has been removed.

Changes:
- Delete frappe_manager/display_manager/ directory completely
- Update tests to use get_global_output_handler() instead of richprint
- Remove mock_richprint fixtures (no longer needed)
- Remove richprint patches from integration tests

Migration:
OLD: from frappe_manager.display_manager.DisplayManager import richprint
NEW: from frappe_manager.output_manager import get_global_output_handler

Files changed:
- frappe_manager/display_manager/DisplayManager.py (DELETED)
- tests/unit/logger/test_live_aware_handler.py (use get_global_output_handler)
- tests/unit/output_manager/conftest.py (remove mock_richprint fixture)
- tests/integration/test_migration_flow.py (remove richprint patches)
- tests/unit/ssl_manager/conftest.py (remove mock_richprint fixture)

Tests:
- All 228 tests passing (142 output_manager + 86 logger)
- No references to DisplayManager or richprint remain in codebase

Note: Docker/frappe/fmx/ has its own DisplayManager (separate package, not affected)
LoggingOutputHandler wraps RichOutputHandler but didn't forward the
set_interactive_mode() call to its delegate, causing --non-interactive
flag to be ignored.

The wrapper's _interactive was set correctly, but RichOutputHandler
(which renders spinners) still had _interactive=None, falling back to
TTY detection and showing spinners in non-interactive mode.

Fix: Override set_interactive_mode() to forward to delegate after
setting wrapper's state. Now both wrapper and delegate respect the
--non-interactive flag.

Changes:
- Add set_interactive_mode() override in LoggingOutputHandler
- Add 3 regression tests for interactive mode forwarding
- All 145 output_manager tests pass
…n caching + emoji constants)

- Add console_singleton.py for shared Rich Console instances
- Reuse Console objects across RichOutputHandler instances (~30-50% faster init)
- Cache deprecation warning flag at module load (~10-15% faster start/stop)
- Add emoji constants (EMOJI_WORKING, etc.) for consistency
- Remove unused Style/Theme objects

Performance improvements:
- Handler initialization: ~30-50% faster (measured: 0.003ms per handler)
- start()/stop() methods: ~10-15% faster (deprecation flag cached)
- Memory: ~2-4MB saved per handler instance
- Code quality: Centralized emojis prevent magic strings

Note: Regex optimization tested but reverted - Python's optimized string
operations are faster than regex for simple substring matching.

All 145 output_manager tests pass.
- Reuse Table object in live_lines() instead of recreating per iteration
- Use table.rows.clear() to reset between iterations
- Reduces object allocation in log streaming hot path

Performance improvements:
- Log streaming: ~40-60% faster for long-running operations
- Reduced GC pressure during live output display
- Memory: Eliminates N table allocations for N log lines

Impact: For 1000 log lines, saves 1000 Table object allocations.
Particularly beneficial for long-running operations like bench builds.

All 145 output_manager tests pass.
…timization)

- Update prompt_ask() signature: list → Sequence[str] for better type safety
- Import Sequence from collections.abc for proper type annotations
- Optimize print() method: avoid double f-string creation when no prefix
- Improve code clarity: check prefix first, build string once

Code quality improvements:
- Better type safety: Sequence accepts list, tuple, and other sequences
- Micro-optimization: Single f-string creation instead of two
- Cleaner logic flow: prefix check determines which string to build

Note: Lock granularity reviewed but deemed optimal as-is. The lock
protects critical spinner state changes and Rich Live operations.
Moving deprecation warnings outside lock would introduce race risks
for minimal benefit.

All 145 output_manager tests pass.
- error() requires exception parameter and raises it
- display_error() shows error without raising exception
- Fixed 9 files with incorrect usage:
  - commands: migrate, __init__, create, ngrok, self/compose, ssl/dns_config/cloudflare
  - utils: docker, site
  - main: exception handler already used display_error correctly

Issue: Commands calling output.error(text) without exception parameter
were failing with 'missing 1 required positional argument: exception'

Solution: Use display_error() for error display without exception raising
Issue: bench.info() crashed with KeyError when site_config.json doesn't exist
Root cause: get_bench_db_connection_info() only populates 'name' key if
site_config.json exists, but display_info() always accessed bench_db_info['name']

When bench creation fails early, site hasn't been created yet, so
site_config.json doesn't exist. The subsequent bench.info() call in error
handler would crash with 'name' KeyError.

Solution: Use .get() with default 'N/A' for name and password keys
This allows bench info to display even for incomplete benches
The Phase 2 optimization (ac5df5b0) reused a single Table object by clearing
rows between updates. This caused a race condition where Rich's rendering
engine would access the rows list while it was being cleared, resulting in:
  IndexError: list index out of range

Root cause: table.rows.clear() modifies internal state while Rich Live
display is rendering asynchronously.

Fix: Revert to creating fresh Table objects for each update. This sacrifices
~33% performance gain but ensures stability during high-volume streaming
output (e.g., UV dependency installation).

Verified:
- All 145 output_manager tests pass
- UV installation completes successfully without IndexError
- live_lines() streams Docker output correctly

Trade-off: Performance vs stability - choosing stability for production use.
…er context managers

- Add prompt_fuzzy() method to OutputHandler interface for fuzzy selection prompts
- Implement in all 4 OutputHandler subclasses (Rich, JSON, Silent, Logging)
- Fix sitename_callback() and prompt_for_bench_selection() to use OutputHandler
- Remove double-stop anti-pattern in migration prompts (lines 318, 418)
- Add 10 comprehensive tests for prompt_fuzzy() across all handlers

Fixes: fm -n delete now properly errors with helpful message instead of showing interactive prompt
Fixes: Migration prompts properly resume spinners after user interaction

Tests: 155 passing in output_manager suite
Add missing required_flag parameters to 6 remaining prompts that were
silently using default values instead of showing clear error messages
in non-interactive mode.

Changes:
- site.py:759 - Add --force for bench removal confirmation
- site.py:820 - Add --delete-db-from-global-db flags for DB deletion
- site.py:915 - Add --admin-pass for reset password prompt
- migration_base.py:248 - Add --skip-all-backup flags for backup skip
- migration_executor.py:212 - Add --force for migration proceed prompt
- migration_error_handler.py:134 - Add --force for archive prompt
- bench_service.py:389 - Already has required_flag (verified)

All flag names verified against actual CLI command definitions in:
- commands/delete.py (--force, --delete-db-from-global-db)
- commands/reset.py (--admin-pass)
- commands/migrate.py (--force, --skip-all-backup, --skip-backup-for)

Tests: All 155 output_manager tests passing
Fix critical flag name mismatch in SSL certificate removal prompts.

Issue:
- CLI command uses --force/-f flag for confirmation skip
- required_flag parameter incorrectly referenced --yes/-y
- Users saw wrong flag suggestion in non-interactive mode errors

Changes:
- bench_helpers.py:108 - Change required_flag from '--yes or -y' to '--force or -f'
- external_helpers.py:287 - Change required_flag from '--yes or -y' to '--force or -f'

Impact:
Before: fm -n ssl remove mybench example.com
  Error: Provide: --yes or -y (flag doesn't exist!)

After: fm -n ssl remove mybench example.com
  Error: Provide: --force or -f (correct flag)

Verified against: commands/ssl/remove.py line 24 (actual flag definition)
Tests: All 155 output_manager tests passing
Standardize all confirmation skip flags to use --yes/-y instead of --force/-f
for semantic clarity and consistency.

Semantic distinction:
- --yes/-y = Skip confirmation prompts (answer yes to all)
- --force/-f = Force actions beyond normal behavior (different purpose)

BREAKING CHANGES:
- fm delete: --force → --yes
- fm migrate: --force → --yes
- fm ssl remove: --force → --yes

Updated files:
- commands: delete.py, migrate.py, ssl/remove.py
- helpers: ssl/bench_helpers.py, ssl/external_helpers.py
- services: bench_service.py, site.py
- migration: migration_executor.py, migration_error_handler.py

Migration guide for users:
- fm delete mybench --force → fm delete mybench --yes
- fm migrate --force → fm migrate --yes
- fm ssl remove domain --force → fm ssl remove domain --yes

Unchanged (--force has different purpose):
- fm start --force (recreates containers)
- fm ssl renew --force (forces renewal when not due)

fix: update auto-migration MigrationExecutor calls to use yes parameter

Update internal auto-migration flows in app_callback() to use the new
'yes' parameter instead of 'force' (renamed in previous commit).
Update test assertions and method calls to use the new 'yes' parameter:
- test_migration_executor_options.py: Update all force assertions to yes
- test_migration_executor.py: Remove obsolete _ensure_global_services_running patches
- Update print message check from --force to --yes

Note: 2 pre-existing test failures remain in test_migration_executor.py
(unrelated to this change - these tests need refactoring)
Replace single --yes flag with two explicit flags:
- --auto-proceed (skip confirmation prompt)
- --on-failure {prompt|archive|rollback} (failure strategy)

This allows users to express:
- 'Auto-proceed but let me decide on failure' (--auto-proceed only)
- 'Fully automated safe mode' (--auto-proceed --on-failure=rollback)
- 'Partial success acceptable' (--auto-proceed --on-failure=archive)

Changes:
- commands/migrate.py: Add new CLI parameters (removed old --yes flag)
- migration_manager/migration_executor.py: Replace yes with auto_proceed/on_failure
- migration_manager/migration_error_handler.py: Handle on_failure strategy
- commands/__init__.py: Update auto-migration calls
- tests/: Update tests, add new test cases, remove obsolete test file

Test results: 47/47 passing in tests/unit/migration_manager/
Corrected flag names to match current implementation:

- delete: --force → --yes
- code: -d/-e/-f/-w → --debugger/--extension/--force-start/--work-dir
- migrate: removed obsolete --system/--force flags, added --auto-proceed/--on-failure
- ssl remove: --force → --yes

These changes ensure CLI help examples match the actual command parameters.
Docstrings now explain what commands do, not how to use them.
Examples are maintained in examples.json which is loaded dynamically
by the CLI help system.

Changed files:
- commands/delete.py: Explain deletion behavior and flags
- commands/start.py: Describe starting and reconfiguration options
- commands/migrate.py: Clarify migration levels and new flags
- commands/list.py: Describe bench listing output
- commands/__init__.py: Simplify internal helper documentation
Typer doesn't support Literal types directly. Created MigrationFailureAction
enum to properly represent the three failure handling strategies: prompt,
archive, and rollback.

This fixes the CLI startup error and properly displays enum choices in help text.
- Added COMMANDS_WITHOUT_BENCHNAME list ['list', 'services']
- Refactored benchname injection logic to:
  * Skip benchname for excluded commands (list, services)
  * Support explicit benchname override via JSON
  * Use default 'mybench' when no override present
- Fixed bug: desc.format() now uses element_example_data not example_data

Before: 'fm list mybench', 'fm delete' (wrong)
After: 'fm list', 'fm delete mybench' (correct)
Archive feature is only useful for bulk migrations when some benches
fail but you want to keep successful ones. For single bench migrations,
archiving adds confusion - the bench just gets rolled back and user
can retry.

Changes:
- Single bench migration failures now skip archive prompt entirely
- Always rollback single bench (no yes/no prompt)
- Show helpful message: "You can retry migration with: fm migrate <bench>"
- Bulk migrations keep existing archive/rollback prompt
- Handle --on-failure=archive for single bench: warn and rollback instead

Behavior:
- fm migrate mybench (fails) → Auto rollback, no prompt
- fm migrate --all-benches (some fail) → Prompt: archive or rollback?
- fm migrate mybench --on-failure=archive → Warning + rollback

This makes single-bench UX simple (just retry) while keeping bulk
migration UX powerful (choose what to do with partial failures).
- Single-bench migrations now prompt: 'Do you want to rollback?'
- User can choose yes (rollback) or no (leave bench in current state)
- Archive option not available for single bench (only bulk migrations)
- Pip install downgrade message hidden for single-bench rollbacks
- Bulk migrations unchanged: archive vs rollback prompt with pip message

Fixes the confusing behavior where single-bench showed archive option
and always displayed pip install command.
Two-layer defense against bash redirect interpretation bug:

Layer 1: Parse version requirements (migrate_0_19_0.py only)
- Import parse_python_version_for_runtime/parse_node_version_for_runtime
- Convert '>=3.14,<3.15' -> '3.14' before use
- bench_app.py already did this correctly

Layer 2: Quote bash tokens (both files, defense in depth)
- Use shlex.quote() on all uv command arguments
- Prevents shell metacharacters (<, >, ^, etc) from being interpreted
- Generated commands safe: uv python install 'cpython-3.14'

Fixes migration error:
  bash: line 10: 3.15: No such file or directory
  bash: line 13: 3.15*: No such file or directory

Before: uv python install cpython->=3.14,<3.15  (bash treats <3.15 as redirect)
After:  uv python install 'cpython-3.14'         (parsed + quoted = safe)

Files changed:
- frappe_manager/migration_manager/migrations/migrate_0_19_0.py
  - Parse raw version from config before use
  - Quote package names in uv python install
  - Quote glob patterns in ls commands
- frappe_manager/site_manager/modules/bench_app.py
  - Quote package names in uv python install (defense in depth)
  - Quote directory names in uv venv --python
- Add auto-streaming mode that returns SubprocessOutput while displaying live output
- Use itertools.tee() to split iterator for display and capture
- Add use_original_implementation parameter to docker_command decorator
- Convert methods to use decorator: down, start, restart, stop, exec, ps, logs, run, cp
- Change stream parameter default from False to None for auto-detection
- Update migrate command to use spinner context manager and print_data
- Pass output handler to MigrationBench for docker operation streaming

This enables live docker output display in migrations while preserving the output for verification.
Xieyt and others added 29 commits April 15, 2026 11:17
Update documentation links and site logo to new domain
- Introduce `--newrelic` and `--newrelic-license-key` options to `create` and `update` commands
- Store NewRelic configuration in `BenchConfig` and pass environment variables to the web container
- Implement `fm-web-server.sh` wrapper script to conditionally configure and run Gunicorn with NewRelic agent
- Update supervisor configuration to execute the new Gunicorn wrapper script for the web process

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Remove explicit `_create_venv` method from `BenchApp`
- Update `_install_python_deps_with_uv` to use `uv pip install -e` for individual apps
- Add `recreate_python_env=True` flag to environment setup call

Signed-off-by: aloksingh <alokmilenium@gmail.com>
Add NewRelic APM integration and refactor Python dependency installation
- Add `is_service_profile_disabled` method to `ComposeFile` to check service profiles
- Enhance `get_services_list` to optionally exclude services with 'disabled' profile
- Update service startup and wait logic to respect disabled service profiles

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Introduce `db_info` variable for database server information
- Modify `candidates` list to explicitly pass the relevant compose file manager instance for each service
- Update the service loop to unpack the compose file manager and use it for profile disabling checks

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Add `exclude_disabled` argument to `get_services` to filter out services with the 'disabled' profile.
- Enhance `is_service_profile_disabled` to correctly parse string profiles and handle non-dict service definitions.
- Introduce optional `compose_file_manager` in `BenchSiteManager` for skipping health checks on disabled services.

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Introduce `TestServiceProfileDisabled` to verify profile handling
- Add tests for `is_service_profile_disabled` with various profile configurations (string, list, mixed)
- Add tests for `get_services_list` to ensure correct filtering of disabled services

Signed-off-by: aloksingh <alokmilenium@gmail.com>
…/checkout-6

build(deps): bump actions/checkout from 4 to 6
…/setup-python-6

build(deps): bump actions/setup-python from 5 to 6
…ps/action-gh-release-3

build(deps): bump softprops/action-gh-release from 2 to 3
…sh/setup-uv-7

build(deps): bump astral-sh/setup-uv from 5 to 7
Enhance service profile handling and availability checks
- Update main documentation link to point to the `/dev/` path
- Modify all command-specific documentation links to include `/dev/`
- Adjust general documentation site link to reflect the `/dev/` path
- Export `UV_PYTHON_INSTALL_DIR` environment variable
- Specify `/workspace/frappe-bench/.uv/python` as the installation directory
- Ensure `uv python install` installs Python to the designated path

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Update the version string for `MigrationV0190` class
- Change version from `0.19.0` to `0.19.0.dev0`

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Upgrade multiple Python package dependencies in `uv.lock`.
- Revamp installation instructions in `README.md` and docs for clarity.
- Adjust local development setup by removing `--frozen` from `uv sync`.
- Configure `zensical.toml` for improved documentation version management.

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Adjust Gunicorn worker calculation to factor in both CPU cores and available RAM for better resource allocation.
- Introduce `gthread` worker class with configurable threads per worker, defaulting to `max(2, min(cpus, 4))`.
- Automate the generation and patching of `newrelic.ini` with production-tuned settings for improved observability.
- Implement Gunicorn `post_fork` hook to ensure New Relic agent properly registers in each worker process.

Signed-off-by: aloksingh <alokmilenium@gmail.com>
…ll script

Signed-off-by: aloksingh <alokmilenium@gmail.com>
Extracts NewRelic-specific supervisor config generation into a focused method,
replacing the call to the broader setup_supervisor in the update flow.

Signed-off-by: aloksingh <alokmilenium@gmail.com>
Enable --drain-workers by default to prevent job interruption during restart.
Workers now gracefully finish in-progress jobs before service restart.
Use --no-drain-workers flag to force immediate restart when needed.

Signed-off-by: aloksingh <alokmilenium@gmail.com>
Update default timeout values from 300s to 0 (infinite) for migration
and worker drain operations. This prevents premature aborts during
long-running migrations or worker jobs in production environments.

- Change migrate_timeout default from 300s to 0 (infinite)
- Change drain_workers_timeout default from 300s to 0 (infinite)
- Update help text to clarify that 0 means wait indefinitely
- Add conditional timeout checks to only enforce when > 0
- Update documentation examples to reflect new safer defaults
- Implement `tag` method to tag a source image with a new target name
- Implement `rmi` method to remove one or more Docker images by name or ID
- Support streaming output and parameter conversion for both commands

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Add `DeserializationError` handling when fetching `job.func_name` for RQ workers
- Attempt to extract the function name from raw job data using `pickle` if deserialization fails
- Prevent crashes when `rq` job data refers to modules or functions that no longer exist
- Display `[unresolvable]` for jobs whose modules or functions cannot be loaded

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Use `uv sync --frozen` in `.envrc` for stricter local dependency installation that matches the lock file exactly.
- Add a guard in the web server script to exit with an error if New Relic is enabled but its configuration file is missing, preventing startup failures.
- Refactor the `restart` command's `--drain-workers` option to use the modern `--[no-]drain-workers` syntax for Typer boolean flags.
- Refresh the `uv.lock` file, updating package metadata and the lock file revision number.

Signed-off-by: aloksingh <alokmilenium@gmail.com>
- Replace complex `pickle` introspection with direct job attributes
- Use `job.description` or `job.id` as a robust fallback for job identification
- Improve error handling when a job's module can no longer be deserialized

Signed-off-by: aloksingh <alokmilenium@gmail.com>
Update documentation, enhance Gunicorn, and refactor New Relic setup
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.47 to 3.1.49.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](gitpython-developers/GitPython@3.1.47...3.1.49)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-version: 3.1.47
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump gitpython from 3.1.47 to 3.1.49
@Xieyt Xieyt changed the title bump v0.19.0 v0.19.0 - Major Release: Runtime Modernization & Enhanced Operations May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants