refactor: replace custom CRM with Monica fork
Some checks failed
Build & Push Monica Image to Gitea Registry / build-and-push (push) Failing after 9s

This commit is contained in:
Kroonk
2026-05-22 16:19:55 +02:00
parent 38cc4c09ca
commit a213a1dba0
2215 changed files with 242567 additions and 6015 deletions

View File

@@ -0,0 +1,54 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Redirect to https
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,N]
<IfModule mod_headers.c>
# Activate HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload;"
Header always set Referrer-Policy "no-referrer"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Download-Options "noopen"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Permitted-Cross-Domain-Policies "none"
Header always set X-Robots-Tag "none"
Header always set X-XSS-Protection "1; mode=block"
# Assets expire after 1 month
<filesMatch ".(css|js|json|woff2?|ttf|eot|svg)$">
Header set Cache-Control "public, max-age=2628000"
</filesMatch>
</IfModule>
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect .well-known urls (https://en.wikipedia.org/wiki/List_of_/.well-known/_services_offered_by_webservers)
RewriteCond %{REQUEST_URI} .well-known/carddav
RewriteRule ^ /dav/ [L,R=301,N]
RewriteCond %{REQUEST_URI} .well-known/caldav
RewriteRule ^ /dav/ [L,R=301,N]
RewriteCond %{REQUEST_URI} .well-known/security.txt
RewriteRule ^ /security.txt [L,R=301,N]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !dav/*
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>

28
scripts/ci/.env.mysql Normal file
View File

@@ -0,0 +1,28 @@
# ENV FILE FOR THE GITHUB ACTION RUNNING MYSQL
APP_ENV=testing
APP_KEY=base64:NTrXToqFZJlv48dgPc+kNpc3SBt333TfDnF1mDShsBg=
APP_DEBUG=true
APP_URL=http://localhost:8000
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=monica
DB_USERNAME=root
DB_PASSWORD=root
DB_USE_UTF8MB4=true
BROADCAST_DRIVER=log
LOG_CHANNEL=testing
# Values from phpunit.xml
DEBUGBAR_ENABLED=false
CACHE_DRIVER=array
CHECK_VERSION=false
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
MAIL_MAILER=array
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME=
APP_EMAIL_NEW_USERS_NOTIFICATION=

17
scripts/ci/.env.postgres Normal file
View File

@@ -0,0 +1,17 @@
APP_ENV=testing
APP_KEY=base64:NTrXToqFZJlv48dgPc+kNpc3SBt333TfDnF1mDShsBg=
APP_URL=http://localhost:8000
DB_CONNECTION=pgsqltesting
DB_TEST_HOST=127.0.0.1
DB_TEST_DATABASE=monica
DB_TEST_USERNAME=postgres
DB_TEST_PASSWORD=
CACHE_DRIVER=array
SESSION_DRIVER=file
QUEUE_CONNECTION=sync
LOG_CHANNEL=testing
MFA_ENABLED=true
DAV_ENABLED=true

101
scripts/ci/package.sh Normal file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
set -eo pipefail
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && /bin/pwd -P)
source $SELF_PATH/../realpath.sh
ROOT=$(realpath $SELF_PATH/../..)
version=$1
if [ -z "$version" ]; then
echo "Version parameter is mandatory" >&2
exit 1
fi
commit=$2
if [ -z "$commit" ]; then
commit=$(git --git-dir $ROOT/.git log --pretty="%H" -n1 HEAD)
release=$(git --git-dir $ROOT/.git log --pretty="%h" -n1 HEAD)
fi
set -v
echo -n "$version" | tee $ROOT/config/.version
echo -n $commit | tee $ROOT/config/.commit
echo -n ${release:-$version} | tee $ROOT/config/.release
# BUILD
composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader --no-dev --working-dir=$ROOT
yarn --cwd $ROOT run inst
yarn --cwd $ROOT run production
# PACKAGE
package=monica-$version
mkdir -p $package/database
ln -s $ROOT/.env.example $package/
ln -s $ROOT/app.json $package/
ln -s $ROOT/artisan $package/
ln -s $ROOT/CHANGELOG.md $package/
ln -s $ROOT/CONTRIBUTING.md $package/
ln -s $ROOT/CONTRIBUTORS $package/
ln -s $ROOT/composer.json $package/
ln -s $ROOT/composer.lock $package/
ln -s $ROOT/LICENSE.md $package/
ln -s $ROOT/nginx_app.conf $package/
ln -s $ROOT/package.json $package/
ln -s $ROOT/Procfile $package/
ln -s $ROOT/README.md $package/
ln -s $ROOT/server.php $package/
ln -s $ROOT/webpack.mix.js $package/
ln -s $ROOT/yarn.lock $package/
ln -s $ROOT/app $package/
ln -s $ROOT/bootstrap $package/
ln -s $ROOT/config $package/
ln -s $ROOT/docs $package/
ln -s $ROOT/public $package/
ln -s $ROOT/resources $package/
ln -s $ROOT/routes $package/
ln -s $ROOT/vendor $package/
ln -s $ROOT/database/factories $package/database/
ln -s $ROOT/database/migrations $package/database/
ln -s $ROOT/database/seeds $package/database/
mkdir -p $package/storage/app/public
mkdir -p $package/storage/logs
mkdir -p $package/storage/framework/cache
mkdir -p $package/storage/framework/views
mkdir -p $package/storage/framework/sessions
tar chfj $package.tar.bz2 --exclude .gitignore --exclude .gitkeep $package
sha512sum "$package.tar.bz2" > "$package.tar.bz2.sha512"
echo "package=$package.tar.bz2" >> $GITHUB_OUTPUT
# ASSETS
assets=monica-assets-$version
mkdir -p $assets/public
ln -s $ROOT/public/mix-manifest.json $assets/public/
ln -s $ROOT/public/js $assets/public/
ln -s $ROOT/public/css $assets/public/
ln -s $ROOT/public/fonts $assets/public/
tar chfj $assets.tar.bz2 --exclude .gitignore --exclude .gitkeep $assets
sha512sum "$assets.tar.bz2" > "$assets.tar.bz2.sha512"
echo "assets=$assets.tar.bz2" >> $GITHUB_OUTPUT
# SIGN
if [ -n "${GPG_FINGERPRINT:-}" -a -n "${GPG_PASSPHRASE:-}" ]; then
for f in {$package,$assets}.tar.bz2{,.sha512}; do
echo "Signing '$f'..."
echo "$GPG_PASSPHRASE" | gpg --batch --yes --passphrase-fd 0 --pinentry-mode=loopback --local-user $GPG_FINGERPRINT --sign --armor --detach-sig --output "$f.asc" "$f"
echo -e "\nSigned with key fingerprint $GPG_FINGERPRINT" >> "$f.asc"
done
fi

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
backupStaticAttributes="false"
bootstrap="vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Unit Tests">
<directory suffix="Test.php">./tests/Unit/Models</directory>
</testsuite>
<testsuite name="Helpers Tests">
<directory suffix="Test.php">./tests/Unit/Helpers</directory>
</testsuite>
<testsuite name="Feature Tests">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
<testsuite name="Api Tests">
<directory suffix="Test.php">./tests/Api</directory>
</testsuite>
<testsuite name="Commands Tests">
<directory suffix="Test.php">./tests/Commands</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>
<exclude>
<file>./app/Http/routes.php</file>
</exclude>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing"/>
<env name="APP_KEY" value="base64:NTrXToqFZJlv48dgPc+kNpc3SBt333TfDnF1mDShsBg="/>
<env name="DB_CONNECTION" value="pgsqltesting"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="APP_DEFAULT_LOCALE" value="en"/>
</php>
<logging>
<log type="coverage-clover" target="./results/coverage.xml"/>
<log type="junit" target="./results/junit.xml"/>
</logging>
</phpunit>

106
scripts/ci/update-assets.sh Normal file
View File

@@ -0,0 +1,106 @@
#!/bin/bash
if [ "$CIRCLECI" == "true" ]; then
if [[ ! -z $CIRCLE_PULL_REQUEST ]] ; then
CIRCLE_PR_NUMBER="${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}"
REPO=$CIRCLE_PULL_REQUEST
REPO=${REPO##https://github.com/}
REPO=${REPO%%/pull/$CIRCLE_PR_NUMBER}
else
REPO=$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
fi
BRANCH=${CIRCLE_BRANCH:-$CIRCLE_TAG}
PR_NUMBER=${CIRCLE_PR_NUMBER:-false}
elif [ "$TRAVIS" == "true" ]; then
REPO=$TRAVIS_REPO_SLUG
BRANCH=${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}
PR_NUMBER=$TRAVIS_PULL_REQUEST
elif [ "$TF_BUILD" == "True" ]; then
REPO=$BUILD_REPOSITORY_NAME
BRANCH=${SYSTEM_PULLREQUEST_SOURCEBRANCH:-$BUILD_SOURCEBRANCHNAME}
PR_NUMBER=${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER:-false}
elif [[ -n $BUILD_NUMBER ]]; then
echo "CHANGE_ID=$CHANGE_ID"
echo "CHANGE_URL=$CHANGE_URL"
REPO=${CHANGE_URL##https://github.com/}
if [[ ! -z $CHANGE_ID ]] ; then
REPO=${REPO%%/pull/$CHANGE_ID}
fi
PR_NUMBER=${CHANGE_ID:-false}
BRANCH=$BRANCH_NAME
fi
REPOSITORY_OWNER=monicahq/monica
set -euo pipefail
# Update assets
echo -e "\033[1;32m# Build assets ...\033[0;37m"
echo -e "\033[1;36myarn run production\033[0;37m"
yarn run production
echo ""
# Check if there is zero update needed
status=$(git status --porcelain)
if [ "$status" = "" ]; then
echo "Nothing to push, already up to date."
exit 0;
fi
echo "Waiting modifications:"
echo $status
# Add files
git add public/mix-manifest.json
git add public/js/*
git add public/css/*
git add public/fonts/*
# Commit
if [ -z "${ASSETS_USERNAME:-}" ]; then
#No username
echo -e "\033[0;31mMonica asset are not up to date.\033[0;37m"
echo "Please update the Monica assets yourself by running:"
echo " ~ yarn run production"
exit 2
fi
git config user.email $ASSETS_EMAIL
git config user.name $ASSETS_USERNAME
git commit -m "chore(assets): Update assets"
# Push
if [ "$BRANCH" == "main" ] && [ "$PR_NUMBER" == "false" ]; then
echo -e "\033[0;31mmain branch is not up to date, but we can't update it directly...\033[0;37m"
exit 0
elif [ -n "${ASSETS_GITHUB_TOKEN:-}" ]; then
REPOS_VALUES=($(curl -H "Authorization: token $ASSETS_GITHUB_TOKEN" -sSL https://api.github.com/repos/$REPO/pulls/$PR_NUMBER | jq -r -c ".head.repo.full_name, .head.ref"))
PULL_REQUEST_BRANCH=
PULL_REQUEST_REPOSITORY=${REPOS_VALUES[0]}
PULL_REQUEST_HEADBRANCH=${REPOS_VALUES[1]}
if [ -z "${PULL_REQUEST_REPOSITORY:-}" ] || [ "$PULL_REQUEST_REPOSITORY" == "null" ]; then
echo -e "\033[0;31mError with github api call\033[0;37m"
exit 1
elif [ "$PULL_REQUEST_REPOSITORY" == "$REPOSITORY_OWNER" ]; then
PULL_REQUEST_BRANCH=$PULL_REQUEST_HEADBRANCH
else
echo -e "\033[0;31mMonica asset are not up to date.\033[0;37m"
echo "We can't commit in $PULL_REQUEST_REPOSITORY to update them directly."
echo "Please update the Monica assets yourself by running:"
echo " ~ yarn run production"
exit 2
fi
echo "Pushing files to $PULL_REQUEST_BRANCH branch ..."
remote=monica-origin
remoteurl="https://$ASSETS_USERNAME:$ASSETS_GITHUB_TOKEN@github.com/$REPO"
git remote remove $remote || true
git remote add -f $remote $remoteurl || true
git push $remote HEAD:$PULL_REQUEST_BRANCH
# Exit with error to stop the current build
echo "...pushed files successfully."
echo "Exit with error to stop the current build."
exit -1
fi

View File

@@ -0,0 +1,10 @@
#!/bin/sh
file=$1
release=$2
curl -H "Authorization: token $GITHUB_TOKEN" \
-H "Content-Type: application/octet-stream" \
-X POST \
--data-binary @"$file" \
"https://uploads.github.com/repos/monicahq/monica/releases/$release/assets?name=$(basename $file)"

1874
scripts/database.test.sql Normal file

File diff suppressed because one or more lines are too long

181
scripts/docker/Dockerfile Normal file
View File

@@ -0,0 +1,181 @@
###
### ~ Monica dev Dockerfile
###
### This file is used for dev purpose.
### The standard monica image definition will be found here: https://github.com/monicahq/docker
### This file is based off of the `apache` variant in the above mentioned repo
###
FROM php:8.1-apache
# opencontainers annotations https://github.com/opencontainers/image-spec/blob/master/annotations.md
LABEL org.opencontainers.image.authors="Alexis Saettler <alexis@saettler.org>" \
org.opencontainers.image.title="MonicaHQ, the Personal Relationship Manager" \
org.opencontainers.image.description="This is MonicaHQ, your personal memory! MonicaHQ is like a CRM but for the friends, family, and acquaintances around you." \
org.opencontainers.image.url="https://monicahq.com" \
org.opencontainers.image.vendor="Monica"
# entrypoint.sh dependencies
RUN set -ex; \
\
apt-get update; \
apt-get install -y --no-install-recommends \
bash \
busybox-static \
; \
rm -rf /var/lib/apt/lists/*
# Install required PHP extensions
RUN set -ex; \
\
savedAptMark="$(apt-mark showmanual)"; \
\
apt-get update; \
apt-get install -y --no-install-recommends \
libicu-dev \
zlib1g-dev \
libzip-dev \
libpng-dev \
libxml2-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libgmp-dev \
libmemcached-dev \
libmagickwand-dev \
libwebp-dev \
; \
\
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
if [ ! -e /usr/include/gmp.h ]; then ln -s /usr/include/$debMultiarch/gmp.h /usr/include/gmp.h; fi;\
docker-php-ext-configure intl; \
docker-php-ext-configure gd --with-jpeg --with-freetype --with-webp; \
docker-php-ext-configure gmp; \
docker-php-ext-install -j$(nproc) \
intl \
zip \
bcmath \
gd \
gmp \
pdo_mysql \
mysqli \
soap \
; \
\
# pecl will claim success even if one install fails, so we need to perform each install separately
pecl install APCu; \
pecl install memcached; \
pecl install redis; \
\
docker-php-ext-enable \
apcu \
memcached \
redis \
; \
\
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark; \
ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
| awk '/=>/ { print $3 }' \
| sort -u \
| xargs -r dpkg-query -S \
| cut -d: -f1 \
| sort -u \
| xargs -rt apt-mark manual; \
\
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*
# Set crontab for schedules
RUN set -ex; \
\
mkdir -p /var/spool/cron/crontabs; \
rm -f /var/spool/cron/crontabs/root; \
echo '*/5 * * * * php /var/www/html/artisan schedule:run -v' > /var/spool/cron/crontabs/www-data
# Opcache
ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS="0" \
PHP_OPCACHE_MAX_ACCELERATED_FILES="20000" \
PHP_OPCACHE_MEMORY_CONSUMPTION="192" \
PHP_OPCACHE_MAX_WASTED_PERCENTAGE="10"
RUN set -ex; \
\
docker-php-ext-enable opcache; \
{ \
echo '[opcache]'; \
echo 'opcache.enable=1'; \
echo 'opcache.revalidate_freq=0'; \
echo 'opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS}'; \
echo 'opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES}'; \
echo 'opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION}'; \
echo 'opcache.max_wasted_percentage=${PHP_OPCACHE_MAX_WASTED_PERCENTAGE}'; \
echo 'opcache.interned_strings_buffer=16'; \
echo 'opcache.fast_shutdown=1'; \
} > $PHP_INI_DIR/conf.d/opcache-recommended.ini; \
\
echo 'apc.enable_cli=1' >> $PHP_INI_DIR/conf.d/docker-php-ext-apcu.ini; \
\
echo 'memory_limit=512M' > $PHP_INI_DIR/conf.d/memory-limit.ini
RUN set -ex; \
\
a2enmod headers rewrite remoteip; \
{ \
echo RemoteIPHeader X-Real-IP; \
echo RemoteIPTrustedProxy 10.0.0.0/8; \
echo RemoteIPTrustedProxy 172.16.0.0/12; \
echo RemoteIPTrustedProxy 192.168.0.0/16; \
} > $APACHE_CONFDIR/conf-available/remoteip.conf; \
a2enconf remoteip
RUN set -ex; \
APACHE_DOCUMENT_ROOT=/var/www/html/public; \
sed -ri -e "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" $APACHE_CONFDIR/sites-available/*.conf; \
sed -ri -e "s!/var/www/!${APACHE_DOCUMENT_ROOT}!g" $APACHE_CONFDIR/apache2.conf $APACHE_CONFDIR/conf-available/*.conf
WORKDIR /var/www/html
# Copy the local (outside Docker) source into the working directory,
# copy system files into their proper homes, and set file ownership
# correctly
COPY --chown=www-data:www-data . ./
RUN set -ex; \
\
mkdir -p bootstrap/cache; \
mkdir -p storage; \
chown -R www-data:www-data bootstrap/cache storage; \
chmod -R g+w bootstrap/cache storage
COPY --chown=www-data:www-data .env.example .env
# Composer installation
COPY scripts/docker/install-composer.sh /usr/local/sbin/
RUN install-composer.sh
# Install composer dependencies
RUN set -ex; \
\
mkdir -p storage/framework/views; \
composer install --no-interaction --no-progress --no-dev; \
composer clear-cache; \
rm -rf .composer
# Install node dependencies
RUN set -ex; \
\
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -; \
apt-get install -y nodejs; \
npm install -g yarn; \
yarn run inst; \
yarn run dev; \
\
rm -rf /var/lib/apt/lists/*
COPY scripts/docker/entrypoint.sh \
scripts/docker/cron.sh \
scripts/docker/queue.sh \
/usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
CMD ["apache2-foreground"]

50
scripts/docker/build.sh Normal file
View File

@@ -0,0 +1,50 @@
#!/bin/bash
set -eo pipefail
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && /bin/pwd -P)
source $SELF_PATH/../realpath.sh
ROOT=$(realpath $SELF_PATH/../..)
version=$(git --git-dir $ROOT/.git describe --abbrev=0 --tags | sed 's/^v//')
commit=$1
if [ "$commit" == "--skip-build" ]; then
shift
tag=$commit
commit=$1
fi
if [ -z "$commit" ]; then
commit=$(git --git-dir $ROOT/.git log --pretty="%H" -n1 HEAD)
release=$(git --git-dir $ROOT/.git log --pretty="%h" -n1 HEAD)
else
shift
release=$(git --git-dir $ROOT/.git describe --abbrev=0 --tags --exact-match $commit 2>/dev/null || git --git-dir $ROOT/.git log --pretty="%h" -n1 $commit)
fi
if [ -z "$tag" ]; then
tag=${1:-monica-dev}
fi
echo Version
echo -n "$version" | tee config/.version
echo -e "\nCommit"
echo -n "$commit" | tee config/.commit
echo -e "\nRelease"
echo -n "$release" | tee config/.release
echo -e "\n"
# BUILD
composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader --no-dev --working-dir=$ROOT
yarn --cwd $ROOT run inst
yarn --cwd $ROOT run production
# DOCKER BUILD
if [ "$tag" != "--skip-build" ]; then
docker build -t $tag -f $SELF_PATH/Dockerfile $ROOT
rm -f config/.{version,commit,release}
fi

4
scripts/docker/cron.sh Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
set -eu
exec busybox crond -f -l 0 -L /proc/1/fd/1

View File

@@ -0,0 +1,63 @@
#!/bin/bash
set -Eeo pipefail
# wait for the database to start
waitfordb() {
HOST=${DB_HOST:-mysql}
PORT=${DB_PORT:-3306}
echo "Connecting to ${HOST}:${PORT}"
attempts=0
max_attempts=30
while [ $attempts -lt $max_attempts ]; do
busybox nc -w 1 "${HOST}:${PORT}" && break
echo "Waiting for ${HOST}:${PORT}..."
sleep 1
let "attempts=attempts+1"
done
if [ $attempts -eq $max_attempts ]; then
echo "Unable to contact your database at ${HOST}:${PORT}"
exit 1
fi
echo "Waiting for database to settle..."
sleep 3
}
if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ]; then
MONICADIR=/var/www/html
ARTISAN="php ${MONICADIR}/artisan"
# Ensure storage directories are present
STORAGE=${MONICADIR}/storage
mkdir -p ${STORAGE}/logs
mkdir -p ${STORAGE}/app/public
mkdir -p ${STORAGE}/framework/views
mkdir -p ${STORAGE}/framework/cache
mkdir -p ${STORAGE}/framework/sessions
chown -R www-data:www-data ${STORAGE}
chmod -R g+rw ${STORAGE}
if [ -z "${APP_KEY:-}" -o "$APP_KEY" = "ChangeMeBy32KeyLengthOrGenerated" ]; then
${ARTISAN} key:generate --no-interaction
else
echo "APP_KEY already set"
fi
# Run migrations
waitfordb
${ARTISAN} monica:update --force -vv
if [ ! -f "${STORAGE}/oauth-public.key" -o ! -f "${STORAGE}/oauth-private.key" ]; then
echo "Passport keys creation ..."
${ARTISAN} passport:keys
${ARTISAN} passport:client --personal --no-interaction
echo "! Please be careful to backup $MONICADIR/storage/oauth-public.key and $MONICADIR/storage/oauth-private.key files !"
fi
fi
exec "$@"

View File

@@ -0,0 +1,23 @@
#!/bin/sh
set -v
SETUP=composer-setup.php
cd /tmp
EXPECTED_SIGNATURE=$(curl -sS https://composer.github.io/installer.sig)
curl -sS -o $SETUP https://getcomposer.org/installer
ACTUAL_SIGNATURE=$(openssl sha384 $SETUP | cut -d' ' -f2)
if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
then
>&2 echo 'ERROR: Invalid installer signature'
rm $SETUP
exit 1
fi
php $SETUP --quiet --install-dir=/usr/local/bin --filename=composer
RESULT=$?
rm $SETUP
exit $RESULT

4
scripts/docker/queue.sh Normal file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
set -eu
exec php /var/www/html/artisan queue:work --sleep=10 --timeout=0 --tries=3 --queue=default,migration >/proc/1/fd/1 2>/proc/1/fd/2

16
scripts/realpath.sh Normal file
View File

@@ -0,0 +1,16 @@
realpath ()
{
f=$@;
if [ -z "$f" ]; then
f=$(pwd)
fi
if [ -d "$f" ]; then
base="";
dir="$f";
else
base="/$(basename "$f")";
dir=$(dirname "$f");
fi;
dir=$(cd "$dir" && /bin/pwd -P);
echo "$dir$base"
}

View File

@@ -0,0 +1,7 @@
#!/bin/bash
sudo apt-get update
sudo apt-get install lsb-release
curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome.deb
sudo sed -i 's|HERE/chrome"|HERE/chrome" --disable-setuid-sandbox --no-sandbox|g' /opt/google/chrome/google-chrome
rm google-chrome.deb

View File

@@ -0,0 +1,36 @@
<?php
/**
* Copy of server.php with Code Coverage capture.
*/
/** Coverage files destination. */
const STORAGE = '/results/cov';
$root = realpath(__DIR__.'/../../');
$uri = urldecode(
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)
);
// This file allows us to emulate Apache's "mod_rewrite" functionality from the
// built-in PHP web server. This provides a convenient way to test a Laravel
// application without having installed a "real" web server software here.
if ($uri !== '/' && file_exists($root.'/public'.$uri)) {
return false;
}
/**
* Set CodeCoverage via LiveCodeCoverage.
*/
require $root.'/vendor/autoload.php';
$shutDownCodeCoverage = \LiveCodeCoverage\LiveCodeCoverage::bootstrap(
true,
$root.STORAGE,
$root.'/phpunit.xml'
);
require_once $root.'/public/index.php';
$shutDownCodeCoverage();

