Skip to content

Conversation

@dryan
Copy link
Owner

@dryan dryan commented Nov 19, 2025

No description provided.

dryan added 30 commits November 18, 2025 12:21
- Added Phase 2.1 to remove Python 3.9 support
- Updated AGENTS.md with Python version policy per devguide.python.org
- Reorganized roadmap phases accordingly
Phase 1.1 is now complete - warning release has been tagged and pushed
Document that all release tags should be signed for security
Resolved merge conflict in AGENTS.md by keeping both signed tags and Python versions requirements
- Updated minimum Python requirement to 3.14 (latest feature release)
- Simplified CI/CD matrix to single Python version (3.14 for bundling)
- Updated classifiers to reflect bundled Python version only
- Completed Phase 2.1 of roadmap

This modernizes the codebase and simplifies testing since Briefcase
bundles Python into the standalone executable.
- Added Briefcase configuration to pyproject.toml with Textual dependency
- Created __main__.py entry point for console app execution
- Installed and verified Briefcase development mode works
- Updated dependencies to use Textual instead of colorama/tqdm
- Added *.dist-info/ to .gitignore for build artifacts
- Tested basic Briefcase functionality with d3ploy --version

Phase 2.2 mostly complete - basic Briefcase setup working
- Add config loading with support for d3ploy.json and .d3ploy.json
- Implement config validation and versioning (v1)
- Add environment variable support with D3PLOY_ prefix
- Create config migration logic for future upgrades
- Implement config merger with priority: CLI > Env > File > Defaults
- Add 'recommended' cache preset for best practices
- Create comprehensive test suite for config module
- Remove default catch-all (everything must be explicitly specified)
- Set text/html to 0 (no cache for entry points)
- Set CSS/JS/JSON to 1 year (assuming cache-busting)
- Set images and fonts to 1 year with wildcard patterns
- Set manifest to 1 day
- Add NO_CACHE, ONE_DAY, ONE_YEAR constants
- Improves readability and maintainability
- Document automated pre-commit checks with Lefthook
- Add Python linting guidelines with Ruff (never use noqa without approval)
- Add type checking guidelines with ty
- Document pytest testing practices
- Add pytest and ty conversion tasks to Phase 5 of roadmap
- Mark Phase 3 tasks as completed in roadmap
- Add note to not use MCP servers for this project
- Fix check-versions-match.py to handle refactored __init__.py
- Replace tqdm with Rich progress bars in ui/progress.py
- Replace colorama with Rich output in ui/output.py
- Implement confirmation dialogs using Rich prompts
- Create application wrapper in ui/app.py
- Update sync/operations.py to use new UI components
- Update core/cli.py, core/signals.py, core/updates.py to use Rich
- All UI components use Rich library (part of Textual ecosystem)
- Support quiet mode for CI/CD usage
- Mark Phase 4.1 complete in roadmap
- Create full Textual TUI application in ui/tui.py
- Add environment selection screen with interactive buttons
- Add sync progress screen that performs actual deployment
- Add settings and help screens with navigation
- Implement keyboard shortcuts (q=quit, h=help, s=settings)
- Auto-detect interactive terminal (hasattr sys.ps1 or isatty)
- Default to TUI when interactive, CLI fallback for non-interactive
- Add --no-tui flag to force CLI mode
- Require environment in non-interactive mode or error
- CLI mode uses Rich components for progress and output
- Both modes share sync business logic
- Test verified: TUI launches interactively, CLI works in pipes
- Mark Phase 4.2 and most of 4.3 complete in roadmap
BREAKING CHANGE: Configuration files must be updated

- Changed 'environments' to 'targets' in config JSON structure
- Updated TUI interface: EnvironmentSelectionScreen → TargetSelectionScreen
- Updated CLI arguments: 'environment' → 'target'
- Updated sync operations: sync_environment() → sync_target()
- Updated all error messages and help text
- Updated all variable names and function parameters
- Updated tests and test data
- Updated README.md and ROADMAP.md documentation

