From 3ea1f527c7913390c59a82d773070d0e7cf5b96a Mon Sep 17 00:00:00 2001 From: Gwyn Ciesla Date: Dec 15 2023 21:18:13 +0000 Subject: 3.10.0 --- diff --git a/.gitignore b/.gitignore index 705075f..ec44035 100644 --- a/.gitignore +++ b/.gitignore @@ -184,3 +184,12 @@ buildbot-0.7.12.tar.gz /buildbot-worker-3.9.2.tar.gz /buildbot-wsgi-dashboards-3.9.2.tar.gz /buildbot-www-3.9.2.tar.gz +/buildbot-3.10.0.tar.gz +/buildbot-badges-3.10.0.tar.gz +/buildbot-console-view-3.10.0.tar.gz +/buildbot-grid-view-3.10.0.tar.gz +/buildbot-pkg-3.10.0.tar.gz +/buildbot-waterfall-view-3.10.0.tar.gz +/buildbot-worker-3.10.0.tar.gz +/buildbot-wsgi-dashboards-3.10.0.tar.gz +/buildbot-www-3.10.0.tar.gz diff --git a/7026.patch b/7026.patch new file mode 100644 index 0000000..24f7aea --- /dev/null +++ b/7026.patch @@ -0,0 +1,450 @@ +diff --git a/master/buildbot/plugins/db.py b/master/buildbot/plugins/db.py +index f08833e9993..15c6ebf8740 100644 +--- a/master/buildbot/plugins/db.py ++++ b/master/buildbot/plugins/db.py +@@ -25,6 +25,7 @@ + + from buildbot.errors import PluginDBError + from buildbot.interfaces import IPlugin ++from buildbot.util.importlib_compat import entry_points_get + + # Base namespace for Buildbot specific plugins + _NAMESPACE_BASE = 'buildbot' +@@ -34,8 +35,8 @@ def find_distribution_info(entry_point_name, entry_point_group): + for distribution in distributions(): + # each distribution can have many entry points + try: +- for ep in distribution.entry_points: +- if ep.name == entry_point_name and ep.group == entry_point_group: ++ for ep in entry_points_get(distribution.entry_points, entry_point_group): ++ if ep.name == entry_point_name: + return (distribution.metadata['Name'], distribution.metadata['Version']) + except KeyError as exc: + raise PluginDBError("Plugin info was found, but it is invalid.") from exc +@@ -242,7 +243,7 @@ def _load_entry(self, entry): + def _tree(self): + if self._real_tree is None: + self._real_tree = _NSNode() +- entries = entry_points().get(self._group, []) ++ entries = entry_points_get(entry_points(), self._group) + for entry in entries: + self._real_tree.add(entry.name, + _PluginEntry(self._group, entry, +diff --git a/master/buildbot/test/util/www.py b/master/buildbot/test/util/www.py +index df3ab34443c..dc312828842 100644 +--- a/master/buildbot/test/util/www.py ++++ b/master/buildbot/test/util/www.py +@@ -29,6 +29,7 @@ + from buildbot.test.fake import fakemaster + from buildbot.util import bytes2unicode + from buildbot.util import unicode2bytes ++from buildbot.util.importlib_compat import entry_points_get + from buildbot.www import auth + from buildbot.www import authz + +@@ -123,7 +124,7 @@ def getSession(self): + class RequiresWwwMixin: + # mix this into a TestCase to skip if buildbot-www is not installed + +- if not [ep for ep in entry_points().get('buildbot.www', []) if ep.name == 'base']: ++ if not [ep for ep in entry_points_get(entry_points(), 'buildbot.www') if ep.name == 'base']: + if 'BUILDBOT_TEST_REQUIRE_WWW' in os.environ: + raise RuntimeError('$BUILDBOT_TEST_REQUIRE_WWW is set but ' + 'buildbot-www is not installed') +diff --git a/master/buildbot/util/importlib_compat.py b/master/buildbot/util/importlib_compat.py +new file mode 100644 +index 00000000000..9c0aa3eecbe +--- /dev/null ++++ b/master/buildbot/util/importlib_compat.py +@@ -0,0 +1,33 @@ ++# This file is part of Buildbot. Buildbot is free software: you can ++# redistribute it and/or modify it under the terms of the GNU General Public ++# License as published by the Free Software Foundation, version 2. ++# ++# This program is distributed in the hope that it will be useful, but WITHOUT ++# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ++# details. ++# ++# You should have received a copy of the GNU General Public License along with ++# this program; if not, write to the Free Software Foundation, Inc., 51 ++# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++# ++# Copyright Buildbot Team Members ++ ++# This module is for backward compatibility of importlib. ++ ++ ++def entry_points_get(entry_points, group): ++ """ Since Python 3.12 dictionary access is removed and replaced by new interface. ++ see: https://github.com/python/cpython/issues/97781 ++ """ ++ if hasattr(entry_points, "select"): ++ return entry_points.select(group=group) ++ else: ++ if isinstance(entry_points, list): ++ filtered_entry_points = [] ++ for ep in entry_points: ++ if ep.group == group: ++ filtered_entry_points.append(ep) ++ return filtered_entry_points ++ else: ++ return entry_points.get(group, []) + +From 501a2edcc13bdad04cae5f8f01e2bb94009af4b9 Mon Sep 17 00:00:00 2001 +From: Pavol Misik +Date: Mon, 20 Nov 2023 23:07:10 +0100 +Subject: [PATCH 07/15] test: Disable twisted generated warning "the (type, + exc, tb) signature of throw() is deprecated" on Python 3.12 + +--- + master/buildbot/test/__init__.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/master/buildbot/__init__.py b/master/buildbot/__init__.py +index c7640ce56a1..0681ee8d516 100644 +--- a/master/buildbot/__init__.py ++++ b/master/buildbot/__init__.py +@@ -53,7 +53,7 @@ def mTimeVersion(init_file): + for root, _, files in os.walk(cwd): + for f in files: + m = max(os.path.getmtime(os.path.join(root, f)), m) +- d = datetime.datetime.utcfromtimestamp(m) ++ d = datetime.datetime.fromtimestamp(m, datetime.timezone.utc) + return d.strftime("%Y.%m.%d") + + +@@ -80,7 +80,7 @@ def getVersionFromArchiveId(git_archive_id='$Format:%ct %d$'): + + # archived revision is not tagged, use the commit date + tstamp = git_archive_id.strip().split()[0] +- d = datetime.datetime.utcfromtimestamp(int(tstamp)) ++ d = datetime.datetime.fromtimestamp(int(tstamp), datetime.timezone.utc) + return d.strftime('%Y.%m.%d') + return None + +diff --git a/master/buildbot/changes/gerritchangesource.py b/master/buildbot/changes/gerritchangesource.py +index 3971173603d..308188e035f 100644 +--- a/master/buildbot/changes/gerritchangesource.py ++++ b/master/buildbot/changes/gerritchangesource.py +@@ -543,7 +543,7 @@ def reconfigService(self, + @staticmethod + def now(): + """patchable now (datetime is not patchable as builtin)""" +- return datetime.datetime.utcnow() ++ return datetime.datetime.now(datetime.timezone.utc) + + @defer.inlineCallbacks + def poll(self): +@@ -553,7 +553,7 @@ def poll(self): + # the last event time to some historical look-back + last_event = self.now() - datetime.timedelta(days=self._first_fetch_lookback) + else: +- last_event = datetime.datetime.utcfromtimestamp(last_event_ts) ++ last_event = datetime.datetime.fromtimestamp(last_event_ts, datetime.timezone.utc) + last_event_formatted = last_event.strftime("%Y-%m-%d %H:%M:%S") + + if self.debug: +diff --git a/master/buildbot/changes/mail.py b/master/buildbot/changes/mail.py +index e9907c9aa5b..6f39f3880a5 100644 +--- a/master/buildbot/changes/mail.py ++++ b/master/buildbot/changes/mail.py +@@ -116,7 +116,7 @@ def parse(self, m, prefix=None): + else: + when = mktime_tz(dateTuple) + +- theTime = datetime.datetime.utcfromtimestamp(float(when)) ++ theTime = datetime.datetime.fromtimestamp(float(when), datetime.timezone.utc) + rev = theTime.strftime('%Y-%m-%d %H:%M:%S') + + catRE = re.compile(r'^Category:\s*(\S.*)') +diff --git a/master/buildbot/configurators/janitor.py b/master/buildbot/configurators/janitor.py +index adfe8112186..27924edb295 100644 +--- a/master/buildbot/configurators/janitor.py ++++ b/master/buildbot/configurators/janitor.py +@@ -32,7 +32,7 @@ + + def now(): + """patchable now (datetime is not patchable as builtin)""" +- return datetime.datetime.utcnow() ++ return datetime.datetime.now(datetime.timezone.utc) + + + class LogChunksJanitor(BuildStep): +diff --git a/master/buildbot/schedulers/timed.py b/master/buildbot/schedulers/timed.py +index a36fbb92689..3318d28c1bf 100644 +--- a/master/buildbot/schedulers/timed.py ++++ b/master/buildbot/schedulers/timed.py +@@ -286,7 +286,8 @@ def now(self): + + def current_utc_offset(self, tm): + return ( +- datetime.datetime.fromtimestamp(tm) - datetime.datetime.utcfromtimestamp(tm) ++ datetime.datetime.fromtimestamp(tm).replace(tzinfo=datetime.timezone.utc) ++ - datetime.datetime.fromtimestamp(tm, datetime.timezone.utc) + ).total_seconds() + + @defer.inlineCallbacks +diff --git a/master/buildbot/test/unit/test_util.py b/master/buildbot/test/unit/test_util.py +index dfd4e1f42a0..8e2eb482a9d 100644 +--- a/master/buildbot/test/unit/test_util.py ++++ b/master/buildbot/test/unit/test_util.py +@@ -204,7 +204,7 @@ def test_UTC(self): + datetime.timedelta(0)) + self.assertEqual(util.UTC.dst(datetime.datetime.now()), + datetime.timedelta(0)) +- self.assertEqual(util.UTC.tzname(datetime.datetime.utcnow()), "UTC") ++ self.assertEqual(util.UTC.tzname(datetime.datetime.now(datetime.timezone.utc)), "UTC") + + def test_epoch2datetime(self): + self.assertEqual(util.epoch2datetime(0), +diff --git a/master/buildbot/www/rest.py b/master/buildbot/www/rest.py +index 0685f8bbade..83090779122 100644 +--- a/master/buildbot/www/rest.py ++++ b/master/buildbot/www/rest.py +@@ -337,7 +337,7 @@ def writeError(msg, errcode=404, jsonrpccode=None): + + # set up caching + if self.cache_seconds: +- now = datetime.datetime.utcnow() ++ now = datetime.datetime.now(datetime.timezone.utc) + expires = now + datetime.timedelta(seconds=self.cache_seconds) + expiresBytes = unicode2bytes( + expires.strftime("%a, %d %b %Y %H:%M:%S GMT")) +diff --git a/master/buildbot/www/service.py b/master/buildbot/www/service.py +index f07c95cd90f..99e2897bc93 100644 +--- a/master/buildbot/www/service.py ++++ b/master/buildbot/www/service.py +@@ -130,7 +130,7 @@ def uid(self): + + This should actually only be used for cookie generation + """ +- exp = datetime.datetime.utcnow() + self.expDelay ++ exp = datetime.datetime.now(datetime.timezone.utc) + self.expDelay + claims = { + 'user_info': self.user_info, + # Note that we use JWT standard 'exp' field to implement session expiration +diff --git a/master/buildbot/process/remotetransfer.py b/master/buildbot/process/remotetransfer.py +index 76a13faadf3..8ac5f888d28 100644 +--- a/master/buildbot/process/remotetransfer.py ++++ b/master/buildbot/process/remotetransfer.py +@@ -126,7 +126,10 @@ def remote_unpack(self): + + # Unpack archive and clean up after self + with tarfile.open(name=self.tarname, mode=mode) as archive: +- archive.extractall(path=self.destroot) ++ if hasattr(tarfile, 'data_filter'): ++ archive.extractall(path=self.destroot, filter='data') ++ else: ++ archive.extractall(path=self.destroot) + os.remove(self.tarname) + + +diff --git a/master/buildbot/test/integration/test_upgrade.py b/master/buildbot/test/integration/test_upgrade.py +index 66669b1b340..40867e4fabc 100644 +--- a/master/buildbot/test/integration/test_upgrade.py ++++ b/master/buildbot/test/integration/test_upgrade.py +@@ -77,7 +77,10 @@ def setUpUpgradeTest(self): + with tarfile.open(tarball) as tf: + prefixes = set() + for inf in tf: +- tf.extract(inf) ++ if hasattr(tarfile, 'data_filter'): ++ tf.extract(inf, filter='data') ++ else: ++ tf.extract(inf) + prefixes.add(inf.name.split('/', 1)[0]) + + # (note that tf.extractall isn't available in py2.4) + +From c47b372fe1b577ed1aa5c003ee17e25514bcda49 Mon Sep 17 00:00:00 2001 +From: Pavol Misik +Date: Tue, 5 Dec 2023 21:47:40 +0100 +Subject: [PATCH 11/15] test: Disable datetime.utcnow and + datetime.utcfromtimestamp warnings on Python 3.12 + +--- + master/buildbot/test/__init__.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/master/buildbot/util/private_tempdir.py b/master/buildbot/util/private_tempdir.py +index ee6c4eae3d0..b2dba0b46a6 100644 +--- a/master/buildbot/util/private_tempdir.py ++++ b/master/buildbot/util/private_tempdir.py +@@ -16,6 +16,7 @@ + import os + import shutil + import stat ++import sys + import tempfile + + +@@ -46,5 +47,8 @@ def remove_readonly(func, path, _): + """ + os.chmod(path, stat.S_IWRITE) + func(path) +- shutil.rmtree(self.name, onerror=remove_readonly) ++ if sys.version_info >= (3, 12): ++ shutil.rmtree(self.name, onexc=remove_readonly) ++ else: ++ shutil.rmtree(self.name, onerror=remove_readonly) + self._cleanup_needed = False + +From c44051639eb2acbb4357c273af46b0e3292bab61 Mon Sep 17 00:00:00 2001 +From: Pavol Misik +Date: Wed, 6 Dec 2023 17:13:39 +0100 +Subject: [PATCH 13/15] Fix asyncio changes in Python 3.12 + +Problem observed: + - failing tests buildbot.test.integration.test_worker_proxy + - failing with stack traces like + +[ERROR] +Traceback (most recent call last): + File "C:\P\.venv\Lib\site-packages\twisted\internet\defer.py", line 1996, in _inlineCallbacks + result = context.run( + File "C:\P\.venv\Lib\site-packages\twisted\python\failure.py", line 519, in throwExceptionIntoGenerator + return g.throw(self.type, self.value, self.tb) + File "C:\P\buildbot\master\buildbot\test\integration\interop\test_transfer.py", line 197, in test_no_exist_multiple_file_upload + yield self.setup_config_single_step(step) + File "C:\P\.venv\Lib\site-packages\twisted\internet\defer.py", line 1996, in _inlineCallbacks + result = context.run( + File "C:\P\.venv\Lib\site-packages\twisted\python\failure.py", line 519, in throwExceptionIntoGenerator + return g.throw(self.type, self.value, self.tb) + File "C:\P\buildbot\master\buildbot\test\integration\interop\test_transfer.py", line 130, in setup_config_single_step + yield self.setup_master(c) + File "C:\P\.venv\Lib\site-packages\twisted\internet\defer.py", line 1996, in _inlineCallbacks + result = context.run( + File "C:\P\.venv\Lib\site-packages\twisted\python\failure.py", line 519, in throwExceptionIntoGenerator + return g.throw(self.type, self.value, self.tb) + File "C:\P\buildbot\master\buildbot\test\integration\test_worker_proxy.py", line 159, in setup_master + yield super().setup_master(config_dict, startWorker, + File "C:\P\.venv\Lib\site-packages\twisted\internet\defer.py", line 2000, in _inlineCallbacks + result = context.run(gen.send, result) + File "C:\P\buildbot\master\buildbot\test\util\integration.py", line 249, in setup_master + self.w = Worker( + File "C:\P\buildbot\worker\buildbot_worker\pb.py", line 667, in __init__ + proxy_endpoint = clientFromString(reactor, proxy_connection_string) + File "C:\P\.venv\Lib\site-packages\twisted\internet\endpoints.py", line 2137, in clientFromString + kwargs = _clientParsers[name](*args, **kwargs) + File "C:\P\.venv\Lib\site-packages\twisted\internet\endpoints.py", line 1861, in _parseClientTCP + kwargs["port"] = int(args[1]) +builtins.ValueError: invalid literal for int() with base 10: 'test_worker_proxy_stdout_11208.txt' + +But real problem seems to be in start of proxy + +Exception Raised: There is no current event loop +Traceback (most recent call last): + File "C:\P\buildbot\master\buildbot\test\integration\test_worker_proxy.py", line 92, in run_proxy + loop = asyncio.get_event_loop() + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Python312\Lib\asyncio\events.py", line 693, in get_event_loop + warnings.warn('There is no current event loop', +DeprecationWarning: There is no current event loop + +Fix is inspired by https://github.com/danigm/jupyter_client/blob/9c1ddf4a50a71181e60be7045d954a3fafa91357/jupyter_client/utils.py#L14-L29 +--- + .../test/integration/test_worker_proxy.py | 20 ++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/master/buildbot/test/integration/test_worker_proxy.py b/master/buildbot/test/integration/test_worker_proxy.py +index 3ac22cd51b2..f62551bdca6 100644 +--- a/master/buildbot/test/integration/test_worker_proxy.py ++++ b/master/buildbot/test/integration/test_worker_proxy.py +@@ -18,6 +18,7 @@ + import os + import signal + import socket ++import sys + + from twisted.internet import defer + +@@ -89,12 +90,21 @@ def run_proxy(queue): + + try: + try: +- loop = asyncio.get_event_loop() ++ loop = asyncio.get_running_loop() + except RuntimeError: +- # We can get RuntimeError due to current thread being not main thread on Python 3.8. +- # It's not clear why that happens, so work around it. +- loop = asyncio.new_event_loop() +- asyncio.set_event_loop(loop) ++ # https://github.com/python/cpython/issues/83710 ++ if sys.version_info <= (3, 10, 8): ++ # Workaround for bugs.python.org/issue39529. ++ try: ++ loop = asyncio.get_event_loop_policy().get_event_loop() ++ except RuntimeError: ++ # We can get RuntimeError due to current thread being not main thread ++ # on Python 3.8. It's not clear why that happens, so work around it. ++ loop = asyncio.new_event_loop() ++ asyncio.set_event_loop(loop) ++ else: ++ loop = asyncio.new_event_loop() ++ asyncio.set_event_loop(loop) + + coro = asyncio.start_server(handle_client, host="127.0.0.1") + server = loop.run_until_complete(coro) + +From 1d0892db19777155f30796bbcfa348dc0317931c Mon Sep 17 00:00:00 2001 +From: Pavol Misik +Date: Fri, 8 Dec 2023 22:14:04 +0100 +Subject: [PATCH 14/15] test: Disable sqlalchemy generated warning + +--- + master/buildbot/test/__init__.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/master/buildbot/test/__init__.py b/master/buildbot/test/__init__.py +index 2d56617ca2f..0855c555e80 100644 +--- a/master/buildbot/test/__init__.py ++++ b/master/buildbot/test/__init__.py +@@ -19,6 +19,7 @@ + from unittest import mock + + import setuptools # force import setuptools before any other distutils imports ++from sqlalchemy.exc import RemovedIn20Warning + + from buildbot import monkeypatches + from buildbot.test.util.warnings import assertProducesWarning # noqa pylint: disable=wrong-import-position +From bcd5b44aae05a8ba6738de3294980c712a1361d9 Mon Sep 17 00:00:00 2001 +From: Pavol Misik +Date: Fri, 15 Dec 2023 01:00:31 +0100 +Subject: [PATCH 15/15] test_asyncio_gather: Fix test + +[ERROR] +Traceback (most recent call last): + File "C:\P\.venv\Lib\site-packages\twisted\internet\defer.py", line 1996, in _inlineCallbacks + result = context.run( + File "C:\P\.venv\Lib\site-packages\twisted\python\failure.py", line 519, in throwExceptionIntoGenerator + return g.throw(self.type, self.value, self.tb) + File "C:\P\buildbot\master\buildbot\test\unit\test_asyncio.py", line 83, in test_asyncio_gather + yield as_deferred(f1) + File "C:\P\.venv\Lib\site-packages\twisted\internet\defer.py", line 1248, in adapt + extracted: _SelfResultT | Failure = result.result() + File "C:\P\buildbot\master\buildbot\test\unit\test_asyncio.py", line 73, in main_coro + await asyncio.gather(*dl) + File "C:\Python312\Lib\asyncio\tasks.py", line 674, in _wrap_awaitable + return await awaitable +builtins.TypeError: __await__() returned non-iterator of type '_asyncio.Future' + +buildbot.test.unit.test_asyncio.TestAsyncioTestLoop.test_asyncio_gather +--- + master/buildbot/test/unit/test_asyncio.py | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/master/buildbot/test/unit/test_asyncio.py b/master/buildbot/test/unit/test_asyncio.py +index e6e18b98d83..355edc4ee73 100644 +--- a/master/buildbot/test/unit/test_asyncio.py ++++ b/master/buildbot/test/unit/test_asyncio.py +@@ -40,8 +40,7 @@ async def coro1(): + d1.callback(None) + return defer.Deferred.fromFuture(f) + +- @defer.inlineCallbacks +- def test_asyncio_gather(self): ++ async def test_asyncio_gather(self): + self.calls = 0 + + async def coro1(): diff --git a/7268.patch b/7268.patch new file mode 100644 index 0000000..4c3dced --- /dev/null +++ b/7268.patch @@ -0,0 +1,108 @@ +From 76574401b18eb86d1a3f9d367b7cba7f44f7bed5 Mon Sep 17 00:00:00 2001 +From: Povilas Kanapickas +Date: Wed, 13 Dec 2023 18:12:46 +0200 +Subject: [PATCH 1/5] asyncio: Fix crash in deferred_await() + +asyncio.get_event_loop() would throw if there's no loop associated with +the thread. +--- + master/buildbot/asyncio.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/master/buildbot/asyncio.py b/master/buildbot/asyncio.py +index 6c91a5a80fa..6fc437a4198 100644 +--- a/master/buildbot/asyncio.py ++++ b/master/buildbot/asyncio.py +@@ -26,7 +26,12 @@ def deferred_await(self): + # if a deferred is awaited from a asyncio loop context, we must return + # the future wrapper, but if it is awaited from normal twisted loop + # we must return self. +- if isinstance(asyncio.get_event_loop(), AsyncIOLoopWithTwisted): ++ try: ++ loop = asyncio.get_event_loop() ++ except RuntimeError: ++ return self ++ ++ if isinstance(loop, AsyncIOLoopWithTwisted): + return self.asFuture(asyncio.get_event_loop()) + return self + + +From fc77a04195c11d7f6044961b3947bdd5d7056d28 Mon Sep 17 00:00:00 2001 +From: Povilas Kanapickas +Date: Wed, 13 Dec 2023 18:13:55 +0200 +Subject: [PATCH 2/5] master: Bump maximum allowed Twisted version to 23.10.0 + +--- + master/setup.py | 2 +- + newsfragments/allow-twisted-dep-23-10.bugfix | 1 + + requirements-ci.txt | 2 +- + requirements-ciworker.txt | 2 +- + 4 files changed, 4 insertions(+), 3 deletions(-) + create mode 100644 newsfragments/allow-twisted-dep-23-10.bugfix + +diff --git a/newsfragments/allow-twisted-dep-23-10.bugfix b/newsfragments/allow-twisted-dep-23-10.bugfix +new file mode 100644 +index 00000000000..383df957899 +--- /dev/null ++++ b/newsfragments/allow-twisted-dep-23-10.bugfix +@@ -0,0 +1 @@ ++Fix support for Twisted 23.10 +From 58a69d050f10e92ac0de22b50e3d3815f117491b Mon Sep 17 00:00:00 2001 +From: Povilas Kanapickas +Date: Wed, 13 Dec 2023 18:52:36 +0200 +Subject: [PATCH 4/5] www: Use notFound() on Twisted 22.10 and newer + +--- + master/buildbot/www/service.py | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/master/buildbot/www/service.py b/master/buildbot/www/service.py +index f07c95cd90f..402f5b46eae 100644 +--- a/master/buildbot/www/service.py ++++ b/master/buildbot/www/service.py +@@ -19,6 +19,7 @@ + from binascii import hexlify + + import jwt ++from packaging.version import parse as parse_version + + from twisted.application import strports + from twisted.cred.portal import IRealm +@@ -275,7 +276,13 @@ def refresh_base_plugin_name(self, new_config): + def configPlugins(self, root, new_config): + plugin_root = root + if self.base_plugin_name == 'base_react': +- plugin_root = resource.NoResource() ++ current_version = parse_version(twisted.__version__) ++ if current_version < parse_version("22.10.0"): ++ from twisted.web.resource import NoResource ++ plugin_root = NoResource() ++ else: ++ from twisted.web.pages import notFound ++ plugin_root = notFound() + root.putChild(b"plugins", plugin_root) + + known_plugins = set(new_config.www.get('plugins', {})) | set([self.base_plugin_name]) + +From 7df2c48c7f9f69c516bb26da7f45e9c007d8adfe Mon Sep 17 00:00:00 2001 +From: Povilas Kanapickas +Date: Wed, 13 Dec 2023 19:32:59 +0200 +Subject: [PATCH 5/5] test: Fix deprecation warning coming from autobahn + +--- + master/buildbot/test/__init__.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/master/buildbot/test/__init__.py b/master/buildbot/test/__init__.py +index 5e89e85eb4a..af487313b8d 100644 +--- a/master/buildbot/test/__init__.py ++++ b/master/buildbot/test/__init__.py +@@ -135,3 +135,7 @@ + # boto3 shows this warning when on old Python + warnings.filterwarnings('ignore', ".*Boto3 will no longer support Python .*", + category=Warning) ++ ++# autobahn is not updated for Twisted 22.04 and newer ++warnings.filterwarnings("ignore", "twisted.web.resource.NoResource was deprecated in", ++ category=DeprecationWarning) diff --git a/buildbot.spec b/buildbot.spec index b29cc4f..110860e 100644 --- a/buildbot.spec +++ b/buildbot.spec @@ -20,8 +20,8 @@ %endif Name: buildbot -Version: 3.9.2 -Release: 3%{?dist} +Version: 3.10.0 +Release: 1%{?dist} Summary: Build/test automation system License: GPL-2.0-only @@ -40,7 +40,10 @@ Source8: %{pypi_source buildbot-pkg} # Service template units for buildbot instances Source10: buildbot-master@.service Source11: buildbot-worker@.service -Patch: twisted-pin.patch +Patch0: twisted-pin.patch +Patch1: undo-importlib.patch +Patch2: 7268.patch +Patch3: 7026.patch BuildArch: noarch @@ -332,7 +335,10 @@ Summary: Buildbot documentation %prep %setup -q -b0 -b1 -b2 -b3 -b4 -b5 -b6 -b7 -b8 -%patch -P 0 -p1 -b .twisted +%patch -P 0 -p0 -b .twisted +%patch -P 1 -p0 -b .importlib +%patch -P 2 -p2 -b .7268 +%patch -P 3 -p2 -b .7026 cd .. @@ -410,6 +416,9 @@ trial buildbot.test %endif %changelog +* Tue Dec 05 2023 Gwyn Ciesla - 3.10.0-1 +- 3.10.0 + * Thu Sep 28 2023 Gwyn Ciesla - 3.9.2-3 - Upgrade master databases and restart masters and workers on upgrade. diff --git a/sources b/sources index 4463523..4177eb3 100644 --- a/sources +++ b/sources @@ -1,9 +1,9 @@ -SHA512 (buildbot-3.9.2.tar.gz) = 268a9c6ac62ef137b6c23ef10245f960001f36babba6b0266541d9e158a05b468bfb1621d27ff9cd1350f136d5899cd778cfeafd2cfed3285886739f156a0dc9 -SHA512 (buildbot-badges-3.9.2.tar.gz) = c5a2ab99eb75c9de2880e4438ced32e5e8fc61c82e3fa491ba85b71c97989bc746d97d931f5b5789a9d2d3af170958bc03fa6201b00abde11e1c1664c2b35d37 -SHA512 (buildbot-console-view-3.9.2.tar.gz) = 212bbf50280f7deb177bf755b1789175eff2e90324e55aa55fd8bef5183bae2732b746089011d437f29ea724f164ad284e048d8d662af0bbd877bcc781febbe9 -SHA512 (buildbot-grid-view-3.9.2.tar.gz) = 74ddaa2889caf56b1409f9e37677e68dcb7f002e2e073369c0a6fd694378b10225026e4d05b3123721cdf174afe3f420cffbad38b097c7d804853921aaecc367 -SHA512 (buildbot-pkg-3.9.2.tar.gz) = 655cbb67ca4c010c78b784ea8d9ac6885baa17283ab89eccc6d3220f6c9f24099df0c65435dd03f5ac829719a521a5576d0964df94adec7a0c4cdb5b30722704 -SHA512 (buildbot-waterfall-view-3.9.2.tar.gz) = c5bbbeeb58909f8411f908d37151646a1719a8dfaefa4fd27fff3bb1729de3cb43c30b8f55392ee5e6a7a6248ee3eb47def6cbc45549cdff6fd2b41fdc0da005 -SHA512 (buildbot-worker-3.9.2.tar.gz) = ebcca76fa21316cffcaf5dd0fe4b7fa21b6103e1a60ec04c6011c29ad9ecb02f4e3f1b9897d8f48f33b5b5ee8938c04932e90b28f8492e4429ac39ceb444e009 -SHA512 (buildbot-wsgi-dashboards-3.9.2.tar.gz) = a4c3313fe8386bd848f5328ca8c5d8daa9938fb4ef35da52a2939ed9bff201d50940df78d440d6280891a011d47777585ee90c6415e1918665d7dcce6d570fe2 -SHA512 (buildbot-www-3.9.2.tar.gz) = 1fd9ab412db1623fb732462e3bb92e39d39de1b982b994415118afb06c6848d60522dc157ddf73b8966566cf7c8eba3b471e621fe21dfc9eee33c0c5ff3757fd +SHA512 (buildbot-3.10.0.tar.gz) = d798b48a02e18e3e3b6c8696c60f4ef35934e3f6d82f0222c98f5630ef98e20f08292c41e326af87a20c7f8338bd3b6bc4331b5784808c23b07422df6488b067 +SHA512 (buildbot-badges-3.10.0.tar.gz) = 8c3d7b9db686a455f80bdeb1ef57955b5cea289e92cb01e3387f62cd6cb76e4de8996a7691b72526e0ab8655236c561f390659fea2f830f0136adcdb4b8c1b5f +SHA512 (buildbot-console-view-3.10.0.tar.gz) = c570a6d9b609c3005f6abd05b3e31c4a05d0ae2351fa5e0b5d3882749a8ce1d6d1f8fdca3c6300d7a7c680e157a5fef42837939e7829d0afba327d5898ee6239 +SHA512 (buildbot-grid-view-3.10.0.tar.gz) = e883f072ead39043c67ff13de199779c24fb2522d6b889365e1fe0a57067440e95677c759e633516e10428b1ed818cdef8332723831fe1d3f3121688e941b417 +SHA512 (buildbot-pkg-3.10.0.tar.gz) = c028943c11e28b8cf08ebb9cddcfbfe5137a1ffd248f020df1b0adb4333b4d87d43a9bd946d8f0bdfc2c728de24ad75d1fa00246f6092738622fe976836e3ed3 +SHA512 (buildbot-waterfall-view-3.10.0.tar.gz) = 8d87d03af19c9821ea39426e39cd4b4572dd09290fe07ec6a2f5fb2d238254e25deeec7f87f865c0ba7a16e5039ba87224866dc360f156be64715ddb5778041a +SHA512 (buildbot-worker-3.10.0.tar.gz) = 39676857aaeb1b8ef41d599fcadd8530184841e2e4689e74638661c58aa1bad1cef00f61901b6997e33c4263386e53806bcdbbe3e98b1560c2f1c64e068ede4e +SHA512 (buildbot-wsgi-dashboards-3.10.0.tar.gz) = 62eb5c5c8c74591241ed10fe7523fb13c61e495b0a372b3dcfec25ed39fbe5c050f6c3b11126c8f78cbbf77fb6935475594ea5874011c329d024d4bb9f1839a3 +SHA512 (buildbot-www-3.10.0.tar.gz) = f1416eb17cde3627f0daa5a541b04c3688ed7f9d17a609e0fad4e1fdd43d3ab189fcbf2b77781ad9647f24e2778a985786402d427e4b4a4c70e44af31f573a84 diff --git a/twisted-pin.patch b/twisted-pin.patch index dec0b11..4d9ec98 100644 --- a/twisted-pin.patch +++ b/twisted-pin.patch @@ -1,8 +1,8 @@ ---- buildbot-3.9.2/setup.py~ 2023-09-02 15:48:25.167284000 -0500 -+++ buildbot-3.9.2/setup.py 2023-09-08 16:37:00.350198843 -0500 -@@ -488,7 +488,7 @@ - if parse_version(pip_dist.version) < parse_version('1.4'): - raise RuntimeError(VERSION_MSG) +--- setup.py~ 2023-12-04 19:56:01.312614000 -0600 ++++ setup.py 2023-12-05 11:14:06.316927591 -0600 +@@ -467,7 +467,7 @@ + if not py_38: + raise RuntimeError("Buildbot master requires at least Python-3.8") -twisted_ver = ">= 18.7.0, <=22.10.0" +twisted_ver = ">= 18.7.0" diff --git a/undo-importlib.patch b/undo-importlib.patch new file mode 100644 index 0000000..8203a26 --- /dev/null +++ b/undo-importlib.patch @@ -0,0 +1,33 @@ +--- buildbot/www/plugin.py~ 2023-12-04 19:56:01.256614200 -0600 ++++ buildbot/www/plugin.py 2023-12-05 11:32:56.652503945 -0600 +@@ -14,7 +14,7 @@ + # Copyright Buildbot Team Members + + +-import importlib_resources ++import importlib.resources + + from twisted.web import static + +@@ -25,9 +25,9 @@ + + def __init__(self, modulename, description, ui=True): + self.description = description +- self.version = importlib_resources.files(modulename).joinpath("VERSION") ++ self.version = importlib.resources.files(modulename).joinpath("VERSION") + self.version = bytes2unicode(self.version.read_bytes()) +- self.static_dir = importlib_resources.files(modulename) / "static" ++ self.static_dir = importlib.resources.files(modulename) / "static" + self.resource = static.File(self.static_dir) + self.ui = ui + +--- setup.py~ 2023-12-05 11:24:57.136686896 -0600 ++++ setup.py 2023-12-05 11:33:27.901491993 -0600 +@@ -478,7 +478,6 @@ + 'Jinja2 >= 2.1', + 'msgpack >= 0.6.0', + "croniter >= 1.3.0", +- 'importlib-resources >= 5', + # required for tests, but Twisted requires this anyway + 'zope.interface >= 4.1.1', + 'sqlalchemy >= 1.3.0, < 1.5',