Skip to content

Instantly share code, notes, and snippets.

@quinncomendant
Last active May 13, 2023 05:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save quinncomendant/6605356f8e5db92e657902303f10aaf3 to your computer and use it in GitHub Desktop.
Save quinncomendant/6605356f8e5db92e657902303f10aaf3 to your computer and use it in GitHub Desktop.
Use this script as `deploy.git/hooks/post-receive` in a bare git repo (`git init --bare`) on a server to deploy application files with, e.g., `git push deploy-production main`.
#!/usr/bin/env bash
#
# git post-receive hook to deploy releases via git push.
#
# @see https://gist.github.com/quinncomendant/6605356f8e5db92e657902303f10aaf3
# @author Quinn Comendant <quinn@strangecode.com>
# @version 2023-05-12
# Config
sitedir="/path/to/deploy/location";
logfile="$sitedir/log/deploy.log";
# shellcheck disable=SC2034
ENVIRONMENT="production-or-dev-or-staging";
PATH="./node_modules/.bin:$PATH";
# shellcheck disable=SC2174
mkdir -p -m 0777 "$(dirname "$logfile")";
touch "$logfile";
# Use variables from stdin.
read -r from to branch;
# Remove "refs/heads".
branch=$(cut -d / -f3- <<<"$branch");
date=$(date '+%F %T');
ip=$(awk '{print $1}' <<<"$SSH_CLIENT");
echo "${date} ${ip} Deploying $branch ${from:0:7}→${to:0:7} to $sitedir" | tee -a "$logfile";
# Only deploy if the required branch was pushed (e.g., use `main` in production, `dev` for dev, etc).
required_branch='main';
if [[ $branch != "$required_branch" ]]; then
echo "Branch $branch is not $required_branch; not deploying" | tee -a "$logfile";
exit 1;
fi
# Copy files to deploy directory.
export GIT_WORK_TREE="$sitedir";
git checkout -f "$branch";
# Deployment tasks.
cd "$sitedir" || exit 1;
echo "Running npm install --omit=dev && npm run build" | tee -a "$logfile";
# Need to unset GIT_WORK_TREE before running bower.
GIT_WORK_TREE="" npm install --omit=dev && npm run build;
build_exit_code=$?;
cd - &>/dev/null || exit 1;
echo "Deployment $( ((build_exit_code == 0)) && echo 'succeeded 🏆' || echo 'failed 💀' )" | tee -a "$logfile";
(( build_exit_code == 0 )) || exit $build_exit_code;
#
# Discord integration. Generate Discord webhook and update «placeholders» below before using.
#
# change_summary="**$ip deployed $branch ${from:0:7}→${to:0:7} to $(basename "$sitedir")**";
# # shellcheck disable=SC2016
# changelog_text=$(git log --oneline --pretty=format:'- [`%h`](https://bitbucket.org/«organization»/«project»/commits/%h) %aN: “%s”' "${from:0:7}..${to:0:7}");
# changelog_url="https://bitbucket.org/«organization»/«project»/branches/compare/${to:0:7}..${from:0:7}?#commits";
# programmer_wisdom_json=$(curl -s --compressed https://raw.githubusercontent.com/skolakoda/programming-quotes-api/master/Data/quotes.json | jq ".[$((RANDOM%501))]" 2>/dev/null);
# programmer_wisdom='';
# if [[ -n $programmer_wisdom_json ]]; then
# programmer_wisdom=$(printf '“%s” — %s' "$(jq -r '.en' <<<"$programmer_wisdom_json")" "$(jq -r '.author' <<<"$programmer_wisdom_json")");
# fi
#
# echo -e "\nNotifying Discord…";
# # Manage this bot at «https://discord.com/channels/…»
# # Docs at https://birdie0.github.io/discord-webhooks-guide/discord_webhook.html
# # Preview at https://leovoel.github.io/embed-visualizer/
# # Disable embed preview by wrapping URLs in <…>; see https://support.discord.com/hc/en-us/articles/206342858--How-do-I-disable-auto-embed-
# discord_jsondata=$(jq --null-input \
# --arg content "$change_summary" \
# --arg description "$changelog_text" \
# --arg url "$changelog_url" \
# --arg footer "$programmer_wisdom" \
# '{
# "content": $content,
# "embeds": [
# {
# "title": "View full changelog",
# "url": $url,
# "description": $description,
# "footer": {
# "text": $footer
# }
# }
# ]
# }');
# discord_message_id=$(curl -s -X POST -H 'Content-type: application/json' --data "$discord_jsondata" «https://discord.com/api/webhooks/…»?wait=true | jq -r '.id' 2>/dev/null)
# if [[ -n $discord_message_id ]]; then
# printf "Discord post: «https://discord.com/channels/…»/%s\n" "$discord_message_id" | tee -a "$logfile";
# printf "Delete post: \`curl -X DELETE «https://discord.com/api/webhooks/…»/messages/%s\`\n" "$discord_message_id" | tee -a "$logfile";
# else
# echo "Failed to notify Discord" | tee -a "$logfile";
# fi
#
# Slack integration. Generate Slack webhook and update «placeholders» below before using.
#
# change_summary="$ip deployed $branch ${from:0:7}→${to:0:7} to $(basename "$sitedir")";
# # shellcheck disable=SC2016
# changelog_text=$(git log --oneline --pretty=format:'- `<https://bitbucket.org/«organization»/«project»/commits/%h|%h>` <mailto:%ae|%aN>: “%s”' "${from:0:7}..${to:0:7}");
# changelog_url="https://bitbucket.org/«organization»/«project»/branches/compare/${to:0:7}..${from:0:7}?#commits";
#
# echo -en "\nNotifying Slack…";
# # Manage this bot at https://api.slack.com/apps/
# # Docs at https://api.slack.com/reference/block-kit
# # Preview at https://app.slack.com/block-kit-builder/
# slack_jsondata=$(jq --null-input \
# --arg title "$change_summary" \
# --arg text "$changelog_text" \
# --arg url "$changelog_url" \
# '{
# text: $text,
# blocks: [
# {
# type: "header",
# text: {
# type: "plain_text",
# text: $title
# }
# },
# {
# type: "section",
# text: {
# type: "mrkdwn",
# text: $text
# }
# },
# {
# type: "actions",
# elements: [
# {
# type: "button",
# text: {
# type: "plain_text",
# text: "View full changelog"
# },
# url: $url
# }
# ]
# }
# ]
# }');
# curl -s -X POST -H 'Content-type: application/json' --data "$slack_jsondata" «https://hooks.slack.com/services/…»
# echo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment