Skip to content

WP Origin: expose WordPress as a Git remote#240

Open
adamziel wants to merge 4 commits intotrunkfrom
adamziel/wp-origin-e2e
Open

WP Origin: expose WordPress as a Git remote#240
adamziel wants to merge 4 commits intotrunkfrom
adamziel/wp-origin-e2e

Conversation

@adamziel
Copy link
Copy Markdown
Collaborator

What it does

Exposes WordPress posts and pages as a Git remote at /wp-json/git/v1/md.git, with Markdown export/import, stale-push protection, and real end-to-end coverage for stock git.

This branch also makes the WP Origin flow runnable in Docker via bin/test-wp-origin-git-actions-docker.sh.

Rationale

The PRD only matters if the full loop works with the real CLI: git clone, edit Markdown, git push, and have WordPress reflect the change. That required two pieces:

  • WP Origin runtime code that can deterministically project WordPress content into a Git repository and import pushes back.
  • Git transport and Docker-backed e2e coverage so the flow is tested with stock git, not just in-process unit tests.

I kept the default sandbox service on network_mode: none and added a dedicated sandbox-wp-origin-e2e service instead, because WordPress Playground still needs network access during boot.

Implementation

  • Adds the wp-origin plugin runtime for /wp-json/git/v1/md.git.
  • Exports posts/pages to post/*.md and page/*.md with front matter.
  • Imports pushed Markdown back into WordPress, including create, update, and delete-to-trash behavior.
  • Rejects stale pushes when WordPress content changed after the client cloned.
  • Sends a Basic Auth challenge so stock git retries correctly with WordPress application passwords.
  • Fixes the Git component so repositories created here work with the real CLI, including root commits.
  • Adds Git CLI e2e coverage plus Markdown round-trip contract tests.
  • Adds Docker/Playground bootstrapping so the WP Origin Git flow can be exercised in an isolated container.

This includes the Git groundwork from #237 because WP Origin depends on those real-CLI compatibility fixes.

Testing instructions

vendor/bin/phpunit components/Git/Tests/GitCliEndToEndTest.php
vendor/bin/phpunit components/Markdown/Tests/
bash bin/test-wp-origin-git-actions.sh
bash bin/test-wp-origin-git-actions-docker.sh

Repo-wide composer lint still reports the existing warning baseline outside this change set.

Review ping: @artpi

Adds the WP Origin plugin, which makes WordPress posts and pages available as a
Git remote. Users and coding agents can clone, pull, and push Markdown files
using standard Git tooling, with WordPress as the source of truth.

The plugin exposes a Git Smart HTTP endpoint at /wp-json/git/v1/md.git, backed
by HTTP Basic Auth with application passwords. Posts and pages are serialized as
Markdown with YAML front matter. Pushes validate staleness before applying
changes and move deleted files to trash rather than destroying content.

This commit also renames the Markdown fenced-code block language from `block`
to `gutenberg` (the old name is still accepted on import), and adds a real
end-to-end test script that boots a WordPress Playground instance, clones the
repo, edits and pushes a post, and verifies that a stale push is rejected.
The round-trip tests lock in the byte-preservation promise: Markdown that
enters WordPress and comes back out must be identical, and block markup that
is exported to Markdown and pushed back must produce the same blocks.
29 test cases cover paragraphs, headings, lists, tables, blockquotes,
images, links, gutenberg fences (opaque unsupported-block preservation),
front matter, and mixed content.

The plugin gains several stability improvements: the repository now lives
in a per-request temp directory that is always cleaned up in a finally
block, binary Git responses bypass WordPress REST JSON encoding via a
rest_pre_serve_request hook, permission checks cover both editing existing
posts and creating new ones, and metadata values are correctly wrapped in
arrays as BlocksWithMetadata requires.
@adamziel
Copy link
Copy Markdown
Collaborator Author

@artpi review ping for the WP Origin Git remote work and Docker e2e coverage.

@artpi
Copy link
Copy Markdown
Contributor

artpi commented Apr 23, 2026

Amazing! 🤯 After a few hacks i was able to make it work:

I hit a packaging-only fatal when testing the uploaded WP Origin plugin zip in a real WordPress install:

PHP Fatal error: Cannot redeclare wp_read_audio_metadata()
(previously declared in phar:///srv/htdocs/wp-content/plugins/wp-origin/php-toolkit.phar/components/Polyfill/wordpress.php:244)
in /wordpress/core/6.9.4/wp-admin/includes/media.php on line 3686

Root cause: the packaged php-toolkit.phar autoloads components/Polyfill/wordpress.php. That file is useful for standalone/non-WP runtimes, but unsafe inside real WordPress because it can define WP core shim functions before core loads the real implementations later in the request. In this case, the shim declared wp_read_audio_metadata(), then wp-admin later loaded wp-admin/includes/media.php, which tried to declare the real function and fataled.

The existing Docker e2e path did not catch this because it uses the dev bootstrap/mounted repo path, not the packaged phar path.

For local testing I fixed the built artifact by removing components/Polyfill/wordpress.php from the phar’s generated Composer autoload maps:

  • vendor/composer/autoload_files.php
  • vendor/composer/autoload_static.php

After rebuilding the plugin zip, the fatal went away and the needed classes still autoloaded.

Suggested upstream fix: build WP plugin phars/zips without components/Polyfill/wordpress.php, or split standalone WP shims from plugin-safe runtime files. It would also be useful to add a packaged-plugin smoke test that activates the zip/phar version inside WordPress, so this path is covered.

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