Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package opi for openSUSE:Factory checked in at 2026-09-09 16:22:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/opi (Old) and /work/SRC/openSUSE:Factory/.opi.new.1265 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "opi" Wed Sep 9 16:22:04 2026 rev:82 rq:1376570 version:5.16.0 Changes: -------- --- /work/SRC/openSUSE:Factory/opi/opi.changes 2026-07-21 23:12:32.778699871 +0200 +++ /work/SRC/openSUSE:Factory/.opi.new.1265/opi.changes 2026-09-09 16:23:47.001616790 +0200 @@ -1,0 +2,10 @@ +Wed Sep 9 09:20:16 UTC 2026 - Dominik Heidler <[email protected]> + +- Version 5.16.0 + * Fix 10_chatgpt_plugin.py + * Add ChatGPT desktop app plugin (#223) + * Allow repos with local gpgkey + * refactor: use python built-in for os-release (#224) + * Fix testsuite for Leap 16.0 + +------------------------------------------------------------------- Old: ---- opi-5.15.0.tar.gz New: ---- opi-5.16.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ opi.spec ++++++ --- /var/tmp/diff_new_pack.0EXXnP/_old 2026-09-09 16:23:47.874653277 +0200 +++ /var/tmp/diff_new_pack.0EXXnP/_new 2026-09-09 16:23:47.876653361 +0200 @@ -20,7 +20,7 @@ %define pythons %{use_python} Name: opi -Version: 5.15.0 +Version: 5.16.0 Release: 0 Summary: OBS Package Installer (CLI) License: GPL-3.0-only ++++++ opi-5.15.0.tar.gz -> opi-5.16.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/opi/__init__.py new/opi-5.16.0/opi/__init__.py --- old/opi-5.15.0/opi/__init__.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/opi/__init__.py 2026-09-09 11:20:06.000000000 +0200 @@ -1,4 +1,5 @@ import os +import platform import sys import subprocess import re @@ -51,25 +52,8 @@ cpu_arch = 'i586' return cpu_arch -os_release = {} -def get_os_release(): - global os_release - if not os_release: - with open('/etc/os-release') as f: - for line in f.readlines(): - line = line.strip() - if line.startswith('#') or '=' not in line: - continue - key, value = line.split('=', 1) - key = key.strip() - value = value.strip() - if '"' in value: - value = value.split('"', 1)[1].split('"', 1)[0] - os_release[key] = value - return os_release - def get_distribution(prefix=False, use_releasever_variable=False): - os_release = get_os_release() + os_release = platform.freedesktop_os_release() name = os_release['NAME'] version = os_release.get('VERSION') # VERSION is not set for TW if version: @@ -97,7 +81,7 @@ return project def get_version() -> str: - os_release = get_os_release() + os_release = platform.freedesktop_os_release() version = os_release.get('VERSION') # VERSION is not set for TW return version @@ -145,7 +129,7 @@ dist_upgrade(from_repo='packman', allow_downgrade=True, allow_vendor_change=True) def add_openh264_repo(dup=False): - project = get_os_release()['NAME'] + project = platform.freedesktop_os_release()['NAME'] project = project.replace('-Slowroll', '') project = project.replace('openSUSE MicroOS', 'openSUSE Tumbleweed') project = project.replace('openSUSE Leap Micro', 'openSUSE Leap') @@ -681,7 +665,10 @@ return options[num - 1] def ask_import_key(keyurl): - keys = requests.get(expand_vars(keyurl)).text + if keyurl.startswith('file://'): + keys = open(expand_vars(keyurl[7:])).read() + else: + keys = requests.get(expand_vars(keyurl)).text db_keys = get_keys_from_rpmdb() for key in split_keys(keys): for line in subprocess.check_output(['gpg', '--quiet', '--show-keys', '--with-colons', '-'], input=key.encode()).decode().strip().split('\n'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/opi/plugins/chatgpt.py new/opi-5.16.0/opi/plugins/chatgpt.py --- old/opi-5.15.0/opi/plugins/chatgpt.py 1970-01-01 01:00:00.000000000 +0100 +++ new/opi-5.16.0/opi/plugins/chatgpt.py 2026-09-09 11:20:06.000000000 +0200 @@ -0,0 +1,94 @@ +import subprocess +import tempfile + +from termcolor import cprint + +import opi +from opi.rpmbuild import RPMBuild +from opi.plugins import BasePlugin + + +SUPPORTED_ARCHITECTURES = {'x86_64', 'aarch64'} +COMPAT_PACKAGE = 'chatgpt-opensuse-compat' +REPO_ALIAS = 'openai-chatgpt' +REPO_URL = 'https://persistent.oaistatic.com/codex-app-prod/linux/rpm/$basearch' +REPO_KEY_PATH = '/etc/pki/rpm-gpg/RPM-GPG-KEY-chatgpt-3BFA0E4AE8B8CC16A2D9BA684A3B4A566C4660E4.asc' +DEFAULTS_PATH = '/etc/default/chatgpt' +# Extracted from the official ChatGPT RPM. Fingerprint: +# 3BFA 0E4A E8B8 CC16 A2D9 BA68 4A3B 4A56 6C46 60E4 +REPO_KEY = '''-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGpypFUBEACi1Vvzq9pIpA6lj7chbqELuxJtVuzUzxrasa6ZU0yF4yhq7jf8 +3YkJRHwbezBKeQyzJ5lkX0EhXS8aXxUhMAm3PFpAlwcInfKzmV7atJwvaxIw6Rmd +GYe9fBWKjTN/SmPIjtyxrTznZY97+TfD1AeGZpLaJ8fsnhrC+HkiN2TACiTocgpe +hFiP0OWK7mWZeTWnY2scpIYXP1Ro7nQv4KacmY4JacTQ7m/HM0Qej/3olhuEv2Cw +lMVWw57/oHhmTllfLDQOogFQyIVqaaR98y/Eu6cAabSfcsqAAZ2A8vfHYD27z28J +vLO2PZEJd5ThlnX4Zqv0eIpZdBj//8Sl/MSqTshFZ1NDsRoqwdqw284X5MpnOJ4k +4Sc2Se8tJxt/nCeibH3dJ504Fb1X/mnOqhCAQ6pVJz4RB5HRlFPSkxVPyag1v1m/ +7T4vie+OR4eqFQNz6mudrOoMmeVIfyL5fbe4cOr4fk/FyvEE2xMgkFatPqXn7vM9 +og+zremPCfwRAFpBPyX74VowFY7llcdaj/w8K5T8PzM14Hb3E4ZKizMluKmTvTq9 +WE1/eSQJLLQqXD5VmtmdUaC/VyE/1ZlIxcA1LWqvEQ327UXREvX/nHsrkKrl956W +jzkiHFUTsD1NJ0dMfs+csOt8Furb5jZj+HsMmCm9jLdfz5b/4WKLPbvxIwARAQAB +tBZDb2RleCBMaW51eCBSZXBvc2l0b3J5iQJRBBMBCgA7FiEEO/oOSui4zBai2bpo +SjtKVmxGYOQFAmpypFUCGwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQ +SjtKVmxGYORlCQ/9FyikZo8HQcJBP9E/oXVPds/fQnIFB2qJR2z3DrfYEonNt/ev +SAySkPPq4/mEOjaI0pFlDDGSaps+FTcJFgoVRTasBIF7JJivvjW9ap8iWEbhhVLe +IrFLbMLpUcTRntUx7R4fVMJ/1/cGn+NWZmNwS9ORorzSyCH0IAgCw1Xc3ZrjuMbF +VjdToMC1TiXXCEmlYpQakmQ3Ay1cH0FHC2BBNn1MNVkJdPhpZIZCdhaMPHfYFpyo +pg8wFvZ5iIcvlbMgyuy8CPJVRWUcYy2dOhEOGnYJnXRPkE3E1hf8YOHNzRlduH89 +6lT9qcEK2+fpLfrVGoc4zscLZ+Ey+Ko6iQRdVE1j67+wNR3hX8ukue574v1N/xxu +i575jumSE19lEj1sH4+P4gFHOtTbF0JhKKzLctbga0IAwTPKhnt3qzj1U5Yj/MZS +uEVjrLhdRauOuFBXUclgyVf2w/lE85UUOdlcollsYA6Huq7xDamqf8SslZQGre3E +I+lhpqJR1cOwDMUzzcl40uTyhrxXXd/bk4QSlhZbwHR25Pnt+ZMtWavlQWS0eDEV +8djuXAURCmx5WOqAFB/TJe1mn5EvyWg4VFzrY/NVNOpzgY5+Xp7J28z7f637r712 +Eu9j4imVcdPigwS+jf/0f81i2o9b82Y26TN8+EtDLCY841MJ1lrjDrX/dno= +=Y+3h +-----END PGP PUBLIC KEY BLOCK----- +''' + + +def install_file(contents, destination): + with tempfile.NamedTemporaryFile('w') as source: + source.write(contents) + source.flush() + subprocess.check_call([ + 'sudo', 'install', '-D', '-m', '0644', source.name, destination, + ]) + + +class ChatGPT(BasePlugin): + main_query = 'chatgpt' + description = 'Official ChatGPT desktop app' + queries = ['chatgpt'] + + @classmethod + def run(cls, query): + arch = opi.get_cpu_arch() + if arch not in SUPPORTED_ARCHITECTURES: + cprint(f'The ChatGPT OPI plugin does not support architecture {arch}.', 'red') + return + if not opi.ask_yes_or_no('Do you want to install ChatGPT from the official OpenAI repository?'): + return + + compat = RPMBuild( + COMPAT_PACKAGE, + '1', + 'openSUSE compatibility dependencies for ChatGPT', + requires=['libvulkan_lvp'], + provides=['mesa-vulkan-drivers'], + autoreq=False, + ) + compat.build() + opi.install_packages([compat.rpmfile_path], allow_unsigned=True) + + install_file(REPO_KEY, REPO_KEY_PATH) + install_file('repo_add_once="false"\n', DEFAULTS_PATH) + + opi.add_repo( + filename=REPO_ALIAS, + name='ChatGPT', + url=REPO_URL, + gpgkey=f"file://{REPO_KEY_PATH}", + ) + opi.install_packages(['chatgpt']) + opi.ask_keep_repo(REPO_ALIAS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/opi/version.py new/opi-5.16.0/opi/version.py --- old/opi-5.15.0/opi/version.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/opi/version.py 2026-09-09 11:20:06.000000000 +0200 @@ -1 +1 @@ -__version__ = '5.15.0' +__version__ = '5.16.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/opi.changes new/opi-5.16.0/opi.changes --- old/opi-5.15.0/opi.changes 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/opi.changes 2026-09-09 11:20:06.000000000 +0200 @@ -1,4 +1,14 @@ ------------------------------------------------------------------- +Wed Sep 9 09:19:44 UTC 2026 - Dominik Heidler <[email protected]> + +- Version 5.16.0 + * Fix 10_chatgpt_plugin.py + * Add ChatGPT desktop app plugin (#223) + * Allow repos with local gpgkey + * refactor: use python built-in for os-release (#224) + * Fix testsuite for Leap 16.0 + +------------------------------------------------------------------- Tue Jul 21 12:18:33 UTC 2026 - Dominik Heidler <[email protected]> - Version 5.15.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/05_install_from_local_repo.py new/opi-5.16.0/test/05_install_from_local_repo.py --- old/opi-5.15.0/test/05_install_from_local_repo.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/test/05_install_from_local_repo.py 2026-09-09 11:20:06.000000000 +0200 @@ -11,7 +11,7 @@ c.expect('Pick a number') c.sendline(entry_id) -c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository)', timeout=10) +c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository|repo-oss)', timeout=10) entry_id = c.match.groups()[0] print(f'PEXPECT: Found entry id {entry_id!r}') c.sendline(entry_id) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/06_install_non_interactive.py new/opi-5.16.0/test/06_install_non_interactive.py --- old/opi-5.15.0/test/06_install_non_interactive.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/test/06_install_non_interactive.py 2026-09-09 11:20:06.000000000 +0200 @@ -8,7 +8,7 @@ c.expect(r'([0-9]+)\. bottom', timeout=20) c.expect('Pick a number') -c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository)', timeout=20) +c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository|repo-oss)', timeout=20) c.expect('Installing from existing repo', timeout=20) c.expect('Continue?', timeout=60) c.interact() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/07_install_multiple.py new/opi-5.16.0/test/07_install_multiple.py --- old/opi-5.15.0/test/07_install_multiple.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/test/07_install_multiple.py 2026-09-09 11:20:06.000000000 +0200 @@ -21,7 +21,7 @@ c.expect(r'([0-9]+)\. tmux', timeout=60) c.expect('Pick a number') -c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository)', timeout=10) +c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository|repo-oss)', timeout=10) c.expect('Installing from existing repo', timeout=10) c.expect('Continue?', timeout=60) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/09_install_with_multi_repos_in_single_file_non_interactive.py new/opi-5.16.0/test/09_install_with_multi_repos_in_single_file_non_interactive.py --- old/opi-5.15.0/test/09_install_with_multi_repos_in_single_file_non_interactive.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/test/09_install_with_multi_repos_in_single_file_non_interactive.py 2026-09-09 11:20:06.000000000 +0200 @@ -12,7 +12,7 @@ c.expect(r'([0-9]+)\. tmux', timeout=10) c.expect('Pick a number') -c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository)', timeout=10) +c.expect(r'([0-9]+)\. [^ ]*(openSUSE-Tumbleweed-Oss|Main Repository|repo-oss)', timeout=10) c.expect('Installing from existing repo', timeout=10) c.expect('Continue?', timeout=60) c.interact() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/10_chatgpt_plugin.py new/opi-5.16.0/test/10_chatgpt_plugin.py --- old/opi-5.15.0/test/10_chatgpt_plugin.py 1970-01-01 01:00:00.000000000 +0100 +++ new/opi-5.16.0/test/10_chatgpt_plugin.py 2026-09-09 11:20:06.000000000 +0200 @@ -0,0 +1,54 @@ +#!/usr/bin/python3 + +import os +import sys +from unittest.mock import MagicMock, patch + +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/..')) + +import opi.plugins.chatgpt as chatgpt + + +assert chatgpt.SUPPORTED_ARCHITECTURES == {'x86_64', 'aarch64'} + + +with patch.object(chatgpt.opi, 'get_cpu_arch', return_value='x86_64'), \ + patch.object(chatgpt.opi, 'ask_yes_or_no', return_value=False) as ask: + chatgpt.ChatGPT.run('chatgpt') + ask.assert_called_once() + +with patch.object(chatgpt.opi, 'get_cpu_arch', return_value='ppc64le'), \ + patch.object(chatgpt.opi, 'ask_yes_or_no') as ask: + chatgpt.ChatGPT.run('chatgpt') + ask.assert_not_called() + +builder = MagicMock() +with patch.object(chatgpt, 'RPMBuild', return_value=builder) as rpm_build, \ + patch.object(chatgpt.opi, 'get_cpu_arch', return_value='aarch64'), \ + patch.object(chatgpt.opi, 'ask_yes_or_no', return_value=True), \ + patch.object(chatgpt.opi, 'install_packages') as install_packages, \ + patch.object(chatgpt.opi, 'add_repo') as add_repo, \ + patch.object(chatgpt.opi, 'ask_keep_repo') as ask_keep_repo, \ + patch.object(chatgpt, 'install_file') as install_file, \ + patch.object(chatgpt.subprocess, 'check_call') as check_call: + chatgpt.ChatGPT.run('chatgpt') + kwargs = rpm_build.call_args.kwargs + assert kwargs['requires'] == ['libvulkan_lvp'] + assert kwargs['provides'] == ['mesa-vulkan-drivers'] + assert kwargs['autoreq'] is False + builder.build.assert_called_once_with() + assert install_packages.call_args_list[0].args == ([builder.rpmfile_path],) + assert install_packages.call_args_list[0].kwargs == {'allow_unsigned': True} + install_file.assert_any_call(chatgpt.REPO_KEY, chatgpt.REPO_KEY_PATH) + install_file.assert_any_call('repo_add_once="false"\n', chatgpt.DEFAULTS_PATH) + add_repo.assert_called_once_with( + filename=chatgpt.REPO_ALIAS, + name='ChatGPT', + url=chatgpt.REPO_URL, + gpgkey=f"file://{chatgpt.REPO_KEY_PATH}", + ) + assert install_packages.call_args_list[1].args == (['chatgpt'],) + assert install_packages.call_args_list[1].kwargs == {} + ask_keep_repo.assert_called_once_with(chatgpt.REPO_ALIAS) + +print('ChatGPT plugin tests passed') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/99_install_opi.py new/opi-5.16.0/test/99_install_opi.py --- old/opi-5.15.0/test/99_install_opi.py 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/test/99_install_opi.py 2026-09-09 11:20:06.000000000 +0200 @@ -1,14 +1,17 @@ #!/usr/bin/python3 import subprocess +import tempfile + +build_dir = tempfile.TemporaryDirectory() def run(cmd, **kwargs): print('% ' + (' '.join(cmd) if isinstance(cmd, list) else cmd)) subprocess.check_call(cmd, **kwargs) version = subprocess.check_output(['python3', 'setup.py', '--version']).decode().strip() -run(['python3', '-mpip', 'wheel', '--verbose', '--progress-bar', 'off', '--disable-pip-version-check', '--use-pep517', '--no-build-isolation', '--no-deps', '--wheel-dir', './build', '.']) -cmd = ['python3', '-mpip', 'install', '--root-user-action=ignore', '--break-system-packages', '--verbose', '--progress-bar', 'off', '--disable-pip-version-check', '--no-compile', '--ignore-installed', '--no-deps', '--no-index', '--find-links', './build', f"opi=={version}"] +run(['python3', '-mpip', 'wheel', '--verbose', '--progress-bar', 'off', '--disable-pip-version-check', '--use-pep517', '--no-build-isolation', '--no-deps', '--wheel-dir', build_dir.name, '.']) +cmd = ['python3', '-mpip', 'install', '--root-user-action=ignore', '--break-system-packages', '--verbose', '--progress-bar', 'off', '--disable-pip-version-check', '--no-compile', '--ignore-installed', '--no-deps', '--no-index', '--find-links', build_dir.name, f"opi=={version}"] if subprocess.run('grep "openSUSE Leap" /etc/os-release', shell=True).returncode == 0: cmd.remove('--root-user-action=ignore') cmd.remove('--break-system-packages') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/opi-5.15.0/test/run_all.sh new/opi-5.16.0/test/run_all.sh --- old/opi-5.15.0/test/run_all.sh 2026-07-21 14:18:36.000000000 +0200 +++ new/opi-5.16.0/test/run_all.sh 2026-09-09 11:20:06.000000000 +0200 @@ -9,7 +9,7 @@ for t in *.py ; do let total_tests++ - if ! sudo ./run_container_test.sh "$t" "$1" ; then + if ! ./run_container_test.sh "$t" "$1" ; then let failed_tests++ fi done