View File

@@ -0,0 +1,29 @@
#!/bin/bash
set -evuo pipefail
SELF_PATH=$(cd -P -- "$(dirname -- "$0")" && /bin/pwd -P)
source $SELF_PATH/../realpath.sh
ROOT=$(realpath $SELF_PATH/../..)
if [ -z "${DISPLAY:-}" ]; then
echo Start Xvfb;
export DISPLAY=:99.0;
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x24 || true;
fi
if ! $(nc -z localhost 4444); then
$ROOT/vendor/bin/selenium-server-standalone -role hub -log "$ROOT/selenium-server.log" &
until $(nc -z localhost 4444); do
echo Waiting for selenium hub to start...;
sleep 1;
done
fi
if ! $(nc -z localhost 8910); then
java -Dwebdriver.chrome.driver="$ROOT/vendor/bin/chromedriver" -jar "$ROOT/vendor/se/selenium-server-standalone/bin/selenium-server-standalone.jar" -role node -port 8910 -log "$ROOT/selenium-node.log" &
until $(nc -z localhost 8910); do
echo Waiting for selenium node to start...;
sleep 1;
done
fi

84
scripts/update/debian.sh Normal file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
#
# ABOUT THIS SCRIPT
# -----------------
# Last updated: 2021-10-26
# Last tested: Monica v3.3.1
#
# USE AT YOUR OWN RISK! Make sure you have a good, working backup of
# your database and other files before using this script.
#
# WHAT THIS SCRIPT DOES
# ---------------------
# This script has been written to run the various steps required to
# upgrade Monica to the specified version. You can check which is the
# current version here: https://github.com/monicahq/monica/releases
#
# HOW TO USE THIS SCRIPT
# ----------------------
# To run this command, you run the shell script and specify the version
# you want to update to, like so:
#
# $ ./debian.sh 3.3.1
#
# Replacing "3.3.1" with the version you want. The script will then run
# through the required steps to update you to 3.3.1.
# THE SCRIPT ITSELF
# -----------------
# 1. Open Monica's directory
cd /var/www/monica ; \
# 2. Checkout the current version
git fetch ; \
git checkout tags/v$1
# 3. Delete Composer packages
rm -rf vendor ; \
# Note: This step might *not* be strictly necessary, but it avoids fatal
# errors when attempting to update Monica on a Debian system.
# More information: https://github.com/monicahq/monica/issues/5308
# 4. Now (re)install all required Composer packages
composer install --no-dev ; \
# 5. Delete all the node modules installed by yarn
rm -rf node_modules
# Note: This step might *not* be strictly necessary, but it avoids yarn
# throwing 126 exit errors that I can't otherwise fix.
# 6. Now (re)install required yarn packages
yarn install ; \
# 7. Generate assets (CSS, JS, others) using yarn
yarn run production ; \
# 8. Update Monica itself. Per the README, this "runs migration scripts
# for the database, and flushes all caches for config, route, and
# view as an optimization process. Its easier than running every
# required command individually".
php artisan monica:update --force ; \
# 9. And finally, set correct ownership and permissions for Monica.
# This is another step that may not be necessary, but it should avoid
# any "permission denied" or HTTP 500 errors being created.
chown -R www-data:www-data /var/www/monica ; \
find /var/www/monica -type f -exec chmod 664 {} \;
find /var/www/monica -type d -exec chmod 775 {} \;
# And that's it!

