Skip to content

build(images): install pluggable authentication modules for Cyrus SASL on Ubuntu to provide auth mechanisms required for tests#2296

Merged
empiredan merged 1 commit intomasterfrom
build-env-ubuntu-sasl2-modules
Sep 19, 2025
Merged

build(images): install pluggable authentication modules for Cyrus SASL on Ubuntu to provide auth mechanisms required for tests#2296
empiredan merged 1 commit intomasterfrom
build-env-ubuntu-sasl2-modules

Conversation

@empiredan
Copy link
Copy Markdown
Contributor

@empiredan empiredan commented Sep 16, 2025

#2292

To support tests that connect to ZooKeeper via SASL, auth modules should be
introduced. Otherwise, those tests would fail due to missing necessary mechanisms.

…L on Ubuntu to provide auth mechanisms required for tests
@empiredan
Copy link
Copy Markdown
Contributor Author

Failure example for the SASL tests due to missing related auth mechanisms is as follows (from #2293):

[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from ZookeeperSASLAuthTest/ZookeeperSessionTest/0, where TypeParam = dsn::dist::ZookeeperSessionSASLAuthTest
[ RUN      ] ZookeeperSASLAuthTest/ZookeeperSessionTest/0.OperateNode
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1250: Client environment:zookeeper.version=zookeeper C client 3.9.4
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1254: Client environment:host.name=a7254a4ba88c
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1261: Client environment:os.name=Linux
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1262: Client environment:os.arch=6.11.0-1018-azure
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1263: Client environment:os.version=#18~24.04.1-Ubuntu SMP Sat Jun 28 04:46:03 UTC 2025
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1271: Client environment:user.name=(null)
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1279: Client environment:user.home=/root
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@log_env@1291: Client environment:user.dir=/__w/incubator-pegasus/incubator-pegasus/build/latest/bin/zookeeper_sasl_auth_test
2025-09-15 12:15:36,421:246(0x149baefcb640):ZOO_INFO@zookeeper_init_internal@1335: Initiating client connection, host=localhost:22181 sessionTimeout=30000 watcher=0x5625a3e26460 sessionId=0 sessionPasswd=<null> context=0x5625cab1a000 flags=0
2025-09-15 12:15:36,422:246(0x149bade14640):ZOO_INFO@check_events@2988: initiated connection to server 127.0.0.1:22181
2025-09-15 12:15:36,432:246(0x149bade14640):ZOO_ERROR@zoo_sasl_client_start@284: Starting SASL negotiation: no mechanism available SASL(-4): no mechanism available: No worthy mechs found
2025-09-15 12:15:36,432:246(0x149bade14640):ZOO_ERROR@_zsasl_fail@148: SASL authentication failed. rc=-1
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1250: Client environment:zookeeper.version=zookeeper C client 3.9.4
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1254: Client environment:host.name=a7254a4ba88c
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1261: Client environment:os.name=Linux
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1262: Client environment:os.arch=6.11.0-1018-azure
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1263: Client environment:os.version=#18~24.04.1-Ubuntu SMP Sat Jun 28 04:46:03 UTC 2025
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1271: Client environment:user.name=(null)
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1279: Client environment:user.home=/root
[==========] Running 1 test from 1 test suite.
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@log_env@1291: Client environment:user.dir=/__w/incubator-pegasus/incubator-pegasus/build/latest/bin/zookeeper_sasl_auth_test
2025-09-15 12:15:37,421:246(0x149bb2feb640):ZOO_INFO@zookeeper_init_internal@1335: Initiating client connection, host=localhost:22181 sessionTimeout=30000 watcher=0x5625a3e26460 sessionId=0 sessionPasswd=<null> context=0x5625cab1a120 flags=0
2025-09-15 12:15:37,421:246(0x149bada12640):ZOO_INFO@check_events@2988: initiated connection to server 127.0.0.1:22181
[----------] Global test environment set-up.
[----------] 1 test from ZookeeperSASLAuthTest/ZookeeperSessionTest/0, where TypeParam = dsn::dist::ZookeeperSessionSASLAuthTest
[ RUN      ] ZookeeperSASLAuthTest/ZookeeperSessionTest/0.OperateNode
2025-09-15 12:15:37,424:246(0x149bada12640):ZOO_ERROR@zoo_sasl_client_start@284: Starting SASL negotiation: no mechanism available SASL(-4): no mechanism available: No worthy mechs found
2025-09-15 12:15:37,424:246(0x149bada12640):ZOO_ERROR@_zsasl_fail@148: SASL authentication failed. rc=-1
/__w/incubator-pegasus/incubator-pegasus/src/zookeeper/test/zookeeper_session_test_base.cpp:50: Failure
Expected equality of these values:
  ZOO_CONNECTED_STATE
    Which is: 3
  _zoo_state
    Which is: 2

[  FAILED  ] ZookeeperSASLAuthTest/ZookeeperSessionTest/0.OperateNode, where TypeParam = dsn::dist::ZookeeperSessionSASLAuthTest (30001 ms)
[----------] 1 test from ZookeeperSASLAuthTest/ZookeeperSessionTest/0 (30001 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (30001 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] ZookeeperSASLAuthTest/ZookeeperSessionTest/0.OperateNode, where TypeParam = dsn::dist::ZookeeperSessionSASLAuthTest

 1 FAILED TEST
dsn exit with code 1
run zookeeper_sasl_auth_test failed
---- ls ----
total 2768
-rw-r--r-- 2 root root   12597 Sep 15 11:41 Makefile
-rw-r--r-- 2 root root    1653 Sep 15 11:41 cmake_install.cmake
-rw-r--r-- 2 root root    2523 Sep 15 11:38 config-test.ini
drwxr-xr-x 5 root root    4096 Sep 15 12:15 data
-rwxr-xr-x 2 root root    1462 Sep 15 11:38 run.sh
-rw-r--r-- 2 root root      17 Sep 15 11:38 sasl_auth.password
-rwxr-xr-x 2 root root 2793920 Sep 15 11:53 zookeeper_sasl_auth_test
---- tail -n 100 pegasus.log.* ----
I2025-09-15 12:15:36.414 (1757938536414064053 246) unknown.io-thrd.246: service_api_c.cpp:484:run(): process(246) start: 1757938536411, date: 2025-09-15 12:15:36.411
D2025-09-15 12:15:36.414 (1757938536414437280 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.414 (1757938536414449313 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.414 (1757938536414591739 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 0, fmt = 1 ...
D2025-09-15 12:15:36.414 (1757938536414643576 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.414 (1757938536414648525 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.414 (1757938536414785491 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 1, fmt = 1 ...
D2025-09-15 12:15:36.414 (1757938536414910605 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.414 (1757938536414917828 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.414 (1757938536414944909 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 0, fmt = 2 ...
D2025-09-15 12:15:36.414 (1757938536414989061 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.414 (1757938536414993119 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.415 (1757938536415117371 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 1, fmt = 2 ...
D2025-09-15 12:15:36.415 (1757938536415244739 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.415 (1757938536415251571 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.415 (1757938536415278372 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 0, fmt = 3 ...
D2025-09-15 12:15:36.415 (1757938536415337382 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.415 (1757938536415344916 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.415 (1757938536415470741 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 1, fmt = 3 ...
D2025-09-15 12:15:36.415 (1757938536415590565 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.415 (1757938536415597348 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.415 (1757938536415623666 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 0, fmt = 4 ...
D2025-09-15 12:15:36.415 (1757938536415666136 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.415 (1757938536415670033 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.415 (1757938536415824722 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [client] network client started at port 1, channel = 1, fmt = 4 ...
I2025-09-15 12:15:36.415 (1757938536415856251 246) unknown.io-thrd.246: rpc_engine.cpp:530:start(): === service_node=[client], primary_address=[a7254a4ba88c:1(172.18.0.2:1)] ===
W2025-09-15 12:15:36.415 (1757938536415920707 266) client.io-thrd.266: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.416 (1757938536416064698 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [client]: thread pool [THREAD_POOL_DEFAULT] started, pool_code = THREAD_POOL_DEFAULT, worker_count = 2, worker_share_core = true, partitioned = false, ...
W2025-09-15 12:15:36.416 (1757938536416169714 269) client.io-thrd.269: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.416 (1757938536416281022 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [client]: thread pool [THREAD_POOL_REPLICATION] started, pool_code = THREAD_POOL_REPLICATION, worker_count = 2, worker_share_core = true, partitioned = false, ...
W2025-09-15 12:15:36.416 (1757938536416413860 272) client.io-thrd.272: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.416 (1757938536416625615 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [client]: thread pool [THREAD_POOL_REPLICATION_LONG] started, pool_code = THREAD_POOL_REPLICATION_LONG, worker_count = 2, worker_share_core = true, partitioned = false, ...
W2025-09-15 12:15:36.416 (1757938536416697979 275) client.io-thrd.275: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.416 (1757938536416864430 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [client]: thread pool [THREAD_POOL_PLOG] started, pool_code = THREAD_POOL_PLOG, worker_count = 2, worker_share_core = true, partitioned = false, ...
I2025-09-15 12:15:36.416 (1757938536416872255 246) unknown.io-thrd.246: task_engine.cpp:266:start(): [client]: task engine started
D2025-09-15 12:15:36.417 (1757938536417111913 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.417 (1757938536417120729 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.417 (1757938536417151487 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 0, fmt = 1 ...
D2025-09-15 12:15:36.417 (1757938536417197232 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.417 (1757938536417201740 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.417 (1757938536417366077 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 1, fmt = 1 ...
D2025-09-15 12:15:36.417 (1757938536417520576 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.417 (1757938536417527859 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.417 (1757938536417556142 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 0, fmt = 2 ...
D2025-09-15 12:15:36.417 (1757938536417600295 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.417 (1757938536417609772 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.417 (1757938536417733163 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 1, fmt = 2 ...
D2025-09-15 12:15:36.417 (1757938536417852426 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.417 (1757938536417859169 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.417 (1757938536417885638 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 0, fmt = 3 ...
D2025-09-15 12:15:36.417 (1757938536417928648 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.417 (1757938536417932636 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.418 (1757938536418065444 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 1, fmt = 3 ...
D2025-09-15 12:15:36.418 (1757938536418183745 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.418 (1757938536418190617 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.418 (1757938536418216696 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 0, fmt = 4 ...
D2025-09-15 12:15:36.418 (1757938536418265688 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.418 (1757938536418270116 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
I2025-09-15 12:15:36.418 (1757938536418420136 246) unknown.io-thrd.246: rpc_engine.cpp:489:start(): [server] network client started at port 2, channel = 1, fmt = 4 ...
D2025-09-15 12:15:36.418 (1757938536418545801 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.418 (1757938536418553305 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
W2025-09-15 12:15:36.418 (1757938536418633134 246) unknown.io-thrd.246: rpc_engine.cpp:519:start(): [server] network server started at port 20101, channel = 0, ...
D2025-09-15 12:15:36.418 (1757938536418697675 246) unknown.io-thrd.246: rpc_address.cpp:181:ipv4_from_network_interface(): skip interface(lo), address(1.0.0.127)
I2025-09-15 12:15:36.418 (1757938536418703506 246) unknown.io-thrd.246: rpc_address.cpp:188:ipv4_from_network_interface(): get ip address from network interface(eth0), addr(172.18.0.2), input interface()
W2025-09-15 12:15:36.418 (1757938536418864066 246) unknown.io-thrd.246: rpc_engine.cpp:519:start(): [server] network server started at port 20101, channel = 1, ...
I2025-09-15 12:15:36.418 (1757938536418921713 246) unknown.io-thrd.246: rpc_engine.cpp:530:start(): === service_node=[server], primary_address=[a7254a4ba88c:20101(172.18.0.2:20101)] ===
W2025-09-15 12:15:36.419 (1757938536419019126 298) server.io-thrd.298: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.419 (1757938536419173594 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [server]: thread pool [THREAD_POOL_DEFAULT] started, pool_code = THREAD_POOL_DEFAULT, worker_count = 2, worker_share_core = true, partitioned = false, ...
W2025-09-15 12:15:36.419 (1757938536419245880 301) server.io-thrd.301: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.420 (1757938536420520835 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [server]: thread pool [THREAD_POOL_REPLICATION] started, pool_code = THREAD_POOL_REPLICATION, worker_count = 2, worker_share_core = true, partitioned = false, ...
W2025-09-15 12:15:36.420 (1757938536420586483 304) server.io-thrd.304: task_worker.cpp:147:set_priority(): You may need priviledge to set thread priority: errno = 1, msg = Operation not permitted
I2025-09-15 12:15:36.420 (1757938536420728981 246) unknown.io-thrd.246: task_engine.cpp:109:start(): [server]: thread pool [THREAD_POOL_PLOG] started, pool_code = THREAD_POOL_PLOG, worker_count = 2, worker_share_core = true, partitioned = false, ...
I2025-09-15 12:15:36.420 (1757938536420738428 246) unknown.io-thrd.246: task_engine.cpp:266:start(): [server]: task engine started
Error: Process completed with exit code 1.

@empiredan empiredan marked this pull request as ready for review September 16, 2025 09:57
@acelyc111 acelyc111 requested a review from Copilot September 19, 2025 06:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds the libsasl2-modules package to Ubuntu Docker build environments to enable SASL authentication mechanisms required for ZooKeeper connectivity tests.

  • Installs pluggable authentication modules for Cyrus SASL across all Ubuntu versions
  • Ensures test compatibility with SASL-enabled ZooKeeper connections
  • Maintains consistency across Ubuntu 18.04, 20.04, and 22.04 build environments

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
docker/pegasus-build-env/ubuntu1804/Dockerfile Adds libsasl2-modules package to Ubuntu 18.04 build environment
docker/pegasus-build-env/ubuntu2004/Dockerfile Adds libsasl2-modules package to Ubuntu 20.04 build environment
docker/pegasus-build-env/ubuntu2204/Dockerfile Adds libsasl2-modules package to Ubuntu 22.04 build environment

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@empiredan empiredan merged commit b89ef3e into master Sep 19, 2025
29 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants