RPM Package Compatibility Fix (#757)

This commit is contained in:
Chris Caron 2022-11-15 14:21:20 -05:00 committed by GitHub
parent fc16c7bf0b
commit 949f88a0dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 330 additions and 7 deletions

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ __pycache__/
env/
.venv*
build/
BUILDROOT/
develop-eggs/
dist/
downloads/

36
Dockerfile.el8 Normal file
View File

@ -0,0 +1,36 @@
# Base
FROM rockylinux:8
ENV container docker
RUN ( \
cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
echo "assumeyes=1" >> /etc/yum.conf; \
dnf install -y epel-release; \
dnf install -y rpm-build rpmlint python3-pip python3-virtualenv rubygem-ronn \
dnf-plugins-core 'dnf-command(config-manager)' \
'dnf-command(builddep)' sudo rsync rpmdevtools; \
dnf config-manager --set-enabled powertools;
COPY packaging/redhat/python-apprise.spec /
# Place our build file into the path
COPY bin/build-rpm.sh /usr/bin
RUN rpmspec -q --buildrequires /python-apprise.spec | cut -f1 -d' ' | \
xargs dnf install -y
# RPM Build Structure Setup
ENV FLAVOR=rpmbuild OS=centos DIST=el8
RUN useradd builder -u 1000 -m -G users,wheel &>/dev/null && \
echo "builder ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers
VOLUME ["/apprise"]
WORKDIR /apprise
# RPMs should never be built as root
USER builder

36
Dockerfile.el9 Normal file
View File

@ -0,0 +1,36 @@
# Base
FROM rockylinux:9
ENV container docker
RUN ( \
cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*; \
echo "assumeyes=1" >> /etc/yum.conf; \
dnf install -y epel-release; \
dnf install -y rpm-build rpmlint python3-pip rubygem-ronn \
dnf-plugins-core 'dnf-command(config-manager)' \
'dnf-command(builddep)' sudo rsync rpmdevtools; \
dnf config-manager --set-enabled crb;
COPY packaging/redhat/python-apprise.spec /
# Place our build file into the path
COPY bin/build-rpm.sh /usr/bin
RUN rpmspec -q --buildrequires /python-apprise.spec | cut -f1 -d' ' | \
xargs dnf install -y
# RPM Build Structure Setup
ENV FLAVOR=rpmbuild OS=centos DIST=el8
RUN useradd builder -u 1000 -m -G users,wheel &>/dev/null && \
echo "builder ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers
VOLUME ["/apprise"]
WORKDIR /apprise
# RPMs should never be built as root
USER builder

33
Dockerfile.f37 Normal file
View File

@ -0,0 +1,33 @@
# Base
FROM fedora:37
ENV container docker
RUN \
rm -f /usr/lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /usr/lib/systemd/system/local-fs.target.wants/*; \
rm -f /usr/lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /usr/lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /usr/lib/systemd/system/basic.target.wants/*;\
rm -f /usr/lib/systemd/system/anaconda.target.wants/*; \
echo "assumeyes=1" >> /etc/dnf/dnf.conf; \
dnf install -y epel-release; \
dnf install -y rpm-build rpmlint python3-pip rubygem-ronn \
dnf-plugins-core 'dnf-command(config-manager)' \
'dnf-command(builddep)' sudo rsync rpmdevtools;
COPY packaging/redhat/python-apprise.spec /
# Place our build file into the path
COPY bin/build-rpm.sh /usr/bin
RUN rpmspec -q --buildrequires /python-apprise.spec | cut -f1 -d' ' | \
xargs dnf install -y
# RPM Build Structure Setup
ENV FLAVOR=rpmbuild OS=centos DIST=el8
RUN useradd builder -u 1000 -m -G users,wheel &>/dev/null && \
echo "builder ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers
VOLUME ["/apprise"]
WORKDIR /apprise
# RPMs should never be built as root
USER builder

View File

@ -1,5 +1,6 @@
# Apprise Development Tools
# Common Testing
This directory just contains some tools that are useful when developing with Apprise. It is presumed that you've set yourself up with a working development environment before using the tools identified here:
```bash
@ -47,3 +48,16 @@ export PATH="$(pwd)/bin:$PATH"
# Now you can call the scripts identified above from anywhere...
```
## RPM Testing
Apprise is also packaged for Redhat/Fedora as an RPM. To verify this processs works correctly an additional tool called `build-rpm.sh` is provided. It's best tested using the Docker environments:
```bash
# To test with el8; do the following:
docker-compose run --rm rpmbuild.el8 build-rpm.sh
# To test with el9; do the following:
docker-compose run --rm rpmbuild.el9 build-rpm.sh
# To test with f37; do the following:
docker-compose run --rm rpmbuild.f37 build-rpm.sh
```

110
bin/build-rpm.sh Executable file
View File

@ -0,0 +1,110 @@
#!/bin/bash
# Copyright (C) 2022 Chris Caron <lead2gold@gmail.com>
# All rights reserved.
#
# This code is licensed under the MIT License.
#
# 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 where Apprise Source Code can be found
APPRISE_DIR="/apprise"
PYTHON=python3
PIP=pip3
VENV_CMD="$PYTHON -m venv"
mkenv(){
# Prepares RPM Environment
cat << _EOF > $HOME/.rpmmacros
# macros
%_topdir $APPRISE_DIR
%_sourcedir %{_topdir}/dist
%_specdir %{_topdir}/dist
%_rpmdir %{_topdir}/dist/rpm
%_srcrpmdir %{_topdir}/dist/rpm
%_builddir %{_topdir}/build/rpm
_EOF
# Prepare our working directories if not already present
mkdir -p $APPRISE_DIR/{dist/rpm,build/rpm}
return 0
}
clean(){
# Tidy .pyc files
find $APPRISE_DIR -name '*.pyc' -delete &>/dev/null
find $APPRISE_DIR -type d -name '__pycache__' -exec rm -rf {} \ &>/dev/null;
# Remove previously build details
[ -d "$APPRISE_DIR/apprise.egg-info" ] && rm -rf $APPRISE_DIR/apprise.egg-info
[ -d "$APPRISE_DIR/build" ] && rm -rf $APPRISE_DIR/build
[ -d "$APPRISE_DIR/BUILDROOT" ] && rm -rf $APPRISE_DIR/BUILDROOT
}
build(){
# Test spec file for any issues
rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
[ $? -ne 0 ] && echo "RPMLint Failed!" && return 1
# Prepare RPM Package
# Detect our version
local VER=$(rpmspec -q --qf "%{version}\n" \
"$APPRISE_DIR/packaging/redhat/python-apprise.spec" 2>/dev/null | head -n1)
[ -z "$VER" ] && echo "Could not detect Apprise RPM Version" && return 1
if [ ! -f "$APPRISE_DIR/dist/apprise-$VER.tar.gz" ]; then
# Build Apprise
if [ ! -x $HOME/dev/bin/activate ]; then
$VENV_CMD $HOME/dev
[ $? -ne 0 ] && echo "Could not create Virtual Python Environment" && return 1
fi
. $HOME/dev/bin/activate
$PIP install coverage babel wheel markdown
pushd $APPRISE_DIR
# Build Man Page
ronn --roff $APPRISE_DIR/packaging/man/apprise.md
$PYTHON setup.py extract_messages
$PYTHON setup.py sdist
# exit from our virtual environment
deactivate
fi
# Prepare our RPM Source and SPEC dependencies
find "$APPRISE_DIR/packaging/man/" -type f -name '*.1' \
-exec cp --verbose {} "$APPRISE_DIR/dist" \;
find "$APPRISE_DIR/packaging/redhat" -type f -name '*.patch' \
-exec cp --verbose {} "$APPRISE_DIR/dist" \;
find "$APPRISE_DIR/packaging/redhat" -type f -name '*.spec' \
-exec cp --verbose {} "$APPRISE_DIR/dist" \;
# Build and Test our RPM Package
rpmbuild -ba "$APPRISE_DIR/dist/python-apprise.spec"
return $?
}
# Prepare our environment
mkenv
# Clean
clean
# Build
build
# Return our build status
exit $?

View File

@ -14,6 +14,28 @@ services:
volumes:
- ./:/apprise
rpmbuild.el8:
build:
context: .
dockerfile: Dockerfile.el8
volumes:
- ./:/apprise
rpmbuild.el9:
build:
context: .
dockerfile: Dockerfile.el9
volumes:
- ./:/apprise
rpmbuild.f37:
build:
context: .
dockerfile: Dockerfile.f37
volumes:
- ./:/apprise
# Connect to web and create a new project using the manage script
# -> docker-compose run --rm test.py36 bash
# bin/apprise -
@ -33,3 +55,14 @@ services:
#
# # Now produce a report
# docker-compose run --rm test.py310 coverage report --show-missing
#
# RPM Building
#
# el8
# - docker-compose run --rm rpmbuild.el8 build-rpm.sh
# el9
# - docker-compose run --rm rpmbuild.el9 build-rpm.sh
# f37 (Fedora)
# - docker-compose run --rm rpmbuild.f37 build-rpm.sh

View File

@ -0,0 +1,12 @@
diff -Naur apprise-1.2.0/test/test_plugin_macosx.py apprise-1.2.0.patched/test/test_plugin_macosx.py
--- apprise-1.2.0/test/test_plugin_macosx.py 2022-11-02 14:59:59.000000000 -0400
+++ apprise-1.2.0.patched/test/test_plugin_macosx.py 2022-11-15 13:25:27.991284405 -0500
@@ -38,7 +38,7 @@
logging.disable(logging.CRITICAL)
-if sys.platform not in ["darwin", "linux"]:
+if sys.platform not in ["darwin"]:
pytest.skip("Only makes sense on macOS, but also works on Linux",
allow_module_level=True)

View File

@ -0,0 +1,19 @@
diff -Naur apprise-1.2.0/test/conftest.py apprise-1.2.0.patched/test/conftest.py
--- apprise-1.2.0/test/conftest.py 2022-11-02 14:00:13.000000000 -0400
+++ apprise-1.2.0.patched/test/conftest.py 2022-11-15 10:28:23.793969418 -0500
@@ -32,12 +32,12 @@
sys.path.append(os.path.join(os.path.dirname(__file__), 'helpers'))
-@pytest.fixture(scope="session", autouse=True)
-def no_throttling_everywhere(session_mocker):
+@pytest.fixture(autouse=True)
+def no_throttling_everywhere(mocker):
"""
A pytest session fixture which disables throttling on all notifiers.
It is automatically enabled.
"""
for notifier in NOTIFY_MODULE_MAP.values():
plugin = notifier["plugin"]
- session_mocker.patch.object(plugin, "request_rate_per_sec", 0)
+ mocker.patch.object(plugin, "request_rate_per_sec", 0)

View File

@ -54,10 +54,25 @@ Summary: A simple wrapper to many popular notification services used toda
License: MIT
URL: https://github.com/caronc/%{pypi_name}
Source0: %{url}/archive/v%{version}/%{pypi_name}-%{version}.tar.gz
# RHEL/Rocky 8 ship with Click v6.7 which does not support the .stdout
# directive used in the unit testing. This patch just makes it so our package
# continues to be compatible with these linux distributions
Patch0: %{pypi_name}-click67-support.patch
# RHEL/Rocky 8 ship with Pytest v3.4.2 which does not support the
# session_mocker fixture. This patch removes the session_mocker
# Patch thanks to Andreas Motl and his PR:
# - https://github.com/caronc/apprise/pull/763
Patch1: %{pypi_name}-pytest-session_mocker-removal.patch
# RHEL/Rocky 8 ship with Pytest v3.4.2 which does not support the
# tmp_path fixture. This patch removes the macos testing as it
# leverages this unavailabe fixture.
# At the end of the day, the macos testing it is not needed by a
# RHEL/Fedora environment anyway for obvious reasons.
Patch2: %{pypi_name}-no-macosx-testing.patch
BuildArch: noarch
%description %{common_description}
@ -86,11 +101,18 @@ BuildRequires: python%{python3_pkgversion}-markdown
BuildRequires: python%{python3_pkgversion}-yaml
BuildRequires: python%{python3_pkgversion}-babel
BuildRequires: python%{python3_pkgversion}-cryptography
BuildRequires: python%{python3_pkgversion}-paho-mqtt
Requires: python%{python3_pkgversion}-requests
Requires: python%{python3_pkgversion}-requests-oauthlib
Requires: python%{python3_pkgversion}-markdown
Requires: python%{python3_pkgversion}-cryptography
Requires: python%{python3_pkgversion}-yaml
Recommends: python%{python3_pkgversion}-paho-mqtt
%if 0%{?rhel} && 0%{?rhel} <= 8
BuildRequires: python%{python3_pkgversion}-dataclasses
Requires: python%{python3_pkgversion}-dataclasses
%endif
%if %{with tests}
%if 0%{?rhel} >= 9
@ -100,7 +122,10 @@ Requires: python%{python3_pkgversion}-yaml
BuildRequires: python%{python3_pkgversion}-mock
%endif
BuildRequires: python%{python3_pkgversion}-pytest
BuildRequires: python%{python3_pkgversion}-pytest-mock
BuildRequires: python%{python3_pkgversion}-pytest-runner
BuildRequires: python%{python3_pkgversion}-pytest-cov
BuildRequires: python%{python3_pkgversion}-pytest-xdist
%endif
%description -n python%{python3_pkgversion}-%{pypi_name} %{common_description}
@ -110,6 +135,10 @@ BuildRequires: python%{python3_pkgversion}-pytest-runner
%if 0%{?rhel} && 0%{?rhel} <= 8
# Rocky/RHEL 8 click v6.7 unit testing support
%patch0 -p1
# Rocky/RHEL 8 Drop session_mocker support
%patch1 -p1
# Rocky/RHEL 8 Lose MacOSX Testing
%patch2 -p1
%endif
%if 0%{?rhel} >= 9

View File

@ -16,7 +16,7 @@ builtins = _
test=pytest
[tool:pytest]
addopts = --verbosity=3 -ra
addopts = -ra
python_files = test/test_*.py
norecursedirs=test/helpers
filterwarnings =

View File

@ -45,7 +45,7 @@ def mqtt_client_mock(mocker):
"""
if "paho" not in sys.modules:
raise pytest.skip(reason="Requires that `paho-mqtt` is installed")
raise pytest.skip("Requires that `paho-mqtt` is installed")
# Establish mock of the `publish()` response object.
publish_result = Mock(**{

View File

@ -24,6 +24,7 @@
# THE SOFTWARE.
import re
import sys
import pytest
from unittest import mock
@ -34,12 +35,11 @@ import socket
import logging
logging.disable(logging.CRITICAL)
# Skip tests when Python environment does not provide the `syslog` package.
if 'syslog' not in sys.modules:
pytest.skip("Skipping syslog based tests", allow_module_level=True)
# The `syslog` module is not available on Windows.
# `ModuleNotFoundError: No module named 'syslog'`
NotifySyslog = pytest.importorskip(
"apprise.plugins.NotifySyslog",
reason="`syslog` module not available on Windows").NotifySyslog
from apprise.plugins.NotifySyslog import NotifySyslog # noqa E402
@mock.patch('syslog.syslog')