Last active
August 23, 2018 10:46
-
-
Save jeffryang24/b27829e0a9a63216b51ea9fcf3abfbd9 to your computer and use it in GitHub Desktop.
GitHub Auto Deployment Script Installation for NodeJS with PM2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# GitHub (NodeJS) Auto Deployment Script | |
# for debug | |
#set -o xtrace | |
# Version | |
_GHPLOY_VERSION="0.1a1" | |
# Reserved variables | |
_gh_query=() | |
version() { | |
printf "%s\n" "GHPloy Version ${_GHPLOY_VERSION}" | |
} | |
usage() { | |
printf "%s\n" "Usage: ghploy -q [remote-host:project-folder-name[:clone-location]] [ssh-arguments]" | |
} | |
help() { | |
version | |
printf "\n" | |
usage | |
printf "\n" | |
printf "\t%s\n" "[remote-host] => SSH remote host, ie. username@hostname." | |
printf "\t%s\n" "[project-folder-name] => GitHub project's folder name." | |
printf "\t%s\n" "[clone-location] => Clone location path." | |
} | |
do_ssh() { | |
local _ssh_script | |
if ! command -v ssh >/dev/null 2>&1; then | |
printf "%s\n" "ERROR! Please install ssh on your rig to use this script." | |
exit 1 | |
fi | |
# Check remote host | |
if [[ -z "${_gh_query[0]:-}" ]]; then | |
printf "%s\n" "ERROR! Please specify remote host." | |
exit 1 | |
elif [[ ! ${_gh_query[0]:-} =~ ^[a-zA-Z0-9_\-]+\@.+$ ]]; then | |
# shellcheck disable=SC1001 | |
printf "%s\n" "ERROR! Doesn't match pattern {username}@{hostname}." | |
exit 1 | |
fi | |
# Check project folder name | |
if [[ -z "${_gh_query[1]:-}" ]]; then | |
printf "%s\n" "ERROR! Please specify project folder name." | |
exit 1 | |
fi | |
# Check clone location | |
if [[ -z "${_gh_query[2]:-}" ]]; then | |
_gh_query[2]="\${HOME}/${_gh_query[1]}" | |
else | |
_gh_query[2]="${_gh_query[2]}/${_gh_query[1]}" | |
fi | |
_ssh_script="$(cat <<EOF | |
#!/usr/bin/env bash | |
# Check Git and SSH is installed or not | |
printf "%s\n" "[*] Checking SSH Command." | |
if ! command -v ssh >/dev/null 2>&1; then | |
printf "%s\n" "ERROR! Please install openssh on your remote rig." | |
exit 1 | |
fi | |
printf "%s\n\n" "[OK]. Done" | |
printf "%s\n" "[*] Checking Git Command." | |
if ! command -v git >/dev/null 2>&1; then | |
printf "%s\n" "ERROR! Please install git on your remote rig." | |
exit 1 | |
fi | |
printf "%s\n\n" "[OK]. Done" | |
# Add Github Fingerprint | |
if ! ssh-keygen -F github.com >/dev/null 2>&1; then | |
printf "%s\n" "[*] Add GitHub fingerprint." | |
mkdir -p \${HOME}/.ssh | |
[ -f "\${HOME}/.ssh/known_hosts" ] && | |
cp "\${HOME}/.ssh/known_hosts" "\${HOME}/.ssh/known_hosts.bak.\$(date +'%Y%m%d')" | |
(ssh-keyscan -H github.com >> \${HOME}/.ssh/known_hosts && | |
printf "%s\n\n" "[OK]. Done") || | |
exit 1 | |
fi | |
# Initialize git bare repository. | |
printf "%s\n" "[*] Initialize bare repository." | |
# Force remove existed directory. | |
[ -d "${_gh_query[2]}" ] && rm -rf "${_gh_query[2]}" | |
(git init --bare "${_gh_query[2]}/.git" && | |
printf "%s\n\n" "[OK]. Done") || | |
exit 1 | |
# Add Hook Script | |
cat > "${_gh_query[2]}/.git/hooks/post-receive" <<HOOK | |
#!/bin/sh | |
# Export Path | |
export PATH="\${PATH}:/usr/bin:/usr/local/bin:/usr/sbin" | |
# For nvm | |
if [ -d "\$HOME/.nvm" ]; then | |
export NVM_DIR="\$HOME/.nvm" | |
. "\$HOME/.nvm/nvm.sh" | |
fi | |
# Make sure pm2 is installed. | |
if ! command -v pm2 >/dev/null 2>&1; then | |
printf "%s\n" "[*] Installing PM2" && | |
npm install -g pm2 && | |
printf "%s\n\n" "[OK]. Done" | |
fi | |
cd "${_gh_query[2]}" | |
# Checkout directory | |
printf "%s\n" "[*] Checking out HEAD." && | |
git --git-dir="${_gh_query[2]}/.git"\ | |
--work-tree="${_gh_query[2]}"\ | |
checkout -f && | |
printf "%s\n\n" "[OK]. Done" | |
# Checkout Submodule | |
printf "%s\n" "[*] Updating submodule." && | |
git --git-dir="${_gh_query[2]}/.git"\ | |
--work-tree="${_gh_query[2]}"\ | |
submodule update --init --recursive && | |
printf "%s\n\n" "[OK]. Done" | |
# Fix submodule ownership | |
chown -R \${USER}:\${USER} . | |
# NPM Install and Build | |
printf "%s\n" "[*] Installing package.json." && | |
npm install && | |
printf "%s\n\n" "[OK]. Done" | |
printf "%s\n" "[*] Building project." && | |
npm run build && | |
printf "%s\n\n" "[OK]. Done" | |
# Create ecosystem file | |
if [ ! -f "${_gh_query[2]}/ecosystem.config.js" ]; then | |
cat > "${_gh_query[2]}/ecosystem.config.js" <<'ECOS' | |
module.exports = { | |
apps : [{ | |
name: '${_gh_query[1]}', | |
script: 'npm', | |
args: ['run', 'start'], | |
env: { | |
NODE_ENV: 'staging' | |
}, | |
env_production : { | |
NODE_ENV: 'production' | |
} | |
}], | |
}; | |
ECOS | |
fi | |
# Run pm2 | |
printf "%s\n" "[*] Starting pm2." && | |
(pm2 delete "${_gh_query[2]}/ecosystem.config.js" || true) && | |
pm2 start "${_gh_query[2]}/ecosystem.config.js" && | |
printf "%s\n\n" "[OK]. Done" | |
HOOK | |
chmod +x "${_gh_query[2]}/.git/hooks/post-receive" | |
EOF | |
)" | |
#echo "${_ssh_script}" | |
# shellcheck disable=SC2029 | |
ssh -T "$@" "${_gh_query[0]}" "${_ssh_script}" | |
} | |
main(){ | |
local -a _parameters=() | |
local _OLD_IFS="${IFS}" | |
[[ "$#" -eq "0" ]] && help && exit 0 | |
while [[ "$#" -gt "0" ]]; do | |
local _key="$1" | |
case ${_key} in | |
-h|--help) | |
help | |
shift | |
exit $? | |
;; | |
-q) | |
if [[ -z "$2" ]]; then | |
printf "%s\n" "ERROR! Please specify the query." | |
exit 1 | |
fi | |
IFS=":" read -r -a _gh_query <<< "$2" | |
IFS="${_OLD_IFS}" | |
shift 2 | |
;; | |
*) | |
_parameters+=("${_key}") | |
shift | |
;; | |
esac | |
done | |
# Restore positional arguments | |
eval set -- "${_parameters[@]}" | |
# Make sure user is not root | |
if [[ "${_gh_query[0]%@*}" == "root" ]]; then | |
printf "%s\n" "ERROR! For security purpose, please leave root account!" | |
exit 1 | |
fi | |
# Set ssh argument | |
do_ssh "$@" | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment