General refactoring

master
Lukas Bestle 4 years ago
parent 1e3f6f05ec
commit 07cf718ad9

@ -1,4 +1,4 @@
![](https://cdn.codesignd.net/projects/projectr/logo.svg)
# ![projectr](https://cdn.codesignd.net/projects/projectr/logo.svg)
> A collection of tools to manage and automatically deploy sites or other repositories on a server
@ -6,9 +6,9 @@
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 do 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.
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 hoster 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.
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.
projectr makes it easy to create and remove these links to connect your deployed sites to one or more domains.
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).
@ -17,7 +17,7 @@ The tools have been tested on Uberspace and are especially great for their setup
#### Introduction
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 FTP.
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.
The result is the following setup:
example.com/example.net -> Main site ("main_site")
@ -43,7 +43,7 @@ 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).
Generally, these tools work very similar. You can find more information in the scripts themselves.
Generally, these tools work in a very similar way. You can find more information in the scripts themselves.
#### Get the site code from the Git repository (our first deployment)
@ -59,7 +59,7 @@ If you omit the Git revision, the latest one is used instead. But if you want to
site_deploy main_site 78ca1d2fa93147b0...
```
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 a deployment succeeded.
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.
@ -110,14 +110,13 @@ The automatic rollback does essentially the same thing. It only changes the link
## Setup
1. Put this project 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 delete all contents. You can then setup all your sites using projectr.
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.**
4. There is no step 4.
### Deployment setup
@ -143,7 +142,7 @@ CONFIG_DEFAULT_BRANCH="master"
# Default is a full-length SHA-1 hash, use 7 as value when using short hashes.
CONFIG_HASH_LENGTH=40
# Number of deployed versions to preserve (0 for infinite (be careful, that might use loads of storage space!))
# Number of deployed versions to preserve (0 for no limit; be careful, that might use loads of storage space!)
# Versions older than the latest n versions get deleted automatically, logs are always preserved
CONFIG_PRESERVE_VERSIONS=5
```
@ -177,7 +176,7 @@ Every project/site follows this directory structure:
### Directory structure of a non-deployable project
If you don't want to keep old versions of your code and use automatic deployment, simply leave out the `<origin>` parameter when creating the project and you end up with a structure like this:
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:
.domains # Site-specific: List of linked domains for this site
.project # Empty file determining that this is a project
@ -190,8 +189,8 @@ This is useful for projects that aren't using version control. You can still use
## Author
- Lukas Bestle <mail@lukasbestle.com>
- Lukas Bestle <project-projectr@lukasbestle.com>
## License
This project was published under the terms of the MIT license. You can find a copy [over at the repository](https://git.lukasbestle.com/projectr/projectr/blob/master/LICENSE.md).
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).

@ -1,14 +1,15 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Creates a project directory, bootstraps it with a basic directory
# structure and optionally prepares it for deployments.
#
# Usage: project_add <project> [<origin>]
#
# <project> Path to the project
# <origin> Repository URL and branch name (<url>[#<branch>])
# <project> Path to the project
# <origin> Repository URL and branch name (<url>[#<branch>])
########################################################################
project="$1"
@ -29,7 +30,7 @@ fi
# Create project directory
echo -e "\033[1mCreating project at \033[34m$project\033[0;1m...\033[0m"
if ! (mkdir "$project" && mkdir "$project/data" && touch "$project/.project"); then
echo -e "\033[31mCould not create directory structure at \033[34m$project\033[31m.\033[0m" >&2
echo -e " => \033[31mCould not create directory structure at \033[34m$project\033[31m.\033[0m" >&2
exit 1
fi
echo -e " => \033[32mSuccess.\033[0m"
@ -49,10 +50,8 @@ if [[ -n "$origin" ]]; then
else
echo -e "\033[1mInitializing local project directory at \033[34m$project/current\033[0;1m...\033[0m"
if ! mkdir "$project/current"; then
echo -e "\033[31mCould not create local project directory.\033[0m" >&2
echo -e " => \033[31mCould not create local project directory.\033[0m" >&2
exit 1
fi
echo -e " => \033[32mSuccess.\033[0m"
exit 0
fi

