Skip to content
Corex

Deploy & distribute

A professional Corex setup keeps each website in its own Azure DevOps repo and ships Corex framework updates separately. This guide covers the per-site repo, deployment, branch policies, and update packaging.

  • Each website is its own Azure DevOps repo (generated by make:site). The Corex framework lives in its own repo and is updated separately — client teams never edit it.
  • Host on Azure App Service + Azure Database for MySQL.
  • Deploy from develop (staging) and main (production), or from tags.
  • Secrets go in App Service application settings — never a committed .env or wp-config.php. Uploads are not committed.
  • Rollback: redeploy the previous tag / App Service deployment slot.

Protect main and develop; require, before merge:

  1. a pull-request review,
  2. a green pipeline (build + the headless tests),
  3. wp corex compliance:check — fails the PR if it touches Corex framework folders,
  4. wp corex readiness before release or client-site kickoff.
Terminal window
# In CI: fail the build if a client PR edited the Corex framework.
wp corex compliance:check --files="$(git diff --name-only origin/develop...HEAD | paste -sd,)"

The check passes client plugin/theme/docs/specs changes and fails (naming them) any change under a Corex framework folder. An approved framework change uses --allow-framework.

Terminal window
wp corex readiness

The readiness report covers runtime add-on gating, release metadata, CI/security, make:site validation, deployment, component coverage, Free/Core boundaries, and multi-agent workflow safety. It reports exact evidence and a next action for every non-pass row.

Metadata mismatches include the path, field, expected release, and actual value. Explicit policy exceptions, such as the npm workspace root version being independent from Corex release tags, remain visible in the report.

environment-gated is not a pass. It means the result depends on an external environment or repository setting, such as wp-env/browser availability, branch protection, required checks, or secret scanning. Verify those gates in their owning environment before release.

Deploy a built, flat WordPress tree instead:

  1. Assemble a clean tree in dist/: WordPress core + a real (non-symlinked) wp-content containing the CoreX framework theme/plugins/add-ons you actually use and the generated client theme/plugin as real folders.
  2. Include production vendor + built assets. npm run build builds the assets; npm run build:dist (below) installs the production Composer packages inside dist/wp-content/vendor/ itself, so do not run composer install --no-dev on the checkout.
  3. Exclude dev-only files: node_modules, tests, caches, .env, SQL dumps, and local agent state (.corex/, PROGRESS.md-style working files are repo-only).
  4. Migrate the database separately (export local → import to the target), run a site-URL search-replace (wp search-replace http://acme.local https://acme.example), and sync uploads (wp-content/uploads/).
  5. Provide the target’s own wp-config.php (its DB creds and salts) — never ship local config.
  6. Keep a rollback: snapshot the previous release + a DB export before swapping.

On cPanel / shared hosting, the uploaded tree must be this built dist/ artifact (real folders), not the local symlinked/junctioned wp/. The shared-host profile below records the no-symlink upload shape.

There is now a first-class builder for the flat artifact:

Terminal window
npm run build:dist -- --client=acme # assemble dist/ from repo source (de-symlinked, dev files stripped)
npm run verify:dist # the package loads the framework; no dev or host-owned files; manifest valid

It writes dist/ (git-ignored, never committed) with a corex-release.json manifest. The verifier includes the packaged core plugin in a PHP process of its own and fails unless it finds the packaged autoloader and a class from every packaged plugin, add-on and the CLI package loads. CI split: GitHub Actions runs PR/code-quality gates; Azure Pipelines (azure-pipelines.yml) builds dist/ and deploys it over SFTP from release tags, with credentials in Azure secrets and production runtime files protected. Full guides: docs/en/05-deployment/shared-host-dist.md and docs/en/05-deployment/azure-pipelines.md.

On shared hosting where the only ways in are a file manager and wp-admin, a release is not uploaded over the running site. npm run build:dist -- --client=acme --zip writes one package, and the site installs it from CoreX → Releases: the package is checked against its own description, each folder the release owns is replaced whole, the database step runs before visitors are let back in, and the previous release is kept to go back to. A plugin that is neither CoreX’s nor the site’s own travels in the package when it is named with --with-plugin=<folder>. A site that sets DISALLOW_FILE_MODS allows it with define( 'COREX_ALLOW_RELEASE_INSTALL', true ); in wp-config.php.

It is not a backup and it downloads nothing. Full guides: docs/en/05-deployment/releases-from-the-admin.md and, for the one installation that is still done by hand, docs/en/05-deployment/first-installation-by-hand.md.

A WordPress-aware wp corex package:site wrapper (calling the same builder) is on the backlog; the framework-only package:update command is documented under Packaging a Corex update.

Spec 055 records these profiles in the readiness check:

ProfilePackage shapeCommandsBlocker status
minimalCorex source, vendor, and built assetscomposer install --no-dev --optimize-autoloader; npm run buildNo known blocker
standardTagged Corex release with core plugins and themecomposer validate --no-check-publish; composer test; npm run buildNo known blocker
fullFirst-party Corex runtime with optional add-ons gated by statecomposer test; npm run build; npm run test:jsNo known blocker
wooCorex plus WooCommerce and Woo kitcomposer test; npm run build; wp plugin is-installed woocommerceNo known blocker
client-siteGenerated client plugin/theme consuming Corexwp corex make:site Acme --dir=sites/acme; wp corex compliance:checkNo known blocker
shared-hostFlat WordPress tree copied to shared hostingnpm run build; npm run build:dist; npm run verify:distVerify PHP extensions, permissions, and no-symlink upload shape
azure-containerProduction Docker image on Azure App Servicedocker build --target prod -t corex:prod .; az webapp config container setRequires live Azure and repo secret verification
local-dockerDocker Compose local stackdocker compose up -d --build; docker compose exec php composer testRequires Docker daemon
wp-env-stablewp-env stable smoke/browser targetnpm run env:start; npm run test:e2e; npm run env:stopRequires Docker/wp-env
wp-env-trunkwp-env trunk compatibility targetnpm run env:start -- --update; npm run test:e2e; npm run env:stopRequires Docker/wp-env and may fail on upstream trunk regressions

The framework update mechanism (in-admin “update available”) ships already; to produce an update:

Terminal window
wp corex package:update 0.25.0 --download-url=https://example.com/corex/corex-0.25.0.zip --changelog="Bug fixes."

This emits the manifest.json the self-update mechanism reads (version / requires / requires_php / tested / download_url / changelog) for the framework only — never client code, content, uploads, or secrets. Build the ZIP from the planned framework paths and publish it + the manifest (e.g. a GitHub Release / static host).

Terminal window
wp corex docs:sync # locate the built docs to copy into .corex/docs/ (git-ignored)
wp corex docs:serve # how to run the docs app locally (no hosted site needed)