This is a breaking change that requires users to update their .d3ploy.json
config files to use 'targets' instead of 'environments' as the top-level key.

All code, tests, and documentation now use 'target' consistently.
IMPORTANT: Configs are never modified without explicit user permission

CLI Mode:
- Detects old config and exits with migration instructions
- Shows command to run: d3ploy --migrate-config <path>
- User must manually run migration command
- Migration shows what will change before applying

TUI Mode:
- Shows migration confirmation dialog
- Explains changes (environments→targets, version update)
- User can accept or decline
- If declined, app exits gracefully

New --migrate-config flag:
- Dedicated command for config migration
- Shows version change and modifications
- Only modifies file after showing what will change
- Saves with proper JSON formatting

Helper functions:
- needs_migration(): Check if config needs upgrading
- save_migrated_config(): Save migrated config to disk
- get_migration_command(): Generate migration command string

Tests updated to verify v0→v2 and v1→v2 migration paths work correctly.

This ensures users are always in control of config file modifications.
Created tests/fixtures/configs/ to maintain sample configs for each version:
- v0-config.json: Original format (no version field, uses 'environments')
- v1-config.json: Version 1 (has version field, uses 'environments')
- v2-config.json: Current version (uses 'targets')

Added comprehensive README in fixtures directory documenting:
- Purpose of each version
- What changed between versions
- Step-by-step process for adding new versions
- Usage examples for tests

Updated AGENTS.md with 'Configuration Version Management' section:
- Mandates creating fixture files when changing config structure
- Documents 5-step process for version changes
- Explains migration testing requirements
- Emphasizes user permission requirement (never auto-modify configs)

Added 3 new tests using fixtures:
- test_migrate_v0_fixture: Validates v0→v2 with realistic config
- test_migrate_v1_fixture: Validates v1→v2 preserves all fields
- test_v2_fixture_current: Ensures current version needs no migration

All 15 tests pass. This ensures config evolution is documented,
testable, and provides reference examples for users upgrading.
- Allow d3ploy to run without config file when bucket_name is provided via CLI args
- Create synthetic targets when no config exists
- Show 'Syncing to {bucket-name}' message for config-less operations
- Show 'Using settings for {target} target' when using config
- Disable TUI mode when no config file exists (TUI requires config for now)
- Add has_config check to TUI mode detection
- Pass using_config flag to sync_target to determine message type
- Update roadmap with future TUI config-less operation feature
- Implement proper exit codes in TUI mode
- Add _exit_code tracking to D3ployTUI
- Override exit() method to store return_code
- Return proper exit codes from run_tui()
- Use os.EX_CONFIG for config migration errors
- Use os.EX_NOINPUT for missing config file
- Update run_tui() to return app._exit_code
- Verify quiet mode suppresses all non-error output
- Verify CLI requires all parameters when no config
- Mark all phase 4.3 tasks as complete in roadmap
- Remove TODO placeholders in action_help() and action_settings()
- Push HelpScreen when 'h' key is pressed
- Push SettingsScreen when 's' key is pressed
- Pass config_data and config_path to SettingsScreen
- Mark completed tasks in roadmap:
  - Interactive target selection (verified working)
  - Configuration editing within TUI (basic viewer)
  - Help system and keyboard shortcuts screen
- Remove Textual dependency and full TUI implementation
- Add Rich for beautiful CLI output and interactive prompts
- Create new prompts module with keyboard-selectable menus
- Remove --no-tui flag (no longer needed)
- Update documentation to reflect Rich-based approach
- Disable legacy colorama-based tests
- Update dependency management guidelines in AGENTS.md

This simplifies the codebase while maintaining interactive
capabilities through Rich prompts and styled output.
- Replace argparse with Typer for modern CLI experience
- Add 'sync' subcommand for deployment operations
- Add 'migrate-config' subcommand for config migration
- Maintain backward compatibility (args without subcommand → sync)
- Improve help output with Rich formatting
- Add type safety with Annotated types
- Better validation and error messages
- Cleaner command structure and organization