@ -1,6 +1,7 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Clones the repository of a project from the server, runs the script
# .postdeploy.sh in the repository (if existing) and links the version
@ -8,9 +9,9 @@
#
# Usage: project_deploy <project> [<revision>]
#
# <project> Path to the project
# <revision> SHA-1 commit hash of the revision to checkout
# Defaults to the latest commit on the set branch
# <project> Path to the project
# <revision> SHA-1 commit hash of the revision to checkout
# Defaults to the latest commit on the set branch.
########################################################################
# Functions
@ -36,7 +37,7 @@ function project_deploy::reverse() {
# Builds the paths to a version
declare directoryCount versionNumber versionName destinationRelative destination
function buildVersionPath() {
function project_deploy::buildVersionPath() {
destinationRelative="versions/$versionName"
destination="$(cd "$project" && echo -n "$(pwd)/$destinationRelative")"
}
@ -44,7 +45,7 @@ function buildVersionPath() {
########################################################################
project="$1"
revision="$2"
revision="${2:-latest}"
# Load configuration
CONFIG_PRESERVE_VERSIONS=5
@ -62,14 +63,11 @@ if [[ -z "$project" ]]; then
echo -e "\033[1mUsage:\033[0m \033[34mproject_deploy\033[0m <project> [<revision>]"
exit 1
fi
if [[ -z "$revision" ]]; then
revision="latest"
# Check if the default value for $CONFIG_HASH_LENGTH has been changed
if [[ $CONFIG_HASH_LENGTH != 40 ]]; then
echo -e "\033[31mYou changed the default value of \033[34m\$CONFIG_HASH_LENGTH\033[31m. To make sure the deployed revisions are unique and never duplicated, deployments of the latest revision aren't supported with a custom value of this option. Please give me the exact revision string in your custom length.\033[0m" >&2
exit 1
fi
# Check if the default value for $CONFIG_HASH_LENGTH has been changed
if [[ "$revision" == "latest" ]] && [[ $CONFIG_HASH_LENGTH != 40 ]]; then
echo -e "\033[31mYou have changed the default value of \033[34m\$CONFIG_HASH_LENGTH\033[31m. To make sure the deployed revisions are unique and never duplicated, deployments of the latest revision aren't supported with a custom value of this option. Please give me the exact revision string in your custom length.\033[0m" >&2
exit 1
fi
# Check if the project exists
@ -98,7 +96,7 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
# We only need to do this if the revision was not deployed yet
if ! ls "$project/versions"/*-$revision &> /dev/null; then
# Check if the repository has already been cloned
url=$(cat "$project/.origin")
url="$(cat "$project/.origin")"
if ! [[ -d "$project/repo" ]]; then
# No, clone it now
echo -e "\033[1mCloning from \033[34m$url\033[0;1m for the first time...\033[0m"
@ -110,7 +108,7 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
else
# Yes, only fetch from the remote repository
echo -e "\033[1mFetching new commits from \033[34m$url\033[0;1m...\033[0m"
if ! (cd "$project/repo"; git fetch); then
if ! (git -C "$project/repo" fetch); then
echo -e " => \033[31mCould not fetch from \033[34m$url\033[31m.\033[0m" >&2
exit 1
fi
@ -127,15 +125,15 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
fi
else
# Check if the set branch exists
branch=$(cat "$project/.branch")
branch="$(cat "$project/.branch")"
echo -e "\033[1mDetermining current revision for branch \033[34m$branch\033[0;1m...\033[0m"
if ! (cd "$project/repo"; git show-branch "$branch" &> /dev/null); then
echo -e "\033[31mThe set branch \033[34m$branch\033[31m does not exist.\033[0m" >&2
if ! (git -C "$project/repo" show-branch "$branch" &> /dev/null); then
echo -e " => \033[31mThe set branch \033[34m$branch\033[31m does not exist.\033[0m" >&2
exit 1
fi
# Get the commit hash from the set branch
revision="$(cd "$project/repo"; git rev-list --max-count=1 "origin/$branch")"
revision="$(git -C "$project/repo" rev-list --max-count=1 "origin/$branch")"
if [[ $? != 0 ]]; then
echo -e " => \033[31mCould not determine current revision.\033[0m" >&2
exit 1
@ -149,8 +147,8 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
# Yes, use that
# Build the pathname of the destination directory
versionName=$(basename $(echo "$project/versions"/*-$revision))
buildVersionPath
versionName="$(basename "$(echo "$project/versions"/*-$revision)")"
project_deploy::buildVersionPath
echo -e "\033[1mThis revision has already been installed, using previous installation \033[34m$versionName\033[0;1m.\033[0m"
else
@ -161,7 +159,7 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
latestVersion=$(echo "$(ls "$project/versions" | tail -1)" | cut -f1 -d- | sed 's/^0*//')
versionNumber=$(($latestVersion + 1)) # Next is +1
versionName="$(printf "%05d" "$versionNumber")-$revision"
buildVersionPath
project_deploy::buildVersionPath
# Copy repository to new destination
echo -e "\033[1mCopying repository to deployment destination...\033[0m"
@ -174,7 +172,7 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
# Checkout correct revision
echo -e "\033[1mChecking out revision \033[34m$revision\033[0;1m...\033[0m"
if ! cd "$destination" || ! git checkout "$revision"; then
if ! git -C "$destination" checkout "$revision"; then
echo -e " => \033[31mCould not checkout revision \033[34m$revision\033[31m of project \033[34m$project\033[31m.\033[0m" >&2
project_deploy::reverse "$project" "$destination"
exit 1
@ -183,7 +181,7 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
# Update submodules
echo -e "\033[1mUpdating submodules...\033[0m"
if ! cd "$destination" || ! git submodule update --init --recursive; then
if ! git -C "$destination" submodule update --init --recursive; then
echo -e " => \033[31mCould not update submodules of project \033[34m$project\033[31m.\033[0m" >&2
project_deploy::reverse "$project" "$destination"
exit 1
@ -256,5 +254,3 @@ echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n---
echo -e " => \033[32mSuccess.\033[0m"
} 2>&1 | tee -a "$log" # Duplicate output to log file
exit 0

@ -1,6 +1,7 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Lists all known project directories.
#

@ -1,17 +1,18 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Prepares a project for deployment and sets the origin repository and
# branch the project is connected to.
#
# Usage: project_origin <project> [<origin>]
#
# <project> Path to the project
# <origin> Repository URL and branch name (<url>[#<branch>])
# If omitted, the origin gets deleted.
# If the string does not contain a "#", the branch is
# set to "master" ($CONFIG_DEFAULT_BRANCH).
# <project> Path to the project
# <origin> Repository URL and branch name (<url>[#<branch>])
# If omitted, the origin gets deleted.
# If the string does not contain a "#", the branch is
# set to "master" ($CONFIG_DEFAULT_BRANCH).
########################################################################
project="$1"
@ -58,7 +59,7 @@ if [[ -n "$origin" ]]; then
else
# No branch given, set to master
url="$origin"
branch=$CONFIG_DEFAULT_BRANCH
branch="$CONFIG_DEFAULT_BRANCH"
fi
# Check if the required directory structure already exists

@ -1,12 +1,13 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Removes a project directory.
#
# Usage: project_remove <project>
#
# <project> Path to the project
# <project> Path to the project
########################################################################
project="$1"
@ -39,5 +40,3 @@ if ! sed -i "/${realpath//\//\/}/d" "$HOME/.projects"; then # Replace / with \/
exit 1
fi
echo -e " => \033[32mSuccess.\033[0m"
exit 0

@ -1,12 +1,13 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Reverses a deployable project to the last version.
#
# Usage: project_rollback <project>
#
# <project> Path to the project
# <project> Path to the project
########################################################################
project="$1"
@ -32,14 +33,13 @@ fi
# Check if the project currently has a last version
if [[ ! -e "$project/last" ]]; then
echo -e "\033[31mThe project \033[34m$project\033[31m currently does not have a last version.\033[0m" >&2
echo -e "\033[31mProbably, it has already been rolled back since the latest deployment.\033[0m" >&2
echo -e "\033[31mIt has probably already been rolled back since the latest deployment.\033[0m" >&2
exit 1
fi
echo -e "\033[1mRolling project \033[34m$project\033[0;1m back to last version...\033[0m"
if rm -f "$project/current" && mv "$project/last" "$project/current"; then
echo -e " => \033[32mSuccess.\033[0m"
exit 0
else
echo -e " => \033[31mSomething went wrong.\033[0m" >&2
exit 1

@ -1,14 +1,15 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Creates a site directory in ~/web/sites/, bootstraps it with a basic
# directory structure and optionally prepares it for deployments.
#
# Usage: site_add <site> [<origin>]
#
# <site> Name of the site (directory in ~/web/sites/)
# <origin> Repository URL and branch name (<url>[#<branch>])
# <site> Name of the site (directory in ~/web/sites/)
# <origin> Repository URL and branch name (<url>[#<branch>])
########################################################################
site="$1"
@ -42,5 +43,3 @@ if ! touch "$HOME/web/sites/$site/.domains"; then
exit 1
fi
echo -e " => \033[32mSuccess.\033[0m"
exit 0

@ -1,6 +1,7 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Clones the repository of a site from the server, runs the script
# .postdeploy.sh in the repository (if existing) and links the version
@ -8,9 +9,9 @@
#
# Usage: site_deploy <site> [<revision>]
#
# <site> Name of the site (directory in ~/web/sites/)
# <revision> SHA-1 commit hash of the revision to checkout
# Defaults to the latest commit on the set branch
# <site> Name of the site (directory in ~/web/sites/)
# <revision> SHA-1 commit hash of the revision to checkout
# Defaults to the latest commit on the set branch.
########################################################################
site="$1"

@ -1,13 +1,14 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Creates a link for the webserver pointing a domain to a site.
#
# Usage: site_link <site> <domain>
#
# <site> Name of the site (directory in ~/web/sites/)
# <domain> FQDN of the domain (like "example.com")
# <site> Name of the site (directory in ~/web/sites/)
# <domain> FQDN of the domain (like "example.com")
########################################################################
site="$1"
@ -40,7 +41,7 @@ fi
# Create link
echo -e "\033[1mCreating link from site \033[34m$site\033[0;1m to domain \033[34m$domain\033[0;1m...\033[0m"
if ! ln -s "sites/$site/current" "$HOME/web/$domain"; then
echo -e "\033[31mCould not create link at \033[34m$HOME/web/$domain\033[31m.\033[0m" >&2
echo -e " => \033[31mCould not create link at \033[34m$HOME/web/$domain\033[31m.\033[0m" >&2
exit 1
fi
echo -e " => \033[32mSuccess.\033[0m"
@ -50,7 +51,6 @@ echo -e "\033[1mAdding domain to site's domains (\033[34m.domains\033[0;1m file)
echo "$domain" >> "$HOME/web/sites/$site/.domains"
if [[ $? == 0 ]]; then
echo -e " => \033[32mSuccess.\033[0m"
exit 0
else
echo -e " => \033[31mSomething went wrong.\033[0m" >&2
exit 1

@ -1,6 +1,7 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Lists all known sites.
#

@ -1,17 +1,18 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Prepares a site for deployment and sets the origin repository and
# branch the site is connected to.
#
# Usage: site_origin <site> [<origin>]
#
# <site> Name of the site (directory in ~/web/sites/)
# <origin> Repository URL and branch name (<url>[#<branch>])
# If omitted, the origin gets deleted.
# If the string does not contain a "#", the branch is
# set to "master".
# <site> Name of the site (directory in ~/web/sites/)
# <origin> Repository URL and branch name (<url>[#<branch>])
# If omitted, the origin gets deleted.
# If the string does not contain a "#", the branch is
# set to "master".
########################################################################
site="$1"

@ -1,12 +1,13 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Unlinks and removes a site directory in ~/web/sites/.
#
# Usage: site_remove <site>
#
# <site> Name of the site (directory in ~/web/sites/)
# <site> Name of the site (directory in ~/web/sites/)
########################################################################
site="$1"

@ -1,12 +1,13 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Reverses a deployable site to the last version.
#
# Usage: site_rollback <site>
#
# <site> Name of the site (directory in ~/web/sites/)
# <site> Name of the site (directory in ~/web/sites/)
########################################################################
site="$1"

@ -1,14 +1,15 @@
#!/usr/bin/env bash
########################################################################
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
# Copyright 2014 Lukas Bestle <project-projectr@lukasbestle.com>
# License MIT
########################################################################
# Removes a link for the webserver pointing a domain to a site.
#
# Usage: site_unlink <site> [<domain>]
#
# <site> Name of the site (directory in ~/web/sites/)
# <domain> FQDN of the domain (like "example.com")
# If not given, the site is completely unlinked
# <site> Name of the site (directory in ~/web/sites/)
# <domain> FQDN of the domain (like "example.com")
# If not given, the site is completely unlinked.
########################################################################
site="$1"
@ -65,17 +66,16 @@ fi
# Remove link
echo -e "\033[1mRemoving link from site \033[34m$site\033[0;1m to domain \033[34m$domain\033[0;1m...\033[0m"
if ! rm -f "$HOME/web/$domain"; then
echo -e "\033[31mCould not remove link at \033[34m$HOME/web/$domain\033[31m.\033[0m" >&2
echo -e " => \033[31mCould not remove link at \033[34m$HOME/web/$domain\033[31m.\033[0m" >&2
exit 1
fi
echo -e " => \033[32mSuccess.\033[0m"
# Remove from site's domains
echo -e "\033[1mRemoving domain from site's domains (\033[34m.domains\033[0;1m file)...\033[0m"
sed -i "/$domain/d" "$HOME/web/sites/$site/.domains"
sed -i "/${domain//\//\/}/d" "$HOME/web/sites/$site/.domains" # Replace / with \/ because of the sed separators
if [[ $? == 0 ]]; then
echo -e " => \033[32mSuccess.\033[0m"
exit 0
else
echo -e " => \033[31mSomething went wrong.\033[0m" >&2
exit 1

@ -1,13 +1,14 @@
<?php
/**
* Project management tools
* projectr
* Tools for deployments and project management
*
* GitHub frontend for deployments
*
* @author Lukas Bestle <mail@lukasbestle.com>
* @author Lukas Bestle <project-projectr@lukasbestle.com>
* @copyright Copyright 2014 Lukas Bestle
* @license MIT
* @file webhook.github.php
*/
@ -36,14 +37,17 @@ define('TOOLKIT_PATH', '/home/<user>/bin');
* 4. You should now be able to access https://hooks.example.com/webhook.github.php
* This should output "Web hook event (X-Github-Event header) is missing from request.".
*
* Then, you can easily create projects and let this script deploy them for you:
* Now you can create projects and let this script deploy them for you:
*
* 5. Create the project on the server by running either `project_add <path> <exact HTTPS clone url from GitHub>#<branch to deploy>` or
* 5. If your project is a private repository:
* 5.1. Generate an SSH key by using `ssh-keygen`. The default values are alright for this purpose.
* 5.2. Copy the contents of `~/.ssh/id_rsa.pub` to your clipboard and add it as "Deploy Key" in your project's GitHub settings interface.
* 6. Create the project on the server by running either `project_add <path> <exact HTTPS clone url from GitHub>#<branch to deploy>` or
* `site_add <name> <exact HTTPS clone url from GitHub>#<branch to deploy>`.
* It's important to use the exact HTTPS url (not the SSH one), so this script can find the project!
* 6. Add the URL (the one you tested in 4.) of the script to your project's web hooks.
* It's important to use the exact HTTPS url (not the SSH one) so this script can find the project!
* 7. Add the URL (the one you tested in 4.) of the script to your project's web hooks.
* Make sure to add the secret configured above and select "Just the push event".
* 7. GitHub now sends a "ping" event, which is ignored by this script. To test if it all works, push some code to your GitHub repository.
* 8. GitHub now sends a "ping" event, which is ignored by this script. To test if it everything works, push some code to your GitHub repository.
*
* Troubleshooting:
* - Use `tail -f <path to project>/logs/*.log`. This should tell you what went wrong.
@ -62,18 +66,18 @@ define('TOOLKIT_PATH', '/home/<user>/bin');
header('Content-Type: text/plain');
// Check if a secret has been set
if(SECRET == '<long token>') {
http_response_code(400);
die('No secret has been set in ' . basename(__FILE__) . '. This script won\'t work without one.');
if (SECRET === '<long token>') {
http_response_code(500);
die('No secret has been set in ' . basename(__FILE__) . ". This script won't work without one.");
}
// Check which event this is
if(!isset($_SERVER['HTTP_X_GITHUB_EVENT'])) {
if (isset($_SERVER['HTTP_X_GITHUB_EVENT']) !== true) {
http_response_code(400);
die('Web hook event (X-Github-Event header) is missing from request.');
}
$event = $_SERVER['HTTP_X_GITHUB_EVENT'];
switch($event) {
switch ($event) {
case 'ping':
die('Received ping event, ignoring.');
break;
@ -87,37 +91,37 @@ switch($event) {
// Get the request body
$input = false;
switch($_SERVER['CONTENT_TYPE']) {
switch ($_SERVER['CONTENT_TYPE']) {
case 'application/json':
echo "Received JSON data in body.\n";
$input = file_get_contents('php://input');
break;
case 'application/x-www-form-urlencoded':
echo "Received URL-encoded form data in body.\n";
$input = (isset($_POST['payload']))? $_POST['payload'] : '';
$input = (isset($_POST['payload']) === true)? $_POST['payload'] : '';
break;
default:
http_response_code(400);
die("Don't know what to do with {$_SERVER['CONTENT_TYPE']} content type.");
}
if(!$input) {
if (!$input) {
http_response_code(400);
die('No POST body sent.');
}
// Check if the authentication is valid
if(!isset($_SERVER['HTTP_X_HUB_SIGNATURE'])) {
if (isset($_SERVER['HTTP_X_HUB_SIGNATURE']) !== true) {
http_response_code(401);
die('Secret (X-Hub-Signature header) is missing from request. Have you set a secret in GitHub\'s project settings?');
die("Secret (X-Hub-Signature header) is missing from request. Have you set a secret in GitHub's project settings?");
}
if('sha1=' . hash_hmac('sha1', $input, SECRET, false) !== $_SERVER['HTTP_X_HUB_SIGNATURE']) {
if (hash_equals('sha1=' . hash_hmac('sha1', $input, SECRET, false), $_SERVER['HTTP_X_HUB_SIGNATURE']) !== true) {
http_response_code(403);
die('Secret (X-Hub-Signature header) is wrong or does not match request body.');
}
// Parse payload
$payload = json_decode($input, true);
if(!is_array($payload)) {
if (is_array($payload) !== true) {
http_response_code(400);
die('Invalid payload (no JSON?).');
}
@ -126,7 +130,7 @@ if(!is_array($payload)) {
$url = $payload['repository']['clone_url'];
$commit = $payload['after'];
$ref = $payload['ref'];
if(!preg_match('{(?:.*/){2}(.*)}', $ref, $matches)) {
if (preg_match('{(?:.*/){2}(.*)}', $ref, $matches) !== 1) {
http_response_code(400);
die('Invalid ref field (does not match regular expression "(?:.*/){2}(.*)").');
}
@ -138,23 +142,27 @@ echo "Received commit hash \"$commit\" for repository URL \"$url\" (branch \"$br
// Open ~/.projects and iterate through every project
$listPointer = fopen($_SERVER['HOME'] . '/.projects', 'r');
$exitCode = 0;
while(($project = fgets($listPointer)) !== false) {
while (($project = fgets($listPointer)) !== false) {
// Trim whitespace
$project = trim($project);
// Only deployable projects are interesting for us
if(!is_file($project . '/.origin') || !is_file($project . '/.branch')) continue;
if (is_file($project . '/.origin') !== true || is_file($project . '/.branch') !== true) {
continue;
}
// If there is a .origin and .branch file, check if they match
if(file_get_contents($project . '/.origin') == $url && file_get_contents($project . '/.branch') == $branch) {
if (trim(file_get_contents($project . '/.origin')) === $url && trim(file_get_contents($project . '/.branch')) === $branch) {
// Found the right project
echo "Found project at $project, running deploy script.\n";
// Run deploy script (in the background, because GitHub doesn't like requests > 30sec)
passthru('export PATH=' . escapeshellarg(TOOLKIT_PATH) . ':$PATH; project_deploy ' . escapeshellarg($project) . ' ' . escapeshellarg($commit) . ' > /dev/null 2>&1 &', $exitCode);
// Run deploy script (in the background, because GitHub doesn't like responses > 30sec)
passthru('export PATH=' . escapeshellarg(TOOLKIT_PATH) . ':$PATH; project_deploy ' . escapeshellarg($project) . ' ' . escapeshellarg($commit) . ' &> /dev/null &', $exitCode);
// If it didn't work, add debug statement
if($exitCode !== 0) echo "Something didn't work.\n";
if ($exitCode !== 0) {
echo "Something didn't work.\n";
}
}
}

@ -1,13 +1,14 @@
<?php
/**
* Project management tools
* projectr
* Tools for deployments and project management
*
* GitLab frontend for deployments
*
* @author Lukas Bestle <mail@lukasbestle.com>
* @author Lukas Bestle <project-projectr@lukasbestle.com>
* @copyright Copyright 2014 Lukas Bestle
* @license MIT
* @file webhook.gitlab.php
*/
@ -35,16 +36,17 @@ define('TOOLKIT_PATH', '/home/<user>/bin');
* 3. Place this script in a directory in ~/web/ (something like "~/web/hooks.example.com")
* 4. You should now be able to access https://hooks.example.com/webhook.gitlab.php?token=<AUTH_TOKEN>
* This should output "Authenticated, but no POST body sent.".
* 5. Generate an SSH key by using `ssh-keygen`. The default values are alright for this purpose.
* 6. Copy the contents of ~/.ssh/id_rsa.pub to your clipboard and add it as "Deploy Key" in your project's GitLab settings interface.
*
* Then, you can easily create projects and let this script deploy them for you:
* Now you can create projects and let this script deploy them for you:
*
* 7. Create the project on the server by running either `project_add <path> <exact SSH url from GitLab>#<branch to deploy>` or
* 5. If your project is a private repository:
* 5.1. Generate an SSH key by using `ssh-keygen`. The default values are alright for this purpose.
* 5.2. Copy the contents of `~/.ssh/id_rsa.pub` to your clipboard and add it as "Deploy Key" in your project's GitLab settings interface.
* 6. Create the project on the server by running either `project_add <path> <exact SSH url from GitLab>#<branch to deploy>` or
* `site_add <name> <exact SSH url from GitLab>#<branch to deploy>`.
* It's important to use the exact SSH url (not the HTTPS one), so this script can find the project!
* 8. Add the URL (the one you tested in 4.) of the script to your project's web hooks.
* 9. Hit "Test Hook" in GitLab's settings interface. The project should be deployed a few seconds later.
* It's important to use the exact SSH url (not the HTTPS one) so this script can find the project!
* 7. Add the URL (the one you tested in 4.) of the script to your project's web hooks.
* 8. Hit "Test Hook" in GitLab's settings interface. The project should be deployed a few seconds later.
*
* Troubleshooting:
* - Use `tail -f <path to project>/logs/*.log`. This should tell you what went wrong.
@ -64,27 +66,31 @@ define('TOOLKIT_PATH', '/home/<user>/bin');
header('Content-Type: text/plain');
// Check if an auth token has been set
if(AUTH_TOKEN == '<long token>') {
http_response_code(400);
die('No auth token has been set in ' . basename(__FILE__) . '. This script won\'t work without one.');
if (AUTH_TOKEN === '<long token>') {
http_response_code(500);
die('No auth token has been set in ' . basename(__FILE__) . ". This script won't work without one.");
}
// Check if the authentication is valid
if(!isset($_GET['token']) || $_GET['token'] !== AUTH_TOKEN) {
if (isset($_GET['token']) !== true) {
http_response_code(401);
die('Missing authentication.');
}
if (hash_equals(AUTH_TOKEN, $_GET['token']) !== true) {
http_response_code(403);
die('Invalid authentication.');
}
// Get the request body
$input = file_get_contents('php://input');
if(!$input) {
http_response_code(405);
if (!$input) {
http_response_code(400);
die('Authenticated, but no POST body sent.');
}
// Parse payload
$payload = json_decode($input, true);
if(!is_array($payload)) {
if (is_array($payload) !== true) {
http_response_code(400);
die('Invalid payload (no JSON?).');
}
@ -93,7 +99,7 @@ if(!is_array($payload)) {
$url = $payload['repository']['url'];
$commit = $payload['after'];
$ref = $payload['ref'];
if(!preg_match('{(?:.*/){2}(.*)}', $ref, $matches)) {
if (preg_match('{(?:.*/){2}(.*)}', $ref, $matches) !== 1) {
http_response_code(400);
die('Invalid ref field (does not match regular expression "(?:.*/){2}(.*)").');
}
@ -105,23 +111,27 @@ echo "Received commit hash \"$commit\" for repository URL \"$url\" (branch \"$br
// Open ~/.projects and iterate through every project
$listPointer = fopen($_SERVER['HOME'] . '/.projects', 'r');
$exitCode = 0;
while(($project = fgets($listPointer)) !== false) {
while (($project = fgets($listPointer)) !== false) {
// Trim whitespace
$project = trim($project);
// Only deployable projects are interesting for us
if(!is_file($project . '/.origin') || !is_file($project . '/.branch')) continue;
if (is_file($project . '/.origin') !== true || is_file($project . '/.branch') !== true) {
continue;
}
// If there is a .origin and .branch file, check if they match
if(file_get_contents($project . '/.origin') == $url && file_get_contents($project . '/.branch') == $branch) {
if (trim(file_get_contents($project . '/.origin')) === $url && trim(file_get_contents($project . '/.branch')) === $branch) {
// Found the right project
echo "Found project at $project, running deploy script.\n";
// Run deploy script (in the background, because GitLab doesn't like requests > 10sec by default)
passthru('export PATH=' . escapeshellarg(TOOLKIT_PATH) . ':$PATH; project_deploy ' . escapeshellarg($project) . ' ' . escapeshellarg($commit) . ' > /dev/null 2>&1 &', $exitCode);
// Run deploy script (in the background, because GitLab doesn't like responses > 10sec by default)
passthru('export PATH=' . escapeshellarg(TOOLKIT_PATH) . ':$PATH; project_deploy ' . escapeshellarg($project) . ' ' . escapeshellarg($commit) . ' &> /dev/null &', $exitCode);
// If it didn't work, add debug statement
if($exitCode !== 0) echo "Something didn't work.\n";
if ($exitCode !== 0) {
echo "Something didn't work.\n";
}
}
}

Loading…
Cancel
Save