mirror of https://github.com/caronc/apprise
202 lines
6.6 KiB
Python
202 lines
6.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
# A Conducto Pipeline
|
|
# Visit https://www.conducto.com for more information.
|
|
import os
|
|
import conducto as co
|
|
from inspect import cleandoc
|
|
|
|
|
|
def all_checks(release=None) -> co.Serial:
|
|
"""
|
|
Define our Full Conducto Pipeline
|
|
"""
|
|
# Dockerfile Context
|
|
context = '.'
|
|
|
|
# Shared Pipeline Directory
|
|
share = '/conducto/data/pipeline/apprise'
|
|
|
|
# The directory the project can be found in within the containers
|
|
repo = '/apprise'
|
|
|
|
# Unit Testing
|
|
dockerfiles = (
|
|
# Define our Containers
|
|
("Python 3.9", os.path.join('.conducto', 'Dockerfile.py39')),
|
|
("Python 3.8", os.path.join('.conducto', 'Dockerfile.py38')),
|
|
("Python 3.7", os.path.join('.conducto', 'Dockerfile.py37')),
|
|
("Python 3.6", os.path.join('.conducto', 'Dockerfile.py36')),
|
|
("Python 3.5", os.path.join('.conducto', 'Dockerfile.py35')),
|
|
("Python 2.7", os.path.join('.conducto', 'Dockerfile.py27')),
|
|
)
|
|
|
|
# Package Testing
|
|
pkg_dockerfiles = (
|
|
# Define our Containers
|
|
("EL8 RPM", os.path.join('.conducto', 'Dockerfile.el8')),
|
|
("EL7 RPM", os.path.join('.conducto', 'Dockerfile.el7')),
|
|
)
|
|
|
|
# find generated coverage filename and store it in the pipeline
|
|
coverage_template = cleandoc('''
|
|
pip install -r requirements.txt -r dev-requirements.txt || exit 1
|
|
|
|
mkdir --verbose -p {share}/coverage && \\
|
|
coverage run --parallel -m pytest && \\
|
|
find . -mindepth 1 -maxdepth 1 -type f \\
|
|
-name '.coverage.*' \\
|
|
-exec mv --verbose -- {{}} {share}/coverage \;''')
|
|
|
|
# pull generated file from the pipeline and place it back into
|
|
# our working directory
|
|
coverage_report_template = cleandoc('''
|
|
pip install coverage || exit 1
|
|
|
|
find {share}/coverage -mindepth 1 -maxdepth 1 -type f \\
|
|
-name '.coverage.*' \\
|
|
-exec mv --verbose -- {{}} . \;
|
|
|
|
coverage combine . && \\
|
|
coverage report --ignore-errors --skip-covered --show-missing
|
|
|
|
# Push our coverage report to codecov.io
|
|
retry=3
|
|
iter=0
|
|
while [ $iter -lt $retry ]; do
|
|
bash <(curl -s https://codecov.io/bash) -Z
|
|
[ $? -eq 0 ] && break
|
|
sleep 1s
|
|
# loop to try again
|
|
let iter+=1
|
|
done
|
|
''')
|
|
|
|
# RPM Packaging Templates (assumes we're building as the user 'builder')
|
|
rpm_pkg_template = cleandoc('''
|
|
# copy our environment over
|
|
rsync -a ./ /home/builder/
|
|
|
|
# Permissions
|
|
chmod ug+rw -R /home/builder
|
|
chown -R builder /home/builder
|
|
|
|
# Advance to our build directory
|
|
cd /home/builder
|
|
|
|
# Prepare Virtual Environment
|
|
PYTHON=python3
|
|
VENV_CMD="$PYTHON -m venv"
|
|
|
|
# Enterprise Linux 7 (Python v2.7.5) Support
|
|
[ "$DIST" == "el7" ] && \\
|
|
VENV_CMD=virtualenv && \\
|
|
PYTHON=python2
|
|
|
|
sudo -u builder \\
|
|
$VENV_CMD . && . bin/activate && \\
|
|
pip install coverage babel wheel markdown && \\
|
|
$PYTHON setup.py extract_messages && \\
|
|
$PYTHON setup.py sdist
|
|
|
|
# Build Man Page
|
|
sudo -u builder \\
|
|
ronn --roff packaging/man/apprise.md
|
|
|
|
# Prepare RPM Package
|
|
find dist -type f -name '*.gz' \\
|
|
-exec mv --verbose {{}} packaging/redhat/ \\;
|
|
find packaging/man -type f -name '*.1' \\
|
|
-exec mv --verbose {{}} packaging/redhat/ \\;
|
|
|
|
# Build Source RPM Package
|
|
sudo -u builder \\
|
|
rpmbuild -bs packaging/redhat/python-apprise.spec || exit 1
|
|
|
|
# Install Missing RPM Dependencies
|
|
if [ -x /usr/bin/dnf ]; then
|
|
# EL8 and Newer
|
|
dnf builddep -y rpm/*.rpm || exit 1
|
|
else
|
|
# EL7 Backwards Compatibility
|
|
yum-builddep -y rpm/*.rpm || exit 1
|
|
fi
|
|
|
|
# Build our RPM using the environment we prepared
|
|
sudo -u builder \\
|
|
rpmbuild -bb packaging/redhat/python-apprise.spec''') \
|
|
.format(repo=repo)
|
|
|
|
# Define our default image keyword argument defaults
|
|
image_kwargs = {
|
|
'copy_repo': True,
|
|
'path_map': {'.': repo},
|
|
}
|
|
|
|
if release:
|
|
# Prepare release details into environment
|
|
image_kwargs.update({'env': {'PRODUCT_RELEASE': release}})
|
|
|
|
# Our base image is always the first entry defined in our dockerfiles
|
|
base_image = co.Image(
|
|
dockerfile=dockerfiles[0][1], context=context, **image_kwargs)
|
|
base_pkg_image = co.Image(
|
|
dockerfile=pkg_dockerfiles[0][1], context=context, **image_kwargs)
|
|
|
|
with co.Serial() as pipeline:
|
|
with co.Parallel(name="Presentation"):
|
|
# Code Styles
|
|
co.Exec(
|
|
'pip install flake8 && '
|
|
'flake8 . --count --show-source --statistics',
|
|
name="Style Guidelines", image=base_image)
|
|
|
|
# RPM Checking
|
|
co.Exec(
|
|
cleandoc('''rpmlint --verbose -o "NetworkEnabled False" \\
|
|
packaging/redhat/python-apprise.spec'''),
|
|
name="RPM Guidelines", image=base_pkg_image)
|
|
|
|
with co.Parallel(name="Tests"):
|
|
for entry in dockerfiles:
|
|
name, dockerfile = entry
|
|
|
|
# Prepare our Image
|
|
image = co.Image(
|
|
dockerfile=dockerfile, context=context, **image_kwargs)
|
|
|
|
# Unit Tests
|
|
# These produce files that look like:
|
|
# .coverage.{userid}.{hostname}.NNNNNN.NNNNNN where:
|
|
# - {userid} becomes the user that ran the test
|
|
# - {hostname} identifies the hostname it was built on
|
|
# - N gets replaced with a number
|
|
|
|
# The idea here is that the .coverage.* file is unique
|
|
# from others being built in other containers
|
|
co.Exec(
|
|
coverage_template.format(share=share),
|
|
name="{} Coverage".format(name), image=image)
|
|
|
|
# Coverage Reporting
|
|
co.Exec(
|
|
coverage_report_template.format(share=share),
|
|
name="Test Code Coverage", image=base_image)
|
|
|
|
with co.Parallel(name="Packaging"):
|
|
for entry in pkg_dockerfiles:
|
|
name, dockerfile = entry
|
|
image = co.Image(
|
|
dockerfile=dockerfile, context=context, **image_kwargs)
|
|
|
|
# Build our packages
|
|
co.Exec(rpm_pkg_template, name=name, image=image)
|
|
|
|
return pipeline
|
|
|
|
|
|
if __name__ == "__main__":
|
|
"""
|
|
Execute our pipeline
|
|
"""
|
|
co.main(default=all_checks)
|