Benefits:
- Automatic help generation with better formatting
- Type-safe argument handling
- Built-in validation (e.g., --processes range)
- Rich-styled output for errors and help
- More maintainable code structure
- Add typer dependency to all Briefcase platform configs
- Update rich version to match current dependency
- Verify all commands work in Briefcase dev mode

Tested:
- briefcase dev -- --help ✓
- briefcase dev -- --version ✓
- briefcase dev -- sync --help ✓
- briefcase dev -- migrate-config --help ✓
- Update distribution strategy: PyPI packages + Briefcase installers
- Expand Python support to all maintained versions (3.10-3.14)
- Update CI/CD matrix to test against all supported versions
- Add future distribution exploration: Debian packages and Homebrew
- Correct understanding: Briefcase creates installers, not embedded binaries
- Add config-less interactive operation with prompts for bucket setup
- Implement interactive target selection with keyboard navigation
- Add interactive ACL selection menu with descriptions
- Add confirmation prompts for destructive operations
- Prompt for missing configuration options in interactive mode
- Auto-save config file when user confirms
- Fall back to non-interactive mode in CI/CD environments
- All prompts respect quiet mode and terminal detection
- Replace text-based ACL selection with questionary arrow-key navigation
- Add questionary dependency for keyboard-selectable menus
- Update target selection to use arrow keys
- Display choices with helpful descriptions inline
- Maintains fallback to CLI args in non-interactive mode
- Ask user if they want existing or new bucket
- Fetch and display list of existing S3 buckets with arrow-key selection
- Option to manually enter bucket name if not in list
- For new buckets, note that d3ploy won't create it
- All bucket selection uses arrow-key navigation
- Gracefully handles case when bucket list fails
- Add tree-like config display with merged defaults
- Add LiveProgressDisplay for real-time sync tracking
- Add display_table, display_panel, display_json, display_config_tree functions
- Add new show-config command with --json option
- Enhance migrate-config to show before/after comparison
- Default values are dimmed in targets, normal in defaults section
- Update version to 4.4.4
- Rename init-config to create-config for clarity
- Add skip_no_config_message parameter to prompt_for_bucket_config
- Display clear status messages about config existence
- Only show preview when user chooses not to save
- Show plain JSON preview (no syntax highlighting) when not saving
- Update sync command to show checked paths and ask confirmation
- Save caches field to config when recommended cache settings chosen
All testing framework conversion tasks complete:
- 55 tests passing with function-based pytest style
- Exception-based killswitch for clean Ctrl+C handling
- 39.69% code coverage
- Zero skipped tests - all features implemented
- CI/CD already configured to use pytest
- pytest.ini_options configured in pyproject.toml
@dryan dryan marked this pull request as draft November 19, 2025 18:50
@dryan dryan self-assigned this Nov 19, 2025
dryan added 27 commits November 19, 2025 13:55
Phase 6.2: Type Checking Implementation
- Add ty (pyright CLI wrapper) to dev dependencies
- Add boto3-stubs for S3 and CloudFront type hints
- Configure [tool.ty] section in pyproject.toml
- Baseline: 30 type checking diagnostics to resolve
- Import proper S3ServiceResource type from mypy-boto3-s3
- Use TYPE_CHECKING guard for type-only imports
- Quote forward references properly
- Handle None case for boto3 credentials
- Resolves 8 type checking errors (30 → 22 remaining)
Phase 6.2 Complete:
- Fixed boto3 type hints with proper S3ServiceResource types
- Resolved Optional/None handling in sync_target parameters
- Fixed alert function to use keyword-only error_code parameter
- Added type assertions for guaranteed non-None values
- Fixed UI dialog return type with assertion
- Simplified progress.update() calls for type safety
- Fixed test fixtures with proper Generator type hints
- Added Union[str, Path] to upload_file for backward compatibility

