feat(recipe): actionable recipe validation and review navigation gating - #342
Merged
Merged
Conversation
… and metadata fields - Centralize Python version check with float format and accepted range (3.8-3.14) - Add validation for container port (1-65535) and GitHub username format - Enforce valid Python identifier for package name and legal characters for project name - Wire metadata validator registry into decode_recipe - Render hints with error messages in TUI preview and propagate errors in headless mode
- Disable Continue button and guard ctrl+s when recipe draft has errors - Check draft validity synchronously on field change to update button state - Emit PlanUpdated message from PlanPreview to keep continue button in sync - Verify with TUI tests that ctrl+s and continue are blocked until issues resolved
… value Validation now rejects only values that are actually invalid: - Python versions: any 3.x[.y] is accepted. The 3.8-3.14 range blocked adopting a project with requires-python >=3.7 and would have broken every recipe and config recording 3.15. A malformed version and a non-3 major get separate hints. - GitHub usernames: legacy names ending in or repeating a hyphen, and Enterprise Managed User `_shortcode` names, are accepted. - Container ports: exactly digits, so '+8000' and ' 80 ' no longer pass and render verbatim into generated files. - Empty metadata is unset, not invalid, and clearing Minimum Python in the editor falls back to the default again. - Project names: the rule main enforced; a whitespace-only name is not newly rejected. The editor checks field values with the new check_draft, which renders nothing, instead of running resolve_init on the UI thread. Nits: validator typing, the dead key branch in validate_metadata, lazy imports in config.py, and PlanPreview's unused error attribute.
The constraints test asserted right after pilot.click, before the Checkbox.Changed handler had run, which failed on a slow Windows runner.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary & Motivation
Previously, entering invalid values in recipe fields (such as minimum Python version, container port, or GitHub username) produced generic or obscure errors like
Invalid [tool.protostar] project recipe. Users received no guidance on whether an input was fundamentally malformed or simply out of accepted bounds. Furthermore, when fatal validation issues were shown in the TUI live preview, users could still press^s(ctrl+s) or click Continue, navigating into an empty Review screen that failed to prepare.This pull request:
--jsonenvelopes.Planning & Key Decisions
decode_recipecan safely check recorded state on sync. An earlier revision range-checked Python to 3.8–3.14. That rejected adopting a project withrequires-python = ">=3.7"and would have broken every recipe recording 3.15, which ships next month. Minor versions are no longer range-checked.foo,3,3.x) getsWrite the Python version as major.minor, such as '3.13'., and a well-formed non-3 major (2.7,4.0) getsUnsupported Python version, which explains that Protostar scaffolds Python 3 projects.docker_port: exactly digits, or an integer, from 1 to 65535.+8000and80are rejected because they would be copied as written into generated files.github_username: rejects a leading@(the hint gives the corrected name). Otherwise it follows GitHub's own rules: at most 39 characters, starting with a letter or digit. Legacy names that end in or repeat a hyphen, and Enterprise Managed User_shortcodenames, stay valid.package_nameandproject_name: the rulesdecode_recipealready enforced, now with specific messages and hints.author_email,author_name,description) are deliberately left unvalidated.src/protostar/workspace.pyand the metadata validators insrc/protostar/metadata.py.MetadataField.validatorletsdecode_recipevalidate every metadata field present.UserConfigcheckspython_versionandgithub_usernamewhen the config loads.check_draft(init_draft.py) synchronously. It applies the same validators without rendering the template, so Continue is disabled at once without blocking the UI thread.PlanPreview.PlanUpdatedkeeps Continue's disabled state in sync with the background planner, so any plan error also blocks it.action_continuere-checks the draft so^scan't openReviewScreenwhile a field is invalid.Architectural Invariants
ReviewScreen, eliminating empty review states.ConfigurationError) containing user-facinghintfields.