mirror of
https://github.com/lukasbestle/projectr.git
synced 2026-10-11 23:10:19 +02:00
The repository is now only fetched for each deployment, which makes the whole process much faster especially for large repositories and repositories with many submodules.
218 lines
7.3 KiB
Bash
Executable File
218 lines
7.3 KiB
Bash
Executable File
#!/bin/bash
|
|
########################################################################
|
|
# 2014-09-07 Lukas Bestle mail@lukasbestle.com
|
|
########################################################################
|
|
# Clones the repository of a project from the server, runs the script
|
|
# .postdeploy.sh in the repository (if existing) and links the version
|
|
# as current.
|
|
#
|
|
# Usage: project_deploy <project> <revision>
|
|
#
|
|
# <project> Path to the project
|
|
# <revision> SHA-1 commit hash of the revision to checkout
|
|
########################################################################
|
|
# Functions
|
|
|
|
# Reverses changes
|
|
function project_deploy::reverse() {
|
|
local project="$1"
|
|
local destination="$2"
|
|
local shiftLinks=$3
|
|
|
|
echo -e "\033[1mReversing changes...\033[0m"
|
|
|
|
# Remove destination directory
|
|
rm -Rf "$destination"
|
|
|
|
# Shift links back to their old state
|
|
if [[ $shiftLinks == true ]]; then
|
|
rm -f "$project/current"
|
|
if [[ -e "$project/last" ]]; then
|
|
mv "$project/last" "$project/current"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Builds the paths to a version
|
|
declare directoryCount versionNumber versionName destinationRelative destination
|
|
function buildVersionPath() {
|
|
destinationRelative="versions/$versionName"
|
|
destination="$(cd "$project" && echo -n "$(pwd)/$destinationRelative")"
|
|
}
|
|
|
|
########################################################################
|
|
|
|
project="$1"
|
|
revision="$2"
|
|
|
|
# Load configuration
|
|
CONFIG_PRESERVE_VERSIONS=5
|
|
CONFIG_HASH_LENGTH=40
|
|
if [[ -f "$HOME/.project.cnf" ]]; then
|
|
source "$HOME/.project.cnf"
|
|
fi
|
|
if [[ $CONFIG_PRESERVE_VERSIONS == 1 ]]; then
|
|
echo -e "\033[31mThe value of \033[34m\$CONFIG_PRESERVE_VERSIONS\033[31m is too low (\033[34m1\033[31m), setting it to \033[34m2\033[31m.\033[0m" >&2
|
|
CONFIG_PRESERVE_VERSIONS=2
|
|
fi
|
|
|
|
if [[ -z "$revision" ]]; then
|
|
# Print help
|
|
echo -e "\033[1mUsage:\033[0m \033[34mproject_deploy\033[0m <project> <revision>"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if the project exists
|
|
if [[ ! -f "$project/.project" ]]; then
|
|
echo -e "\033[31mThe project \033[34m$project\033[31m does not exist or is invalid.\033[0m" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Check if the project can be updated
|
|
if [[ ! -f "$project/.origin" ]]; then
|
|
echo -e "\033[31mThe project \033[34m$project\033[31m is not deployable.\033[0m" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Check if the commit hash is valid
|
|
if [[ ${#revision} != $CONFIG_HASH_LENGTH ]]; then
|
|
echo -e "\033[31mThe length of the revision name \033[34m$revision\033[31m is not equal to the configured \033[34m$CONFIG_HASH_LENGTH\033[31m characters.\033[0m" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Add header to log
|
|
log="$project/logs/$revision.log"
|
|
if [[ -f "$log" ]]; then
|
|
# Separator between multiple logs
|
|
echo -e "\033[1;35m======\033[0m" >> "$log"
|
|
fi
|
|
echo -e "\033[1;35mRun on \033[34m$(date)\033[35m by \033[34m$USER\033[35m:\n------\033[0m" >> "$log"
|
|
|
|
# Log everything beginning here
|
|
{
|
|
# Check if we already installed this version
|
|
if ls "$project/versions"/*-$revision &> /dev/null; then
|
|
# Yes, use that
|
|
|
|
# Build the pathname of the destination directory
|
|
versionName=$(basename $(echo "$project/versions"/*-$revision))
|
|
buildVersionPath
|
|
|
|
echo -e "\033[1mThis revision has already been installed, using previous installation \033[34m$versionName\033[0;1m.\033[0m"
|
|
else
|
|
# No, fetch and install
|
|
|
|
# Check if the repository has already been cloned
|
|
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"
|
|
if ! git clone --recursive "$url" "$project/repo"; then
|
|
echo -e " => \033[31mCould not clone project \033[34m$project\033[31m from \033[34m$url\033[31m.\033[0m" >&2
|
|
exit 1
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
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; git submodule update --init --recursive); then
|
|
echo -e " => \033[31mCould not fetch from \033[34m$url\033[31m.\033[0m" >&2
|
|
exit 1
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
fi
|
|
|
|
# Build the pathname of the destination directory
|
|
# Get all version names, get the last one, split it by "-" and get the first part, remove leading zeros
|
|
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
|
|
|
|
# Copy repository to new destination
|
|
echo -e "\033[1mCopying repository to deployment destination...\033[0m"
|
|
if ! cp -R "$project/repo" "$destination"; then
|
|
echo -e " => \033[31mCould not copy repository.\033[0m" >&2
|
|
project_deploy::reverse "$project" "$destination"
|
|
exit 1
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
|
|
# Checkout correct revision
|
|
echo -e "\033[1mChecking out revision \033[34m$revision\033[0;1m...\033[0m"
|
|
if ! $(cd "$destination" && git 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
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
|
|
# Run post-deploy script if existing
|
|
if [[ -f "$destination/.postdeploy.sh" ]]; then
|
|
# Set the working directory to the destination
|
|
oldpwd="$(pwd)"
|
|
cd "$destination"
|
|
|
|
echo -e "\033[1mRunning post-deploy script...\033[0m"
|
|
if ! $destination/.postdeploy.sh; then
|
|
echo -e " => \033[31mSomething went wrong.\033[0m" >&2
|
|
project_deploy::reverse "$project" "$destination"
|
|
exit 1
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
|
|
cd "$oldpwd"
|
|
fi
|
|
|
|
# Remove .git directory
|
|
echo -e "\033[1mDeleting \033[34m.git\033[0;1m directory...\033[0m"
|
|
if ! rm -Rf "$destination/.git"; then
|
|
echo -e " => \033[31mCould not delete \033[34m.git\033[31m directory.\033[0m" >&2
|
|
project_deploy::reverse "$project" "$destination"
|
|
exit 1
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
|
|
# Clean up old versions
|
|
if [[ $CONFIG_PRESERVE_VERSIONS -gt 0 ]]; then
|
|
echo -e "\033[1mCleaning up old versions...\033[0m"
|
|
# Delete the first version until there are $CONFIG_PRESERVE_VERSIONS versions
|
|
while [[ $(ls -q "$project/versions" | wc -l) -gt $CONFIG_PRESERVE_VERSIONS ]]; do
|
|
item="$(ls -d "$project/versions"/* | head -1)"
|
|
echo -e " - Deleting \033[34m$item\033[0m..."
|
|
rm -Rf "$item"
|
|
done
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
else
|
|
echo -e "\033[1;31mNot\033[0;1m cleaning up old versions (disabled in configuration).\033[0m"
|
|
fi
|
|
fi
|
|
|
|
# Create symlinks to current version
|
|
echo -e "\033[1mSymlinking new version...\033[0m"
|
|
# Remove old symlink
|
|
if ! rm -f "$project/last"; then
|
|
echo -e " => \033[31mCould not delete old link.\033[0m" >&2
|
|
project_deploy::reverse "$project" "$destination"
|
|
exit 1
|
|
fi
|
|
# Move current symlink to old symlink
|
|
if [[ -e "$project/current" ]]; then
|
|
if ! mv "$project/current" "$project/last"; then
|
|
echo -e " => \033[31mCould not shift current link to old link.\033[0m" >&2
|
|
project_deploy::reverse "$project" "$destination"
|
|
exit 1
|
|
fi
|
|
fi
|
|
# Create new symlink
|
|
if ! ln -s "$destinationRelative" "$project/current"; then
|
|
echo -e " => \033[31mCould not create new link.\033[0m" >&2
|
|
project_deploy::reverse "$project" "$destination" true
|
|
exit 1
|
|
fi
|
|
echo -e " => \033[32mSuccess.\033[0m"
|
|
|
|
} 2>&1 | tee -a "$log" # Duplicate output to log file
|
|
|
|
exit 0
|