2
scripts/vagrant/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.log
.vagrant/

35
scripts/vagrant/Vagrantfile vendored Normal file
View File

@@ -0,0 +1,35 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION ||= "2"
$script = <<SCRIPT
MONICADIR=/var/www/html/monica
ARTISAN="php ${MONICADIR}/artisan"
echo -e "\n\033[4;32mConfiguring Monica\033[0;40m"
cd $MONICADIR
APP_KEY=$(source .env 2>/dev/null || echo $APP_KEY)
if [[ -z ${APP_KEY:-} || "$APP_KEY" == "ChangeMeBy32KeyLengthOrGenerated" ]]; then
${ARTISAN} key:generate --no-interaction
else
echo "APP_KEY already set"
fi
# Run migrations
${ARTISAN} monica:update --force -v
echo -e "\n\n\033[1;32mDone! You can access Monica by visiting \033[4;96mhttp://localhost:8080\033[0;40m\033[1;32m from your host machine\033[0;40m"
SCRIPT
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "monicahq/monicahq"
config.vm.hostname = "monica"
config.vm.define "monica"
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.provision "shell", inline: $script, keep_color: true
end

3
scripts/vagrant/build/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.box
*.log
.vagrant/

View File

@@ -0,0 +1,22 @@
GIT_TAG := $(shell git describe --abbrev=0 --tags)
VERSION := $(subst v,,$(GIT_TAG))
build: base
rm -rf .vagrant
GIT_TAG=$(GIT_TAG) vagrant up monicahq-stable
base:
vagrant box list | grep -q "ubuntu/bionic64" || vagrant box add ubuntu/bionic64
vagrant box update --box ubuntu/bionic64
package: build
rm -f monicahq-stable.box
vagrant box remove monicahq/monicahq --box-version 0 || true
vagrant package monicahq-stable --output ./monicahq-stable.box --vagrantfile ../Vagrantfile
vagrant box add monicahq/monicahq ./monicahq-stable.box
upload:
mv monicahq-stable.box monicahq-$(GIT_TAG).box
./vagrant-upload.sh
.PHONY: build base package

