diff --git a/.github/actions/pydpkg/action.yml b/.github/actions/pydpkg/action.yml new file mode 100644 index 000000000..e80b3722a --- /dev/null +++ b/.github/actions/pydpkg/action.yml @@ -0,0 +1,72 @@ +inputs: + workaround: + default: "" + required: true + path: + default: "debian" + required: true + +branding: + icon: "rotate-cw" + color: "red" + +env: + # note that some tools care only for the name, not the value + FORCE_COLOR: 1 + + # reduce metadata. unlike elsewhere, build artifacts should differ by content only + SOURCE_DATE_EPOCH: 0 + +runs: + using: "composite" + steps: + - name: prepare deb source dir (${{ inputs.path }}) + # why the incorrect version? because this way we can skip rewrite debian/changelog for now + shell: bash + run: | + mkdir --verbose --parents upload/${{ inputs.path }} + mkdir --verbose --parents ${{ inputs.path }} + ( cd source/ && git archive --format=tar --prefix=gunicorn-21.2.0/ HEAD | gzip ) > ${{ inputs.path }}/gunicorn_21.2.0.orig.tar.gz + ( cd ${{ inputs.path }}/ && tar --extract --file gunicorn_21.2.0.orig.tar.gz gunicorn-21.2.0 ) + test -s ${{ inputs.path }}/gunicorn-21.2.0/pyproject.toml + rsync -vrlt source/.github/packaging/debian/ ${{ inputs.path }}/gunicorn-21.2.0/debian + chmod --changes +x ${{ inputs.path }}/gunicorn-21.2.0/debian/control + ls -l ${{ inputs.path }}/gunicorn-21.2.0/ + - name: prepare workarounds (${{ inputs.path }}) + if: ${{ inputs.workaround != '' }} + shell: bash + run: | + echo 'extend-diff-ignore = "^setup\.cfg$"' >> ${{ inputs.path }}/gunicorn-21.2.0/debian/source/options + mv --verbose ${{ inputs.path }}/gunicorn-21.2.0/debian/setup.cfg ${{ inputs.path }}/gunicorn-21.2.0/ + # ideally, build-dep step would be executed by dkpg scripts + - name: Install dpkg Dependencies + shell: bash + run: | + sudo apt-get update + sudo DEBIAN_FRONTEND=noninteractive apt-get -y install dpkg-dev make python3-all quilt debhelper dh-python python3-setuptools pybuild-plugin-pyproject + # print versions + apt policy python3-all + apt policy dh-python + apt policy python3-setuptools + apt policy python3-distutils + apt policy python3-toml + apt policy python3-tomli + apt policy python3-setuptools-whl + apt policy python3-pep517 + apt policy python3-build + apt policy pybuild-plugin-pyproject + - name: verify workarounds (${{ inputs.path }}) + if: ${{ inputs.workaround != '' }} + shell: bash + run: | + test -s ${{ inputs.path }}/gunicorn-21.2.0/setup.cfg + - name: build deb (${{ inputs.path }}) + shell: bash + run: | + test -s ${{ inputs.path }}/gunicorn-21.2.0/pyproject.toml + test -s ${{ inputs.path }}/gunicorn-21.2.0/debian/control + test -d ${{ inputs.path }}/gunicorn-21.2.0/tests + ( cd ${{ inputs.path }}/gunicorn-21.2.0/ && dpkg-buildpackage --unsigned-source --unsigned-changes ) + # note that Ubuntu 22.04 does not allow zstd in dpkg tools + rsync --ignore-missing-args -trv ${{ inputs.path }}/*.{deb,tar.gz,tar.xz,tar.zstd,buildinfo,changes,dsc} upload/${{ inputs.path }}/ + diff --git a/.github/packaging/debian/changelog b/.github/packaging/debian/changelog new file mode 100644 index 000000000..2cde17018 --- /dev/null +++ b/.github/packaging/debian/changelog @@ -0,0 +1,6 @@ +gunicorn (21.2.0-0~ci0+github1) unstable; urgency=low + + * Initial release (not actually installable package. built for git). + + -- Octocat Sun, 10 Dec 2023 23:28:24 +0100 + diff --git a/.github/packaging/debian/clean b/.github/packaging/debian/clean new file mode 100644 index 000000000..2675facbe --- /dev/null +++ b/.github/packaging/debian/clean @@ -0,0 +1,8 @@ +gunicorn.egg-info/ +gunicorn.egg-info/entry_points.txt +gunicorn.egg-info/dependency_links.txt +gunicorn.egg-info/SOURCES.txt +gunicorn.egg-info/not-zip-safe +gunicorn.egg-info/top_level.txt +gunicorn.egg-info/requires.txt +gunicorn.egg-info/PKG-INFO diff --git a/.github/packaging/debian/control b/.github/packaging/debian/control new file mode 100644 index 000000000..82b90db94 --- /dev/null +++ b/.github/packaging/debian/control @@ -0,0 +1,68 @@ +Source: gunicorn +Section: httpd +Priority: optional +Homepage: https://gunicorn.org/ +Maintainer: Octocat +Build-Depends: + debhelper-compat (= 13), + dh-python, + pybuild-plugin-pyproject, + python3-all, + python3-setuptools, +Standards-Version: 4.6.2 +Testsuite: autopkgtest-pkg-python +Rules-Requires-Root: no + +Package: gunicorn +Section: httpd +Priority: optional +Architecture: all +Depends: + python3-gunicorn (= ${binary:Version}), + ${misc:Depends}, + ${python3:Depends}, +Provides: + gunicorn3, + httpd-wsgi3 +Conflicts: + gunicorn3, +Replaces: + gunicorn3, +Suggests: + python3-setproctitle, + python3-pastedeploy, + python3-eventlet, + python3-tornado, +Description: Event-based HTTP/WSGI server + Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork + worker model ported from Ruby's Unicorn_ project. The Gunicorn server is broadly + compatible with various web frameworks, simply implemented, light on server + resource usage, and fairly speedy. + . + This is the server. + +Package: gunicorn-examples +Section: python +Priority: optional +Architecture: all +Description: Event-based HTTP/WSGI server (examples) + Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork + worker model ported from Ruby's Unicorn_ project. The Gunicorn server is broadly + compatible with various web frameworks, simply implemented, light on server + resource usage, and fairly speedy. + . + These are the examples. + +Package: python3-gunicorn +Section: python +Priority: optional +Architecture: all +Suggests: gunicorn +Depends: ${misc:Depends}, ${python3:Depends} +Description: Event-based HTTP/WSGI server (Python 3 libraries) + Gunicorn 'Green Unicorn' is a Python WSGI HTTP Server for UNIX. It's a pre-fork + worker model ported from Ruby's Unicorn_ project. The Gunicorn server is broadly + compatible with various web frameworks, simply implemented, light on server + resource usage, and fairly speedy. + . + This is the Python library for Python 3. diff --git a/.github/packaging/debian/copyright b/.github/packaging/debian/copyright new file mode 100644 index 000000000..88ce2f7df --- /dev/null +++ b/.github/packaging/debian/copyright @@ -0,0 +1,87 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: gunicorn +Upstream-Contact: Benoît Chesneau +Source: http://gunicorn.org/ + +Files: * +Copyright: +2009-2023 (c) Benoît Chesneau +2009-2015 (c) Paul J. Davis +License: MIT + +Files: debian/* +Copyright: invalid +License: Expat + +Files: docs/sitemap_gen.py +Copyright: © 2004, 2005 Google Inc. +License: BSD-3-Clause + +License: Expat + 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. + +License: MIT +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. + + +License: BSD-3-Clause +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/.github/packaging/debian/gunicorn-examples.examples b/.github/packaging/debian/gunicorn-examples.examples new file mode 100644 index 000000000..e39721e20 --- /dev/null +++ b/.github/packaging/debian/gunicorn-examples.examples @@ -0,0 +1 @@ +examples/* diff --git a/.github/packaging/debian/rules b/.github/packaging/debian/rules new file mode 100755 index 000000000..f0a5c0f92 --- /dev/null +++ b/.github/packaging/debian/rules @@ -0,0 +1,30 @@ +#!/usr/bin/make -f + +export DH_VERBOSE = 1 +export PYBUILD_NAME = gunicorn + +export PYBUILD_DISABLE = test + +# until this works: use debian/tests/upstream +# export PYBUILD_TEST_PYTEST = 0 + +# pyproject.toml referring to not installed plugins could otherwise confuse pytest +export PYBUILD_TEST_ARGS = --override-ini=addopts= + +# distutils: try running via setup.py +# assuming pyproject is broken, as it decided to create UNKNOWN.egg-info +# export PYBUILD_SYSTEM = distutils +export PYBUILD_SYSTEM = pyproject + +%: + dh $@ --with=python3 --buildsystem=pybuild + +override_dh_auto_install: + # super() + dh_auto_install + # split binary/library into separate packages + mkdir -p debian/gunicorn/usr/bin + find debian/ + mv debian/python3-gunicorn/usr/bin/gunicorn debian/gunicorn/usr/bin + +# split of examples into separate package is handled by dh_installexamples(1) diff --git a/.github/packaging/debian/setup.cfg b/.github/packaging/debian/setup.cfg new file mode 100644 index 000000000..b2277b29d --- /dev/null +++ b/.github/packaging/debian/setup.cfg @@ -0,0 +1,21 @@ +# copying this file into build tree permits build w/o pyproject.toml support +# e.g. see .github/actions/pydpkg/action.yml + +[metadata] +license_files = ['LICENSE'] +name = gunicorn +version = attr: gunicorn.__version__ +author = Benoit Chesneau +license = MIT +description = WSGI HTTP Server for UNIX + +[options] +packages = find: +install_requires = + packaging +include_package_data = True +python_requires = >=3.8 + +[options.entry_points] +console_scripts = + gunicorn = gunicorn.app.wsgiapp:run diff --git a/.github/packaging/debian/source/format b/.github/packaging/debian/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/.github/packaging/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/.github/packaging/debian/source/linitian-overrides b/.github/packaging/debian/source/linitian-overrides new file mode 100644 index 000000000..fa22c1501 --- /dev/null +++ b/.github/packaging/debian/source/linitian-overrides @@ -0,0 +1 @@ +debian-watch-does-not-check-openpgp-signature diff --git a/.github/packaging/debian/tests/control b/.github/packaging/debian/tests/control new file mode 100644 index 000000000..f6d18e336 --- /dev/null +++ b/.github/packaging/debian/tests/control @@ -0,0 +1,10 @@ +Tests: upstream +Depends: + python3-all, + @, + @builddeps@, + +Tests: curl + curl, + procps, + @, diff --git a/.github/packaging/debian/tests/curl b/.github/packaging/debian/tests/curl new file mode 100644 index 000000000..66f2f8a34 --- /dev/null +++ b/.github/packaging/debian/tests/curl @@ -0,0 +1,11 @@ +#!/bin/sh + +set -eu + +cd debian/tests +gunicorn --daemon --bind unix:gunicorn.sock --pid=gunicorn.pid --workers=2 test:app +sleep 5 + +curl --unix-socket gunicorn.sock http://localhost/ | grep -F 'DEBIAN' +kill $(cat gunicorn.pid) +rm -f gunicorn.pid gunicorn.sock diff --git a/.github/packaging/debian/tests/test.py b/.github/packaging/debian/tests/test.py new file mode 100644 index 000000000..e78b5c655 --- /dev/null +++ b/.github/packaging/debian/tests/test.py @@ -0,0 +1,8 @@ +def app(env, start): + body = b'DEBIAN\n' + header = [ + ('CONTENT-LENGTH', str(len(body))), + ('CONTENT-TYPE', 'text/plain'), + ] + start_response("200 OK", header) + return iter([body]) diff --git a/.github/packaging/debian/tests/upstream b/.github/packaging/debian/tests/upstream new file mode 100644 index 000000000..ffc2cdccb --- /dev/null +++ b/.github/packaging/debian/tests/upstream @@ -0,0 +1,14 @@ +#!/bin/sh + +set -e + +cp -r tests ${AUTOPKGTEST_TMP} +cd ${AUTOPKGTEST_TMP} + +# why that --override-ini=? +# pyproject.toml could mention plugins not installed during build +# => workaround by setting empty + +for p in $(pyversions -s); do + $p -m pytest --override-ini=addopts= tests/ +done diff --git a/.github/packaging/debian/watch b/.github/packaging/debian/watch new file mode 100644 index 000000000..fd097e778 --- /dev/null +++ b/.github/packaging/debian/watch @@ -0,0 +1,2 @@ +version=4 +https://github.com/benoitc/gunicorn/tags .*/(.*)\.tar\.gz diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml new file mode 100644 index 000000000..03debcb91 --- /dev/null +++ b/.github/workflows/packaging.yml @@ -0,0 +1,68 @@ +name: packaging +# Goal: produce .deb files on Ubuntu >= 22.04 (jammy) or Debian >= 12 (bookworm/bullseye-backports) +# https://wiki.debian.org/Packaging +# https://www.debian.org/doc/debian-policy/ +# https://www.debian.org/doc/packaging-manuals/python-policy/ + +# https://docs.github.com/articles/events-that-trigger-workflows +on: + push: + tags: + - '*' + pull_request: + # self + paths: + - .github/workflows/packaging.yml + - .github/actions/pydpkg/* + - .github/packaging/debian/* + - pyproject.toml + workflow_dispatch: + # https://docs.github.com/articles/configuring-a-workflow#manually-running-a-workflow + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + # note that some tools care only for the name, not the value + FORCE_COLOR: 1 + + # reduce metadata. unlike elsewhere, build artifacts should differ by content only + SOURCE_DATE_EPOCH: 0 + +jobs: + dpkg-buildpackage: + name: buildpackage-${{ matrix.python-version }} + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes + timeout-minutes: 5 + # https://docs.github.com/articles/virtual-environments-for-github-actions + runs-on: ubuntu-latest + strategy: + fail-fast: true + # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix + matrix: + python-version: [ "os-py" ] + steps: + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + path: source + - name: "Build dpkg package (with workaround)" + uses: ./source/.github/actions/pydpkg + with: + path: debian-workaround + workaround: "all" + - name: "Build dpkg package (default)" + uses: ./source/.github/actions/pydpkg + continue-on-error: true + with: + path: debian + workaround: "" + - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 + with: + path: | + upload/debian-workaround/* + upload/debian/* + name: deb + retention-days: 5 + # deb and source tarball are already compressed + compression-level: 0 + if-no-files-found: error diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..61468649b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,37 @@ +name: release + +on: + push: + tags: + - '*' + # FIXME: enable for for CI-triggered pypi uploads: + # release: + # types: + # - published + workflow_dispatch: + +permissions: + contents: read + # FIXME: enable for "trusted" publishing: + # id-token: write + +jobs: + pypi-publish: + runs-on: ubuntu-latest + environment: + name: gunicorn + # FIXME: this is just the TEST pypi url! + url: https://test.pypi.org/p/gunicorn + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Install dist Dependencies + run: | + python -m pip install build + - run: python -m build + - name: do release + if: ${{ github.event_name == 'release' }} + uses: pypa/gh-action-pypi-publish@2f6f737ca5f74c637829c0f5c3acd0e29ea5e8bf # v1.8.11 + with: + # FIXME: this is just the TEST pypi url! + repository-url: https://test.pypi.org/legacy/ + verbose: true