build environment improvements (#1385)

pull/1395/head
Chris Caron 2025-08-16 18:19:33 -04:00 committed by GitHub
parent 92d5d7cc8a
commit c15243a9cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 249 additions and 70 deletions

View File

@ -39,7 +39,7 @@ jobs:
with:
name: built-rpms
path: |
dist/**/*.rpm
dist/rpm/*/*.rpm
if-no-files-found: error
retention-days: 5

1
.gitignore vendored
View File

@ -17,6 +17,7 @@ __pycache__/
env/
.venv*
build/
BUILD/
BUILDROOT/
SOURCES/
SRPMS/

22
.vscode/settings.json vendored
View File

@ -1,9 +1,17 @@
{
"python.testing.pytestArgs": [],
"python.testing.cwd": "${workspaceFolder}",
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"terminal.integrated.env.linux": {
"PYTHONPATH": "${workspaceFolder}"
}
"python.testing.pytestArgs": [
"tests"
],
"python.linting.enabled": true,
"python.linting.ruffEnabled": true,
"python.linting.ruffPath": "ruff",
"python.formatting.provider": "none",
"editor.formatOnSave": true,
"python.testing.cwd": "${workspaceFolder}",
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.envFile": "${workspaceFolder}/.env",
"terminal.integrated.env.linux": {
"PYTHONPATH": "${workspaceFolder}"
}
}

View File

@ -20,19 +20,87 @@ merge your contributions smoothly.
tox -e qa
```
- ✔️ All tests pass locally.
- ✔️ Your code is clean and consistently formatted:
```bash
tox -e format
```
- ✔️ You followed the plugin template (if adding a new plugin).
- ✔️ You included inline docstrings and respected the BSD 2-Clause license.
- ✔️ Your commit message is descriptive.
---
## 📦 Local Development Setup
To get started with development:
### 🧰 System Requirements
- Python >= 3.9
- `pip`
- `git`
- Optional: `VS Code` with the Python extension
### 🚀 One-Time Setup
```bash
git clone https://github.com/caronc/apprise.git
cd apprise
# Install all runtime + dev dependencies
pip install .[dev]
```
(Optional, but recommended if actively developing):
```bash
pip install -e .[dev]
```
---
## 🧪 Running Tests
```bash
pytest # Run all tests
pytest tests/foo.py # Run a specific test file
```
Run with coverage:
```bash
pytest --cov=apprise --cov-report=term
```
---
## 🧹 Linting & Formatting with ruff
```bash
ruff check apprise tests # Check linting
ruff check apprise tests --fix # Auto-fix
ruff format apprise tests # Format files
```
---
## 🧰 Optional: Using VS Code
1. Open the repo: `code .`
2. Press `Ctrl+Shift+P → Python: Select Interpreter`
3. Choose the same interpreter you used for `pip install .[dev]`
4. Press `Ctrl+Shift+P → Python: Discover Tests`
`.vscode/settings.json` is pre-configured with:
- pytest as the test runner
- ruff for linting
- PYTHONPATH set to project root
No `.venv` is required unless you choose to use one.
---
## 📌 How to Contribute
1. **Fork the repository** and create a new branch.

View File

@ -10,6 +10,9 @@ include dev-requirements.txt
include all-plugin-requirements.txt
recursive-include tests *
recursive-include packaging *
recursive-include apprise/i18n *.pot
recursive-include apprise/i18n *.po
recursive-include apprise/i18n */LC_MESSAGES/*.po
global-exclude *.pyc
global-exclude *.pyo
global-exclude __pycache__

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: apprise 1.4.5\n"
"Report-Msgid-Bugs-To: lead2gold@gmail.com\n"
"POT-Creation-Date: 2025-08-02 17:51+0000\n"
"POT-Creation-Date: 2025-08-03 13:22+0000\n"
"PO-Revision-Date: 2019-05-24 20:00-0400\n"
"Last-Translator: Chris Caron <lead2gold@gmail.com>\n"
"Language: en\n"

View File

View File

@ -27,56 +27,60 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#!/usr/bin/env bash
set -e
set -euo pipefail
# Set Apprise root directory
APPRISE_DIR="${APPRISE_DIR:-/apprise}"
DIST_DIR="${DIST_DIR:-$PWD/dist/rpm}"
SOURCES_DIR="$APPRISE_DIR/SOURCES"
SRPM_DIR="$DIST_DIR/"
PYTHON=python3
TOX="tox -c $APPRISE_DIR/tox.ini"
DIST_DIR="${DIST_DIR:-$PWD/dist}"
mkdir -p "$DIST_DIR"
echo "==> Cleaning previous builds"
$TOX -e clean --notest
if [ ! -d "$DIST_DIR" ]; then
echo "==> Cleaning previous builds"
$TOX -e clean --notest
echo "==> Linting RPM spec"
rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
echo "==> Linting RPM spec"
rpmlint "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
echo "==> Running tests"
$TOX -e py312
echo "==> Generating man pages"
ronn --roff --organization="Chris Caron <lead2gold@gmail.com>" \
"$APPRISE_DIR/packaging/man/apprise.md"
echo "==> Generating man pages"
ronn --roff --organization="Chris Caron <lead2gold@gmail.com>" \
"$APPRISE_DIR/packaging/man/apprise.md"
echo "==> Extracting translations"
$TOX -e i18n
echo "==> Extracting translations"
$TOX -e i18n || { echo "Translation extraction failed!" ; exit 1; }
echo "==> Compiling translations"
$TOX -e compile
echo "==> Compiling translations"
$TOX -e compile || { echo "Translation compilation failed!" ; exit 1; }
echo "==> Building source distribution"
$TOX -e build-sdist || { echo "sdist build failed!" ; exit 1; }
echo "==> Building source distribution"
$TOX -e build-sdist
fi
VERSION=$(rpmspec -q --qf "%{version}\n" "$APPRISE_DIR/packaging/redhat/python-apprise.spec" | head -n1)
TARBALL="$APPRISE_DIR/dist/apprise-${VERSION}.tar.gz"
if [[ ! -f "$TARBALL" ]]; then
echo "Tarball not found: $TARBALL"
echo "Tarball not found: $TARBALL"
exit 1
fi
echo "==> Copying tarball to SOURCES directory"
mkdir -p "$APPRISE_DIR/SOURCES"
cp "$TARBALL" "$APPRISE_DIR/SOURCES/"
echo "==> Preparing SOURCES directory"
mkdir -p "$SOURCES_DIR"
cp "$TARBALL" "$SOURCES_DIR/"
find $APPRISE_DIR/packaging/redhat/ -iname '*.patch' -exec cp {} "$SOURCES_DIR" \;
echo "==> Building RPM"
echo "==> Building RPM (source and binary)"
mkdir -p "$DIST_DIR"
rpmbuild --define "_topdir $APPRISE_DIR" \
--define "_sourcedir $APPRISE_DIR/SOURCES" \
--define "_sourcedir $SOURCES_DIR" \
--define "_specdir $APPRISE_DIR/packaging/redhat" \
--define "_srcrpmdir $APPRISE_DIR/SRPMS" \
--define "_srcrpmdir $DIST_DIR" \
--define "_rpmdir $DIST_DIR" \
-ba "$APPRISE_DIR/packaging/redhat/python-apprise.spec"
echo "✅ RPM build completed successfully"
echo "📦 Artifacts:"
find "$DIST_DIR" -type f -name "*.rpm"

19
codecov.yml Normal file
View File

@ -0,0 +1,19 @@
codecov:
require_ci_to_pass: false
comment:
layout: "reach,diff,flags,files"
require_changes: false
behavior: update
after_n_builds: 1
coverage:
status:
project:
default:
target: auto
threshold: 1%
patch:
default:
target: auto
threshold: 1%

View File

@ -5,6 +5,8 @@ services:
dockerfile: tests/docker/Dockerfile.py39
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
test.py310:
build:
@ -12,6 +14,8 @@ services:
dockerfile: tests/docker/Dockerfile.py310
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
test.py311:
build:
@ -19,6 +23,8 @@ services:
dockerfile: tests/docker/Dockerfile.py311
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
test.py312:
build:
@ -26,6 +32,8 @@ services:
dockerfile: tests/docker/Dockerfile.py312
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
rpmbuild.el9:
build:
@ -33,6 +41,8 @@ services:
dockerfile: tests/docker/Dockerfile.el9
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
rpmbuild.f42:
build:
@ -40,6 +50,8 @@ services:
dockerfile: tests/docker/Dockerfile.f42
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
rpmbuild.rawhide:
build:
@ -47,6 +59,8 @@ services:
dockerfile: tests/docker/Dockerfile.rawhide
volumes:
- ./:/apprise
working_dir: /apprise
user: "1000:1000"
#
# Every Day testing

View File

@ -1,6 +1,8 @@
## Packaging
This directory contains any supporting files to grant usage of Apprise in various distributions.
Let me know if you'd like to help me host on more platforms or can offer to do it yourself!
### RPM Based Packages
* [EPEL](https://fedoraproject.org/wiki/EPEL) based distributions are only supported if they are of v9 or higher. This includes:
* Red Hat 9.x (or higher)
@ -17,7 +19,17 @@ Provided you are connected to the [EPEL repositories](https://fedoraproject.org/
dnf install python3-apprise apprise
```
Let me know if you'd like to help me host on more platforms or can offer to do it yourself!
You can build your own rpm packges with the following:
```bash
# EPEL9 (CentOS/Rocky/RedHat/Oracle Linux)
tox -e build-el9-rpm
# Fedora 42
tox -e build-f42-rpm
# Fedora Rawhide
tox -e build-rawhide-rpm
```
## Man Pages Information
The man page were generated using [Ronn](http://github.com/rtomayko/ronn/tree/0.7.3).

View File

@ -79,7 +79,7 @@ notification services. It supports sending alerts to platforms such as: \
Name: python-%{pypi_name}
Version: 1.9.4
Release: 1%{?dist}
Release: 3%{?dist}
Summary: A simple wrapper to many popular notification services used today
License: BSD-2-Clause
URL: https://github.com/caronc/%{pypi_name}
@ -147,17 +147,7 @@ BuildRequires: python%{python3_pkgversion}-pytest-cov
%description -n python%{python3_pkgversion}-%{pypi_name} %{common_description}
%prep
%setup -q -n %{pypi_name}-%{version}
# 2023.08.27: This test fails for some uknown reason only during the test
# section of this RPM, but works completley fine under all other circumstances.
# As a workaround, just remove the file so it doesn't hold up the RPM
# Preparation
%{__rm} tests/test_plugin_bulksms.py
# 2023.08.27: rawhide does not install translationfiles for some reason
# at this time; remove failing test until this is resolved
%{__rm} tests/test_apprise_translations.py
%autosetup -n %{pypi_name}-%{version}
%build
%if %{legacy_python_build}
@ -167,13 +157,13 @@ BuildRequires: python%{python3_pkgversion}-pytest-cov
%pyproject_wheel
%endif
%install
%if %{legacy_python_build}
# backwards compatible
%py3_install
%else
%pyproject_install
%pyproject_save_files apprise
%endif
%{__install} -p -D -T -m 0644 packaging/man/%{pypi_name}.1 \
@ -205,7 +195,7 @@ LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib}:%{_builddir}/%{name}-%{ve
%endif
# Localised Files
%lang(en) %{python3_sitelib}/%{pypi_name}/i18n/en/LC_MESSAGES/messages.mo
%lang(en) %{python3_sitelib}/%{pypi_name}/i18n/en/LC_MESSAGES/apprise.mo
%files -n %{pypi_name}
%{_bindir}/%{pypi_name}
@ -214,6 +204,12 @@ LANG=C.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib}:%{_builddir}/%{name}-%{ve
%{python3_sitelib}/%{pypi_name}/__pycache__/cli*.py?
%changelog
* Sat Aug 16 2025 Chris Caron <lead2gold@gmail.com> - 1.9.4-3
- Spec file modernization BZ2377453
* Fri Aug 15 2025 Python Maint <python-maint@redhat.com> - 1.9.4-2
- Rebuilt for Python 3.14.0rc2 bytecode
* Sat Aug 2 2025 Chris Caron <lead2gold@gmail.com> - 1.9.4
- Updated to v1.9.4

View File

@ -347,11 +347,11 @@ section-order = ["future", "standard-library", "third-party", "first-party", "lo
builtins-ignorelist = ["_"]
[tool.pytest.ini_options]
addopts = "-ra"
python_files = ["tests/test_*.py"]
filterwarnings = ["once::Warning"]
norecursedirs = ["tests/helpers", "dist", ".tox", ".venv", ".eggs", ".local", "venv"]
# Keep pytest-cov minimal, let Coverage.py control formatting.
addopts = "-ra --cov=apprise --cov-branch --cov-report=xml"
testpaths = ["tests"]
python_files = ["test_*.py", "tests/test_*.py"]
filterwarnings = ["once::Warning"]
[tool.coverage.run]
branch = true
@ -361,6 +361,7 @@ source = ["apprise"]
relative_files = true
[tool.coverage.paths]
# Normalise .tox and site-packages layouts back to 'apprise'
source = [
"apprise",
"/apprise/apprise",
@ -369,6 +370,20 @@ source = [
]
[tool.coverage.report]
# Controls terminal and XML content when Coverage.py renders reports
show_missing = true
skip_covered = true
skip_empty = true
precision = 1
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING:",
"if __name__ == .__main__.:",
"raise NotImplementedError",
"pass$",
]
[tool.coverage.xml]
# Ensure GitHub Action can find a predictable file
output = "coverage.xml"

65
tox.ini
View File

@ -7,13 +7,12 @@ use_discover = False
[tox]
envlist =
clean
validate
i18n
compile
minimal
build
release
validate
twine-check
minversion = 4.0
requires = virtualenv>=20.0.0
isolated_build = True
@ -27,13 +26,54 @@ ensurepip = true
setenv =
COVERAGE_RCFILE = {toxinidir}/pyproject.toml
[testenv:build-rpm]
description = Run RPM packaging via Docker
[testenv:build-src-rpm]
description = Build source RPM and place .src.rpm in dist/
skip_install = true
allowlist_externals =
bash
cp
mkdir
find
rpmbuild
setenv =
HOME = {envtmpdir}
RPMTOP = {envtmpdir}/rpmbuild
commands_pre =
mkdir -p {envtmpdir}/rpmbuild/SOURCES
mkdir -p {envtmpdir}/rpmbuild/SPECS
mkdir -p dist/rpm
cp packaging/man/apprise.1 {envtmpdir}/rpmbuild/SOURCES/
cp packaging/redhat/python-apprise.spec {envtmpdir}/rpmbuild/SPECS/
find packaging/redhat/ -iname '*.patch' -exec cp {} {envtmpdir}/rpmbuild/SOURCES/ \;
bash -c 'cp dist/*.tar.gz {envtmpdir}/rpmbuild/SOURCES/'
bash -c 'echo "%_topdir {envtmpdir}/rpmbuild" > {envtmpdir}/.rpmmacros'
commands =
rpmbuild --nodeps -bs {envtmpdir}/rpmbuild/SPECS/python-apprise.spec
find {envtmpdir}/rpmbuild/SRPMS -name '*.src.rpm' -exec mv {} dist/rpm \;
[testenv:build-el9-rpm]
description = Run RPM packaging for EPEL9 via Docker
skip_install = true
allowlist_externals =
docker
bash
commands =
docker compose run --user root --rm rpmbuild.el9 bash build-rpm.sh
docker compose run --rm rpmbuild.el9 bash /usr/bin/build-rpm.sh
[testenv:build-f42-rpm]
description = Run RPM packaging for Fedora 42 via Docker
skip_install = true
allowlist_externals =
docker
commands =
docker compose run --rm rpmbuild.f42 bash /usr/bin/build-rpm.sh
[testenv:build-rawhide-rpm]
description = Run RPM packaging for Fedora Rawhide via Docker
skip_install = true
allowlist_externals =
docker
commands =
docker compose run --rm rpmbuild.rawhide bash /usr/bin/build-rpm.sh
[testenv:lint]
description = Run static analysis using Ruff
@ -104,8 +144,10 @@ commands =
find . -type f -name "*.pyc" -delete
find . -type f -name "*.pyo" -delete
find . -type f -name "*.orig" -delete
find . -type f -name "*.orig" -delete
find ./apprise/i18n -type f -name "*.mo" -delete
rm -rf BUILD SOURCES SRPMS BUILDROOT .cache .ruff_cache .coverage-reports .coverage coverage.xml dist build apprise.egg-info .mypy_cache .pytest_cache "__pycache__"
find . -type d -name "__pycache__" -delete
rm -rf BUILD SOURCES SRPMS BUILDROOT .cache .ruff_cache .coverage-reports .coverage coverage.xml dist build apprise.egg-info .mypy_cache .pytest_cache
[testenv:i18n]
description = Extract and update .pot/.po files for translation
@ -115,13 +157,13 @@ ensurepip = true
commands =
mkdir -p apprise/i18n
pybabel extract -F babel.cfg -o apprise/i18n/apprise.pot apprise
pybabel update -i apprise/i18n/apprise.pot -d apprise/i18n
pybabel update --domain=apprise -i apprise/i18n/apprise.pot -d apprise/i18n
[testenv:compile]
description = Compile .mo files
deps = Babel
commands =
pybabel compile -d apprise/i18n
pybabel compile --domain=apprise -d apprise/i18n
[testenv:build]
description = Build sdist and wheel (assumes translations compiled)
@ -151,11 +193,8 @@ commands =
[testenv:twine-check]
description = Run twine check on dist artifacts
deps =
build
twine
commands =
rm -rf dist
python -m build
twine check dist/*
[testenv:man]