Result: 0 type errors in d3ploy/ and tests/
(30 → 22 → 10 → 5 → 0 diagnostics)

Note: Remaining 5 warnings in bump-version.py and check-versions-match.py
will be replaced with justfile tasks later.
Added [tool.pyright] include setting to limit type checking scope
to main source and test directories, excluding utility scripts that
will be replaced with justfile tasks.
All tasks completed:
- ty installed and configured
- boto3-stubs added for AWS type hints
- All 30 type errors fixed → 0 diagnostics
- Integrated into lefthook and CI/CD
- Configured to check only d3ploy/ and tests/
Phase 6.3 Progress - Config and AWS Complete:

Config Module (100% coverage):
- test_config_loader.py: 12 tests for file loading, error handling
- test_config_validator.py: 24 tests for validation, caches expansion
- test_config_migration.py: 22 tests for v0→v2 migration paths
- test_config_env.py: 18 tests for environment variable handling
- test_config_merger.py: 17 tests for priority merging logic

AWS Module (98.9% coverage):
- test_cloudfront.py: 15 tests for distribution invalidation
- test_aws_s3_operations.py: 20 tests for bucket operations, key checks

Results:
- Added 120 new tests (55 → 175 total)
- Overall coverage: 22.4% → 43.6% (+21.2%)
- Fixed bug: save_migrated_config now creates parent dirs

Nearly halfway to 80% target
- test_sync_operations.py with 38 tests
- Coverage: sync/operations.py 18.6% → 97.5%
- Tests for get_progress_bar, alert, get_confirmation, killswitch
- Tests for upload_batch with threading and killswitch handling
- Tests for delete_orphans with confirmation and dry run
- Tests for sync_target with CloudFront, delete, and dry run
- Overall coverage: 43.6% → 49.9%
- test_utils_paths.py with 20 tests
- Coverage: utils/paths.py 12.3% → 100%
- Tests for all platform-specific paths (macOS, Windows, Linux)
- Tests for XDG environment variables and fallbacks
- Overall coverage: 49.9% → 53.8%
- Total tests: 213 → 233
- test_core_signals.py with 12 tests
- Coverage: core/signals.py 63.6% → 100%
- Tests for UserCancelled exception
- Tests for bail() signal handler with killswitch
- Tests for setup_signal_handlers() and shutdown_requested()
- Overall coverage: 53.8% → 54.1%
- Total tests: 233 → 245
- test_ui_output.py with 42 tests
- Coverage: ui/output.py 24.3% → 100%
- Tests for display_message, display_error, display_table
- Tests for display_panel, display_json, display_config
- Tests for display_config_tree with merged defaults
- Overall coverage: 54.1% → 59.8%
- Total tests: 245 → 287
- test_ui_app_dialogs.py with 15 tests
- Coverage: ui/app.py 60.0% → 100%
- Coverage: ui/dialogs.py 44.4% → 100%
- Tests for D3ployApp initialization and run_sync
- Tests for confirm_delete and show_dialog with Rich prompts
- Overall coverage: 59.8% → 60.4%
- Total tests: 287 → 302
- Fix test_sync_with_old_deploy_json hanging by adding timeout and proper mocking
- Fix test_sync_invalid_target to simulate sys.exit behavior correctly
- Fix 13 additional test failures:
  - Correct mock paths for ui functions (d3ploy.ui.* instead of d3ploy.core.cli_module.ui.*)
  - Fix TestCliEntryPoint to use cli_module instead of undefined cli
  - Fix mock side_effect signatures for pathlib.Path methods
  - Adjust assertions for multiple print calls and proper error checking
