Skip to content

✨ Make find-replace safer by default by enabling post revisions for changes by defaults.#698

Open
markstos wants to merge 1 commit intoTryGhost:mainfrom
markstos:find-replace-post-revisions
Open

✨ Make find-replace safer by default by enabling post revisions for changes by defaults.#698
markstos wants to merge 1 commit intoTryGhost:mainfrom
markstos:find-replace-post-revisions

Conversation

@markstos
Copy link
Contributor

@markstos markstos commented Mar 4, 2026

fixes #697

This aligns find-replace with how the Admin UI works. A boolean is flag
is available to disable this safety feature for those want to live dangerously
and not generate any more DB storage through their action.

This work uncovered a bug on the server side where disabling post revisions
doesn't actually work. A separate bug and PR was opened to fix that part.

ref TryGhost/Ghost#26677

…hanges by defaults.

fixes TryGhost#697

This aligns find-replace with how the Admin UI works. A boolean is flag
is available to disable this safety feature for those want to live dangerously
and not generate any more DB storage through their action.

This work uncovered a bug on the server side where disabling post revisions
doesn't actually work. A separate bug and PR was opened to fix that part.

ref TryGhost/Ghost#26677
@cursor
Copy link

cursor bot commented Mar 4, 2026

You have run out of free Bugbot PR reviews for this billing cycle. This will reset on April 3.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

Walkthrough

This PR introduces a new --saveRevision flag to the find-replace command that conditionally creates post revisions for edited lexical posts. The feature is enabled by default. Changes include documentation of the flag, CLI flag configuration, user confirmation prompt, and conditional addition of save\_revision parameters during post editing. The implementation is consistent across command setup, user interaction, and task execution layers.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: enabling post revisions by default for the find-replace command to improve safety.
Description check ✅ Passed The description is related to the changeset, explaining the purpose (aligning with Admin UI), the safety mechanism, and referencing the linked issue.
Linked Issues check ✅ Passed The PR implements the core requirement from issue #697 by adding post revision creation for find-replace operations, providing the requested safety net and document history integration.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing post revision functionality for find-replace; no out-of-scope modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
prompts/find-replace.js (1)

105-110: Optional: show saveRevision prompt only when lexical is selected.

Since this setting applies to lexical edits only, you can reduce prompt noise by gating it on answers.where.includes('lexical').

✂️ Suggested refinement
     {
         type: 'confirm',
         name: 'saveRevision',
         message: 'Create a post revision for each edited post? (lexical posts only)',
-        default: true
+        default: true,
+        when: (answers) => Array.isArray(answers.where) && answers.where.includes('lexical')
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@prompts/find-replace.js` around lines 105 - 110, The saveRevision confirm
prompt is shown unconditionally but should only appear when the user selected
lexical edits; update the prompt object named "saveRevision" to include a
conditional "when" that checks answers.where.includes('lexical') (e.g., when:
answers => answers.where && answers.where.includes('lexical')) so the question
is only asked for lexical selections.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Line 447: Add a brief note next to the --no-saveRevision flag documentation
warning that Ghost v6.20.0+ has a known bug (issue `#26677`) where the Admin API
ignores save_revision=false due to revision ordering logic, so revisions will
still be created; reference the Ghost version and issue number and suggest users
expect revisions to be saved until upstream fixes the bug.

In `@tasks/find-replace.js`:
- Around line 144-145: The task uses ctx.args.saveRevision (see the edit call in
find-replace.js where queryParams = ctx.args.saveRevision ? {save_revision:
true} : {}) but initialise() doesn't set a default; update the initialise()
defaults to include saveRevision: true so the task-layer enforces the safety
default even if caller omits it (modify the initialise() function/object that
seeds ctx.args to add saveRevision: true).

---

Nitpick comments:
In `@prompts/find-replace.js`:
- Around line 105-110: The saveRevision confirm prompt is shown unconditionally
but should only appear when the user selected lexical edits; update the prompt
object named "saveRevision" to include a conditional "when" that checks
answers.where.includes('lexical') (e.g., when: answers => answers.where &&
answers.where.includes('lexical')) so the question is only asked for lexical
selections.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0978a015-06aa-41c4-8bb6-4407a58385c4

📥 Commits

Reviewing files that changed from the base of the PR and between 0a8cd93 and 0ed9573.

📒 Files selected for processing (4)
  • README.md
  • commands/find-replace.js
  • prompts/find-replace.js
  • tasks/find-replace.js


Use `-V` (`--verbose`) for detailed output showing which fields matched or were replaced in each post.

By default, `--saveRevision` is enabled, which creates a post revision for each edited post (lexical posts only). Use `--no-saveRevision` to disable this.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Ghost GitHub issue 26677 save_revision false not taking effect

💡 Result:

In Ghost v6.20.0, this is a confirmed bug: the Admin API can create new post revisions even when you send ?save_revision=false (or 0). The issue report (#26677, opened Mar 3, 2026) explains that Ghost’s revision logic picks the wrong “latest” revision due to an ordering mismatch (revisions are fetched newest-first, but the code treats the last array element as “latest”). That makes the “background save” time check almost always pass, so revisions get saved whenever content changes—ignoring save_revision=false. [1]

What you can do

  • If you need it fixed now: patch your Ghost install/fork so “latestRevision” uses the newest revision (e.g., the first element when ordered DESC), or adjust sorting so the newest revision is selected. (That’s the root cause described in the issue.) [1]
  • Otherwise: you’ll likely have to wait for an upstream fix (the issue is labeled needs:triage and, as of the report, has no assignee/milestone). [1]

Note

You may see save_revision=1 in normal Ghost Admin traffic—Ghost Admin appears to always send save_revision=true, which masks this bug for most UI usage. [1][2]

Sources: GitHub issue #26677 [1], related Ghost editor request example showing save_revision usage [2].


Document known Ghost limitation with --no-saveRevision.

Line 447 documents --no-saveRevision without noting that this feature is non-functional due to a confirmed bug in Ghost v6.20.0+ (issue #26677). The Admin API ignores the save_revision=false parameter due to a revision ordering logic error. Users should be warned that revisions will be saved regardless until Ghost upstream releases a fix. Consider adding a brief note to manage expectations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 447, Add a brief note next to the --no-saveRevision flag
documentation warning that Ghost v6.20.0+ has a known bug (issue `#26677`) where
the Admin API ignores save_revision=false due to revision ordering logic, so
revisions will still be created; reference the Ghost version and issue number
and suggest users expect revisions to be saved until upstream fixes the bug.

Comment on lines +144 to +145
let queryParams = ctx.args.saveRevision ? {save_revision: true} : {};
let result = await ctx.api.posts.edit(post, queryParams);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Enforce saveRevision default in task-layer defaults.

Line 144 relies on ctx.args.saveRevision being provided by callers. Add saveRevision: true to initialise() defaults so the safety default is preserved even if this task runner is reused outside current CLI/prompt flows.

💡 Suggested patch
             let defaults = {
                 verbose: false,
                 tag: false,
-                delayBetweenCalls: 50
+                delayBetweenCalls: 50,
+                saveRevision: true
             };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tasks/find-replace.js` around lines 144 - 145, The task uses
ctx.args.saveRevision (see the edit call in find-replace.js where queryParams =
ctx.args.saveRevision ? {save_revision: true} : {}) but initialise() doesn't set
a default; update the initialise() defaults to include saveRevision: true so the
task-layer enforces the safety default even if caller omits it (modify the
initialise() function/object that seeds ctx.args to add saveRevision: true).

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.

feature request: find-replace should update the document version history.

1 participant