diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1596caaa6ccd93c04d3f5af879d081e2f28944ec..87720d088e313e196bc3fd7dbecc9f5488d4c19b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,6 +2,9 @@ image: registry.git.cccv.de/uffd/docker-images/buster variables: DEBIAN_FRONTEND: noninteractive + APT_API_URL: https://packages.cccv.de + APT_REPO: uffd + PYLINT_PIN: pylint~=2.10.0 before_script: - python3 -V @@ -10,6 +13,21 @@ before_script: - python3 -m pylint --version - python3 -m coverage --version +.build: + stage: build + +build:apt: + extends: .build + script: + - ./debian/create_changelog.py uffd-nginxauth > debian/changelog + - dpkg-buildpackage -us -uc + - mv ../*.deb ./ + - dpkg-deb -I *.deb + - dpkg-deb -c *.deb + artifacts: + paths: + - ./*.deb + linter:buster: image: registry.git.cccv.de/uffd/docker-images/buster stage: test @@ -79,3 +97,46 @@ unittests:bullseye: #cobertura: coverage.xml junit: report.xml #coverage: '/^TOTAL.*\s+(\d+\%)$/' + +test:package:apt:buster: + image: registry.git.cccv.de/uffd/docker-images/buster + stage: test + script: + - apt -y install ./*.deb + - service uwsgi start uffd-nginxauth || ( service uwsgi status uffd-nginxauth; sleep 15; cat /var/log/uwsgi/app/uffd-nginxauth.log; ) + - echo "server { listen 127.0.0.1:5000 default_server; include /etc/uffd-nginxauth/nginx.include.conf; }" > /etc/nginx/sites-enabled/uffd-nginxauth.ini + - service nginx start || ( service nginx status; nginx -t; exit 1; ) + - curl -Lv http://127.0.0.1:5000/status + dependencies: + - build:apt + +test:package:apt:bullseye: + image: registry.git.cccv.de/uffd/docker-images/bullseye + stage: test + script: + - apt -y install ./*.deb + - service uwsgi start uffd-nginxauth || ( service uwsgi status uffd-nginxauth; sleep 15; cat /var/log/uwsgi/app/uffd-nginxauth.log; ) + - echo "server { listen 127.0.0.1:5000 default_server; include /etc/uffd-nginxauth/nginx.include.conf; }" > /etc/nginx/sites-enabled/uffd-nginxauth.ini + - service nginx start || ( service nginx status; nginx -t; exit 1; ) + - curl -Lv http://127.0.0.1:5000/status + dependencies: + - build:apt + +.publish: + stage: deploy + rules: + - if: '$CI_COMMIT_TAG =~ /v[0-9]+[.][0-9]+[.][0-9]+.*/' + +publish:apt: + extends: .publish + script: + - export DEBPATH="$(echo *.deb)" + - echo Upload deb file, add it to repo and clean up upload + - curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X POST -F file=@"$DEBPATH" "${APT_API_URL}/api/files/${APT_REPO}-ci-upload-${CI_JOB_ID}" + - curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X POST "${APT_API_URL}/api/repos/${APT_REPO}/file/${APT_REPO}-ci-upload-${CI_JOB_ID}" + - curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X DELETE "${APT_API_URL}/api/files/${APT_REPO}-ci-upload-${CI_JOB_ID}" + - echo Update published repo for all distros + - 'curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X PUT -H "Content-Type: application/json" --data "{ }" "${APT_API_URL}/api/publish/${APT_REPO}/buster"' + - 'curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X PUT -H "Content-Type: application/json" --data "{ }" "${APT_API_URL}/api/publish/${APT_REPO}/bullseye"' + dependencies: + - build:apt diff --git a/debian/contrib/uffd-nginxauth.cfg b/debian/contrib/uffd-nginxauth.cfg new file mode 100644 index 0000000000000000000000000000000000000000..6ff5c1b409784d511b649ceff09c768d2d9d3518 --- /dev/null +++ b/debian/contrib/uffd-nginxauth.cfg @@ -0,0 +1,7 @@ +FLASK_ENV="production" +#SECRET=autogenerated by postinst script + +# URLs of the OAuth2-based identity provider (must be set!) +#OAUTH2_AUTH_URL = 'http://localhost:5001/oauth2/authorize' +#OAUTH2_TOKEN_URL = 'http://localhost:5001/oauth2/token' +#OAUTH2_USERINFO_URL = 'http://localhost:5001/oauth2/userinfo' diff --git a/debian/control b/debian/control new file mode 100644 index 0000000000000000000000000000000000000000..758dd041ad2ba93291e76859495c56af089dc993 --- /dev/null +++ b/debian/control @@ -0,0 +1,24 @@ +Source: uffd-nginxauth +Section: python +Priority: optional +Maintainer: CCCV <it@cccv.de> +Build-Depends: + debhelper-compat (= 12), + dh-python, + python3-all, + python3-setuptools, +Standards-Version: 4.5.0 +Homepage: https://git.cccv.de/uffd/uffd-nginxauth +Vcs-Git: https://git.cccv.de/uffd/uffd-nginxauth.git + +Package: uffd-nginxauth +Architecture: all +Depends: + ${misc:Depends}, + python3-flask, + python3-requests-oauthlib, + uwsgi, + uwsgi-plugin-python3, +Recommends: + nginx, +Description: Small web service for adding uffd OAuth2 authentication to nginx diff --git a/debian/create_changelog.py b/debian/create_changelog.py new file mode 100755 index 0000000000000000000000000000000000000000..b62f211c24403fbfb2a1465cbf58491b5616f5b6 --- /dev/null +++ b/debian/create_changelog.py @@ -0,0 +1,106 @@ +#!/usr/bin/python3 +import sys +import re +import textwrap +import datetime +import email.utils + +import git + +package_name = 'UNKNOWN' + +alias_names = { + 'julian': 'Julian Rother', + 'Julian': 'Julian Rother', +} + +ignore_commit_regexes = [ + '^fixup!', +] + +def print_release(tag=None, commits=tuple(), last_tag=None): + release_version = '0.0.0' + release_author = git.objects.util.Actor('None', 'undefined@example.com') + release_date = 0 + release_status = 'UNRELEASED' + message = '' + + if tag: + release_status = 'unstable' + release_version = tag.name[1:] # strip leading "v" + if isinstance(tag.object, git.TagObject): + release_author = tag.object.tagger + release_date = tag.object.tagged_date + message = tag.object.message.split('-----BEGIN PGP SIGNATURE-----')[0].strip() + else: + release_author = tag.object.committer + release_date = tag.object.committed_date + elif commits: + release_author = commits[0].committer + release_date = commits[0].committed_date + date = datetime.datetime.fromtimestamp(release_date).strftime('%Y%m%dT%H%M%S') + last_version = '0.0.0' + if last_tag: + last_version = last_tag.name[1:] # strip leading "v" + release_version = f'{last_version}+git{date}-{commits[0].hexsha[:8]}' + + print(f'{package_name} ({release_version}) {release_status}; urgency=medium') + print() + if message: + print(textwrap.indent(message, ' ')) + print() + commit_authors = [] # list of (key, author), sorted by first commit date + commit_author_emails = {} # author email -> key + commit_author_names = {} # author name -> key + commit_author_commits = {} # key -> list of commits + for commit in commits: + if any(filter(lambda pattern: re.match(pattern, commit.summary), ignore_commit_regexes)): + continue + if len(commit.parents) > 1: + continue # Ignore merge commits + author_name = alias_names.get(commit.author.name, commit.author.name) + key = commit_author_emails.get(commit.author.email) + if key is None: + key = commit_author_names.get(author_name) + if key is None: + key = commit.author.email + commit_authors.append((key, author_name)) + commit_author_emails[commit.author.email] = key + commit_author_names[author_name] = key + commit_author_commits[key] = commit_author_commits.get(key, []) + [commit] + commit_authors.sort(key=lambda args: len(commit_author_commits[args[0]])) + for key, author_name in commit_authors: + print(f' [ {author_name} ]') + for commit in commit_author_commits[key]: + lines = '\n'.join(textwrap.wrap(commit.summary, 90)) + lines = ' * ' + textwrap.indent(lines, ' ').strip() + print(lines) + print() + print(f' -- {alias_names.get(release_author.name, release_author.name)} <{release_author.email}> {email.utils.formatdate(release_date)}') + +if __name__ == '__main__': + repo = git.Repo('.') + package_name = sys.argv[1] + + version_commits = {} + for tag in repo.tags: + if not re.fullmatch('v[0-9]+[.][0-9]+[.][0-9]+.*', tag.name): + continue + if isinstance(tag.object, git.TagObject): + commit_hexsha = tag.object.object.hexsha + else: + commit_hexsha = tag.object.hexsha + version_commits[commit_hexsha] = tag + + tag = None + commits = [] + for commit in repo.iter_commits('HEAD'): + if commit.hexsha in version_commits: + prev_tag = version_commits[commit.hexsha] + if commits: + print_release(tag, commits, last_tag=prev_tag) + print() + tag = prev_tag + commits = [] + commits.append(commit) + print_release(tag, commits) diff --git a/debian/install b/debian/install new file mode 100644 index 0000000000000000000000000000000000000000..00fab7fe5da70870e5bd3aa9d712ba289dab269e --- /dev/null +++ b/debian/install @@ -0,0 +1,5 @@ +uwsgi.ini /etc/uffd-nginxauth/ +nginx.include.conf /etc/uffd-nginxauth/ +debian/contrib/uffd-nginxauth.cfg /etc/uffd-nginxauth/ +app.py /usr/share/uffd-nginxauth/ +default_config.py /usr/share/uffd-nginxauth/ diff --git a/debian/links b/debian/links new file mode 100644 index 0000000000000000000000000000000000000000..78050aa3a0db1c494b33e89468bd967f97521ceb --- /dev/null +++ b/debian/links @@ -0,0 +1,3 @@ +/etc/uffd-nginxauth/uffd-nginxauth.cfg /usr/share/uffd-nginxauth/instance/config.cfg +/etc/uffd-nginxauth/uwsgi.ini /etc/uwsgi/apps-available/uffd-nginxauth.ini +/etc/uwsgi/apps-available/uffd-nginxauth.ini /etc/uwsgi/apps-enabled/uffd-nginxauth.ini diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 0000000000000000000000000000000000000000..176bc6e9597668a4e776b3840f4b1b511a6f6d07 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,30 @@ +#!/bin/sh + +set -e + +case "$1" in + configure) + getent group uffd-nginxauth >/dev/null 2>&1 || addgroup --system uffd-nginxauth + adduser --system --home /var/lib/uffd-nginxauth --quiet uffd-nginxauth --ingroup uffd-nginxauth || true + + chown -R uffd-nginxauth:uffd-nginxauth /var/lib/uffd-nginxauth + chmod 0770 /var/lib/uffd-nginxauth + + chown root:uffd-nginxauth /etc/uffd-nginxauth/uffd-nginxauth.cfg + chmod 0640 /etc/uffd-nginxauth/uffd-nginxauth.cfg + + invoke-rc.d uwsgi restart uffd-nginxauth + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/debian/postrm b/debian/postrm new file mode 100755 index 0000000000000000000000000000000000000000..c11868c7f50a7bf9fd18c6c380e48f1a87109f76 --- /dev/null +++ b/debian/postrm @@ -0,0 +1,19 @@ +#!/bin/sh + +set -e + +case "$1" in + purge) + delgroup uffd-nginxauth || true + userdel uffd-nginxauth --remove-home || true + ;; + remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + ;; + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 +esac + +#DEBHELPER# + +exit 0 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000000000000000000000000000000000000..cbe925d7587131c8ec8761915930894c60c096fd --- /dev/null +++ b/debian/rules @@ -0,0 +1,3 @@ +#!/usr/bin/make -f +%: + dh $@ diff --git a/nginx.include.conf b/nginx.include.conf new file mode 100644 index 0000000000000000000000000000000000000000..910737826091ce9a13e0a9e7df69f12770e89d4f --- /dev/null +++ b/nginx.include.conf @@ -0,0 +1,4 @@ +location / { + uwsgi_pass unix:///run/uwsgi/app/uffd-nginxauth/socket; + include uwsgi_params; +} diff --git a/uwsgi.ini b/uwsgi.ini new file mode 100644 index 0000000000000000000000000000000000000000..971017a339e43a5b7b95a07b56c107ca633bb2a4 --- /dev/null +++ b/uwsgi.ini @@ -0,0 +1,16 @@ +[uwsgi] +plugin = python3 +manage-script-name = true +workers = %k*2 + +uid = uffd-nginxauth +gid = uffd-nginxauth + +vacuum = true + +env = PYTHONIOENCODING=UTF-8 +env = LANG=en_GB.utf8 +env = TZ=Europe/Berlin +env = CONFIG_FILENAME=/etc/uffd-nginxauth/uffd-nginxauth.cfg +chdir = /usr/share/uffd-nginxauth +module = app:create_app()