Skip to content

Content patches: admin GraphQL API — status, reset, run (P4) #728

Description

@romain-pm

Sub-issue of #725 (P4). Specified in CONTENT-PATCHES-PLAN.md §6/§12 (on feature/js-content-patches). Built once on the Java framework from #697, the admin API serves both bridges — including reset for Groovy patch records, which today means hand-editing the j:bundlesScripts JSON. The developer CLI is deliberately not part of this issue: it is optional sugar over this API, split out to #731.

Scope

  • Status query (engine-provided GraphQL extension, admin-permission-gated): contentPatches { module, name, status } merging the status store with the live registry — the only surface that can show pending (registered but not yet recorded) and held (pending behind a .failed barrier); the raw j:bundlesScripts property cannot show either.
  • reset(module, name) mutation: safe removal of one record (typically a .failed barrier after a fix) instead of read-modify-writing the shared JSON property by hand in the JCR browser.
  • Groovy/Java coverage: status and reset operate on the shared store (/module-managementj:bundlesScripts), so extender-run Groovy patch records are first-class citizens, not just JS entries.
  • runPending(module, dryRun) / run(module, name, force, dryRun) mutations: the trigger that makes the autoRun=false + dry-run-then-apply staging workflow usable — without a trigger surface, autoRun=false leaves patches pending until the setting is flipped back and the module restarts. Document the recipe in the guide.

Assessment & recommendation (pending decision — nothing here is started)

This API is not necessary for the feature itself: with the default autoRun=true, patches run at module start and their outcomes are already readable through the generic JCR GraphQL API (/module-managementj:bundlesScripts — how the e2e asserts them). What justifies a dedicated surface, in decreasing order of pain:

  1. reset — recovering from a .failed barrier today means hand-editing a JSON property shared by every module's records in the JCR browser; the one genuinely dangerous gap.
  2. status with pending/held — only the engine can merge the status store with the live registry: the raw property structurally cannot answer "what runs on the next module start?" or "what is held behind the failure?". Also the only admin surface reachable on Jahia Cloud (no filesystem or Karaf console for customers), and the natural CI polling target after a deploy.
  3. run/runPending — needed only if the autoRun=false deferred-execution workflow (deploy on staging → dry-run → review → apply) is a supported feature; if it is not, descope them together with the dryRun config story.

Layering: the optional CLI (#731) is a client of this API — between the two, this is the fundamental one. Alternatives considered as the server surface and rejected: a provisioning operation (write-only, no status), Karaf/JMX (not customer-accessible), documented Groovy-console scripts (reintroduce the raw-API footguns this framework exists to remove — acceptable only as the documented fallback if this issue is dropped entirely).

Recommendation: minimal scope = status (incl. pending/held) + reset; make run/runPending conditional on an explicit decision to support autoRun=false as a workflow.

Dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions