feat(publish): one Publish for all pending changes #161

Merged
dominik.polakovics merged 1 commit from afk/156 into main 2026-10-07 10:25:14 +02:00

Closes #156

What changes

  • One Publish. The per-page Publish is gone from the page module's toolbar (no primary button there any more, and nothing replaces it) and from the entry editor. The header's button reads Publish ("Publishing…" while busy), standalone and inside a host's bar, and publishes every pending change under content/ and assets/media/ via POST /api/publish-all. The chip, error strip with Retry, build-failed dialog and host-nav refresh are kept.
  • POST /api/page/publish removed. It now answers 404 like any unknown path. handlePagePublish, its route, its mutation-lock entry and publishPathsFor are deleted. gitrepo.PublishPaths and StatusForPaths stay as tested package API.
  • Link check, opt-in. /api/publish-all accepts checkDraftLinks: true. The check runs after the empty check and before the pre-flight.
    • It scans every carried page (.md under content/, added or modified vs main) that is not itself disabled, for links to disabled (front-matter draft) pages.
    • Scanning and matching are unchanged: markdown destinations, <a href> and link-typed params, matched by content path and pretty URL.
    • Hits answer 200 {"warning":{"disabledLinks":[{page,title,linkedFrom:[{page,title}]}]}} and commit nothing.
    • Never-published pages are no longer targets.
    • A {lang}-only request (deckle-hosted's e2e) behaves exactly as before and never warns.
  • Editor dialog. "Linked pages are disabled" lists each disabled page with the pages linking to it. Cancel publishes nothing; Publish anyway posts again without the check. Retry repeats the request that failed, so it doesn't ask again after Publish anyway.
  • Docs. README ("Git backbone", host navigation, entry editor toolbar) and scaffold/site/AGENTS.md now describe one Publish. They say it ships every editor's pending changes, and that Disable and Discard… are the only ways to hold a change back.

Verification

  • make test: web 68 files / 1860 tests passed; go test ./... all ok; tsc --noEmit clean.
  • With Hugo v0.151.0 on PATH, every publish, pre-flight, media and branch-mode server test passes, including the real-Hugo ones that skip without Hugo.
  • New Go tests:
    • /api/page/publish answers 404.
    • A {lang}-only request publishes despite a link to a disabled page.
    • With the check, the warning names the disabled page and its linking pages, and neither main nor origin moves.
    • With the check, no warning for a carried never-published target or for a disabled linking page.
    • With the check and nothing pending, the answer is empty.
  • Per-page coverage that still applies is ported to publish-all: pre-flight failure, feedback polling/static, degraded git, missing library file, branch mode.
  • New web tests:
    • Header label, standalone and in the host bar.
    • checkDraftLinks:true in the request body.
    • Dialog contents; Cancel sends no POST; Publish anyway sends checkDraftLinks:false.
    • Retry after a 502 that followed Publish anyway does not show the dialog again.
    • No Publish and no primary button in the page module's or entry editor's toolbar.
  • Checked deckle-hosted (snapshot c94bc74): it calls only /api/publish-all with {"lang":"en"}.

🤖 Generated with Claude Code

Closes #156 ## What changes - **One Publish.** The per-page Publish is gone from the page module's toolbar (no primary button there any more, and nothing replaces it) and from the entry editor. The header's button reads **Publish** ("Publishing…" while busy), standalone and inside a host's bar, and publishes every pending change under `content/` and `assets/media/` via `POST /api/publish-all`. The chip, error strip with Retry, build-failed dialog and host-nav refresh are kept. - **`POST /api/page/publish` removed.** It now answers 404 like any unknown path. `handlePagePublish`, its route, its mutation-lock entry and `publishPathsFor` are deleted. `gitrepo.PublishPaths` and `StatusForPaths` stay as tested package API. - **Link check, opt-in.** `/api/publish-all` accepts `checkDraftLinks: true`. The check runs after the empty check and before the pre-flight. - It scans every carried page (`.md` under `content/`, added or modified vs `main`) that is not itself disabled, for links to **disabled** (front-matter `draft`) pages. - Scanning and matching are unchanged: markdown destinations, `<a href>` and link-typed params, matched by content path and pretty URL. - Hits answer 200 `{"warning":{"disabledLinks":[{page,title,linkedFrom:[{page,title}]}]}}` and commit nothing. - Never-published pages are no longer targets. - A `{lang}`-only request (deckle-hosted's e2e) behaves exactly as before and never warns. - **Editor dialog.** "Linked pages are disabled" lists each disabled page with the pages linking to it. Cancel publishes nothing; **Publish anyway** posts again without the check. Retry repeats the request that failed, so it doesn't ask again after Publish anyway. - **Docs.** README ("Git backbone", host navigation, entry editor toolbar) and `scaffold/site/AGENTS.md` now describe one Publish. They say it ships every editor's pending changes, and that Disable and Discard… are the only ways to hold a change back. ## Verification - `make test`: web 68 files / 1860 tests passed; `go test ./...` all ok; `tsc --noEmit` clean. - With Hugo v0.151.0 on PATH, every publish, pre-flight, media and branch-mode server test passes, including the real-Hugo ones that skip without Hugo. - New Go tests: - `/api/page/publish` answers 404. - A `{lang}`-only request publishes despite a link to a disabled page. - With the check, the warning names the disabled page and its linking pages, and neither main nor origin moves. - With the check, no warning for a carried never-published target or for a disabled linking page. - With the check and nothing pending, the answer is empty. - Per-page coverage that still applies is ported to publish-all: pre-flight failure, feedback polling/static, degraded git, missing library file, branch mode. - New web tests: - Header label, standalone and in the host bar. - `checkDraftLinks:true` in the request body. - Dialog contents; Cancel sends no POST; Publish anyway sends `checkDraftLinks:false`. - Retry after a 502 that followed Publish anyway does not show the dialog again. - No Publish and no primary button in the page module's or entry editor's toolbar. - Checked deckle-hosted (snapshot `c94bc74`): it calls only `/api/publish-all` with `{"lang":"en"}`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(publish): one Publish for all pending changes
All checks were successful
ci / build-and-test (pull_request) Successful in 9m9s
20cdadccae
Remove the per-page Publish (page module and entry editor toolbars) and
POST /api/page/publish, which now answers 404. The header's button, renamed
"Publish", publishes every pending change under content/ and assets/media/
through /api/publish-all, standalone and inside a host's bar.

The draft-link check moves to publish-all, opt-in through the new
checkDraftLinks request field and narrowed to links to disabled pages
(front-matter draft) from every carried page that is not itself disabled.
A warning answers {"warning":{"disabledLinks":[{page,title,linkedFrom}]}}
and publishes nothing; the editor shows a dialog naming each disabled page
and the pages linking to it, with Cancel and Publish anyway. Retry repeats
the request that failed. A {lang}-only request (deckle-hosted) behaves as
before and never warns.

Per-page publish tests still covering live behavior are ported to
publish-all. README and scaffold/site/AGENTS.md describe the one Publish.

Closes #156

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Owner

[autoland] verdict: pass

This was generated by AI while landing a PR.

PASS — validated against #156.

Signal relied on: Forgejo Actions ci / build-and-test green on head 20cdadc (web build+test, go vet, go test ./... with Hugo 0.163.3 installed, so the real-Hugo publish/pre-flight tests ran). Not re-run. Head already contains main; no conflict.

Checked:

  • Conventions: Conventional Commits title; Closes #156 present (AFK branch afk/156).
  • Server: /api/page/publish route, handler, mutation-lock entry and publishPathsFor removed; /api/publish-all gains opt-in checkDraftLinks, run after the empty check and before the pre-flight. A {lang}-only request is unchanged and never warns (deckle-hosted contract). The check scans added/modified .md under the content root, skips disabled sources, targets only front-matter drafts; node paths are page-file paths, so titles/skip lookups resolve. Remaining helpers all still have callers; PublishPaths/StatusForPaths kept as tested package API, as the issue allows.
  • Web: per-page Publish, its chip/error strip/dialogs and store state removed from the page module and entry editor (no primary button left); header button reads Publish/Publishing…; DisabledLinksDialog lists each disabled page with its linking pages; Publish anyway posts checkDraftLinks:false; Retry repeats the last request's flag; success still refetches badges.
  • Tests cover every acceptance criterion: 404 on the removed endpoint, {lang}-only publishes despite a disabled link, warning shape + no commit/push, carried never-published target and disabled source don't warn, empty when nothing pending; the fixture exercises markdown, <a href> and link-param scans. Per-page coverage ported to publish-all (pre-flight failure, feedback, degraded git, missing library file, branch mode).
  • Docs: README and scaffold/site/AGENTS.md describe one Publish, including that it ships every editor's pending changes and that Disable / Discard… are the only holds. No stale "Publish all" / per-page references remain.

No CONCERNS.

[autoland] verdict: pass > *This was generated by AI while landing a PR.* **PASS** — validated against #156. **Signal relied on:** Forgejo Actions `ci / build-and-test` green on head `20cdadc` (web build+test, `go vet`, `go test ./...` with Hugo 0.163.3 installed, so the real-Hugo publish/pre-flight tests ran). Not re-run. Head already contains `main`; no conflict. **Checked:** - Conventions: Conventional Commits title; `Closes #156` present (AFK branch `afk/156`). - Server: `/api/page/publish` route, handler, mutation-lock entry and `publishPathsFor` removed; `/api/publish-all` gains opt-in `checkDraftLinks`, run after the empty check and before the pre-flight. A `{lang}`-only request is unchanged and never warns (deckle-hosted contract). The check scans added/modified `.md` under the content root, skips disabled sources, targets only front-matter drafts; node paths are page-file paths, so titles/skip lookups resolve. Remaining helpers all still have callers; `PublishPaths`/`StatusForPaths` kept as tested package API, as the issue allows. - Web: per-page Publish, its chip/error strip/dialogs and store state removed from the page module and entry editor (no primary button left); header button reads Publish/Publishing…; `DisabledLinksDialog` lists each disabled page with its linking pages; Publish anyway posts `checkDraftLinks:false`; Retry repeats the last request's flag; success still refetches badges. - Tests cover every acceptance criterion: 404 on the removed endpoint, `{lang}`-only publishes despite a disabled link, warning shape + no commit/push, carried never-published target and disabled source don't warn, empty when nothing pending; the fixture exercises markdown, `<a href>` and link-param scans. Per-page coverage ported to publish-all (pre-flight failure, feedback, degraded git, missing library file, branch mode). - Docs: README and `scaffold/site/AGENTS.md` describe one Publish, including that it ships every editor's pending changes and that Disable / Discard… are the only holds. No stale "Publish all" / per-page references remain. No CONCERNS.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle!161
No description provided.