Composite GitHub Action for deploying PHP projects using Deployer over SSH.
This action sets up SSH securely, verifies your Deployer binary, and runs a deployment to a specified environment and revision. It streams Deployer output to the job log and exposes useful outputs you can consume in later steps.
Note: Although this action is implemented in Node.js, it targets PHP projects that use Deployer (dep) and a deploy.php recipe in your repository.
- Sets up SSH agent with your provided private key
- Optional strict host key checking via
ssh-known-hosts - Verifies your Deployer binary (default
vendor/bin/dep) - Runs
dep deploy <environment> --revision=<hash>with optional verbosity and extra options - Cleans up SSH artifacts after the run
- Exposes deployment status and full Deployer output as action outputs
Prerequisites:
- A PHP project with Deployer installed (usually via Composer) and a
deploy.phpfile in your repo. - An SSH private key with access to your deployment targets.
- Optionally: Known host entries for strict host key checking.
Basic usage example:
name: Deploy
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Composer dependencies
uses: php-actions/composer@v6
with:
php_version: '8.2'
- name: Deploy with Deployer
uses: zeroseven/deployer-action@v1
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
environment: production
revision: ${{ github.sha }}Tip: Replace @v1 with a pinned commit SHA for maximum supply-chain security in your organization.
All inputs map directly to the action’s action.yml.
-
ssh-private-key(required)- Your private key contents. Prefer a repository or organization secret (e.g.,
secrets.DEPLOY_SSH_PRIVATE_KEY). The action loads the key intossh-agentand uses SSH multiplexing for performance.
- Your private key contents. Prefer a repository or organization secret (e.g.,
-
environment(required)- The Deployer target/environment to deploy to (e.g.,
staging,testing,production). Used asdep deploy <environment>.
- The Deployer target/environment to deploy to (e.g.,
-
revision(required)- Git revision hash to deploy. Commonly
${{ github.sha }}.
- Git revision hash to deploy. Commonly
-
deployer-binary(default:vendor/bin/dep)- Path to your Deployer binary relative to
working-directory. The action verifies it and ensures it is executable.
- Path to your Deployer binary relative to
-
ssh-known-hosts(default: empty)- The content for your
known_hostsfile. If provided, strict host key checking is enabled. If omitted, the action setsStrictHostKeyChecking=no(not recommended for production).
- The content for your
-
ssh-port(default:22)- SSH port to use for connections.
-
working-directory(default:.)- Directory where your
deploy.phpanddeployer-binaryreside. Commands run with this as the current working directory.
- Directory where your
-
verbosity(default: empty)- Deployer verbosity level. Pass just
v,vv, orvvvand the action converts it to-v,-vv, or-vvvrespectively.
- Deployer verbosity level. Pass just
-
options(default: empty)- Additional Deployer CLI options, e.g.,
"--parallel --limit=10". The string is split on spaces and appended to the command.
- Additional Deployer CLI options, e.g.,
-
deployment-statussuccessorfaileddepending on the execution. Set even when the action fails.
-
deployer-output- Full combined stdout/stderr from the Deployer run. Can be lengthy; consider saving to an artifact only when needed.
Example of consuming outputs:
- name: Deploy
id: deploy
uses: zeroseven/deployer-action@v1
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
environment: staging
revision: ${{ github.sha }}
- name: Use outputs in a later step
if: ${{ success() }}
run: |
echo "Deployment completed. See previous step logs for details."
# To consume outputs in expressions, reference:
# steps.deploy.outputs['deployment-status'] (success|failed)
# steps.deploy.outputs['deployer-output'] (full logs)Provide known hosts for strict checking:
- name: Deploy with strict host key checking
uses: zeroseven/deployer-action@v1
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
ssh-known-hosts: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
environment: production
revision: ${{ github.sha }}Custom SSH port and working directory:
- name: Deploy to custom port from subdir
uses: zeroseven/deployer-action@v1
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
ssh-known-hosts: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
ssh-port: '2222'
working-directory: app
environment: testing
revision: ${{ github.sha }}Increase verbosity and pass extra options:
- name: Verbose parallel deploy
uses: zeroseven/deployer-action@v1
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
environment: staging
revision: ${{ github.sha }}
verbosity: vvv
options: "--parallel --limit=5"- Always store your SSH private key and known hosts in GitHub Secrets (or higher-scope secrets) and never commit them to the repository.
- Prefer providing
ssh-known-hostsfor production to enable strict host key checking. - Pin the action version to a major tag you control (e.g.,
@v1) or better a specific commit SHA. - Limit the key’s privileges and consider using deploy-only users on your target hosts.
-
Deployer not found / verification failed
- Ensure Composer dependencies are installed and
vendor/bin/depexists, or setdeployer-binaryto the correct path. You can add a step likephp-actions/composer@v6before this action.
- Ensure Composer dependencies are installed and
-
SSH host key verification failed
- Provide
ssh-known-hostsand ensure the entry matches your host and key type. Generate with:ssh-keyscan -p <port> <host>.
- Provide
-
Permission denied (publickey)
- Verify the provided private key has access to the target server and is correctly formatted. Ensure there are no passphrases that require interactive input.
-
Non-zero Deployer exit code
- Check the job logs for the exact failing task. You can increase
verbositytovvvfor more detail.
- Check the job logs for the exact failing task. You can increase
We welcome contributions! To set up a local dev environment:
-
Prerequisites
- Node.js 20+
- npm 9+
- Optional: A sample repo with
deploy.phpfor end-to-end tests
-
Install and build
npm cinpm run all(type-check, format, and package todist/)
-
Lint/format
npm run lintnpm run format- Or run all CI checks locally:
npm run ci
-
Packaging
- The published action uses the compiled files in
dist/. After changes insrc/, runnpm run packageand commit the updateddist/folder.
- The published action uses the compiled files in
-
Updating inputs/outputs
- If you change
action.ymlinputs or outputs, update this README accordingly and bump the version tag in release instructions.
- If you change
-
Pull requests
- Describe the change and motivation
- Include before/after behavior
- Keep changes focused; separate functional changes from formatting when possible
-
Releasing
- Automated via semantic-release. Use Conventional Commits in PR titles and merge commits (e.g.,
fix:,feat:,docs:). On push tomainor manual trigger, the workflow will:- analyze commits and determine the next version (patch/minor/major),
- create a Git tag like
v1.0.1and a GitHub Release with notes, - update the floating major tag (e.g.,
v1) to the new release.
- Manual run: Go to Actions → “Release” → Run workflow.
- Local dry run (optional):
npm run release -- --dry-run(requires repository access token in env if testing outside CI).
Conventional Commits quick ref:
fix:→ patchfeat:→ minorfeat!orfix!:, orBREAKING CHANGE:footer → major
- Automated via semantic-release. Use Conventional Commits in PR titles and merge commits (e.g.,
Licensed under the MIT License. You are free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies under the terms of the MIT license.
If you need the full text, include it in a LICENSE file or see https://opensource.org/licenses/MIT.