{"id":15026217,"url":"https://github.com/banago/phploy","last_synced_at":"2025-05-13T19:03:08.566Z","repository":{"id":13945522,"uuid":"16645488","full_name":"banago/PHPloy","owner":"banago","description":"PHPloy - Incremental Git (S)FTP deployment tool that supports multiple servers, submodules and rollbacks.","archived":false,"fork":false,"pushed_at":"2025-04-21T09:54:12.000Z","size":28098,"stargazers_count":1427,"open_issues_count":25,"forks_count":197,"subscribers_count":54,"default_branch":"master","last_synced_at":"2025-04-28T00:03:14.493Z","etag":null,"topics":["deployment","workflow"],"latest_commit_sha":null,"homepage":"http://wplancer.com/phploy/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/banago.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"contributing.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-02-08T15:06:32.000Z","updated_at":"2025-04-25T07:44:14.000Z","dependencies_parsed_at":"2024-01-15T20:52:13.615Z","dependency_job_id":"572da3e9-bac4-4a78-8a5d-4ec9d4e06a37","html_url":"https://github.com/banago/PHPloy","commit_stats":{"total_commits":414,"total_committers":61,"mean_commits":6.786885245901639,"dds":0.6159420289855073,"last_synced_commit":"6d272e9a04aaf818a89ba146a0fb0350bf7a7e10"},"previous_names":[],"tags_count":78,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banago%2FPHPloy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banago%2FPHPloy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banago%2FPHPloy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banago%2FPHPloy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/banago","download_url":"https://codeload.github.com/banago/PHPloy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010793,"owners_count":21998993,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deployment","workflow"],"created_at":"2024-09-24T20:04:05.127Z","updated_at":"2025-05-13T19:03:08.549Z","avatar_url":"https://github.com/banago.png","language":"PHP","readme":"# PHPloy\n**Version 5.0.0**\n\nPHPloy is an incremental Git FTP and SFTP deployment tool. By keeping track of the state of the remote server(s) it deploys only the files that were committed since the last deployment. PHPloy supports submodules, sub-submodules, deploying to multiple servers and rollbacks. PHPloy requires **PHP 8.0+** (PHP 8.2+ for development/testing) and **Git 1.8+**.\n\n## What's New in 5.0.0\n\n- **Improved File Structure**: Better organized codebase with clear separation of concerns\n- **Flysystem 3.0 Upgrade**: Enhanced file system abstraction with latest Flysystem version\n- **Modern Testing Suite**: \n  - Replaced legacy Vagrant setup with Docker Compose\n  - Migrated from PHPUnit to Pest PHP for more expressive tests\n  - Added FTP and SFTP test servers for comprehensive integration testing\n- **Code Quality Tools**:\n  - PSR-12 coding standards enforcement\n  - Static analysis with PHPStan\n  - Automated code style fixing\n\n## How it works\n\nPHPloy stores a file called `.revision` on your server. This file contains the hash of the commit that you have deployed to that server. When you run phploy, it downloads that file and compares the commit reference in it with the commit you are trying to deploy to find out which files to upload. PHPloy also stores a `.revision` file for each submodule in your repository.\n\n## Install \n\n### Via Composer\n\nIf you have composer installed in your machine, you can pull PHPloy globally like this:\n\n```bash\ncomposer global require \"banago/phploy\"\n```\n\nMake sure to place the `$HOME/.composer/vendor/bin` directory (or the [equivalent directory](http://stackoverflow.com/a/40470979/512277) for your OS) \nin your `$PATH` so the PHPloy executable can be located by your system.\n\n### Via Phar Archive\n\nYou can install PHPloy via a phar archive:\n\n1. **Download**: Get the latest `phploy.phar` from our releases page\n2. **Install**:\n   - **Globally:** Move to `/usr/local/bin/phploy` and make executable:\n     ```bash\n     sudo mv phploy.phar /usr/local/bin/phploy\n     sudo chmod +x /usr/local/bin/phploy\n     ```\n   - **Locally:** Move to your project directory and use as:\n     ```bash\n     php phploy.phar\n     ```\n\n## Usage \n\n*When using PHPloy locally, proceed the command with `php `*\n\n1. Run `phploy --init` in the terminal to create the `phploy.ini` file or create one manually.\n2. Run `phploy` in terminal to deploy.\n\nWindows Users: [Installing PHPloy globally on Windows](https://github.com/banago/PHPloy/issues/214)\n\n## phploy.ini\n\nThe `phploy.ini` file holds your project configuration. It should be located in the root directory of the project. `phploy.ini` is never uploaded to server.  Check the sample below for all available options:\n\n```ini\n; This is a sample deploy.ini file. You can specify as many\n; servers as you need and use normal or quickmode configuration.\n;\n; NOTE: If a value in the .ini file contains any non-alphanumeric \n; characters it needs to be enclosed in double-quotes (\").\n\n[staging]\n    scheme = sftp\n    user = example\n    ; When connecting via SFTP, you can opt for password-based authentication:\n    pass = password\n    ; Or private key-based authentication:\n    privkey = 'path/to/or/contents/of/privatekey'\n    host = staging-example.com\n    path = /path/to/installation\n    port = 22\n    ; You can specify a branch to deploy from\n    branch = develop\n    ; File permission set on the uploaded files/directories\n    permissions = 0700\n    ; File permissions set on newly created directories\n    directoryPerm = 0775\n    ; Deploy only this directory as base directory\n    base = 'directory-name/'\n    ; Files that should be ignored and not uploaded to your server, but still tracked in your repository\n    exclude[] = 'src/*.scss'\n    exclude[] = '*.ini'\n    ; Files that are ignored by Git, but you want to send the the server\n    include[] = 'js/scripts.min.js'\n    include[] = 'directory-name/'\n    ; conditional include - if source file has changed, include file\n    include[] = 'css/style.min.css:src/style.css' \n    ; Directories that should be copied after deploy, from-\u003eto\n    copy[] = 'public-\u003ewww'\n    ; Directories that should be purged before deploy\n    purge-before[] = \"dist/\"\n    ; Directories that should be purged after deploy\n    purge[] = \"cache/\"\n    ; Pre- and Post-deploy hooks\n    ; Use \"DQOUTE\" inside your double-quoted strings to insert a literal double quote\n    ; Use 'QUOTE' inside your qouted strings to insert a literal quote\n    ; For example pre-deploy[] = 'echo \"that'QUOTE's nice\"' to get a literal \"that's\".\n    ; That workaround is based on http://php.net/manual/de/function.parse-ini-file.php#70847\n    pre-deploy[] = \"wget http://staging-example.com/pre-deploy/test.php --spider --quiet\"\n    post-deploy[] = \"wget http://staging-example.com/post-deploy/test.php --spider --quiet\"\n    ; Works only via SSH2 connection\n    pre-deploy-remote[] = \"touch .maintenance\"\n    post-deploy-remote[] = \"mv cache cache2\"\n    post-deploy-remote[] = \"rm .maintenance\"\n    ; You can specify a timeout for the underlying connection which might be useful for long running remote \n    ; operations (cache clear, dependency update, etc.)\n    timeout = 60\n\n[production]\n    quickmode = ftp://example:password@production-example.com:21/path/to/installation\n    passive = true\n    ssl = false\n    ; You can specify a branch to deploy from\n    branch = master\n    ; File permission set on the uploaded files/directories\n    permissions = 0774\n    ; File permissions set on newly created directories\n    directoryPerm = 0755\n    ; Files that should be ignored and not uploaded to your server, but still tracked in your repository\n    exclude[] = 'libs/*'\n    exclude[] = 'config/*'\n    exclude[] = 'src/*.scss'\n    ; Files that are ignored by Git, but you want to send the the server\n    include[] = 'js/scripts.min.js'\n    include[] = 'js/style.min.css'\n    include[] = 'directory-name/'\n    purge-before[] = \"dist/\" \n    purge[] = \"cache/\" \n    pre-deploy[] = \"wget http://staging-example.com/pre-deploy/test.php --spider --quiet\"\n    post-deploy[] = \"wget http://staging-example.com/post-deploy/test.php --spider --quiet\"\n```\n\nIf your password is missing in the `phploy.ini` file or the `PHPLOY_PASS` environment variable, PHPloy will interactively ask you for your password.\nThere is also an option to store the user and password in a file called `.phploy`.\n\n```\n[staging]\n    user=\"theUser\"\n    pass=\"thePassword\"\n    \n[production]\n    user=\"theUser\"\n    pass=\"thePassword\"\n```\n\nThis feature is especially useful if you would like to share your phploy.ini via Git but hide your password from the public.\n\nYou can also use environment variables to deploy without storing your credentials in a file.\nThese variables will be used if they do not exist in the `phploy.ini` file:\n```\nPHPLOY_HOST\nPHPLOY_PORT\nPHPLOY_PASS\nPHPLOY_PATH\nPHPLOY_USER\nPHPLOY_PRIVKEY\n```\n\nThese variables can be used like this;\n```\n$ PHPLOY_PORT=\"21\" PHPLOY_HOST=\"myftphost.com\" PHPLOY_USER=\"ftp\" PHPLOY_PASS=\"ftp-password\" PHPLOY_PATH=\"/home/user/public_html/example.com\" phploy -s servername\n```\n\nOr export them like this, the script will automatically use them:\n```\n$ export PHPLOY_PORT=\"21\"\n$ export PHPLOY_HOST=\"myftphost.com\"\n$ export PHPLOY_USER=\"ftp\"\n$ export PHPLOY_PASS=\"ftp-password\"\n$ export PHPLOY_PATH=\"/home/user/public_html/example.com\"\n$ export PHPLOY_PRIVKEY=\"path/to/or/contents/of/privatekey\"\n$ phploy -s servername\n```\n\n## Multiple servers\n\nPHPloy allows you to configure multiple servers in the deploy file and deploy to any of them with ease. \n\nBy default PHPloy will deploy to *ALL* specified servers.  Alternatively, if an entry named 'default' exists in your server configuration, PHPloy will default to that server configuration. To specify one single server, run:\n\n    phploy -s servername\n\nor:\n\n    phploy --server servername\n    \n`servername` stands for the name you have given to the server in the `phploy.ini` configuration file.\n\nIf you have a 'default' server configured, you can specify to deploy to all configured servers by running:\n\n    phploy --all\n\n## Shared configuration (custom defaults)\n\nIf you specify a server configuration named `*`, all options configured in this section will be shared with other \nservers. This basically allows you to inject custom default values.\n\n```ini\n; The special '*' configuration is shared between all other configurations (think include)\n[*]\n    exclude[] = 'src/*'\n    include[] = \"dist/app.css\"\n\n; As a result both shard1 and shard2 will have the same exclude[] and include[] \"default\" values\n[shard1]\n    quickmode = ftp://example:password@shard1-example.com:21/path/to/installation\n\n[shard2]\n    quickmode = ftp://example:password@shard2-example.com:21/path/to/installation\n```\n\n## Rollbacks\n\n**Warning: the --rollback option does not currently update your submodules correctly.**\n\nPHPloy allows you to roll back to an earlier version when you need to. Rolling back is very easy. \n\nTo roll back to the previous commit, you just run:\n\n    phploy --rollback\n\nTo roll back to whatever commit you want, you run:\n\n    phploy --rollback commit-hash-goes-here\n\nWhen you run a rollback, the files in your working copy will revert **temporarily** to the version of the rollback you are deploying. When the deployment has finished, everything will go back as it was.\n\nNote that there is not a short version of `--rollback`.\n\n\n## Listing changed files\n\nPHPloy allows you to see what files are going to be uploaded/deleted before you actually push them. Just run: \n\n    phploy -l\n\nOr:\n\n    phploy --list\n\n## Updating or \"syncing\" the remote revision\n\nIf you want to update the `.revision` file on the server to match your current local revision, run:\n\n    phploy --sync\n\nIf you want to set it to a previous commit revision, just specify the revision like this:\n\n    phploy --sync your-revision-hash-here\n\n## Creating deployment directory on first deploy\n\nIf the deployment directory does not exits, you can instruct PHPloy to create it for you:\n\n    phploy --force\n\n## Manual fresh upload\n\nIf you want to do a fresh upload, even if you have deployed earlier, use the `--fresh` argument like this:\n\n    phploy --fresh\n\n## Submodules\n\nSubmodules are supported, but are turned off by default since you don't expect them to change very often and you only update them once in a while. To run a deployment with submodule scanning, add the `--submodules` parameter to the command:\n\n    phploy --submodules\n    \n## Purging\n\nIn many cases, we need to purge the contents of a directory after a deployment. This can be achieved by specifying the directories in `phploy.ini` like this:\n\n    ; relative to the deployment path\n    purge[] = \"cache/\"\n\nTo purge a directory before deployment, specify the directories in `phploy.ini` like this:\n\n    ; relative to the deployment path\n    purge-before[] = \"dist/\"\n    \n## Hooks\n\nPHPloy allows you to execute commands before and after the deployment. For example you can use `wget`  call a script on my server to execute a `composer update`.\n\n    ; To execute before deployment\n    pre-deploy[] = \"wget http://staging-example.com/pre-deploy/test.php --spider --quiet\"\n    ; To execute after deployment\n    post-deploy[] = \"wget http://staging-example.com/post-deploy/test.php --spider --quiet\"\n\n## Logging\n\nPHPloy supports simple logging of the activity. Logging is saved in a `phploy.log` file in your project in the following format:\n    \n    2016-03-28 08:12:37+02:00 --- INFO: [SHA: 59a387c26641f731df6f0d1098aaa86cd55f4382] Deployment to server: \"default\" from branch \"master\". 2 files uploaded; 0 files deleted.\n\nTo turn logging on, add this to `phploy.ini`:\n\n    [production]\n        logger = on\n\n## Contribute\n\nCaContributions are very welcome; PHPloy is great because of the contributors. Please check out the [issues](https://github.com/banago/PHPloy/issues). \n\n## Credits\n\n * [Baki Goxhaj](https://twitter.com/banago)\n * [Contributors](https://github.com/banago/PHPloy/graphs/contributors?type=a)\n\n## Version history\n\nPlease check [release history](https://github.com/banago/PHPloy/releases) for details.\n\n## License\n\nPHPloy is licensed under the MIT License (MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbanago%2Fphploy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbanago%2Fphploy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbanago%2Fphploy/lists"}