26
scripts/vagrant/build/Vagrantfile vendored Normal file
View File

@@ -0,0 +1,26 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION ||= "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.synced_folder ".", "/vagrant"
# Create a box with the latest version available
config.vm.define "monicahq-latest", primary: true do |monicahq|
monicahq.vm.box = "ubuntu/bionic64"
monicahq.vm.hostname = "monica"
monicahq.vm.boot_timeout = 180
monicahq.vm.provision "shell", path: "install-monica.sh", keep_color: true
end
# Create a box with the specific version tag
config.vm.define "monicahq-stable" do |monicahq|
monicahq.vm.box = "ubuntu/bionic64"
monicahq.vm.hostname = "monica"
monicahq.vm.boot_timeout = 180
monicahq.vm.provision "shell", path: "install-monica.sh", keep_color: true, env: {"GIT_TAG" => "#{ENV['GIT_TAG']}"}
end
end

View File

@@ -0,0 +1,105 @@
#!/usr/bin/env bash
set -euo pipefail
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-changeme}
MYSQL_DB_DATABASE=${MYSQL_DB_DATABASE:-monica}
MYSQL_DB_USERNAME=${MYSQL_DB_USERNAME:-monica}
MYSQL_DB_PASSWORD=${MYSQL_DB_PASSWORD:-changeme}
DESTDIR=/var/www/html/monica
function update_setting() {
file=$1
name=$2
value=$3
if $(grep -q "$name" $file); then
sed -i "s/\($name\).*/\1=$value/" $file;
else
echo -e "\n$name=$value" | tee -a $file;
fi
}
export DEBIAN_FRONTEND=noninteractive
apt-get update >/dev/null
echo -e "\033[1;32m########################\033[0;40m"
echo -e "\033[1;32mInstalling Monica ${GIT_TAG:-}\033[0;40m"
echo -e "\033[1;32m########################\033[0;40m"
echo -e "\n\033[4;32mInstalling apache\033[0;40m"
apt-get install -y apache2 >/dev/null
echo "ServerName vagrant" >> /etc/apache2/apache2.conf # suppress apache warning
echo -e "\n\033[4;32mInstalling MySQL with default root password\033[0;40m"
debconf-set-selections <<< "mysql-server mysql-server/root_password password $MYSQL_ROOT_PASSWORD"
debconf-set-selections <<< "mysql-server mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD"
apt-get install -y mysql-server mysql-client >/dev/null
echo -e "\n\033[4;32mInstalling PHP 8.1\033[0;40m"
apt-get install -y curl gnupg2 apt-transport-https apt-transport-https lsb-release ca-certificates >/dev/null
add-apt-repository -y ppa:ondrej/php >/dev/null
apt-get update >/dev/null
apt-get install -y php8.1 >/dev/null
echo -e "\n\033[4;32mInstalling git\033[0;40m"
apt-get install -y git >/dev/null
echo -e "\n\033[4;32mInstalling composer\033[0;40m"
apt-get install -y curl php8.1-cli >/dev/null
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer >/dev/null
echo -e "\n\033[4;32mInstalling packages for Monica\033[0;40m"
apt-get install -y php8.1-bcmath php8.1-curl php8.1-common php8.1-fpm \
php8.1-gd php8.1-gmp php8.1-intl php8.1-json php8.1-mbstring php8.1-mysql \
php8.1-opcache php8.1-redis php8.1-xml php8.1-zip >/dev/null
echo -e "\n\033[4;32mInstalling node.js\033[0;40m"
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - >/dev/null
apt-get install -y nodejs >/dev/null
echo -e "\n\033[4;32mInstalling yarn\033[0;40m"
npm install --global yarn >/dev/null
echo -e "\n\033[4;32mGetting database ready\033[0;40m"
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "CREATE DATABASE $MYSQL_DB_DATABASE;
CREATE USER '$MYSQL_DB_USERNAME'@'localhost' IDENTIFIED BY '$MYSQL_DB_PASSWORD';
GRANT ALL ON $MYSQL_DB_DATABASE.* TO '$MYSQL_DB_USERNAME'@'localhost';
FLUSH PRIVILEGES;"
echo -e "\n\033[4;32mInstalling Monica\033[0;40m"
git clone https://github.com/monicahq/monica.git $DESTDIR
cd $DESTDIR
if [ -n "${GIT_TAG:-}" ]; then
git checkout tags/$GIT_TAG
fi
composer install --no-interaction --no-dev --no-progress >/dev/null
composer clear-cache
echo -e "\n\033[4;32mBuild assets\033[0;40m"
yarn install
yarn run production
echo -e "\n\033[4;32mConfiguring Monica\033[0;40m"
cp .env.example .env
update_setting .env DB_DATABASE "$MYSQL_DB_DATABASE"
update_setting .env DB_USERNAME "$MYSQL_DB_USERNAME"
update_setting .env DB_PASSWORD "$MYSQL_DB_PASSWORD"
update_setting .env APP_DISABLE_SIGNUP "false"
chown -R www-data:www-data .
echo -e "\n\033[4;32mConfiguring cron script\033[0;40m"
{ crontab -l -u www-data; echo "* * * * * /usr/bin/php $DESTDIR/artisan schedule:run"; } | crontab -u www-data - || true
echo -e "\n\033[4;32mConfiguring apache\033[0;40m"
a2enmod rewrite
sed -i "s/\(DocumentRoot\).*/\1 ${DESTDIR//\//\\\/}\/public/" /etc/apache2/sites-enabled/000-default.conf
sed -i "s/\/var\/www\//${DESTDIR//\//\\\/}\/public\//" /etc/apache2/apache2.conf
sed -i "/<Directory ${DESTDIR//\//\\\/}\/public\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/" /etc/apache2/apache2.conf
systemctl restart apache2
echo -e "\n\033[4;32mSystem update\033[0;40m"
apt-get -y upgrade
apt-get -y autoremove
apt-get -y clean

