Add experimental scripts for building Debian/Ubuntu packages.

Code is split into pkg/debian for the Debian/Ubuntu specific parts,
and pkg/linux for generic code that can be used on other distros.

Tested on Debian 10 and Ubuntu 18.04 at present.
This commit is contained in:
Dave Page 2020-03-12 15:22:23 +00:00
parent 7cc30e3216
commit a684b48fb3
11 changed files with 462 additions and 2 deletions

3
.gitignore vendored
View File

@ -12,13 +12,14 @@
.idea
.vscode
/dist
/debian-build
/docker-build
/mac-build
/pip-build
/src-build
/win-build
_build
build-*
/build-*
pgadmin4.log
pkg/win32/installer.iss
pkg/mac/codesign.conf

View File

@ -91,7 +91,7 @@ runtime:
cd runtime && qmake CONFIG+=release && make
# Include all clean sub-targets in clean
clean: clean-appbundle clean-dist clean-docs clean-node clean-pip clean-src clean-runtime
clean: clean-appbundle clean-debian clean-dist clean-docs clean-node clean-pip clean-src clean-runtime
rm -rf web/pgadmin/static/js/generated/*
rm -rf web/pgadmin/static/js/generated/.cache
rm -rf web/pgadmin/static/css/generated/*
@ -104,6 +104,9 @@ clean-runtime:
clean-appbundle:
rm -rf mac-build/
clean-debian:
rm -rf debian-build/
clean-dist:
rm -rf dist/
@ -119,6 +122,9 @@ clean-pip:
clean-src:
rm -rf src-build/
debian:
pkg/debian/build.sh
docker:
echo $(APP_NAME)
docker build -t ${APP_NAME} -t $(APP_NAME):latest -t $(APP_NAME):$(APP_RELEASE) -t $(APP_NAME):$(APP_RELEASE).$(APP_REVISION) .

47
pkg/debian/README Normal file
View File

@ -0,0 +1,47 @@
This directory contains the build runner script for creating .DEB packages for
Debian and Ubuntu.
Build configuration
===================
To build Debian/Ubuntu packages, first run the setup.sh script as root to
install the required pre-requisites, e.g.
# pkg/debian/setup.sh
Building packages
=================
To build a set of packages, from the top-level source directory run:
$ make debian
or
$ pkg/debian/build.sh
Four .deb packages will be created in the dist/ directory:
pgadmin4_<version>_<distro>_<distro_version>_all.deb
A convenience package that depends on all the others.
pgadmin4-server_<version>_<distro>_<distro_version>_<arch>.deb
The core server, e.g. the Python and JS code and the online documentation.
pgadmin4-desktop_<version>_<distro>_<distro_version>_<arch>.deb
The desktop runtime. Requires the server package.
pgadmin4-web_<version>_<distro>_<distro_version>_<arch>.deb
The server mode setup script for configuring Apache HTTPD. Requires the
server package.
Supported platforms
===================
Debian 10
Ubuntu 18.04
Warning
=======
These scripts are experimental - use at your own risk!

108
pkg/debian/build.sh Executable file
View File

@ -0,0 +1,108 @@
#!/bin/bash
# Exit when any command fails
set -e
# Debugging shizz
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
OS_NAME=$(cat /etc/os-release | grep "^ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
OS_ARCH=$(dpkg-architecture -qDEB_HOST_ARCH)
# Common Linux build functions
source pkg/linux/build-functions.sh
# Assemble the "standard" installation footprint
_setup_env $0 "debian"
_cleanup "deb"
_setup_dirs
_create_python_virtualenv
_build_runtime
_build_docs
_copy_code
#
# Server package
#
# Create the Debian packaging stuffs for the server
echo "Creating the server package..."
mkdir "${SERVERROOT}/DEBIAN"
cat << EOF > "${SERVERROOT}/DEBIAN/control"
Package: ${APP_NAME}-server
Version: ${APP_LONG_VERSION}
Architecture: ${OS_ARCH}
Depends: python3, libpq5
Recommends: postgresql-client | postgresql-client-12 | postgresql-client-11 | postgresql-client-10
Maintainer: pgAdmin Development Team <pgadmin-hackers@postgresql.org>
Description: The core server package for pgAdmin. pgAdmin is the most popular and feature rich Open Source administration and development platform for PostgreSQL, the most advanced Open Source database in the world.
EOF
# Build the Debian package for the server
dpkg-deb --build "${SERVERROOT}" "${DISTROOT}/${APP_NAME}-server_${APP_LONG_VERSION}_${OS_NAME}_${OS_VERSION}_amd64.deb"
#
# Desktop package
#
# Create the Debian packaging stuffs for the desktop
echo "Creating the desktop package..."
mkdir "${DESKTOPROOT}/DEBIAN"
cat << EOF > "${DESKTOPROOT}/DEBIAN/control"
Package: ${APP_NAME}-desktop
Version: ${APP_LONG_VERSION}
Architecture: ${OS_ARCH}
Depends: ${APP_NAME}-server, libqt5gui5
Maintainer: pgAdmin Development Team <pgadmin-hackers@postgresql.org>
Description: The desktop user interface for pgAdmin. pgAdmin is the most popular and feature rich Open Source administration and development platform for PostgreSQL, the most advanced Open Source database in the world.
EOF
# Build the Debian package for the server
dpkg-deb --build "${DESKTOPROOT}" "${DISTROOT}/${APP_NAME}-desktop_${APP_LONG_VERSION}_${OS_NAME}_${OS_VERSION}_amd64.deb"
#
# Web package
#
# Create the Debian packaging stuffs for the web
echo "Creating the web package..."
mkdir "${WEBROOT}/DEBIAN"
cat << EOF > "${WEBROOT}/DEBIAN/control"
Package: ${APP_NAME}-web
Version: ${APP_LONG_VERSION}
Architecture: all
Depends: ${APP_NAME}-server, apache2, libapache2-mod-wsgi-py3
Maintainer: pgAdmin Development Team <pgadmin-hackers@postgresql.org>
Description: The web interface for pgAdmin, hosted under Apache HTTPD. pgAdmin is the most popular and feature rich Open Source administration and development platform for PostgreSQL, the most advanced Open Source database in the world.
EOF
mkdir -p "${WEBROOT}/etc/apache2/conf-available"
cp "${SOURCEDIR}/pkg/debian/pgadmin4.conf" "${WEBROOT}/etc/apache2/conf-available"
# Build the Debian package for the web
dpkg-deb --build "${WEBROOT}" "${DISTROOT}/${APP_NAME}-web_${APP_LONG_VERSION}_${OS_NAME}_${OS_VERSION}_all.deb"
#
# Meta package
#
# Create the Debian packaging stuffs for the meta package
echo "Creating the meta package..."
mkdir "${METAROOT}/DEBIAN"
cat << EOF > "${METAROOT}/DEBIAN/control"
Package: ${APP_NAME}
Version: ${APP_LONG_VERSION}
Architecture: all
Depends: ${APP_NAME}-server, ${APP_NAME}-desktop, ${APP_NAME}-web
Maintainer: pgAdmin Development Team <pgadmin-hackers@postgresql.org>
Description: Installs all required components to run pgAdmin in desktop and web modes. pgAdmin is the most popular and feature rich Open Source administration and development platform for PostgreSQL, the most advanced Open Source database in the world.
EOF
# Build the Debian meta package
dpkg-deb --build "${METAROOT}" "${DISTROOT}/${APP_NAME}_${APP_LONG_VERSION}_${OS_NAME}_${OS_VERSION}_all.deb"

9
pkg/debian/pgadmin4.conf Normal file
View File

@ -0,0 +1,9 @@
WSGIDaemonProcess pgadmin processes=1 threads=25 python-home=/usr/pgadmin4/venv
WSGIScriptAlias /pgadmin4 /usr/pgadmin4/web/pgAdmin4.wsgi
<Directory /usr/pgadmin4/web/>
WSGIProcessGroup pgadmin
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>

15
pkg/debian/setup.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
sudo apt install curl
# Yarn repo
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update
# Install pre-reqs
echo Installing pre-requisites...
sudo apt install -y build-essential python3-dev python3-venv python3-sphinx libpq-dev qt5-default yarn

3
pkg/linux/README Normal file
View File

@ -0,0 +1,3 @@
This directory contains package build scripts and assets that are common to various Linux distributions.
You should not use them directly!

View File

@ -0,0 +1,147 @@
_setup_env() {
echo "Setting up the environment..."
WD=$(cd `dirname "$1"` && pwd)
SOURCEDIR=$(realpath "${WD}/../..")
BUILDROOT=$(realpath "${WD}/../../$2-build")
DESKTOPROOT=${BUILDROOT}/desktop
METAROOT=${BUILDROOT}/meta
SERVERROOT=${BUILDROOT}/server
WEBROOT=${BUILDROOT}/web
DISTROOT=$(realpath "${WD}/../../dist")
APP_RELEASE=`grep "^APP_RELEASE" web/config.py | cut -d"=" -f2 | sed 's/ //g'`
APP_REVISION=`grep "^APP_REVISION" web/config.py | cut -d"=" -f2 | sed 's/ //g'`
APP_NAME=`grep "^APP_NAME" web/config.py | cut -d"=" -f2 | sed "s/'//g" | sed 's/^ //' | sed 's/ //g' | tr '[:upper:]' '[:lower:]'`
APP_LONG_VERSION=${APP_RELEASE}.${APP_REVISION}
APP_SHORT_VERSION=`echo ${APP_LONG_VERSION} | cut -d . -f1,2`
APP_SUFFIX=`grep "^APP_SUFFIX" web/config.py | cut -d"=" -f2 | sed 's/ //g' | sed "s/'//g"`
if [ ! -z ${APP_SUFFIX} ]; then
APP_LONG_VERSION=${APP_LONG_VERSION}-${APP_SUFFIX}
fi
}
_cleanup() {
echo "Cleaning up the old environment and app..."
if test -f ${SOURCEDIR}/runtime/pgAdmin4; then
rm -rf ${SOURCEDIR}/runtime/pgAdmin4
fi
if test -d ${BUILDROOT}; then
rm -rf ${BUILDROOT}
fi
rm -f ${DISTROOT}/pgadmin4*.$1
}
_setup_dirs() {
echo "Creating output directories..."
test -d ${BUILDROOT} || mkdir ${BUILDROOT}
test -d ${DESKTOPROOT} || mkdir ${DESKTOPROOT}
test -d ${METAROOT} || mkdir ${METAROOT}
test -d ${SERVERROOT} || mkdir ${SERVERROOT}
test -d ${WEBROOT} || mkdir ${WEBROOT}
test -d ${DISTROOT} || mkdir ${DISTROOT}
}
_create_python_virtualenv() {
echo "Creating the virtual environment..."
cd ${SERVERROOT}
# Create the required directories
mkdir -p "usr/${APP_NAME}"
cd "usr/${APP_NAME}"
# Create the blank venv
python3 -m venv venv
source venv/bin/activate
pip3 install --no-cache-dir --no-binary psycopg2 -r ${SOURCEDIR}/requirements.txt
# Figure out some paths for use when completing the venv
# Use "python3" here as we want the venv path
PYMODULES_PATH=$(python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")
DIR_PYMODULES_PATH=`dirname ${PYMODULES_PATH}`
# Use /usr/bin/python3 here as we want the system path
PYSYSLIB_PATH=$(/usr/bin/python3 -c "import sys; print('%s/lib/python%d.%.d' % (sys.prefix, sys.version_info.major, sys.version_info.minor))")
# Symlink in the rest of the Python libs. This is required because the runtime
# will clear PYTHONHOME for safety, which has the side-effect of preventing
# it from finding modules that are not explicitly included in the venv
cd ${DIR_PYMODULES_PATH}
# Files
for FULLPATH in ${PYSYSLIB_PATH}/*.py; do
FILE=${FULLPATH##*/}
if [ ! -e ${FILE} ]; then
ln -s ${FULLPATH} ${FILE}
fi
done
# Paths
for FULLPATH in ${PYSYSLIB_PATH}/*/; do
FULLPATH=${FULLPATH%*/}
FILE=${FULLPATH##*/}
if [ ! -e ${FILE} ]; then
ln -s ${FULLPATH} ${FILE}
fi
done
# Remove tests
cd site-packages
find . -name "test" -type d -print0 | xargs -0 rm -rf
find . -name "tests" -type d -print0 | xargs -0 rm -rf
# Link the python<version> directory to python so that the private environment path is found by the application.
if test -d ${DIR_PYMODULES_PATH}; then
ln -s $(basename ${DIR_PYMODULES_PATH}) ${DIR_PYMODULES_PATH}/../python
fi
}
_build_runtime() {
echo "Building the desktop runtime..."
_create_python_virtualenv
cd ${SOURCEDIR}/runtime
make clean
qmake
make
mkdir -p "${DESKTOPROOT}/usr/${APP_NAME}/bin"
cp pgAdmin4 "${DESKTOPROOT}/usr/${APP_NAME}/bin/pgadmin4"
mkdir -p "${DESKTOPROOT}/usr/${APP_NAME}/share"
cp pgAdmin4.ico "${DESKTOPROOT}/usr/${APP_NAME}/share/pgadmin4.ico"
mkdir -p "${DESKTOPROOT}/usr/share/applications"
cp ../pkg/linux/pgadmin4.desktop "${DESKTOPROOT}/usr/share/applications"
}
_build_docs() {
echo "Building the documentation..."
cd "${SERVERROOT}" && mkdir -p "usr/${APP_NAME}/share/docs/en_US/html"
cd "${SOURCEDIR}/docs/en_US"
python3 build_code_snippet.py
PYTHONPATH=$PYTHONPATH:/usr/lib/python3/:/usr/lib/python3/dist-packages python3 -msphinx . "${SERVERROOT}/usr/${APP_NAME}/share/docs/en_US/html"
}
_copy_code() {
echo "Copying the server code..."
# Remove any TCL-related files that may cause us problems
find "${SERVERROOT}/usr/${APP_NAME}/venv/" -name "_tkinter*" -print0 | xargs -0 rm -rf
pushd ${SOURCEDIR}/web
yarn install
yarn run bundle
popd
# copy the web directory to the bundle as it is required by runtime
cp -r "${SOURCEDIR}/web" "${SERVERROOT}/usr/${APP_NAME}/web/"
cp "${SOURCEDIR}/pkg/linux/config_distro.py" "${SERVERROOT}/usr/${APP_NAME}/web/"
cd "${SERVERROOT}/usr/${APP_NAME}/web/"
rm -f pgadmin4.db config_local.*
rm -rf karma.conf.js package.json node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache
find . -name "tests" -type d -print0 | xargs -0 rm -rf
find . -name "feature_tests" -type d -print0 | xargs -0 rm -rf
find . -name "__pycache__" -type d -print0 | xargs -0 rm -rf
# Web setup script
mkdir -p "${WEBROOT}/usr/${APP_NAME}/bin/"
cp "${SOURCEDIR}/pkg/linux/setup-web.sh" "${WEBROOT}/usr/${APP_NAME}/bin/"
}

