[3.x] New publish command#2500
Draft
emmadesilva wants to merge 18 commits into
Draft
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## v3-dev #2500 +/- ##
=============================================
- Coverage 100.00% 99.65% -0.35%
- Complexity 1608 1751 +143
=============================================
Files 168 175 +7
Lines 4039 4372 +333
=============================================
+ Hits 4039 4357 +318
- Misses 0 15 +15 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Introduces the shared, pure decision primitive for the new publish command: given a source and destination path, it returns copy (missing), skip (unchanged), or blocked (user-modified). Comparison is EOL-agnostic via unixsum so line-ending-only differences (e.g. CRLF checkouts) count as unchanged rather than modified. No console/view/page knowledge; no checksum manifest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Introduces the data model for starter pages used by the new publish command: an immutable PublishablePage value object (key, label, description, source, defaultTarget, alternativeTargets, allowCustomTarget) and the PublishablePages registry (all/get/register) seeded with the default catalog — welcome, posts, blank, and 404. Pages get a value object + registry (unlike the fixed view file-maps) because a page can have multiple valid destinations, carries display metadata, and the registry is an extension point for Hyde Cloud and plugins. Source paths are stored framework-relative for resolution via Hyde::vendorPath() at publish time; destination resolution and publishing land in a later step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Per review decision: `blank` is a general-purpose empty starter you drop anywhere rather than a third homepage variant, so it declares no default target. Makes PublishablePage::$defaultTarget nullable and sets blank's to null; destination resolution (Step 5) will always prompt interactively and require --to non-interactively. This also removes the welcome/blank collision on _pages/index.blade.php that the default catalog would otherwise create. Updates spec 5.1/5.2/5.4 to match so the acceptance sweep stays consistent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Introduces the flag-driven publish command shell that routes to the views and pages flows (both stubbed here, filled in by Steps 4-5). It owns the full flag surface (--layouts --components --all --page[=NAME] --to=PATH --force) and all guardrails: - Raw tag/provider/config publishing is redirected to vendor:publish. These are deliberately not declared as options (which would advertise them in --help, the exact raw-publishing surface this command exists to hide); instead run() intercepts the raw input before Symfony's strict bind. Only those three tokens are short-circuited, so a genuine typo like --layout still hits Symfony's native "unknown option" error rather than being swallowed. - --layouts and --components are mutually exclusive. - --to is only valid alongside --page. - Non-interactive with no actionable flag fails with a usage hint before any prompt is attempted; the interactive wizard (Views / A starter page / Cancel) routes to the stub handlers, with Cancel exiting cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Replace the publishViews() stub with a real ViewsPublisher (§4, §7): - Reads the two declared groups (layouts, components) via ViewPublishGroup; --layouts/--components prefilter the offered set, --all skips the picker, and a non-interactive scoped run behaves exactly like adding --all. - Adds a minimal shared InteractiveMultiselect helper: a grouped multi-select with an "All views" sentinel (selecting it means everything regardless of other checkbox state) and group-prefixed labels (layouts/app.blade.php). - Decides every file's outcome first (OverwritePolicy: copy/skip/blocked), resolves modified-file conflicts second (interactive Skip/Overwrite/Cancel or --force; non-interactive without --force is a hard §7 error), and writes last, so Cancel never leaves a half-published tree. - Cardinality-aware output that reports the real breakdown: "Published all N" prints only when the entire offered set was genuinely copied; mixed runs report copied / already-current / left-modified (with a --force hint). Re-points the four Step 3 views-routing tests off the removed stub string to assert real views behavior, adds a dedicated views-flow test suite, and notes the mixed-run reporting rule in §4 of the spec. Additional commits: - Make the publish multiselect "All" sentinel row optional Add a nullable $allLabel to InteractiveMultiselect::select() so callers can omit the "select all" row entirely. The views picker keeps its "All views" affordance; the pages picker (Step 5) passes no label, since "publish all starter pages at once" is never a sensible selection and would only trip destination resolution and conflict detection. This is a backward-compatible parameter on the shared helper, not a fork — both callers depend on the same picker. - Simplify publish multiselect all sentinel Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Replace the publishPage() stub with a real PagesPublisher backed by the PublishablePages registry (§5): - Selection: --page=NAME publishes one page directly; a bare --page or the wizard opens the interactive multi-select picker. - Destination resolution (§5.4): --to → non-interactive default → interactive prompt (default / alternative / custom path) → default. A page with no default (blank) fails helpfully non-interactively, pointing to --to. - --to validation: must resolve under _pages/ and end in .blade.php. - --to is only valid for a single named page; a bare --page (multi-select) with --to is rejected. Documented as a new line in spec §5.4. - Conflict detection (§5.6): two pages resolving to the same target fail before any write. - Interactive confirm (§5.5): select → resolve → "Ready to publish… Proceed?". - Overwrite policy (§7): reuses OverwritePolicy exactly as the views flow does (missing→copy, identical→skip, modified→confirm-or-force). - Optional rebuild (§5.7): offered interactively only, defaulting to NO. Implemented inline rather than via AsksToRebuildSite, which defaults to YES — a why-comment guards against a future consolidation reintroducing the yes-default. Registry lookups compare ->key (never array access) so the string '404' key survives PHP's numeric-key coercion. The Step 3 routing tests that asserted the old stub are updated to assert the real, non-destructive routing behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Destination resolution UX (§5.4): only prompt interactively when a page is genuinely ambiguous — it has alternative targets or no default. A page whose default is its one sensible destination (welcome, 404) publishes in a single frictionless step instead of asking "Where should this go?" for a near-certain answer. allowCustomTarget now governs only whether a "Custom path…" entry is offered and whether --to is accepted, not whether the prompt appears; custom placement of an otherwise-unambiguous page is reached via --to. Consequently --to is rejected for a page that disallows custom targets (404). Polish: - The overwrite-conflict "Cancel" choice now prints "Cancelled. No pages were published." instead of exiting silently, matching the views flow and the "Proceed? no" path. - The destination-conflict message uses "both target" for a pair and "all target" for three or more colliding pages. - Added tests: --to rejected for 404, the picker round-tripping the numeric '404' key (the coerced-int-key path the named lookup can't reach), and the pages picker omitting the "All" row that the views picker offers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Add a test proving the two --to rejections cannot disagree. Bare --page + --to is caught by the top-level "one path can't serve several pages" guard (message A) before selectPages() runs, so the per-page allowCustomTarget rejection (message B) can never pre-empt it. The test runs interactively — it would hang on an unanswered picker prompt if the picker were reached — and asserts message A wins and message B is absent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Add a single `hyde-config` publish group on ConfigurationServiceProvider that publishes exactly the six Hyde-owned config files (hyde, docs, markdown, view, cache, commands) and not torchlight.php, per spec §6. The legacy `configs` / `hyde-configs` / `support-configs` tags are left in place; the deprecated publish:configs command still relies on them until Step 7. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Per spec §8, publish:views, publish:configs, and publish:homepage become thin delegators that print a one-line deprecation notice and forward to the new surface: - publish:views [group] -> publish --layouts / --components (no group -> --all, keeping legacy non-interactive scripts non-interactive) - publish:configs -> vendor:publish --tag=hyde-config - publish:homepage [template] -> publish --page=[template], forwarding --force The old command classes stay registered and keep working through v3; target removal in v4. Their tests are rewritten to assert the notice and delegation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Rewrite the publishing docs around php hyde publish (views + --page) and php hyde vendor:publish --tag=hyde-config for config. Fix the nonexistent publish:components reference in advanced-markdown.md, and update remaining publish:views/publish:configs/publish:homepage references throughout the primary docs. The deprecated aliases now appear only in a migration note in the console commands reference (historical release notes left as-is). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Gemini <218195315+gemini-cli@users.noreply.github.com>
Co-Authored-By: Codex <codex@openai.com>
Fill the coverage gaps flagged on PagesPublisher and ViewsPublisher by
testing the feature paths they exercise, not lines for their own sake:
Pages (§5, §7):
- interactive overwrite-conflict prompt: overwrite / skip / cancel
(the §7 interactive flow was tested for views but not for pages)
- mixed run reporting published pages alongside already-current ones,
with pluralized cardinality
- three-or-more pages colliding on one target ("all target" wording)
- accepting the §5.7 rebuild offer actually runs the build
- --to path traversal (..) rejected
Views (§4):
- mixed run reporting copied views alongside already-current ones
The only lines left uncovered are unreachable defensive guards behind
`required` multi-selects (empty-selection is rejected by the prompt
before the guard) and joinLabels' <2 branch — not feature paths.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1b5066d to
6f48418
Compare
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.
No description provided.