diff --git a/README.md b/README.md index 382a5e1..99e1053 100644 --- a/README.md +++ b/README.md @@ -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//` 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//` 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//` 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 `` 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 `` 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 +- Lukas Bestle ## 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). diff --git a/bin/project_add b/bin/project_add index 249ee6d..73474dc 100755 --- a/bin/project_add +++ b/bin/project_add @@ -1,14 +1,15 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Creates a project directory, bootstraps it with a basic directory # structure and optionally prepares it for deployments. # # Usage: project_add [] # -# Path to the project -# Repository URL and branch name ([#]) +# Path to the project +# Repository URL and branch name ([#]) ######################################################################## 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 diff --git a/bin/project_deploy b/bin/project_deploy index 28c517b..0018215 100755 --- a/bin/project_deploy +++ b/bin/project_deploy @@ -1,6 +1,7 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# 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 [] # -# Path to the project -# SHA-1 commit hash of the revision to checkout -# Defaults to the latest commit on the set branch +# Path to the project +# 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 []" 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 diff --git a/bin/project_list b/bin/project_list index 917cc2c..19d34b9 100755 --- a/bin/project_list +++ b/bin/project_list @@ -1,6 +1,7 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Lists all known project directories. # diff --git a/bin/project_origin b/bin/project_origin index 26c7d69..51ce622 100755 --- a/bin/project_origin +++ b/bin/project_origin @@ -1,17 +1,18 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Prepares a project for deployment and sets the origin repository and # branch the project is connected to. # # Usage: project_origin [] # -# Path to the project -# Repository URL and branch name ([#]) -# If omitted, the origin gets deleted. -# If the string does not contain a "#", the branch is -# set to "master" ($CONFIG_DEFAULT_BRANCH). +# Path to the project +# Repository URL and branch name ([#]) +# 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 diff --git a/bin/project_remove b/bin/project_remove index cfb3ea5..b99d064 100755 --- a/bin/project_remove +++ b/bin/project_remove @@ -1,12 +1,13 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Removes a project directory. # # Usage: project_remove # -# Path to the 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 diff --git a/bin/project_rollback b/bin/project_rollback index 63c6d22..905056f 100755 --- a/bin/project_rollback +++ b/bin/project_rollback @@ -1,12 +1,13 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Reverses a deployable project to the last version. # # Usage: project_rollback # -# Path to the 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 diff --git a/bin/site_add b/bin/site_add index a72635e..6713c9b 100755 --- a/bin/site_add +++ b/bin/site_add @@ -1,14 +1,15 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# 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 [] # -# Name of the site (directory in ~/web/sites/) -# Repository URL and branch name ([#]) +# Name of the site (directory in ~/web/sites/) +# Repository URL and branch name ([#]) ######################################################################## 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 diff --git a/bin/site_deploy b/bin/site_deploy index 9fcda68..a54f478 100755 --- a/bin/site_deploy +++ b/bin/site_deploy @@ -1,6 +1,7 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# 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 [] # -# Name of the site (directory in ~/web/sites/) -# SHA-1 commit hash of the revision to checkout -# Defaults to the latest commit on the set branch +# Name of the site (directory in ~/web/sites/) +# SHA-1 commit hash of the revision to checkout +# Defaults to the latest commit on the set branch. ######################################################################## site="$1" diff --git a/bin/site_link b/bin/site_link index 66a630a..eb468b8 100755 --- a/bin/site_link +++ b/bin/site_link @@ -1,13 +1,14 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Creates a link for the webserver pointing a domain to a site. # # Usage: site_link # -# Name of the site (directory in ~/web/sites/) -# FQDN of the domain (like "example.com") +# Name of the site (directory in ~/web/sites/) +# 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 diff --git a/bin/site_list b/bin/site_list index 554b4ae..df007c4 100755 --- a/bin/site_list +++ b/bin/site_list @@ -1,6 +1,7 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Lists all known sites. # diff --git a/bin/site_origin b/bin/site_origin index c84de39..fd1f855 100755 --- a/bin/site_origin +++ b/bin/site_origin @@ -1,17 +1,18 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Prepares a site for deployment and sets the origin repository and # branch the site is connected to. # # Usage: site_origin [] # -# Name of the site (directory in ~/web/sites/) -# Repository URL and branch name ([#]) -# If omitted, the origin gets deleted. -# If the string does not contain a "#", the branch is -# set to "master". +# Name of the site (directory in ~/web/sites/) +# Repository URL and branch name ([#]) +# If omitted, the origin gets deleted. +# If the string does not contain a "#", the branch is +# set to "master". ######################################################################## site="$1" diff --git a/bin/site_remove b/bin/site_remove index 964aa49..8c00402 100755 --- a/bin/site_remove +++ b/bin/site_remove @@ -1,12 +1,13 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Unlinks and removes a site directory in ~/web/sites/. # # Usage: site_remove # -# Name of the site (directory in ~/web/sites/) +# Name of the site (directory in ~/web/sites/) ######################################################################## site="$1" diff --git a/bin/site_rollback b/bin/site_rollback index ee96b59..8b64bcc 100755 --- a/bin/site_rollback +++ b/bin/site_rollback @@ -1,12 +1,13 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Reverses a deployable site to the last version. # # Usage: site_rollback # -# Name of the site (directory in ~/web/sites/) +# Name of the site (directory in ~/web/sites/) ######################################################################## site="$1" diff --git a/bin/site_unlink b/bin/site_unlink index 44e803d..28167f6 100755 --- a/bin/site_unlink +++ b/bin/site_unlink @@ -1,14 +1,15 @@ #!/usr/bin/env bash ######################################################################## -# 2014-09-07 Lukas Bestle mail@lukasbestle.com +# Copyright 2014 Lukas Bestle +# License MIT ######################################################################## # Removes a link for the webserver pointing a domain to a site. # # Usage: site_unlink [] # -# Name of the site (directory in ~/web/sites/) -# FQDN of the domain (like "example.com") -# If not given, the site is completely unlinked +# Name of the site (directory in ~/web/sites/) +# 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 diff --git a/webhook.github.php b/webhook.github.php index e34f9b2..cc6024e 100644 --- a/webhook.github.php +++ b/webhook.github.php @@ -1,13 +1,14 @@ + * @author Lukas Bestle * @copyright Copyright 2014 Lukas Bestle + * @license MIT * @file webhook.github.php */ @@ -36,14 +37,17 @@ define('TOOLKIT_PATH', '/home//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 #` 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 #` or * `site_add #`. - * 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 /logs/*.log`. This should tell you what went wrong. @@ -62,18 +66,18 @@ define('TOOLKIT_PATH', '/home//bin'); header('Content-Type: text/plain'); // Check if a secret has been set -if(SECRET == '') { - http_response_code(400); - die('No secret has been set in ' . basename(__FILE__) . '. This script won\'t work without one.'); +if (SECRET === '') { + 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"; + } } } diff --git a/webhook.gitlab.php b/webhook.gitlab.php index 181e92a..6acb86e 100644 --- a/webhook.gitlab.php +++ b/webhook.gitlab.php @@ -1,13 +1,14 @@ + * @author Lukas Bestle * @copyright Copyright 2014 Lukas Bestle + * @license MIT * @file webhook.gitlab.php */ @@ -35,16 +36,17 @@ define('TOOLKIT_PATH', '/home//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= * 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 #` 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 #` or * `site_add #`. - * 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 /logs/*.log`. This should tell you what went wrong. @@ -64,27 +66,31 @@ define('TOOLKIT_PATH', '/home//bin'); header('Content-Type: text/plain'); // Check if an auth token has been set -if(AUTH_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 === '') { + 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"; + } } }