View File

@ -0,0 +1,5 @@
HELP_PATH = '../../../share/docs/en_US/html/'
DEFAULT_BINARY_PATHS = {
'pg': '/usr/bin',
'ppas': ''
}

View File

@ -0,0 +1,10 @@
[Desktop Entry]
Encoding=UTF-8
Name=pgAdmin 4
Exec=/usr/pgadmin4/bin/pgadmin4
Icon=/usr/pgadmin4/share/pgadmin4.ico
Type=Application
Categories=Application;Development;
MimeType=text/html
Comment=Management tools for PostgreSQL
Keywords=database;db;sql;query;administration;development;

109
pkg/linux/setup-web.sh Executable file
View File

@ -0,0 +1,109 @@
#!/bin/bash
#
# Setup pgadmin4 in server mode
#
if [ "$EUID" -ne 0 ]
then echo "This script must be run as root"
exit 1
fi
# Get the distro
IS_REDHAT=0
IS_DEBIAN=0
UNAME=$(uname -a)
if [ -f /etc/redhat-release ]; then
IS_REDHAT=1
APACHE=httpd
echo "Setting up pgAdmin 4 in web mode on a Redhat platform..."
elif [[ ${UNAME} =~ "Ubuntu" ]] || [[ ${UNAME} =~ "debian" ]]; then
IS_DEBIAN=1
APACHE=apache2
echo "Setting up pgAdmin 4 in web mode on a Debian platform..."
fi
# Run setup script first:
echo "Creating configuration database..."
/usr/pgadmin4/venv/bin/python3 /usr/pgadmin4/web/setup.py
if [ $? != 0 ]
then
echo "Error setting up server mode. Please examine the output above."
exit 1
fi
# Create and own directories:
echo "Creating storage and log directories..."
mkdir -p /var/log/pgadmin /var/lib/pgadmin
if [ ${IS_REDHAT} == 1 ]; then
chown apache: /var/log/pgadmin /var/lib/pgadmin -R
else
chown www-data: /var/log/pgadmin /var/lib/pgadmin -R
fi
# Set SELinux up:
if [ ${IS_REDHAT} == 1 ]; then
echo "Configuring SELinux..."
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1
semanage fcontext -a -t httpd_var_lib_t '/var/lib/pgadmin(/.*)?'
restorecon -R -v /var/lib/pgadmin
semanage fcontext -a -t httpd_log_t '/var/log/pgadmin(/.*)?'
restorecon -R -v /var/log/pgadmin
fi
# Setup Apache
read -p "We can now configure the Apache Web server for you. This involves enabling the wsgi module and configuring the pgAdmin 4 application to mount at /pgadmin4. Do you wish to continue (y/n)? " RESPONSE
case ${RESPONSE} in
y|Y )
if [ ${IS_REDHAT} == 1 ]; then
# TODO
true
else
a2enmod wsgi 1> /dev/null
a2enconf pgadmin4 1> /dev/null
fi;;
* )
exit 1;;
esac
APACHE_STATUS=`ps cax | grep ${APACHE}`
if [ $? -eq 0 ]; then
read -p "The Apache web server is running. A restart is required for the pgAdmin 4 installation to complete. Would you like to continue (y/n)? " RESPONSE
case ${RESPONSE} in
y|Y )
systemctl restart ${APACHE}
if [ $? != 0 ]; then
echo "Error restarting ${APACHE}. Please check the systemd logs"
else
echo "Apache successfully restarted. You can now start using pgAdmin 4 in web mode"
fi;;
* )
exit 1;;
esac
else
read -p "The Apache web server is not running. We can enable and start the web server for you to finish pgAdmin 4 installation. Would you like to continue (y/n)? " RESPONSE
case ${RESPONSE} in
y|Y )
systemctl enable ${APACHE}
if [ $? != 0 ]; then
echo "Error enabling ${APACHE}. Please check the systemd logs"
else
echo "Apache successfully enabled."
fi
systemctl start ${APACHE}
if [ $? != 0 ]; then
echo "Error starting ${APACHE}. Please check the systemd logs"
else
echo "Apache successfully started. You can now start using pgAdmin 4 in web mode"
fi;;
* )
exit 1;;
esac
fi
exit 0