Files
Odoo-Build/task
T

1386 lines
39 KiB
Bash
Executable File

#!/bin/bash
cd "$(dirname "$0")" || exit
function help() {
echo
echo "$1 <command> [options]"
echo
echo "commands:"
echo
column -t -s"|" ./task.md | tail -n +3
echo
}
if [[ -a ".env" && "$(cat .env | sed 's/^#.*//g')" ]]; then
export $(cat .env | sed 's/^#.*//g' | xargs)
fi
# Dynamic env vars
PATH="$PATH:./odoo"
GIT_BRANCH=$(git symbolic-ref --short -q HEAD)
LOG_LEVEL=${LOG_LEVEL:="info"}
ODOO_REVISION=${ODOO_REVISION:="$GIT_BRANCH"}
ODOO_LANGUAGE=${ODOO_LANGUAGE:="de_CH"}
ODOO_DEVELOPMENT_CONFIG_DIR="$HOME/.config/odoo-build"
ODOO_PORT=${ODOO_PORT:="8069"}
POSTGRES_PORT=${POSTGRES_PORT:="5432"}
DOCKER_TAG=${DOCKER_TAG:="odoo:${ODOO_REVISION}"}
DOCKER_CONFIG="$HOME/.docker/$DOCKER_REGISTRY"
# Conditional env vars
if [ -z "${DOCKER_REGISTRY}" ]; then
DOCKER_REGISTRY=""
fi
if [[ "$(uname)" == "Darwin" ]]; then
OS_RELEASE="Darwin"
TARGETARCH=linux/arm64/v8
PIP_INOTIFY=""
OS_OPEN="open"
else
OS_RELEASE=$(awk -F= '/^NAME/{print $2}' /etc/os-release | tr -d '"')
TARGETARCH=amd64
PIP_INOTIFY="inotify"
OS_OPEN="xdg-open"
fi
function info() {
set-addons-path
echo "OS Release: $OS_RELEASE"
echo "Target Arch: $TARGETARCH"
echo "Git Branch: $GIT_BRANCH"
echo "Odoo Revision: $ODOO_REVISION"
echo "Odoo Port: $ODOO_PORT"
echo "Postgres Port: $POSTGRES_PORT"
echo "Odoo Language: $ODOO_LANGUAGE"
echo "Docker Registry: $DOCKER_REGISTRY"
echo "Docker Config: $DOCKER_CONFIG"
echo "Docker Tag: $DOCKER_TAG"
echo "Addons Path: $ADDONS_PATH"
}
function set-addons-path() {
# Read addons path list
SUBMODULES_PATH="$(git config --file .gitmodules --get-regexp path | awk '{ print $2 }' | tr '\n' ',' | sed 's/,*$//g')"
EXCLUDES="addons/theme_mint_system addons/company addons/web"
for EXCLUDE in $EXCLUDES; do
SUBMODULES_PATH=$(echo "$SUBMODULES_PATH" | sed "s|${EXCLUDE},||g")
done
# Check if dir exists
for ADDON in $SUBMODULES_PATH; do
if [ -d "$ADDON" ]; then
echo "Path does not exist: $ADDON"
exit 1
fi
done
# Convert to docker paths
DOCKER_ADDONS_PATH="$(echo $SUBMODULES_PATH | sed 's|enterprise|/mnt/enterprise|g'| sed 's|,|,/mnt/|g' | sed 's|,/mnt/odoo||g')"
# Convert to native paths
ADDONS_PATH="$(echo $SUBMODULES_PATH | sed 's|,odoo,|,odoo/addons,|g')"
# Append env var
if [ -n "$ODOO_ADDONS_PATH" ]; then
ADDONS_PATH="${ODOO_ADDONS_PATH},${ADDONS_PATH}"
fi
}
function update-readme() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
FILE_NAME=$(basename "$1")
if [[ "$FILE_NAME" != "README.md" ]]; then echo "\$1 must point to README.md file."; exit; fi
MODULES_DIR=$(dirname "$1")
MANIFEST_FILES="$MODULES_DIR/*/__manifest__.py"
# Find marker in readme and clear content after
echo "Clear modules table for $1."
MARKER="## Available modules"
sed -i "/$MARKER/Q" "$1"
echo "$MARKER" >> "$1"
echo "" >> "$1"
echo "| Module | Summary |" >> "$1"
echo "| --- | --- |" >> "$1"
# Clear table after a marker
for MANIFEST_FILE in $MANIFEST_FILES; do
MODULE_DIR=$(dirname "$MANIFEST_FILE")
MODULE_NAME=$(basename "$MODULE_DIR")
echo "Add summary of $MODULE_NAME to readme file."
SUMMARY=$(grep 'summary' "$MANIFEST_FILE" -A 1 | tail -1)
echo "| [$MODULE_NAME]($MODULE_NAME) | $SUMMARY |" >> "$1"
done
}
function get-module-version() {
if test -z "$1"
then
echo "\$1 is empty."
else
# Get version of module
VERSION=$(grep -m 1 version "$1/__manifest__.py" | sed "s;';\";g" | sed "s/,//g" | sed 's/#.*//g')
VERSION=$(echo "{ $VERSION }" | jq .version | sed 's/"//g' | sed 's/null//g')
# Set default version
[ -z "$VERSION" ] && VERSION=0.0
COUNT_DOTS=$(echo "$VERSION" | grep -o "\." | wc -l)
# check if oca version or enterprise version
if [[ $COUNT_DOTS == 2 ]]; then
VERSION="$GIT_BRANCH.$VERSION"
fi
if [[ $COUNT_DOTS == 1 ]]; then
VERSION="$GIT_BRANCH.$VERSION"
fi
echo "$VERSION"
fi
}
function init-venv() {
if [ ! -d "venv$GIT_BRANCH" ]; then
echo "Init venv$GIT_BRANCH with $(python --version)."
python -m venv "venv$GIT_BRANCH"
fi
}
function activate-venv() {
echo "Source virtualenv venv$GIT_BRANCH."
source "venv$GIT_BRANCH/bin/activate"
echo "$(python --version) is active."
}
function load-env() {
ENV_FILE="$ODOO_DEVELOPMENT_CONFIG_DIR/.env.$1"
echo "Load env file $ENV_FILE"
export $(cat "$ENV_FILE" | sed 's/#.*//g' | xargs)
}
function disable-auto-install() {
echo "Disable auto install for all enterprise modules."
find . -type f -name '__manifest__.py' -exec sed -i'' $'s/\'auto_install\': True,/\'auto_install\': False,/g' {} +
}
function build() {
echo "Run Docker build with tag ${DOCKER_REGISTRY}${DOCKER_TAG}"
docker build . --build-arg TARGETARCH="$TARGETARCH" --build-arg ODOO_IMAGE="${DOCKER_REGISTRY}${DOCKER_TAG}" -t "${DOCKER_REGISTRY}${DOCKER_TAG}"
}
function docker-login() {
echo "Setup Docker Hub login credentials for $DOCKER_REGISTRY"
echo -n "Enter username: "
read DOCKER_REGISTRY_USERNAME
echo -n "Enter password: "
read -s DOCKER_REGISTRY_PASSWORD
docker --config "$HOME/.docker/$DOCKER_REGISTRY" login --username "$DOCKER_REGISTRY_USERNAME" --password "$DOCKER_REGISTRY_PASSWORD"
}
function publish() {
echo "Push Docker image ${DOCKER_REGISTRY}${DOCKER_TAG}"
docker --config "$HOME/.docker/$DOCKER_REGISTRY" push "${DOCKER_REGISTRY}${DOCKER_TAG}"
}
function install-odoo-scripts() {
curl -L https://raw.githubusercontent.com/mint-system/ansible-build/master/roles/odoo_scripts/files/install | bash
}
function install-native() {
init-venv
activate-venv
if [[ "$OS_RELEASE" =~ ^(Ubuntu|Debian|Pop!_OS)$ ]]; then
# Source: https://gist.github.com/faniska/37f896d5e9de5fee925925d7caf3cb9e
echo "Install wkhtmltopdf"
sudo apt remove wkhtmltopdf
wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz
tar xvf wkhtmltox*.tar.xz
sudo mv wkhtmltox/bin/wkhtmlto* /usr/bin
rm -rf wkhtmltox wkhtmltox-0.12.4_linux-generic-amd64.tar.*
echo "Install python-ldap and psycopg2 build dependencies"
sudo apt-get install -y libsasl2-dev python-dev libldap2-dev libssl-dev
echo "Install xmllint"
sudo apt install libxml2-utils
elif [[ "$OS_RELEASE" =~ ^(Darwin)$ ]]; then
echo "Welcome daring Mac user. Let's try our best to get this working."
echo "Install wkhtmltopdf and some dev libraries"
echo "This will give a depreciation warning and you need to enter your sudo password."
brew install wkhtmltopdf libsasl2 openldap openssl libxml2
if ! grep -qxF 'LDFLAGS=-L/opt/homebrew/lib/' .env; then
echo 'LDFLAGS=-L/opt/homebrew/lib/' >> .env
fi
else
echo "The operating system $OS_RELEASE is not supported."
exit 1
fi
echo "Install Odoo development tools"
pip install setuptools wheel ${PIP_INOTIFY} watchdog
echo "Install Odoo dependencies"
pip install -r odoo/requirements.txt
echo "Install OCA development tools"
pip install pre-commit pyyaml docutils rst2html5 odoorpc coverage pylint-odoo
echo "Install OCA openupgrade tools"
pip install git+https://github.com/OCA/openupgradelib.git@master#egg=openupgradelib
echo "Install prometheus_exporter dependency"
pip install prometheus-client
echo "Install base_view_inheritance_extension dependency"
pip install astor
}
function open-url-with-delay(){
if test -z "$1"; then echo "\$1 is empty."; exit; fi
sleep 2
$OS_OPEN "$1"
}
function start() {
set-addons-path
# Exports for Docker Compose
export POSTGRES_PORT
export ODOO_PORT
export DOCKER_TAG
export DOCKER_ADDONS_PATH
# Use default database if second param is not given
DATABASE="$2"
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
fi
if test -z "$1"; then
echo "Start odoo container ${DOCKER_REGISTRY}${DOCKER_TAG}"
echo "Open http://localhost:8069 url in your browser."
docker-compose up -d
fi
if [[ "$1" =~ "db" ]]; then
docker-compose up -d db
fi
if [[ "$1" =~ "admin" ]]; then
docker-compose up -d admin
echo "Open http://localhost:8000 url in your browser."
fi
if [[ "$1" =~ "odoo" ]]; then
echo "Start odoo container ${DOCKER_REGISTRY}${DOCKER_TAG}"
docker-compose up -d odoo
echo "Open http://localhost:8069 url in your browser."
fi
if [[ "$1" =~ "native" ]]; then
activate-venv
echo "Open http://localhost:8069 url in your browser."
open-url-with-delay "http://localhost:8069/web?debug=1&db=$DATABASE" &
odoo-bin --config "config/odoo.conf" --addons-path="$ADDONS_PATH" --dev=all --log-level="$LOG_LEVEL"
fi
if [[ "$1" =~ "mail" ]]; then
echo "Open http://localhost:8025 url in your browser."
docker-compose up -d mail
# echo "Run \`docker exec -it mail setup email add odoo@example.com\`"
# echo "Run \`docker exec -it mail setup email add test@example.com\`"
fi
}
function deploy() {
if [[ "$1" =~ "db" ]]; then
kubectl apply -f k3s/postgres.yml
kubectl port-forward deployments/postgres 5432:5432 > /dev/null 2>&1 &
echo "Port 5432 forwarded to localhost."
fi
}
function down() {
# Exports for Docker Compose
export POSTGRES_PORT
export ODOO_PORT
export DOCKER_TAG
export DOCKER_ADDONS_PATH
if test -z "$1"; then
docker-compose down -v
fi
if [[ "$1" =~ "db" ]]; then
docker-compose rm -f -s -v db
fi
if [[ "$1" =~ "admin" ]]; then
docker-compose rm -f -s -v admin
fi
if [[ "$1" =~ "odoo" ]]; then
docker-compose rm -f -s -v odoo
fi
if [[ "$1" =~ "mail" ]]; then
docker-compose rm -f -s -v mail
fi
}
function restart() {
# Exports for Docker Compose
export POSTGRES_PORT
export ODOO_PORT
export DOCKER_TAG
export DOCKER_ADDONS_PATH
if test -z "$1"; then
docker-compose restart
fi
if [[ "db|mail|odoo" =~ $1 ]]; then
docker-compose restart "$1"
fi
}
function stop() {
# Exports for Docker Compose
export POSTGRES_PORT
export ODOO_PORT
export DOCKER_TAG
export DOCKER_ADDONS_PATH
if test -z "$1"; then
docker-compose stop
fi
docker-compose stop "$1"
}
function start-shell() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
activate-venv
odoo-bin shell -d "$DATABASE" --config 'config/odoo.conf' --no-http
}
function start-psql() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
docker exec -it db psql "postgres://odoo:odoo@localhost:5432/$DATABASE"
}
function init-db() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
activate-venv
set-addons-path
echo "Make sure only one odoo process is running when initalizing the database."
odoo-bin -d "$DATABASE" -i base --config 'config/odoo.conf' --addons-path="$ADDONS_PATH" --stop-after-init --no-http --load-language "$ODOO_LANGUAGE"
}
function odoo-cloc() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
activate-venv
odoo-bin cloc -d "$DATABASE" --config 'config/odoo.conf' --stop-after-init --no-http
}
function lint-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
activate-venv
echo "Set file and folder permissions on $1"
find "$1" -type d -exec chmod u=rwx,go=rx {} \;
find "$1" -type f -exec chmod u=rw,go=r {} \;
echo "Update index.html"
cd "$1" || exit
rst2html5 README.rst static/description/index.html
echo "Stage changes"
git add .
cd .. || exit
echo "Run pre-commit in $PWD"
pre-commit run --all-files
}
function update-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
MODULE_NAME=$(basename "$2")
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
MODULE_NAME=$(basename "$1")
fi
activate-venv
set-addons-path
echo "Updating module $MODULE_NAME on $DATABASE ..."
odoo-bin -d "$DATABASE" -u "$MODULE_NAME" --config 'config/odoo.conf' --addons-path="$ADDONS_PATH" --stop-after-init --no-http
}
function translate-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
MODULE_PATH="$2"
MODULE_NAME=$(basename "$2")
LANGUAGE="$3"
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
MODULE_PATH="$1"
MODULE_NAME=$(basename "$1")
fi
if test -z "$3"; then
LANGUAGE="$ODOO_LANGUAGE"
fi
activate-venv
set-addons-path
echo "Generate $LANGUAGE tranlsation file for $MODULE_NAME on $DATABASE ..."
mkdir -p "$MODULE_PATH/i18n/"
odoo-bin -d "$DATABASE" --config 'config/odoo.conf' --addons-path="$ADDONS_PATH" --modules "$MODULE_NAME" -l "$LANGUAGE" --i18n-export "$MODULE_PATH/i18n/$LANGUAGE.po"
}
function list-addons() {
activate-venv
set-addons-path
echo "$ADDONS_PATH"
}
function install-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
MODULE_NAME=$(basename "$2")
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
MODULE_NAME=$(basename "$1")
fi
activate-venv
set-addons-path
echo "Installing module $MODULE_NAME on $DATABASE ..."
odoo-bin -d "$DATABASE" -i "$MODULE_NAME" --config 'config/odoo.conf' --addons-path="$ADDONS_PATH" --stop-after-init --no-http
}
function install-requirements() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
FILE_PATH="$2"
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
FILE_PATH="$1"
fi
FILE_NAME=$(basename "$FILE_PATH")
if [[ "$FILE_NAME" != "requirements.txt" ]]; then echo "\$1 must point to requirements.txt file."; exit; fi
if [ "$( docker container inspect -f '{{.State.Running}}' odoo )" == "true" ]; then
echo "Installing python packages in Docker container ..."
docker exec -u root odoo python -m pip install -r "/mnt/$FILE_PATH"
else
activate-venv
echo "Installing python packages in virutal env ..."
pip install -r "$FILE_PATH"
fi
}
function test-module() {
DATABASE="$1"
MODULE_NAME=$(basename "$2")
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
MODULE_NAME=$(basename "$1")
fi
activate-venv
set-addons-path
echo "Testing module $MODULE_NAME on $DATABASE ..."
odoo-bin -d "$DATABASE" -i "$MODULE_NAME" --config 'config/odoo.conf' --addons-path="$ADDONS_PATH" --stop-after-init --no-http --test-tags /"$MODULE_NAME"
}
function remove-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
MODULE_NAME=$(basename "$2")
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
MODULE_NAME=$(basename "$1")
fi
activate-venv
set-addons-path
echo "Remove module $MODULE_NAME"
echo "self.env['ir.module.module'].search([('name', '=', '$MODULE_NAME')]).button_immediate_uninstall()" |
odoo-bin shell -d "$DATABASE" --config 'config/odoo.conf' --addons-path="$ADDONS_PATH" --no-http
}
function create-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
MODULE_NAME=$(basename "$1")
PARENT_DIR=$(dirname "$1")
activate-venv
echo "Scaffolding module $MODULE_NAME in $PARENT_DIR ..."
odoo-bin scaffold "$MODULE_NAME" "$PARENT_DIR" -t template/module
}
function drop-db() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
psql "postgres://odoo:odoo@localhost:5432/postgres" -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DATABASE';"
psql "postgres://odoo:odoo@localhost:5432/postgres" -c "DROP DATABASE \"$DATABASE\";"
}
function set-admin() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
psql "postgres://odoo:odoo@localhost:5432/$DATABASE" -c "UPDATE res_users SET active=true,password='\$pbkdf2-sha512\$25000\$JuScEwIg5JzTGqNUivFeqw\$yWTOcix2Afr3XGP2NPY7w4w49e9vpsu14NRndDYXAkbtMF4zkrmx6inVsoLl0zZY30xI/0GzhwonWsK9TUmjWA' WHERE id=2;"
psql "postgres://odoo:odoo@localhost:5432/$DATABASE" -c "SELECT login, password FROM res_users WHERE id=2;"
}
function clear-assets() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
echo "Delete these assets for $DATABASE:"
psql "postgres://odoo:odoo@localhost/$DATABASE" -c "select id,name from ir_attachment where res_model='ir.ui.view' and name like '%assets_%';"
psql "postgres://odoo:odoo@localhost/$DATABASE" -c "delete from ir_attachment where res_model='ir.ui.view' and name like '%assets_%';"
}
function reset-views() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
KEY=$(basename "$2")
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
KEY=$(basename "$1")
fi
activate-venv
echo "Reset views for key $KEY"
echo "self.env['ir.ui.view'].search([('key', 'ilike', '$KEY')]).reset_arch(mode='hard')" |
odoo-bin shell -d "$DATABASE" --config 'config/odoo.conf' --no-http
}
function convert-database() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
unzip "tmp/$1.zip" -d "./tmp/$1"
sed -i'' 's/AS integer//g' "./tmp/$1/dump.sql"
grep -i 'as integer' "./tmp/$1/dump.sql"
cd "tmp/$1" || exit ; zip -r "../${1}2.zip" . ; cd ../.. || exit
rm -r "tmp/$1"
echo "Converted database file $1 to ${1}2"
}
function git-submodule-update() {
echo "Update git submodules."
SUBMODULES=$(git config --file .gitmodules --get-regexp url | sed -e 's/submodule.//g' -e 's/.url.*//g')
for SUBMODULE in $SUBMODULES; do
# The init flag is required for the inital checkout
# The --depth flag cannot be used when working on multiple branches
echo "Update git submodule: $SUBMODULE"
git submodule update --init "$SUBMODULE"
done
}
function git-submodule-switch() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
echo "Switch branch on git submodules."
SUBMODULES=$(git config --file .gitmodules --get-regexp url | sed -e 's/submodule.//g' -e 's/.url.*//g')
for SUBMODULE in $SUBMODULES; do
echo "Switch git submodule branch to $1: $SUBMODULE"
CWD=$(pwd)
cd "$SUBMODULE" || exit
git stash
git switch "$1"
cd "$CWD" || exit
done
}
function checkout-config-files() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
echo "Checkout config files $1 branch."
git checkout "$1" config/checkout-files config/reset-files
echo "Remove reset files."
git rm -r $(tr '\n' ' ' < ./config/reset-files) >/dev/null 2>&1
echo "Sync checkout files from $1 branch."
git checkout "$1" $(tr '\n' ' ' < ./config/checkout-files)
}
function checkout() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
if [[ -n "$2" ]]; then
GIT_BRANCH="$2"
fi
echo "Switch branch."
git switch "$1"
git-submodule-update
git-submodule-switch "$1"
}
function checkout-revision() {
if [ -n "$1" ]; then
echo "Execute script for revision: $1"
./scripts/odoo_revision_"$1"
else
echo "Execute script for revision: $ODOO_REVISION"
./scripts/odoo_revision_"${ODOO_REVISION}"
fi
}
function git-submodule-pull() {
echo "Pull git submodules"
SUBMODULES=$(git config --file .gitmodules --get-regexp url | sed -e 's/submodule.//g' -e 's/.url.*//g')
for SUBMODULE in $SUBMODULES; do
echo "Pull git submodule: $SUBMODULE"
UPDATE=$(git config submodule."$SUBMODULE".update)
CWD=$(pwd)
cd "$SUBMODULE" || exit
if [ -z "$UPDATE" ]; then
git pull
fi;
cd "$CWD" || exit
done
}
function release-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
VERSION=$(get-module-version "$1")
cd "$1" || exit
LAST_TAG=$(git describe --tags)
RELEASE_NOTES=$(git log "$LAST_TAG"..HEAD --oneline)
echo "Tag with v$VERSION ..."
git tag -a "v$VERSION" -m "v$VERSION"
echo "Release notes:"
echo "$RELEASE_NOTES"
# echo "Create release $VERSION ..."
# gh release create "v$VERSION" -t "Release $VERSION"
}
function zip-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
# Get version and module name
VERSION=$(get-module-version "$1")
MODULE=$(basename "$1")
# Copy module to tmp folder
echo "Copy module $MODULE version $VERSION to tmp folder"
MODULE_NAME="$MODULE-$VERSION"
MODULE_PATH="tmp/$MODULE_NAME"
rm -rf "$MODULE_PATH"
mkdir -p "$MODULE_PATH"
cp -r "$1/." "$MODULE_PATH"
find "$MODULE_PATH" -type d -exec chmod u=rwx,go=rx {} \;
find "$MODULE_PATH" -type f -exec chmod u=rw,go=r {} \;
# Configure and zip module
echo "Remove auto install option"
sed -i'' -e "s/'auto_install': True,/'auto_install': False,/" "$MODULE_PATH/__manifest__.py"
echo "Remove pycache and hidden folders"
find "$MODULE_PATH" | grep -E "(\.git|__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
echo "Zip module $MODULE"
cd tmp || exit
rm -f "$MODULE_NAME".zip
zip -q -r "$MODULE_NAME".zip "$MODULE_NAME"
cd .. || exit
}
function clear-filestore() {
echo "Remove directory $HOME/.local/share/Odoo/filestore/$1"
rm -rf "$HOME/.local/share/Odoo/filestore/$1"
}
function disable-mailserver() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
activate-venv
load-env "$1"
scripts/odooctl --model 'ir.mail_server' --field 'active' --value False
scripts/odooctl --model 'fetchmail.server' --field 'active' --value False
}
function change-uuid() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
activate-venv
load-env "$1"
UUID=$(uuidgen)
echo "Set uuid $UUID for $1."
scripts/odooctl --model 'ir.config_parameter' --domain "['key', '=', 'database.uuid']" --field 'value' --value "'$UUID'"
}
function test-jsonrpc() {
activate-venv
[ -n "$1" ] && load-env "$1"
scripts/jsonrpc
}
function generate-admin-passwd() {
activate-venv
if test -z "$1"; then echo "\$1 is empty."; exit; fi
ODOO_PASSWORD="$1"
scripts/hash_password
}
function update-snippet() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
if test -z "$2"; then echo "\$2 is empty."; exit; fi
# Generate view name from filename
FILE=$(basename "$2")
NAME="mint_system.${FILE%.xml}"
activate-venv
load-env "$1"
echo "Update view with name $NAME"
scripts/odooctl --model 'ir.ui.view' --domain "['name', '=', '$NAME']" --field 'arch_base' --value "'''$(cat "$2")'''"
}
function install-snippet() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
if test -z "$2"; then echo "\$2 is empty."; exit; fi
# Generate view name from filename
FILE=$(basename "$2")
NAME="mint_system.${FILE%.xml}"
INHERIT_ID=$(echo 'cat //data/@inherit_id' | xmllint --shell "$2" | awk -F'[="]' '!/>/{print $(NF-1)}')
TYPE=$(echo 'cat //data/@type' | xmllint --shell "$2" | awk -F'[="]' '!/>/{print $(NF-1)}')
MODEL=$(echo 'cat //data/@model' | xmllint --shell "$2" | awk -F'[="]' '!/>/{print $(NF-1)}')
PRIORITY=$(echo 'cat //data/@priority' | xmllint --shell "$2" | awk -F'[="]' '!/>/{print $(NF-1)}')
MODULE_NAME=$(echo "$INHERIT_ID" | cut -d. -f 1 )
XML_ID=$(echo "$INHERIT_ID" | cut -d. -f 2 )
# Set default values
: ${TYPE:='qweb'}
activate-venv
load-env "$1"
echo "Search for view with name $MODULE_NAME.$XML_ID"
INHERIT_ID=$(scripts/odooctl --method 'get_id' --model 'ir.model.data' --value "['$MODULE_NAME','$XML_ID']")
echo "Found view id $INHERIT_ID"
echo "Apply view $NAME"
scripts/odooctl --method 'create' --model 'ir.ui.view' --value "{
'name': '$NAME',
'type': '$TYPE',
'model': '$MODEL',
'mode': 'extension',
'priority': $PRIORITY,
'inherit_id': $INHERIT_ID,
'arch_base': '''$(cat "$2")'''
}"
}
function lint-snippets() {
echo "Lint snippets files ..."
FILES="snippets/*.xml"
for FILE in $FILES; do
# Access various snippet parameters
FILENAME=$(basename "$FILE")
SNIPPET_MODULE=$(echo "$FILENAME" | cut -d. -f1)
REPORT=$(echo "$FILENAME" | cut -d. -f2)
EDIT=$(echo "$FILENAME" | cut -d. -f3)
INHERIT_ID=$(echo 'cat //data/@inherit_id' | xmllint --shell "$FILE" | awk -F'[="]' '!/>/{print $(NF-1)}')
TYPE=$(echo 'cat //data/@type' | xmllint --shell "$FILE" | awk -F'[="]' '!/>/{print $(NF-1)}')
MODEL=$(echo 'cat //data/@model' | xmllint --shell "$FILE" | awk -F'[="]' '!/>/{print $(NF-1)}')
PRIORITY=$(echo 'cat //data/@priority' | xmllint --shell "$FILE" | awk -F'[="]' '!/>/{print $(NF-1)}')
MODULE_NAME=$(echo "$INHERIT_ID" | cut -d. -f 1 )
XML_ID=$(echo "$INHERIT_ID" | cut -d. -f 2 )
# Check filename
COUNT_DOTS=$(echo "$FILENAME" | grep -o "\." | wc -l)
if [ "$COUNT_DOTS" -ge 4 ]; then
echo "Linting failed for $FILE"
echo "Dots count: $COUNT_DOTS"
echo " Filename: $SNIPPET_MODULE.$REPORT"
exit 1
fi
# Check if inherit id matches the filename
if [ -n "$INHERIT_ID" ]; then
if [[ "$INHERIT_ID" != "$SNIPPET_MODULE.$REPORT" ]]; then
echo "Linting failed for $FILE"
echo " Inherit: $INHERIT_ID"
echo "Filename: $SNIPPET_MODULE.$REPORT"
exit 1
fi
fi
# Check if priority is set
if [ -z "$PRIORITY" ] && [ -n "$INHERIT_ID" ]; then
echo "Linting failed for $FILE"
echo "No priority is set."
exit 1
fi
done
echo "No problems with snippets found."
}
function update-app-list() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
activate-venv
echo "env['ir.module.module'].update_list()" | odoo-bin shell -d "$1" --config 'config/odoo.conf' --no-http
}
function init-config-dir() {
echo "Ensure $ODOO_DEVELOPMENT_CONFIG_DIR exists"
mkdir -p "$ODOO_DEVELOPMENT_CONFIG_DIR"
}
function init-odoo-env() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
init-config-dir
ENV_FILEPATH="$ODOO_DEVELOPMENT_CONFIG_DIR/.env.$1"
echo "Init env file: $ENV_FILEPATH"
echo "#ODOO_URL=" > "$ENV_FILEPATH"
echo "ODOO_DATABASE=" >> "$ENV_FILEPATH"
echo "ODOO_USERNAME=" >> "$ENV_FILEPATH"
echo "ODOO_PASSWORD=" >> "$ENV_FILEPATH"
}
function init-nextcloud-env() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
init-config-dir
ENV_FILEPATH="$ODOO_DEVELOPMENT_CONFIG_DIR/.env.$1"
echo "Init env file: $ENV_FILEPATH"
echo "NEXTCLOUD_URL=" > "$ENV_FILEPATH"
echo "NEXTCLOUD_USERNAME=" >> "$ENV_FILEPATH"
echo "NEXTCLOUD_PASSWORD=" >> "$ENV_FILEPATH"
}
function edit-env() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
ENV_FILEPATH="$ODOO_DEVELOPMENT_CONFIG_DIR/.env.$1"
"$EDITOR" "$ENV_FILEPATH"
}
function upload-module() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
if test -z "$2"; then echo "\$2 is empty."; exit; fi
# Check if path is root folder
MODULES="$2"
if [ ! -f "$2/__manifest__.py" ]; then
echo "Identified as root folder"
MODULES="$MODULES/*"
fi
for MODULE in $MODULES; do
if [ -f "$MODULE/__manifest__.py" ]; then
# Create module zip
zip-module "$MODULE"
# Get path to zip file and upload url
FILE_PATH="tmp/$MODULE_NAME.zip"
load-env "$1"
NEXTCLOUD_UPLOAD_URL="$NEXTCLOUD_URL/remote.php/dav/files/$NEXTCLOUD_USERNAME/Odoo-Apps/"
# Upload zip file
curl -u "$NEXTCLOUD_USERNAME:$NEXTCLOUD_PASSWORD" -T "$FILE_PATH" "$NEXTCLOUD_UPLOAD_URL"
echo "File $FILE_PATH uploaded to $NEXTCLOUD_UPLOAD_URL."
UPLOADS+=" - name: $MODULE\n"
UPLOADS+=" version: $VERSION\n"
fi
done
echo "odoo_apps:"
echo -e "$UPLOADS"
}
function save-config() {
DATABASE="$1"
DATABASE=${DATABASE:="$GIT_BRANCH"}
activate-venv
odoo-bin -d "$DATABASE" -s --config 'config/odoo.conf' --stop-after-init --no-http
}
function git-submodule-add() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
if test -z "$2"; then echo "\$2 is empty."; exit; fi
git submodule add -f -b "$GIT_BRANCH" "$1" "$2"
}
function git-submodule-remove() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
echo "Deinit submodule"
git submodule deinit -f "$1"
echo "Move submodule to tmp folder"
mkdir -p tmp/"$1"
mv "$1" tmp/"$1"
echo "Remove submodule from work tree"
git rm -f "$1"
echo "Remove submodule from .git folder"
rm -rf .git/modules/"$1"
}
function git-submodule-list() {
git submodule foreach --quiet 'printf "%-30s %-20s\n" "$name" "$(git rev-parse --abbrev-ref HEAD)"'
# git config --file .gitmodules --get-regexp url | sed -e 's/submodule.//g' -e 's/.url//g' | awk '{ print $1 "," $2}'
}
function git-feature-branch(){
if test -z "$1"; then echo "\$1 is empty."; exit; fi
MODULE_NAME=$(basename "$1")
MODULE_PATH=$(dirname "$1")
echo "Create feature branch for $MODULE_NAME in $MODULE_PATH ..."
cd ./"$MODULE_PATH" || exit
pwd
git switch -c "feature-$MODULE_NAME"
}
function git-mig-branch(){
if test -z "$1"; then echo "\$1 is empty."; exit; fi
MODULE_NAME=$(basename "$1")
MODULE_PATH=$(dirname "$1")
echo "Create mig branch for $MODULE_NAME in $MODULE_PATH ..."
cd ./"$MODULE_PATH" || exit
pwd
git switch -c "$GIT_BRANCH-mig-$MODULE_NAME"
}
function patch-database() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
DATABASE="$1"
FILENAME="$2"
# Use default database if second param is not given
if test -z "$2"; then
DATABASE="$GIT_BRANCH"
FILENAME="$1"
fi
echo "Apply patch $FILENAME to Database $DATABASE."
cat "$FILENAME" | docker exec -i db psql "postgres://$POSTGRES_USER:$POSTGRES_PASSWORD@localhost/$DATABASE"
echo "Patching database succeeded"
}
function generate-snippets-doc() {
echo "Update snippets doc file."
echo "# Snippets" > snippets.md
echo "In Odoo everything is described as an XML document. \
Snippets are modifications (edits) for these XML documents. \
With a snippet you can e.g. hide a field on the contact form. \
A snippet name is unique and follows the \`\$COMPANY.\$MODULE.\$XML_ID.\$DESCRIPTION\` schema." >> snippets.md
PATH_URL="https://github.com/Mint-System/Odoo-Build/tree/16.0"
# Get all modules
MODULES=$(ls snippets/*.xml | xargs -n 1 basename | cut -d. -f1 | sort | uniq)
for MODULE in $MODULES; do
TITLE="${MODULE^}" # Uppercase first letter
TITLE=$(echo "$TITLE" | sed 's/_/ /g') # Replace underline with space
TITLE=$(echo "$TITLE" | sed -r 's/\<./\U&/g') # Uppercase first letter after space
# Create doc file for each module
DOCFILE="snippets/$MODULE.md"
echo -e "# $TITLE" > "$DOCFILE"
echo "## [$TITLE](snippets/$MODULE.md)" >> snippets.md
SIDEBAR_ENTRIES+="'/snippets/$MODULE.md',\n"
# Get all xml ids
XML_IDS=$(ls snippets/$MODULE.*.xml | xargs -n 1 basename | cut -d. -f2 | uniq)
for XML_ID in $XML_IDS; do
XML_ID_TITLE=$(echo "$XML_ID" | sed 's/_/ /g') # Replace underline with space
XML_ID_TITLE=$(echo "$XML_ID_TITLE" | sed -r 's/\<./\U&/g') # Uppercase first letter after space
echo "## $XML_ID_TITLE " >> "$DOCFILE"
# Process each file
FILES="snippets/$MODULE.$XML_ID.*.xml"
for FILE in $FILES; do
# Get snippet params
FILENAME=$(basename "$FILE")
EDIT=$(echo "$FILENAME" | cut -d. -f3)
EDIT_TITLE=$(echo "$EDIT" | sed 's/_/ /g') # Replace underline with space
EDIT_TITLE=$(echo "$EDIT_TITLE" | sed -r 's/\<./\U&/g') # Uppercase first letter after space
# Group by modules
echo "### $EDIT_TITLE " >> "$DOCFILE"
echo "ID: \`mint_system.$MODULE.$XML_ID.$EDIT\` " >> "$DOCFILE"
echo -e '```xml' >> "$DOCFILE"
cat "$FILE" >> "$DOCFILE"
echo -e '\n```' >> "$DOCFILE"
echo -e "Source: [$FILE]($PATH_URL/$FILE)\n" >> "$DOCFILE"
done
done
done
echo -e "export default [$SIDEBAR_ENTRIES]" > .vuepress/sidebar.js
}
function generate-revisions-doc() {
echo "Update revisions doc file."
rm -f "revisions.md"
echo -e "# Odoo Revisions \n\
A Odoo revision is a snapshot of git references of the Odoo source and modules at a specific date.\n\
For each major release there are multiple revisions.\n" > "revisions.md"
declare -A REVISIONS
PATH_URL="https://github.com/Mint-System/Odoo-Build/tree/16.0"
for FILE in scripts/odoo_revision_*; do
if [[ -f "$FILE" ]]; then
REVISION=$(basename "$FILE" | sed 's/odoo_revision_//')
MAJOR_VERSION=$(echo "$REVISION" | cut -d'.' -f1-2)
if [[ -z "${REVISIONS[$MAJOR_VERSION]}" ]]; then
REVISIONS[$MAJOR_VERSION]="## $MAJOR_VERSION"
fi
REVISIONS[$MAJOR_VERSION]+=$'\n\n'
REVISIONS[$MAJOR_VERSION]+="[$REVISION]($PATH_URL/$FILE)"
fi
done
for VERSION in $(echo "${!REVISIONS[@]}" | tr ' ' '\n' | sort -V); do
echo -e "${REVISIONS[$VERSION]}\n" >> "revisions.md"
done
}
function update-docs() {
generate-snippets-doc
generate-revisions-doc
}
function visualize-dependencies() {
if test -z "$1"; then echo "\$1 is empty."; exit; fi
MODULE_DIR="$1"
OUTPUT_FILE="tmp/module_dependencies.mmd"
mkdir -p tmp
echo "graph TD" > "$OUTPUT_FILE"
for MODULE_PATH in "$MODULE_DIR"/*; do
if [[ -d "$MODULE_PATH" ]]; then
MODULE_NAME=$(basename "$MODULE_PATH")
MANIFEST_FILE="$MODULE_PATH/__manifest__.py"
if [[ -f $MANIFEST_FILE ]]; then
DEPENDENCIES=$(grep -Po '(?<="depends": \[)[^\]]*' "$MANIFEST_FILE" | tr -d '"[] ')
if [[ -n "$DEPENDENCIES" ]]; then
for DEPENDENCY in $(echo "$DEPENDENCIES" | tr ',' '\n'); do
echo " $MODULE_NAME --> $DEPENDENCY" >> "$OUTPUT_FILE"
done
fi
fi
fi
done
echo "Mermaid output generated: $OUTPUT_FILE"
echo "Run mermaid-cli with npx and open png file ..."
npx @mermaid-js/mermaid-cli -i $OUTPUT_FILE -o tmp/module_dependencies.png --scale 10
$OS_OPEN tmp/module_dependencies.png
}
case "$1" in
activate-venv)
activate-venv
;;
build)
build
;;
change-uuid)
change-uuid "$2"
;;
checkout)
checkout "$2" "$3"
;;
checkout-config-files)
checkout-config-files "$2"
;;
checkout-revision)
checkout-revision "$2"
;;
clear-assets)
clear-assets "$2"
;;
clear-filestore)
clear-filestore "$2"
;;
convert-database)
convert-database "$2"
;;
create-module)
create-module "$2"
;;
deploy)
deploy "$2"
;;
disable-auto-install)
disable-auto-install
;;
disable-mailserver)
disable-mailserver "$2"
;;
docker-login)
docker-login
;;
down)
down "$2"
;;
drop-db)
drop-db "$2"
;;
edit-env)
edit-env "$2"
;;
generate-admin-passwd)
generate-admin-passwd "$2"
;;
get-module-version)
get-module-version "$2"
;;
git-feature-branch)
git-feature-branch "$2"
;;
git-mig-branch)
git-mig-branch "$2"
;;
git-submodule-add)
git-submodule-add "$2" "$3"
;;
git-submodule-list)
git-submodule-list
;;
git-submodule-pull)
git-submodule-pull
;;
git-submodule-remove)
git-submodule-remove "$2"
;;
git-submodule-switch)
git-submodule-switch "$2"
;;
git-submodule-update)
git-submodule-update
;;
help)
help task
exit 1
;;
info)
info
;;
init-db)
init-db "$2"
;;
init-nextcloud-env)
init-nextcloud-env "$2"
;;
init-odoo-env)
init-odoo-env "$2"
;;
init-venv)
init-venv
;;
install-module)
install-module "$2" "$3"
;;
install-native)
install-native
;;
install-odoo-scripts)
install-odoo-scripts
;;
install-requirements)
install-requirements "$2" "$3"
;;
install-snippet)
install-snippet "$2" "$3"
;;
install-snippets)
install-snippets
;;
install)
install
;;
lint-module)
lint-module "$2"
;;
lint-snippets)
lint-snippets
;;
list-addons)
list-addons
;;
list-env)
ls -f "$ODOO_DEVELOPMENT_CONFIG_DIR"
;;
list)
docker-compose config --services; echo "native"
;;
logs)
docker logs odoo -f
;;
patch-database)
patch-database "$2" "$3"
;;
publish)
publish
;;
ps)
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{(.Label "description")}}\t{{.Status}}'
;;
release-module)
release-module "$2"
;;
remove-module)
remove-module "$2" "$3"
;;
reset-views)
reset-views "$2" "$3"
;;
restart)
restart "$2"
;;
restore-database)
restore-database "$2" "$3"
;;
save-config)
save-config "$2"
;;
send-support-mail)
send-support-mail
;;
set-admin)
set-admin "$2"
;;
source)
activate-venv
;;
start-psql)
start-psql "$2"
;;
start-shell)
start-shell "$2"
;;
start)
start "$2" "$3"
;;
stop)
stop "$2"
;;
test-coverage-module)
test-coverage-module "$2" "$3"
;;
test-jsonrpc)
test-jsonrpc "$2"
;;
test-module)
test-module "$2" "$3"
;;
translate-module)
translate-module "$2" "$3" "$4"
;;
update-app-list)
update-app-list "$2"
;;
update-docs)
update-docs
;;
update-module)
update-module "$2" "$3"
;;
update-readme)
update-readme "$2"
;;
update-snippet)
update-snippet "$2" "$3"
;;
upload-module)
upload-module "$2" "$3"
;;
visualize-dependencies)
visualize-dependencies "$2"
;;
zip-module)
zip-module "$2"
;;
*)
help task
exit 1
;;
esac