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

Reply via email to