Deployer 7 + PHP 8.4 (v4) - #73
Open
mrrobot47 wants to merge 6 commits into
Open
Conversation
Deployer 7 absorbed the deployer/recipes package (the rsync recipe now lives in deployer/deployer's contrib/), so the separate dependency goes away. 7.5.12 is the final 7.x release; Deployer 8 (Apr 2026) exists but introduces a new recipe format and is intentionally out of scope. composer platform is pinned to php 8.4.0 to match the new container runtime (see the Dockerfile commit in this series). BREAKING CHANGE: recipes written against the Deployer 6 API no longer load. Consumers with a custom .github/deploy/deploy.php must port it — see UPGRADE notes in the v4 release.
Mechanical v6 → v7 changes:
- inventory('/hosts.yml') → import('/hosts.yml')
- per-host addSshOption() loop → global ssh_arguments
- deployer/recipes rsync path → deployer/deployer contrib/rsync.php
- 'cleanup' / 'success' → 'deploy:cleanup' / 'deploy:success'
- ssh_type 'native' removed (v7 only has native ssh)
Behavioral changes that needed more than a rename:
- deploy:prepare is a group task in v7 that runs deploy:update_code (fails without a git 'repository' — this action deploys via rsync) and duplicates lock/release/shared. Both task lists now run deploy:info + deploy:setup explicitly instead.
- release_name is seeded from the highest numbered directory in releases/ when .dep/latest_release is absent. Deployer 6 never wrote that file, so without the fallback the first v7 deploy to any existing site aborts with "Release name 1 already exists".
- keep_releases pinned to 5: v7 raised the default to 10, which would silently double disk usage per site.
- cachetool selection unchanged, but $output is initialized in opcache:reset / core_db:update so non-EasyEngine hosts don't emit undefined-variable warnings on PHP 8.
BREAKING CHANGE: task pipeline is Deployer 7-only; custom recipes and addon.php files using the v6 API will fail to load.
Deployer 7's import() validates hosts.yml against a strict schema: hosts must live under a top-level 'hosts:' key and the SSH user key is 'remote_user'. Every existing consumer repo uses the v6 flat format (branch names as top-level keys, 'user:'), which import() rejects outright. setup_hosts_file now rewrites the consumer file into the v7 schema (via PyYAML, already shipped as a shyaml dependency) when writing /hosts.yml. Files that already have a top-level 'hosts:' key pass through untouched, so repos can migrate at their own pace — or never. All other main.sh reads (check_branch_in_hosts_file, setup_ssh_access, setup_wordpress_files, block_emails) keep using the original flat file via shyaml and are unaffected.
php8.4-* packages from the ondrej PPA replace php7.4-*; php-json is dropped (core since PHP 8.0). DEFAULT_PHP_VERSION follows so maybe_run_php_build() restores the right CLI after a consumer's PHP_VERSION override. PHP 8.4 rather than 8.5: wp-cli 2.12 and the WordPress toolchain are proven on 8.4, and 8.4 is what consumer sites (EasyEngine) run today. BREAKING CHANGE: scripts relying on the container's PHP 7.4 behavior must be validated against 8.4.
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Upgrades the action runtime to Deployer 7 / PHP 8.4 while preserving compatibility with consumer repos’ existing hosts.yml and stock workflows.
Changes:
- Transform legacy (v6-style) flat
hosts.ymlinto Deployer 7’s stricthosts:schema before import. - Update the built-in
deploy.phprecipe for Deployer 7 (import API, rsync contrib path, task list adjustments, release counter seeding, keep_releases). - Update the container toolchain to PHP 8.4 packages and defaults.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| main.sh | Adds an on-the-fly YAML transformation step to produce a Deployer 7–compatible /hosts.yml. |
| deploy.php | Ports the built-in recipe to Deployer 7 APIs and behaviors, including release counter migration logic. |
| composer.json | Bumps Deployer to ^7.0 and pins PHP platform to 8.4.0. |
| Dockerfile | Switches installed PHP packages and default PHP version to 8.4. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…mment The hosts transform imports PyYAML at runtime; it was only present transitively via shyaml. Install pyyaml explicitly so the deploy-critical hosts rewrite doesn't depend on shyaml's dependency chain. Also correct the setup_hosts_file comment: a file already in the v7 schema is re-serialized (comments and key order are not preserved), not copied as-is.
The release_name closure trusted .dep/latest_release whenever it existed and only scanned releases/ when the file was absent. A deploy that dies after mkdir releases/N but before persisting the counter leaves the file stale at N-1, so the next deploy returns N, collides with the existing directory, and aborts with "Release name already exists". Always compute both the counter and the highest numbered directory and take max() + 1, so a stale counter can never number below an existing release. This also subsumes the v6-migration case (absent file → counter 0 → falls back to the directory scan).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Upgrades the action's runtime from Deployer 6.9 to Deployer 7.5.12 with PHP 8.4 as updated base, and makes the migration invisible to consumer repos that use the stock pipeline: existing
hosts.ymlfiles and workflows keep working unchanged.This is a major release (v4). The one hard breaking change is for repos that override
.github/deploy/deploy.php(or ship anaddon.php) written against the Deployer 6 API — those recipes fail to load on the new image and must be ported (checklist below).What changed
composer.json/composer.lockdeployer/deployer^6.8→^7.0(locks 7.5.12, the final 7.x).deployer/recipesremoved — Deployer 7 absorbed it; the rsync recipe now lives indeployer/deployer/contrib/rsync.php.7.4.33→8.4.0.deploy.php(built-in recipe)inventory()→import(), per-hostaddSshOption()loop → globalssh_arguments,cleanup/success→deploy:cleanup/deploy:success,ssh_typedropped (v7 is native-ssh only), rsync recipe path updated.deploy:prepareinto a group task that runsdeploy:update_code(requires a gitrepository— this action deploys via rsync, so it throws) and duplicates lock/release/shared. Both task lists now rundeploy:info+deploy:setupexplicitly. Without this, every deploy fails on its first task..dep/latest_release, a file v6 never wrote. On any existing site the first v7 deploy would abort withRelease name "1" already exists. The recipe now seeds the counter from the highest numbered directory inreleases/when the file is absent. (Confirmed against a live server — see Testing.)keep_releasespinned to 5 — v7's new default of 10 would silently double per-site disk usage.$outputinitialized inopcache:reset/core_db:update(PHP 8 undefined-variable warnings on non-EasyEngine hosts).main.shsetup_hosts_filenow rewrites the consumer's v6 flathosts.yml(branch keys at top level,user:) into the v7 schema (hosts:wrapper,remote_user:) before Deployer imports it — v7'simport()schema-rejects the flat format. Files already in v7 format pass through untouched. Every otherhosts.ymlread in main.sh (check_branch_in_hosts_file,setup_ssh_access,setup_wordpress_files,block_emails) uses the original flat file and is unaffected, so consumer repos change nothing.Dockerfilephp7.4-*→php8.4-*(ondrej PPA, resolved at image build time — nothing is installed at deploy time).php-jsondropped (core since 8.0).DEFAULT_PHP_VERSION=8.4.Breaking changes
.github/deploy/)deploy.php/addon.php(Deployer 6 API)inventory()undefined,deployer/recipespath gone)Release mechanics: publish the image as
v4.0.0and tag the actionv4. Do not move anyv3*tag —action.ymlkeeps pinningv3.4.1until the follow-up release commit.Custom
deploy.phpport checklist (v6 → v7)inventory( '/hosts.yml' )→import( '/hosts.yml' ).addSshOption()host loop; useset( 'ssh_arguments', [ '-o UserKnownHostsFile=/dev/null', '-o StrictHostKeyChecking=no' ] );deployer/recipes/recipe/rsync.php→deployer/deployer/contrib/rsync.php(both the local-vendor andCOMPOSER_HOMEfallback paths).set( 'ssh_type', 'native' ).deploy:preparewithdeploy:info,deploy:setup; renamecleanup→deploy:cleanup;after( 'deploy', 'success' )→after( 'deploy', 'deploy:success' ).release_namefallback (copy from this repo'sdeploy.php) so the first v7 deploy on an existing site doesn't collide with v6-era releases.set( 'keep_releases', 5 )— the v7 default is 10.{{hostname}}is the SSH host; use a custom key (e.g.site:) for the EasyEngine site name if they differ.A complete worked example (Bedrock + custom build steps) is in
rtCamp/test-action-deploy-wordpress@dc4c9a8under.github/deploy/.One-time note for existing sites
Releases created by v6 are absent from v7's
.dep/releases_log, sodeploy:cleanupwill never prune them. After switching, delete old numbered directories underreleases/once by hand (keepcurrent's target).Testing
All flows were exercised against a live EasyEngine test site, plus local end-to-end rigs (fresh sshd container) for failure-path cases:
wp core update-dbsucceeding viaee shelldeploy.phpoverridekeep_releases 3applied)releases/1releases/1..4and no.dep/latest_releasehosts.yml(incl. generated file with stray keys)dep deploy <branch>currentretarget, cleanup)Also verified in isolation:
depstill discovers/deploy.phpby walking up from the workspace; positionaldep deploy <alias>host selection; globalssh_argumentsreaching hosts (fresh host key accepted non-interactively); contrib rsync config keys unchanged; jq/shyaml/wp-cli/node toolchain intact on the new base.Follow-ups (separate PRs)
action.yml: bumpruns.imageto the published v4 image at release time.hosts.yml(currently empty —import()of an empty file crashes with a crypticTypeErrorbeforesetup_hosts_filereplaces it),example/workflow, and README for v7-era docs.