View File

@@ -0,0 +1,75 @@
#!/bin/bash
set -euvo pipefail
GIT_TAG=$(git describe --abbrev=0 --tags)
VERSION=${GIT_TAG##v}
API=https://app.vagrantup.com/api/v1
# Create a new version
response=$(
curl -sSL --header "Content-Type: application/json" --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
"$API/box/monicahq/monicahq/versions" \
--data "{ \
\"version\": { \
\"version\": \"$VERSION\", \
\"description\": \"https://github.com/monicahq/monica/releases/tag/$GIT_TAG\" \
} \
}"
)
if [ $(echo "$response" | jq .success) == "false" ]; then
if [ $(echo "$response" | jq .errors[0]) != "Version has already been taken" ]; then
echo "$response" | jq .errors[0]
exit 1
fi
fi
# Create provider
response=$(
curl -sSL --header "Content-Type: application/json" --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
"$API/box/monicahq/monicahq/version/$VERSION/providers" \
--data "{ \
\"provider\": { \
\"name\": \"virtualbox\" \
} \
}"
)
if [ $(echo "$response" | jq .success) == "false" ]; then
if [ $(echo "$response" | jq .errors[0]) != "Metadata provider must be unique for version" ]; then
echo "$response" | jq .errors[0]
exit 1
fi
fi
# Upload the box
response=$(
curl -sSL --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
"$API/box/monicahq/monicahq/version/$VERSION/provider/virtualbox/upload"
)
if [ $(echo "$response" | jq .success) == "false" ]; then
echo "$response" | jq .errors[0]
exit 1
fi
upload_path=$(echo "$response" | jq .upload_path)
upload_path="${upload_path%\"}"
upload_path="${upload_path#\"}"
curl -fL --progress-bar \
--request PUT \
"$upload_path" \
--upload-file "monicahq-$GIT_TAG.box"
retval=$?
if [ $? -ne 0 ]; then
exit 1
fi
# Publish the version
response=$(
curl -sSL --header "Authorization: Bearer $VAGRANT_CLOUD_TOKEN" \
--request PUT \
"$API/box/monicahq/monicahq/version/$VERSION/release"
)
if [ $(echo "$response" | jq .success) == "false" ]; then
echo "$response" | jq .errors[0]
exit 1
fi

View File

@@ -0,0 +1,44 @@
#!/bin/bash
set -euo pipefail
# set version of vagrant to use :
vagrantversion=2.2.15
mkdir -p $HOME/vagrant
pushd $HOME/vagrant > /dev/null
if [ ! -d "vagrant-$vagrantversion" ]; then
mkdir -p "vagrant-$vagrantversion"
pushd "vagrant-$vagrantversion" > /dev/null
curl -Os https://releases.hashicorp.com/vagrant/${vagrantversion}/vagrant_${vagrantversion}_x86_64.deb
curl -Os https://releases.hashicorp.com/vagrant/${vagrantversion}/vagrant_${vagrantversion}_SHA256SUMS
curl -Os https://releases.hashicorp.com/vagrant/${vagrantversion}/vagrant_${vagrantversion}_SHA256SUMS.sig
gpg --keyserver keys.gnupg.net --recv-keys 72D7468F
verif=0
if gpg --quiet --verify vagrant_${vagrantversion}_SHA256SUMS.sig vagrant_${vagrantversion}_SHA256SUMS 2>/dev/null; then
if grep vagrant_${vagrantversion}_x86_64.deb vagrant_${vagrantversion}_SHA256SUMS | shasum -a 256 -c - 2>/dev/null >/dev/null; then
verif=1
else
echo ERROR: checksum don\'t match
fi
else
echo ERROR: signature don\'t match
fi
rm -f vagrant_${vagrantversion}_SHA256SUMS*
popd > /dev/null
if [ "$verif" = 0 ]; then
rm -rf vagrant-$vagrantversion
fi
fi
if [ -f vagrant-$vagrantversion/vagrant_${vagrantversion}_x86_64.deb ]; then
sudo dpkg -i vagrant-$vagrantversion/vagrant_${vagrantversion}_x86_64.deb
fi
popd > /dev/null