- CLI module coverage improved from 12.4% to 98.3%
- Overall project coverage increased from 28.2% to 79.5%
- All 356 tests now passing (54/54 CLI tests, up from 18/54)
- Add test for d3ploy.json config in interactive mode (line 299)
- Add test for .d3ploy.json config in interactive mode (line 301)
- Add test for migrate_config with environments key rename (line 530)
- Add test for create_config finding alternate dotfile (lines 637-638)
- Remove non-existent @pytest.mark.timeout decorator
- CLI module now at 100% coverage (234/234 statements)
- Total coverage improved to 39.8%
- Add test for wildcard cache patterns (text/*) to cover line 188
- Add pragma: no cover for TYPE_CHECKING import block
- aws/s3.py now at 100% coverage (87/87 statements)
- Safely access optional dict keys in boto3 responses
- Fix extra_args type annotation to include dict values
- Extract mimetype to local var to avoid repeated optional checks
- Use .get() with defaults for nested dict access
- All tests passing
- Add test for cloudfront_id=None with using_config=False
- Add test for CloudFront invalidation with dry_run
- Fix type error: handle None local_path before pathlib.Path()
- Add assert for type narrowing after alert check
- sync/operations.py now at 99.2% (121/121 statements, line 318 unreachable)
- Simplify local_path handling to only accept Path | None (not strings)
- Remove unnecessary string-to-Path conversion logic
- Fix test_sync_target_missing_bucket to provide local_path
- Update CLI to convert string paths to Path objects before calling sync_target
- All 118 statements now covered
- Update test assertions to expect pathlib.Path instead of strings
- Tests now correctly validate the Path conversion in CLI
- Add test for get_file_hash() function
- Verify MD5 hash calculation with known file
- All 72 statements now covered
- Overall coverage: 80.5%
- Add tests for NotImplementedError stubs
- Verify Phase 3.6 TODO functions raise appropriately
- All 6 statements now covered
- Overall coverage: 80.7%
- Delete sync/filters.py (functionality already in discovery.py)
- Delete utils/files.py (MD5 already in discovery.get_file_hash)
- Update __init__.py files to remove orphaned imports
- Removed 19 lines of dead code
- Overall coverage: 80.9% (improved by removing untested stubs)
- Replace NotImplementedError stubs with full implementation
- Add custom MIME types from Mozilla reference (webmanifest, woff2, avif, etc.)
- Implement register_custom_types() to register with Python mimetypes
- Implement get_content_type() with charset support
- Add comprehensive tests for all functionality
- utils/mimetypes.py: 100% coverage maintained
- Overall coverage: 81.0%
- Remove unnecessary try/except for packaging import (required dependency)
- Move packaging.version import to top level
- Add proper error handling for file operations (OSError, PermissionError)
- Fix exception handling to properly return None in non-debug mode
- Add tests for error cases and default path usage
- 27 tests passing, 100% coverage (89/89 statements)
- compat.py: Temporary colorama/tqdm compatibility layer no longer needed
- d3ploy.py: Legacy entry point replaced by __init__.py:cli
- Update check-versions-match.py to only check __init__.py
- Coverage increased from 82.2% to 85.9% (1280 → 1224 statements)
- All 382 tests passing
- Test module imports correctly
- Test execution via python -m d3ploy --help
- 100% coverage on __main__.py (3/3 statements)
- 2 tests passing
- Test ProgressDisplay class (11 tests)
- Test LiveProgressDisplay class (16 tests)
- Cover all methods: init, context managers, updates, file operations
- Test both enabled and disabled states
- Test max_recent file list truncation
- 100% coverage (92/92 statements)
- 27 tests passing
Final Statistics:
- 100.0% overall coverage (1224/1224 statements)
- 28 modules at 100% coverage
- 435 tests passing in 13.11 seconds

Recent Achievements:
- core/updates.py: 100% (27 tests)
- __main__.py: 100% (2 tests)
- ui/progress.py: 100% (27 tests)
- ui/prompts.py: 100% (24 tests)

Coverage Journey:
- Starting: 81.0% overall
- After updates.py: 82.2%
- After removing legacy files: 85.9%
- After __main__.py: 86.2%
- After ui/progress.py: ~92%
- Final: 100.0%

All linting and type checks passing
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.

2 participants