mirror of
https://github.com/ConnectedHumber/Air-Quality-Web
synced 2024-12-22 10:25:01 +00:00
Starbeamrainbowlabs
8ccc578e7b
This uses the new sensor_reading_value_types table that was recently added, and also REMOVES the "count" property on returned objects from this API action.
413 lines
13 KiB
Bash
Executable file
413 lines
13 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Make sure the current directory is the location of this script to simplify matters
|
|
cd "$(dirname "$(readlink -f "$0")")" || exit 1;
|
|
|
|
if [ ! -d "${PWD}/.git" ]; then
|
|
# shellcheck disable=SC1117
|
|
echo -e "\033[1m\033[31mError: The .git folder does not appear to exist. Please ensure you clone this repository with git, like this:\n\n\tgit clone https://github.com/ConnectedHumber/Air-Quality-Web.git\n\033[0m";
|
|
exit 1;
|
|
fi
|
|
################
|
|
### Settings ###
|
|
################
|
|
|
|
# The name of this project
|
|
project_name="Air Quality Mapper";
|
|
|
|
# The path to the lantern build engine git submodule
|
|
lantern_path="./lantern-build-engine";
|
|
|
|
###
|
|
# Custom Settings
|
|
###
|
|
|
|
# Put any custom settings here.
|
|
|
|
# Client-side build output
|
|
cache_dir="./.cache";
|
|
build_output_folder="./app";
|
|
|
|
# Database settings for ssh port forwarding task
|
|
database_host="ch-kimsufi";
|
|
database_name="aq_db";
|
|
database_user="www-data";
|
|
|
|
# Minimum major version of npm
|
|
min_npm_version_major="6";
|
|
|
|
# Deployment settings
|
|
deploy_ssh_user="ci";
|
|
# deploy_ssh_host="aq.connectedhumber.org";
|
|
deploy_ssh_host="37.187.118.171";
|
|
deploy_ssh_port="22";
|
|
|
|
deploy_root_dir="Air-Quality-Web";
|
|
deploy_root_dir_beta="Air-Quality-Web-Beta";
|
|
|
|
###############################################################################
|
|
|
|
# Check out the lantern git submodule if needed
|
|
if [ ! -f "${lantern_path}/lantern.sh" ]; then git submodule update --init "${lantern_path}"; fi
|
|
|
|
# shellcheck disable=SC1090
|
|
source "${lantern_path}/lantern.sh";
|
|
|
|
if [[ "$#" -lt 1 ]]; then
|
|
echo -e "${FBLE}${project_name}${RS} build script";
|
|
echo -e " by Starbeamrainbowlabs";
|
|
# shellcheck disable=SC2154
|
|
echo -e "${LC}Powered by the lantern build engine, v${version}${RS}";
|
|
echo -e "";
|
|
echo -e "${CSECTION}Usage${RS}";
|
|
echo -e " ./build ${CTOKEN}{action}${RS} ${CTOKEN}{action}${RS} ${CTOKEN}{action}${RS} ...";
|
|
echo -e "";
|
|
echo -e "${CSECTION}Available actions${RS}";
|
|
echo -e " ${CACTION}setup${RS} - Perform initial setup";
|
|
echo -e " ${CACTION}setup-dev${RS} - Perform additional setup for development environments. Run after ${CACTION}setup${RS}.";
|
|
echo -e " ${CACTION}database${RS} - Connect to the database via SSH & open MariaDB CLI connection, prompting for a password";
|
|
echo -e " ${CACTION}dev-server${RS} - Start a development server";
|
|
echo -e " ${CACTION}dev-server-stop${RS} - Stop the currently running development server";
|
|
echo -e " ${CACTION}client${RS} - Build the client web app";
|
|
echo -e " ${CACTION}client-watch${RS} - Watch for changes to the client code & rebuild automatically";
|
|
echo -e " ${CACTION}docs${RS} - Render the documentation";
|
|
echo -e " ${CACTION}ci${RS} - Perform CI tasks";
|
|
echo -e " ${LC}${CACTION}archive${RS} - CI: Create release archive";
|
|
echo -e "";
|
|
|
|
exit 1;
|
|
fi
|
|
|
|
###############################################################################
|
|
|
|
|
|
# ███████ ███████ ████████ ██ ██ ██████
|
|
# ██ ██ ██ ██ ██ ██ ██
|
|
# ███████ █████ ██ ██ ██ ██████
|
|
# ██ ██ ██ ██ ██ ██
|
|
# ███████ ███████ ██ ██████ ██
|
|
|
|
task_download-composer() {
|
|
if [ -f "${cache_dir}/composer" ]; then
|
|
return 0;
|
|
fi
|
|
[ ! -d "${cache_dir}" ] && mkdir "${cache_dir}";
|
|
|
|
|
|
task_begin "Downloading composer";
|
|
execute curl -sS "https://getcomposer.org/composer.phar" -o "${cache_dir}/composer"; exit_code=$?;
|
|
chmod +x "${cache_dir}/composer";
|
|
task_end ${exit_code};
|
|
}
|
|
|
|
check_php_module() {
|
|
module_name="$1";
|
|
subtask_begin "Checking for ${module_name} PHP module";
|
|
if [[ "$(php -m | grep -ic pdo_mysql)" -eq "0" ]]; then
|
|
subtask_end 1 "Error: The php_mysql PHP module is not installed.";
|
|
fi
|
|
subtask_end 0;
|
|
}
|
|
|
|
task_setup() {
|
|
stage_begin "Setting up";
|
|
|
|
task_begin "Checking environment";
|
|
check_command git true;
|
|
check_command php true;
|
|
check_command node true;
|
|
check_command npm true;
|
|
check_command curl true;
|
|
|
|
check_php_module pdo_mysql;
|
|
check_php_module mbstring;
|
|
|
|
if [ ! -w "${PWD}" ]; then
|
|
task_end 1 "${HC}${FRED}Error: Can't write to the repository directory! This usually you have a permission error of some kind. Try using sudo to run this build command as the user that owns this cloned repository.";
|
|
fi
|
|
|
|
npm_version_major="$(npm --version | head -c 1)";
|
|
if [[ "${npm_version_major}" -lt "${min_npm_version_major}" ]]; then
|
|
echo "${FRED}${HC}Error: Your version of npm is too far out of date. You're running version $(npm --version), but version 6+ is required.";
|
|
fi
|
|
task_end $?;
|
|
|
|
task_begin "Initialising submodules";
|
|
execute git submodule update --init;
|
|
task_end $?;
|
|
|
|
task_begin "Installing client dependencies";
|
|
echo -e "${HC}Not including development dependencies. To complete setup for development, execute the ${CACTION}setup-dev${RS} ${HC}build task.${RS}";
|
|
execute npm install --production;
|
|
task_end $?;
|
|
|
|
tasks_run download-composer;
|
|
|
|
task_begin "Installing server dependencies";
|
|
execute "${cache_dir}/composer" install --no-dev;
|
|
task_end $?;
|
|
|
|
if [ ! -d "./data" ]; then
|
|
task_begin "Setting up initial data folder";
|
|
mkdir "./data"; chmod 0700 "./data";
|
|
|
|
echo -e "# -------[ Custom Settings File - Last updated $(date) ]-------" >"./data/settings.toml";
|
|
echo -e '[database]\nusername = "INSERT_DATABASE_USERNAME_HERE"\npassword = "INSERT_DATABASE_PASSWORD_HERE"' >>"./data/settings.toml";
|
|
chmod 0600 "./data/settings.toml";
|
|
|
|
echo -e "${HC}Don't forget to edit './data/settings.toml' to specify the database username and password${RS}";
|
|
echo -e "";
|
|
|
|
task_end $?;
|
|
fi
|
|
|
|
stage_end $?;
|
|
}
|
|
|
|
task_setup-dev() {
|
|
task_begin "Checking environment";
|
|
check_command mysql true optional;
|
|
task_end $?;
|
|
|
|
task_begin "Installing client development dependencies";
|
|
execute npm install;
|
|
task_end $?;
|
|
|
|
task_begin "Installing server development dependencies";
|
|
execute "${cache_dir}/composer" install;
|
|
task_end $?;
|
|
}
|
|
|
|
|
|
# ██████ ███████ ██ ██
|
|
# ██ ██ ██ ██ ██
|
|
# ██ ██ █████ ██ ██
|
|
# ██ ██ ██ ██ ██
|
|
# ██████ ███████ ████
|
|
|
|
task_database() {
|
|
task_begin "Connecting to the database";
|
|
set_title "Database";
|
|
ssh -TN "${database_host}" -L 3306:localhost:3306 &
|
|
ssh_pid=$!;
|
|
sleep 1;
|
|
mysql --host 127.0.0.1 --port 3306 --database "${database_name}" --user "${database_user}" --password;
|
|
|
|
kill "${ssh_pid}"; wait; sleep 0.5;
|
|
task_end $?;
|
|
}
|
|
|
|
task_dev-server() {
|
|
task_begin "Starting development server";
|
|
php -S "[::1]:40482" &
|
|
exit_code=$?;
|
|
[[ "${exit_code}" -eq "0" ]] && echo $! >/tmp/micro-lantern-dev-server.pid;
|
|
task_end $?; # Should be 0 unless php died for some reason
|
|
sleep 1;
|
|
}
|
|
|
|
task_dev-server-stop() {
|
|
task_begin "Stopping development server";
|
|
|
|
kill "$(cat /tmp/micro-lantern-dev-server.pid)";
|
|
rm /tmp/micro-lantern-dev-server.pid;
|
|
|
|
task_end $?;
|
|
}
|
|
|
|
|
|
# ██████ ██ ██ ███████ ███ ██ ████████
|
|
# ██ ██ ██ ██ ████ ██ ██
|
|
# ██ ██ ██ █████ ██ ██ ██ ██
|
|
# ██ ██ ██ ██ ██ ██ ██ ██
|
|
# ██████ ███████ ██ ███████ ██ ████ ██
|
|
|
|
task_client() {
|
|
task_begin "Packaging Javascript";
|
|
execute node_modules/.bin/rollup --sourcemap --config rollup.config.js;
|
|
task_end $? "Error: rollup packing failed!";
|
|
|
|
task_begin "Copying html";
|
|
execute cp client_src/index.html "${build_output_folder}";
|
|
task_end $?;
|
|
|
|
# task_begin "Copying css";
|
|
# # FUTURE: Package this up too?
|
|
# cp -r client_src/css/ "${build_output_folder}";
|
|
# task_end $?;
|
|
}
|
|
|
|
task_client-watch() {
|
|
set_title "Client Watcher";
|
|
|
|
echo -e "Watching for changes.";
|
|
while :; do # : = infinite loop
|
|
# Wait for an update
|
|
# inotifywait's non-0 exit code forces an exit for some reason :-/
|
|
inotifywait -qr --event modify --format '%:e %f' client_src;
|
|
|
|
# Rebuild the client code - spawn a sub-process to avoid the hard exit
|
|
# This still doesn't work though, which is *really* annoying
|
|
stage_begin "Rebuilding client code";
|
|
./build client;
|
|
stage_end $?;
|
|
done
|
|
}
|
|
|
|
|
|
# ██████ ██████ ██████ ███████
|
|
# ██ ██ ██ ██ ██ ██
|
|
# ██ ██ ██ ██ ██ ███████
|
|
# ██ ██ ██ ██ ██ ██
|
|
# ██████ ██████ ██████ ███████
|
|
|
|
task_docs() {
|
|
task_begin "Rendering docs";
|
|
execute node_modules/.bin/nightdocs --config nightdocs.toml;
|
|
task_end $?;
|
|
|
|
task_begin "Copying images";
|
|
cp -r docs/images/ __nightdocs/;
|
|
task_end $?;
|
|
}
|
|
|
|
|
|
# ██████ ██
|
|
# ██ ██
|
|
# ██ ██
|
|
# ██ ██
|
|
# ██████ ██
|
|
task_ci() {
|
|
tasks_run setup setup-dev
|
|
NODE_ENV="production" tasks_run client docs archive;
|
|
|
|
latest_commit="$(git log -n 1 --pretty=format:"%H")";
|
|
current_commit="$(git rev-parse HEAD)";
|
|
|
|
if [ "${latest_commit}" != "${current_commit}" ]; then
|
|
echo "Not deploying, as this isn't the latest commit on the branch.";
|
|
echo "It's likely that this commit is actually one of several in a queue to be processed by the CI server at once.";
|
|
return 0;
|
|
fi
|
|
|
|
if [ "${GIT_REF_NAME}" == "refs/heads/master" ]; then
|
|
tasks_run deploy;
|
|
elif [ "${GIT_REF_NAME}" == "refs/heads/dev" ]; then
|
|
echo "Deploying as beta release, as we're on the dev branch";
|
|
deploy_root_dir="${deploy_root_dir_beta}";
|
|
tasks_run deploy;
|
|
else
|
|
echo "Not deploying, as we're not on either the master or dev branches.";
|
|
fi
|
|
}
|
|
|
|
task_archive() {
|
|
task_begin "Preparing to archive";
|
|
execute mv vendor vendor.bak;
|
|
execute "${cache_dir}/composer" install --no-dev;
|
|
task_end $?;
|
|
|
|
task_begin "Packing archive";
|
|
# We include the data directory here because we assume that this task is ONLY run in a CI environment, so it should only contain the default setup generated by an earlier task.
|
|
execute tar cafv "${ARCHIVE}/Air-Quality-Web.tar.gz" app/ __nightdocs/ lib/ logic/ vendor/ data/ ./*.php ./*.md LICENSE version settings.default.toml;
|
|
task_end $?;
|
|
|
|
task_begin "Cleaning up";
|
|
execute rm -rf vendor;
|
|
execute mv vendor.bak vendor;
|
|
task_end $?;
|
|
}
|
|
|
|
|
|
task_deploy() {
|
|
stage_begin "Deploying to ${deploy_ssh_host}....";
|
|
if [ "${SSH_KEY_PATH}" == "" ]; then
|
|
echo "${FRED}${HC}Error: Can't find the SSH key as the environment variable SSH_KEY_PATH isn't set.${RS}" >&2;
|
|
stage_end 1;
|
|
fi
|
|
|
|
|
|
task_begin "Preparing upload";
|
|
|
|
subtask_begin "Creating temporary directory";
|
|
temp_dir="$(mktemp -d --suffix "-air-quality-upload")";
|
|
subtask_end $? "Error: Failed to create temporary directory";
|
|
|
|
subtask_begin "Unpacking release files";
|
|
execute tar -xf "${ARCHIVE}/Air-Quality-Web.tar.gz" -C "${temp_dir}";
|
|
subtask_end $? "Failed to unpack release files";
|
|
|
|
subtask_begin "Removing data directory";
|
|
rm -r "${temp_dir}/data"; # Delete the default data directory - there's one on the server already
|
|
subtask_end $?;
|
|
|
|
# subtask_begin "Unwinding symlinks";
|
|
# find "${temp_dir}" -D exec -type l -not -path "./beta" -exec bash -c 'ln -f "$(readlink -m "$0")" "$0"' {} \;
|
|
# subtask_end $?;
|
|
|
|
task_end $?;
|
|
|
|
# Define the directory whose contents we want to upload
|
|
source_upload_dir="${temp_dir}/";
|
|
|
|
task_begin "Acquiring upload lock";
|
|
# Acquire an exclusive project-wide lock so that we only upload stuff one-at-a-time
|
|
exec 9<"${WORKSPACE}";
|
|
flock --exclusive 9;
|
|
task_end $? "Failed to acquire lock!";
|
|
|
|
task_begin "Uploading release";
|
|
sftp -i "${SSH_KEY_PATH}" -P "${deploy_ssh_port}" -o PasswordAuthentication=no "${deploy_ssh_user}@${deploy_ssh_host}" << SFTPCOMMANDS
|
|
mkdir ${deploy_root_dir}/www-new
|
|
put -r ${source_upload_dir}/* ${deploy_root_dir}/www-new
|
|
bye
|
|
SFTPCOMMANDS
|
|
task_end $?;
|
|
|
|
task_begin "Making release live";
|
|
# Actions:
|
|
# 1. Connect to remote server
|
|
# 2. Upload new files
|
|
# 3. Create data dir symlink
|
|
# 4. Swap in new directory
|
|
# 5. Delete old directory
|
|
lftp_commands_filename="$(mktemp --suffix "-commands.lftp")";
|
|
|
|
(
|
|
echo "set sftp:connect-program 'ssh -x -i ${SSH_KEY_PATH}'";
|
|
# We have an extra : before the @ here to avoid the password prompt
|
|
echo "connect sftp://${deploy_ssh_user}:@${deploy_ssh_host}:${deploy_ssh_port}";
|
|
|
|
echo "ln -s \"../data\" \"${deploy_root_dir}/www-new/data\"";
|
|
echo "ln -s \"../../Air-Quality-Web-Beta/www/\" \"${deploy_root_dir}/www-new/beta\"";
|
|
|
|
echo "mv \"${deploy_root_dir}/www\" \"${deploy_root_dir}/www-old\"";
|
|
echo "mv \"${deploy_root_dir}/www-new\" \"${deploy_root_dir}/www\"";
|
|
echo "rm -r \"${deploy_root_dir}/data/cache\"";
|
|
echo "rm -r \"${deploy_root_dir}/www-old\"";
|
|
echo "bye";
|
|
) >"${lftp_commands_filename}";
|
|
|
|
|
|
execute lftp --version;
|
|
execute cat "${lftp_commands_filename}";
|
|
execute lftp -f "${lftp_commands_filename}";
|
|
exit_code=$?
|
|
task_end "${exit_code}" "Failed to make release live";
|
|
|
|
task_begin "Releasing lock";
|
|
exec 9>&- # Close file descriptor 9 and release the lock
|
|
task_end $?;
|
|
|
|
|
|
task_begin "Cleaning up";
|
|
execute rm -r "${temp_dir}";
|
|
task_end $?;
|
|
|
|
|
|
stage_end $? "Failed to deploy to ${deploy_ssh_host}.";
|
|
}
|
|
|
|
|
|
#########################################################################
|
|
|
|
tasks_run "$@";
|