Skip to content

Instantly share code, notes, and snippets.

@Lapsus
Last active December 1, 2020 10:09
Show Gist options
  • Save Lapsus/4ad61b9164a592f5b7f45af1f589d798 to your computer and use it in GitHub Desktop.
Save Lapsus/4ad61b9164a592f5b7f45af1f589d798 to your computer and use it in GitHub Desktop.
Shell script to update wiki-js to the latest version including a backup.
# install requirements with composer. see https://getcomposer.org
# composer global require consolidation/robo
# composer global require symfony/yaml
# rename to robo.yml
database:
host: '127.0.0.1'
port: '3306'
user: '<db-user>'
password: '<db-password>'
database: '<db-name>'
backup:
keep: 3 # number of backups to keep, set to 0 to keep infinite backups
<?php
/**
*
* Copyright 2020 Dirk Benkert <mail@dirk-benkert.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
class RoboFile extends \Robo\Tasks
{
/**
* backup local database
*
* @param string $sqlFileName
* @throws \Robo\Exception\TaskException
*/
public function backupDatabase($sqlFileName = '')
{
$host = \Robo\Robo::Config()->get('database.host');
$port = \Robo\Robo::Config()->get('database.port');
$user = \Robo\Robo::Config()->get('database.user');
$password = \Robo\Robo::Config()->get('database.password');
$database = \Robo\Robo::Config()->get('database.database');
$keep = \Robo\Robo::Config()->get('backup.keep');
// create backup folder if it does not exist.
$this->taskExecStack()
->stopOnFail(false)
->exec('mkdir backup')
->run();
$now = date('Ymd-His');
if ($sqlFileName === '') {
$sqlFileName = $database . '-' . $now . '.sql';
}
// backup local database
$this->taskExecStack()
->exec('cd backup')
->exec('mysqldump -h ' . $host . ' --port=' . $port . ' -u' . $user . ' -p' . $password . ' ' . $database . ' > ' . $sqlFileName)
->run();
$backupfiles = glob(__DIR__ . '/backup/*.sql');
rsort($backupfiles);
if(count($backupfiles) > $keep && $keep > 0) {
$deleteFiles = array_slice($backupfiles, $keep);
$this->yell('removing ' . count($deleteFiles) . ' old backups');
foreach ($deleteFiles as $file) {
$this->taskExecStack()->exec('rm ' . $file)
->run();
}
}
}
/**
* import backup of database
*
* @throws \Robo\Exception\TaskException
*/
public function backupRestore($backupFilename = null)
{
$host = \Robo\Robo::Config()->get('database.host');
$port = \Robo\Robo::Config()->get('database.port');
$user = \Robo\Robo::Config()->get('database.user');
$password = \Robo\Robo::Config()->get('database.password');
$database = \Robo\Robo::Config()->get('database.database');
if (null === $backupFilename) {
$this->yell("provide a backup file to restore ", 40, 'red');
return;
}
// delete integration database
$mysqlCommand = 'mysql -h ' . $host . ' --port=' . $port . ' -u' . $user . ' -p' . $password . " -e 'DROP DATABASE `" . $database . "`;'";
$this->taskExecStack()
->exec($mysqlCommand)
->run();
// create integration database
$mysqlCommand = 'mysql -h ' . $host . ' --port=' . $port . ' -u' . $user . ' -p' . $password . " -e 'CREATE DATABASE `" . $database . "`;'";
$this->taskExecStack()
->exec($mysqlCommand)
->run();
// import backup
$stack = $this->taskExecStack();
// if the filepath provided is relative it can be accessed from devops/base and we do not need to cd to the backup directory.
if (!file_exists($backupFilename)) {
// if the file does not exist try to locate it in the backup folder.
$stack->exec('cd backup');
}
$stack->exec( 'mysql -h ' . $host . ' --port=' . $port . ' -u' . $user . ' -p' . $password . ' ' . $database . ' < ' . $backupFilename)
->run();
$this->yell('imported ' . $backupFilename);
}
}
#!/bin/bash
#
# Copyright 2020 Dirk Benkert <mail@dirk-benkert.de>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
# and associated documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or substantial portions
# of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
# TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
## directory structure
# WORKDIR is where you put devops tools
# $WORKDIR/tmp/ is used for backup files
# $WORKDIR/backup/ is used for database backups
# WEBROOT is where you put your wiki. basically the parent of your wiki/ folder.
## usage
# bash update-wiki-js.sh to update your wiki.js to the latest version
# bash update-wiki-js.sh -f to force an update even if no new version is used
# bash update-wiki-js.sh --rollback to roll back to the previous version
#
# database backups run with robo from robo.li as i manually use this for backups of the database as well.
## CONFIGURATION
WORKDIR=~/devops/wiki
WEBROOT=~/webroot
CURRENT_VERSION=$(sed -nE 's/^\s*"version": "(.*?)",$/\1/p' $WEBROOT/wiki/package.json)
LATEST_VERSION=$(curl -s https://api.github.com/repos/Requarks/wiki/releases/latest | grep tag_name | head -n 1 | cut -d '"' -f 4)
FORCE=false
while test -n "$1" && $cont_optparse true; do
case $1 in
-f | --force) # Proceed even if more than AUTOMATIC_REMOVAL_THRESHOLD backups are to be removed
FORCE=true; shift;;
*)
cont_optparse=false;;
esac
done
if [[ $1 == "--rollback" ]]
then
if [[ -d $WORKDIR/tmp/wiki ]]
then
echo "Stopping Wiki.js ..."
sudo systemctl stop wiki.service
echo "Rolling back files ..."
rm -rf $WEBROOT/wiki/* && cp -r $WORKDIR/tmp/wiki/* $WEBROOT/wiki
echo "Rollback complete, restoring database ..."
LATEST_BACKUP=$(ls $WORKDIR/backup | sort --reverse | grep -P '\d{8}-\d{6}.sql$' | head -1)
robo --load-from ~/devops/wiki/RoboFile.php backup:restore $WORKDIR/backup/$LATEST_BACKUP
echo "restored $LATEST_BACKUP".
echo "Starting Wiki.js. This may take a few seconds ..."
sudo systemctl start wiki.service
exit 0
else
echo "No Backup found :("
exit 1
fi
fi
if [[ $FORCE == true || $CURRENT_VERSION != $LATEST_VERSION ]]
then
# fetch and download latest release
WIKI_URL=https://github.com/Requarks/wiki/releases/download/$LATEST_VERSION/wiki-js.tar.gz
echo "Downloading $WIKI_URL"
curl --progress-bar -LO $WIKI_URL
# remove old backup before updating
if [[ -d $WORKDIR/tmp/wiki ]]
then
rm -rf $WORKDIR/tmp/wiki
fi
# stop the service, assuming you use systemd
sudo systemctl stop wiki.service
# copy config
cp $WEBROOT/wiki/config.yml $WORKDIR/tmp/config.yml.bak
# backup database
robo --load-from ~/devops/wiki/RoboFile.php backup:database
# backup old version in tmp/wiki
mv $WEBROOT/wiki $WORKDIR/tmp
#make dir wiki
mkdir $WEBROOT/wiki
# unpack to ./wiki
tar xzf wiki-js.tar.gz -C $WEBROOT/wiki
# copy config back
cp $WORKDIR/tmp/config.yml.bak $WEBROOT/wiki/config.yml
# start service again
sudo systemctl start wiki.service
# cleanup
rm $WORKDIR/wiki-js.tar.gz
echo "Updated wiki.js to $LATEST_VERSION."
else
echo "Wiki.js $CURRENT_VERSION is already up-to-date, no update needed."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment