Fully automatic deployments from Git repositories on GitHub or GitLab are not hard to do, but setting everything up in the first place can be quite difficult and annoying. There are services like [DeployBot](http://deploybot.com) that can do most of the setup work for you, but for small projects and sites such a service can be overkill.
This toolkit attempts to use as less magic as possible to help you to deploy your sites onto your server and to manage your sites with a few easy to understand command line tools written in Bash.
But there's more: My hosting provider of choice ([Uberspace](https://uberspace.de)) has a great Apache routing setup: You simply place a directory or symbolic link with the name of the domain (like `www.example.com`) in `/var/www/virtual/$USER/` and every request to the domain is routed to the corresponding directory automatically.
The tools have been tested on Uberspace and are especially great for their setup, but you can of course use all tools on any server with a proper shell (no Windows support, I'm sorry).
Let's setup projectr for two example sites: A main site at `example.com` and `example.net` and another project at `subdomain.example.com`. The main site is located at a GitHub repository from where everything should be deployed automatically. The other site however won't use automatic deployments, as the users update the contents using SFTP.
# "other_project" is a local project and does not have an origin
site_add other_project
```
You can now find the sites at `~/web/sites/main_site` and `~/web/sites/other_project`.
There's also `project_add`, which allows you to use a custom path. The `project_*` tools are very useful for repositories/projects that are no sites, for example for command line tools (I setup projectr using projectr on my servers, which is quite awesome).
As `main_site` was setup using a clone URL, you can use `site_deploy <site> [<revision>]` to fetch and install the current state of your project automatically:
```bash
site_deploy main_site
```
If you omit the Git revision, the latest one is used instead. But if you want to deploy a specific revision (you should in production to make sure you deploy exactly the revision that triggered the deployment), that's easy too:
There is now a log of the deployment in `~/web/sites/main_site/logs/`, the project code at `~/web/sites/main_site/versions/00001-78ca1d2fa93147b0...` and a symlink to the code at `~/web/sites/main_site/current`. This symlink is only automatically created if the deployment has succeeded.
Our other project is not deployable. This means that you can put any files manually into `~/web/sites/other_project/current`, which is the web root of the site.
projectr supports hook scripts that are run as part of the deployment and linking process.
Hook scripts need to be executable files in the top level of your repository. Their working directory is always the version directory of the current deployment.
The following hook scripts are currently supported:
-`.postdeploy.sh` will be executed after the deployment, but before the new version is linked.
-`.postlink.sh` will be executed after the active version gets switched or rolled back.
# "other_project" should be available at subdomain.example.com
site_link other_project subdomain.example.com
```
When deleting a site using `site_remove`, all of these domain links are automatically removed as well. You can also use `site_unlink` to unlink specific domains.
#### Webhooks and automatic deployments
If you setup automatic deployments using webhooks (see below), your sites are automatically updated after you push to your repository. This is done by cloning or fetching the repository using `project_deploy` and updating the links, so the domain link always points to the latest revision.
#### Rolling back to the last version
Let's say you committed a mistake (*badumm, tss*) and you want to rollback to the last deployed (working) revision.
Since our example site `main_site` is deployable (it has an origin repository), projectr stores a history of (by default) 5 versions and keeps the link to the last deployed version. This means that you can easily return to the last version and manually to an even older version:
1. Put this repository wherever you want on the destination system and add the `bin` directory to your `$PATH`.
2. Create a backup of your `DocumentRoot` (`/var/www/virtual/<user>/` on Uberspace) and then delete all contents. You can then setup all your sites using projectr.
3. Create a symlink to your `DocumentRoot` in `~/web` (this is what the `site_*` tools use):
`ln -s /var/www/virtual/$USER/ ~/web`
You can also link to a subdirectory of your `DocumentRoot` if you want to manage the sites of this tool separately from your other sites. Completely different destination directories are also possible if you are using a different server setup.
**Please note that the `site_link` functionality doesn't do what you expect when using non-standard paths for `~/web`, because it places the links in `~/web`, not where Uberspace expects them.**
### Deployment setup
The tool `project_deploy` takes the full path to the project and the Git revision to install (`site_deploy` only takes the site name as you saw above). Obviously, this is not very useful, but easy to use in deployment hook scripts.
You can find example PHP implementations for GitHub, GitLab and Gitea webhooks in `webhook.github.php`, `webhook.gitlab.php` and `webhook.gitea.php`, but you can also create your own if you use a different repository service:
1. Write a script that receives webhooks from the repository and gets the repository URL, commit SHA-1 and branch name of the event from the transmitted data.
2. Read the projects file at `~/.config/projectr/projects` if it exists (otherwise `~/.projects`), which contains the paths to all known projects and sites, and iterate through it.
If you want to customize specific settings, you can create a Bash file at `~/.project.cnf` or `$XDG_CONFIG_HOME/projectr/config.sh` (which defaults to `~/.config/projectr/config.sh`) to override the default values. These are the possible settings and also the format of the file:
If you don't want to keep old versions of your code and use automatic deployment, leave out the `<origin>` parameter when creating the project and you end up with a structure like this:
This project was published under the terms of the MIT license. You can find a copy [over at the repository](https://git.codesignd.com/tools/projectr/src/branch/master/LICENSE.md).