Skip to content

🐛 Fixed migrate-export failing to copy a production site's content - #2405

Merged
acburdine merged 1 commit into
mainfrom
fix-migrate-export-sudo
Oct 9, 2026
Merged

acburdine merged 1 commit into
mainfrom
fix-migrate-export-sudo

Conversation

@acburdine

Copy link
Copy Markdown
Member

ref https://linear.app/ghost/issue/PLA-479/s5e-production-import-and-cutover

ghost migrate-export fails on every standard production install in 1.33.3, at "Copying content files":

[FAILED] ui.sudo expects an array of arguments

A production install's content belongs to the ghost user, so the exporter copies it with sudo. #2348 changed ui.sudo to take only an array of arguments, but lib/tasks/migration-export/index.js still passed it shell strings (cp -R …, chown -R …). The unit tests didn't catch it: they stubbed ui.sudo and ran the strings through /bin/sh. Local sites never take the sudo path, so only production exports fail.

ghost-docker's new production import scenario (TryGhost/ghost-docker#382) found it on a real Ghost-CLI production install (Ubuntu 24.04, MySQL, systemd, nginx).

Changes

  • The exporter passes cp and chown their arguments as arrays. ui.sudo never uses a shell, so the shell quoting is removed.
  • In the tests, the ui.sudo stub refuses anything but an array, as the real one does. The copies that really run do so without a shell.

Testing

🤖 Generated with Claude Code

ref https://linear.app/ghost/issue/PLA-479/s5e-production-import-and-cutover

A production install's content belongs to the ghost user, so the export
copies it with sudo. ui.sudo was changed in #2348 to take an array of
arguments and refuse anything else, but the exporter still passed it
shell strings, so every standard production export failed at "Copying
content files" with "ui.sudo expects an array of arguments". The unit
tests stubbed ui.sudo and ran the strings through a shell, so they never
saw the refusal. ghost-docker's production import scenario found it.

The arguments now go to ui.sudo as an array, which also makes the shell
quoting unnecessary: ui.sudo never uses a shell.

- lib/tasks/migration-export/index.js: pass cp and chown their
  arguments as arrays and remove the shell quoting.
- test/unit/tasks/migration-export/index-spec.js: the stub refuses
  anything but an array, as ui.sudo does, and the copies that really
  run do so without a shell.
@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 9857ae19-3449-45db-a35c-0f3eb4be0635

📥 Commits

Reviewing files that changed from the base of the PR and between 05898dd and d5b521f.


📒 Files selected for processing (2)
  • lib/tasks/migration-export/index.js
  • test/unit/tasks/migration-export/index-spec.js

Included review availability: This review used your included allowance. 1 included review remains after this review. Your included PR review attempts over the past 7 days set your current allowance at 2 reviews per hour.



Walkthrough

The migration export task now passes cp and chown commands to ui.sudo as argument arrays and removes the shellQuote helper. Tests enforce the argument-array contract, inspect the arrays, and execute the supplied programs and arguments directly.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to d5b52

The export commands now pass arguments in the format required by ui.sudo. No actionable merge-blocking issue was identified.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check Passed The title clearly describes the primary change: fixing production content-copy failures in migrate-export.
Description check Passed The description directly explains the production failure, the ui.sudo argument mismatch, the implementation changes, and the test coverage.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.


  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR

🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR


  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@acburdine
acburdine enabled auto-merge (squash) October 9, 2026 19:42
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.12%. Comparing base (05898dd) to head (d5b521f).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2405      +/-   ##
==========================================
- Coverage   93.12%   93.12%   -0.01%     
==========================================
  Files         106      106              
  Lines        4410     4408       -2     
  Branches      789      789              
==========================================
- Hits         4107     4105       -2     
  Misses        228      228              
  Partials       75       75              
Flag Coverage Δ
unit-tests 93.12% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@acburdine
acburdine merged commit 488465e into main Oct 9, 2026
17 checks passed
@acburdine
acburdine deleted the fix-migrate-export-sudo branch October 9, 2026 19:45
acburdine added a commit to TryGhost/ghost-docker that referenced this pull request Oct 9, 2026
ref https://linear.app/ghost/issue/PLA-479/s5e-production-import-and-cutover

Ghost-CLI 1.33.3's migrate-export failed on every standard production
install: it copies content owned by the ghost user with sudo, and passed
ui.sudo shell strings after ui.sudo had begun to accept only arrays.
1.33.4 fixes it (TryGhost/Ghost-CLI#2405), so it is the minimum for
exporting, and what the end-to-end scenarios run.

- tests/e2e/import.sh, .github/workflows/test.yml: run 1.33.4.
- docs/install.md, docs/bundle-v1.md, pages/index.html: the minimum,
  and the exporter documentation at that tag.
- manager/src/bundle/manifest.ts: the re-export advice names it.
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.

2 participants