From e354b0e03445b97e26905f9c207230f2a3ce705c Mon Sep 17 00:00:00 2001 From: Ludovic <54670129+lbr38@users.noreply.github.com> Date: Thu, 10 Sep 2026 08:39:04 +0200 Subject: [PATCH] 3.17.2 --- .github/scripts/run-tests.sh | 30 ++++++++- .github/workflows/build-and-test-deb.yml | 15 +++-- .github/workflows/build-and-test-rpm.yml | 41 ++++++++++-- .../install-and-test-on-almalinux10.yml | 2 +- .../install-and-test-on-almalinux9.yml | 2 +- .../workflows/install-and-test-on-centos8.yml | 2 +- .../install-and-test-on-debian11.yml | 2 +- .../install-and-test-on-debian12.yml | 2 +- .../install-and-test-on-debian13.yml | 2 +- .../install-and-test-on-fedora40.yml | 5 +- .../install-and-test-on-fedora41.yml | 5 +- .../install-and-test-on-fedora42.yml | 38 +++++++++++ .../install-and-test-on-fedora43.yml | 38 +++++++++++ .../install-and-test-on-fedora44.yml | 38 +++++++++++ .../install-and-test-on-rockylinux9.yml | 2 +- .../install-and-test-on-ubuntu-2204.yml | 2 +- .../install-and-test-on-ubuntu-2404.yml | 2 +- .../install-and-test-on-ubuntu-2604.yml | 2 +- .github/workflows/packaging/deb/preinst | 4 +- .github/workflows/packaging/rpm/spec | 8 +-- .github/workflows/release.yml | 5 +- CLAUDE.md | 16 +++++ copilot-instructions.md | 17 +++++ src/controllers/Args.py | 10 +++ src/controllers/Package/Dnf.py | 66 ++++++++----------- version | 2 +- 26 files changed, 280 insertions(+), 78 deletions(-) create mode 100644 .github/workflows/install-and-test-on-fedora42.yml create mode 100644 .github/workflows/install-and-test-on-fedora43.yml create mode 100644 .github/workflows/install-and-test-on-fedora44.yml create mode 100644 CLAUDE.md create mode 100644 copilot-instructions.md diff --git a/.github/scripts/run-tests.sh b/.github/scripts/run-tests.sh index 47074090..f3f89be6 100755 --- a/.github/scripts/run-tests.sh +++ b/.github/scripts/run-tests.sh @@ -17,7 +17,25 @@ set -e LINUPDATE_CMD="${LINUPDATE_CMD:-python3 /opt/linupdate/linupdate.py}" -LINUPDATE_PROFILE="${LINUPDATE_PROFILE:ci-default}" +LINUPDATE_PROFILE="${LINUPDATE_PROFILE:-ci-default}" + +# Get OS family (either "debian" or "rhel") +OS_FAMILY="" +if [ -f /etc/os-release ]; then + . /etc/os-release + case "$ID" in + ubuntu|debian) + OS_FAMILY="debian" + ;; + centos|rocky|almalinux|fedora) + OS_FAMILY="rhel" + ;; + *) + echo "Unsupported OS: $ID" + exit 1 + ;; + esac +fi # Wrapper that runs linupdate using the configured command (allowing a sudo # prefix). Word-splitting on LINUPDATE_CMD is intentional here. @@ -35,6 +53,16 @@ run_test() { echo "::endgroup::" } +install_cowsay() { + if [ "$OS_FAMILY" = "debian" ]; then + apt-get install -y cowsay + elif [ "$OS_FAMILY" = "rhel" ]; then + dnf install -y cowsay + fi +} + +run_test "install cowsay for testing purposes" install_cowsay + run_test "print help" \ linupdate --help diff --git a/.github/workflows/build-and-test-deb.yml b/.github/workflows/build-and-test-deb.yml index 422a0e9e..ad52616d 100644 --- a/.github/workflows/build-and-test-deb.yml +++ b/.github/workflows/build-and-test-deb.yml @@ -110,13 +110,14 @@ jobs: # install-debian-10: # Try to install package on Debian 11 - install-debian-11: - name: Install and test on Debian 11 - needs: - - build-deb - - upload - uses: ./.github/workflows/install-and-test-on-debian11.yml - secrets: inherit + # EOL: fails on packages update test + # install-debian-11: + # name: Install and test on Debian 11 + # needs: + # - build-deb + # - upload + # uses: ./.github/workflows/install-and-test-on-debian11.yml + # secrets: inherit # Try to install package on Debian 12 install-debian-12: diff --git a/.github/workflows/build-and-test-rpm.yml b/.github/workflows/build-and-test-rpm.yml index 926d1852..a5e9c4ec 100644 --- a/.github/workflows/build-and-test-rpm.yml +++ b/.github/workflows/build-and-test-rpm.yml @@ -146,13 +146,40 @@ jobs: secrets: inherit # Fedora 41 - # test-fedora41: - # name: Install and test on Fedora 41 - # needs: - # - build-rpm - # - upload - # uses: ./.github/workflows/install-and-test-on-fedora41.yml - # secrets: inherit + test-fedora41: + name: Install and test on Fedora 41 + needs: + - build-rpm + - upload + uses: ./.github/workflows/install-and-test-on-fedora41.yml + secrets: inherit + + # Fedora 42 + test-fedora42: + name: Install and test on Fedora 42 + needs: + - build-rpm + - upload + uses: ./.github/workflows/install-and-test-on-fedora42.yml + secrets: inherit + + # Fedora 43 + test-fedora43: + name: Install and test on Fedora 43 + needs: + - build-rpm + - upload + uses: ./.github/workflows/install-and-test-on-fedora43.yml + secrets: inherit + + # Fedora 44 + test-fedora44: + name: Install and test on Fedora 44 + needs: + - build-rpm + - upload + uses: ./.github/workflows/install-and-test-on-fedora44.yml + secrets: inherit # Rocky Linux test-rockylinux9: diff --git a/.github/workflows/install-and-test-on-almalinux10.yml b/.github/workflows/install-and-test-on-almalinux10.yml index b2a8afac..285519b3 100644 --- a/.github/workflows/install-and-test-on-almalinux10.yml +++ b/.github/workflows/install-and-test-on-almalinux10.yml @@ -4,7 +4,7 @@ on: jobs: # Try to install package on Alma Linux 10 - install-almalinux10: + install-test-almalinux10: runs-on: ubuntu-latest container: image: almalinux:10 diff --git a/.github/workflows/install-and-test-on-almalinux9.yml b/.github/workflows/install-and-test-on-almalinux9.yml index ff5b8843..09ca7672 100644 --- a/.github/workflows/install-and-test-on-almalinux9.yml +++ b/.github/workflows/install-and-test-on-almalinux9.yml @@ -4,7 +4,7 @@ on: jobs: # Try to install package on Alma Linux 9 - install-almalinux9: + install-test-almalinux9: runs-on: ubuntu-latest container: image: almalinux:9 diff --git a/.github/workflows/install-and-test-on-centos8.yml b/.github/workflows/install-and-test-on-centos8.yml index 6e0b5ef2..3e42d990 100644 --- a/.github/workflows/install-and-test-on-centos8.yml +++ b/.github/workflows/install-and-test-on-centos8.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-centos8: + install-test-centos8: runs-on: ubuntu-latest container: image: centos:8 diff --git a/.github/workflows/install-and-test-on-debian11.yml b/.github/workflows/install-and-test-on-debian11.yml index a7da17cc..6b7fe94f 100644 --- a/.github/workflows/install-and-test-on-debian11.yml +++ b/.github/workflows/install-and-test-on-debian11.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-debian-11: + install-test-debian-11: runs-on: ubuntu-latest container: image: debian:11 diff --git a/.github/workflows/install-and-test-on-debian12.yml b/.github/workflows/install-and-test-on-debian12.yml index d5c4455a..181dca98 100644 --- a/.github/workflows/install-and-test-on-debian12.yml +++ b/.github/workflows/install-and-test-on-debian12.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-debian-12: + install-test-debian-12: runs-on: ubuntu-latest container: # Intentionally using an old image to have a list of packages to update diff --git a/.github/workflows/install-and-test-on-debian13.yml b/.github/workflows/install-and-test-on-debian13.yml index 99ba51b0..b883a8df 100644 --- a/.github/workflows/install-and-test-on-debian13.yml +++ b/.github/workflows/install-and-test-on-debian13.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-debian-13: + install-test-debian-13: runs-on: ubuntu-latest container: image: debian:13 diff --git a/.github/workflows/install-and-test-on-fedora40.yml b/.github/workflows/install-and-test-on-fedora40.yml index c5fe2aa7..76316795 100644 --- a/.github/workflows/install-and-test-on-fedora40.yml +++ b/.github/workflows/install-and-test-on-fedora40.yml @@ -4,7 +4,7 @@ on: jobs: # Try to install package on Fedora 40 - install-fedora40: + install-test-fedora40: runs-on: ubuntu-latest container: image: fedora:40 @@ -16,9 +16,6 @@ jobs: - name: Get linupdate version run: echo "VERSION=$(cat ${GITHUB_WORKSPACE}/version)" >> $GITHUB_ENV - # - name: Enable CRB repository (required to install python3-pygments for python3-rich) - # run: dnf config-manager --set-enabled crb - - name: Update system run: dnf update -y diff --git a/.github/workflows/install-and-test-on-fedora41.yml b/.github/workflows/install-and-test-on-fedora41.yml index 5a018a6e..1a9a6742 100644 --- a/.github/workflows/install-and-test-on-fedora41.yml +++ b/.github/workflows/install-and-test-on-fedora41.yml @@ -4,7 +4,7 @@ on: jobs: # Try to install package on Fedora 41 - install-fedora41: + install-test-fedora41: runs-on: ubuntu-latest container: image: fedora:41 @@ -16,9 +16,6 @@ jobs: - name: Get linupdate version run: echo "VERSION=$(cat ${GITHUB_WORKSPACE}/version)" >> $GITHUB_ENV - # - name: Enable CRB repository (required to install python3-pygments for python3-rich) - # run: dnf config-manager --set-enabled crb - - name: Update system run: dnf update -y diff --git a/.github/workflows/install-and-test-on-fedora42.yml b/.github/workflows/install-and-test-on-fedora42.yml new file mode 100644 index 00000000..4c694e9a --- /dev/null +++ b/.github/workflows/install-and-test-on-fedora42.yml @@ -0,0 +1,38 @@ +# Try to install package on Fedora 42 and run some basic commands to check if it's working +on: + workflow_call: + +jobs: + # Try to install package on Fedora 42 + install-test-fedora42: + runs-on: ubuntu-latest + container: + image: fedora:42 + options: --user root + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Get linupdate version + run: echo "VERSION=$(cat ${GITHUB_WORKSPACE}/version)" >> $GITHUB_ENV + + - name: Update system + run: dnf update -y + + # Download builded rpm package artifact + - name: Download artifact + uses: actions/download-artifact@v8 + with: + name: linupdate-test-build-${{ env.VERSION }}.noarch.rpm + + - name: Install package + run: dnf --nogpgcheck install -y ./linupdate-test-build-${{ env.VERSION }}.noarch.rpm + + # Run common test suite (shared across all distributions) + - name: Run test suite + env: + REPOSITORY_TEST_URL: ${{ secrets.REPOSITORY_TEST_URL }} + REPOSITORY_TEST_TOKEN: ${{ secrets.REPOSITORY_TEST_TOKEN }} + REPOS_CONFIG_DIR: /etc/yum.repos.d + LINUPDATE_PROFILE: linupdate-ci-rhel-systems + run: bash ${GITHUB_WORKSPACE}/.github/scripts/run-tests.sh diff --git a/.github/workflows/install-and-test-on-fedora43.yml b/.github/workflows/install-and-test-on-fedora43.yml new file mode 100644 index 00000000..10eca5b2 --- /dev/null +++ b/.github/workflows/install-and-test-on-fedora43.yml @@ -0,0 +1,38 @@ +# Try to install package on Fedora 43 and run some basic commands to check if it's working +on: + workflow_call: + +jobs: + # Try to install package on Fedora 43 + install-test-fedora43: + runs-on: ubuntu-latest + container: + image: fedora:43 + options: --user root + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Get linupdate version + run: echo "VERSION=$(cat ${GITHUB_WORKSPACE}/version)" >> $GITHUB_ENV + + - name: Update system + run: dnf update -y + + # Download builded rpm package artifact + - name: Download artifact + uses: actions/download-artifact@v8 + with: + name: linupdate-test-build-${{ env.VERSION }}.noarch.rpm + + - name: Install package + run: dnf --nogpgcheck install -y ./linupdate-test-build-${{ env.VERSION }}.noarch.rpm + + # Run common test suite (shared across all distributions) + - name: Run test suite + env: + REPOSITORY_TEST_URL: ${{ secrets.REPOSITORY_TEST_URL }} + REPOSITORY_TEST_TOKEN: ${{ secrets.REPOSITORY_TEST_TOKEN }} + REPOS_CONFIG_DIR: /etc/yum.repos.d + LINUPDATE_PROFILE: linupdate-ci-rhel-systems + run: bash ${GITHUB_WORKSPACE}/.github/scripts/run-tests.sh diff --git a/.github/workflows/install-and-test-on-fedora44.yml b/.github/workflows/install-and-test-on-fedora44.yml new file mode 100644 index 00000000..a20379d2 --- /dev/null +++ b/.github/workflows/install-and-test-on-fedora44.yml @@ -0,0 +1,38 @@ +# Try to install package on Fedora 44 and run some basic commands to check if it's working +on: + workflow_call: + +jobs: + # Try to install package on Fedora 44 + install-test-fedora44: + runs-on: ubuntu-latest + container: + image: fedora:44 + options: --user root + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Get linupdate version + run: echo "VERSION=$(cat ${GITHUB_WORKSPACE}/version)" >> $GITHUB_ENV + + - name: Update system + run: dnf update -y + + # Download builded rpm package artifact + - name: Download artifact + uses: actions/download-artifact@v8 + with: + name: linupdate-test-build-${{ env.VERSION }}.noarch.rpm + + - name: Install package + run: dnf --nogpgcheck install -y ./linupdate-test-build-${{ env.VERSION }}.noarch.rpm + + # Run common test suite (shared across all distributions) + - name: Run test suite + env: + REPOSITORY_TEST_URL: ${{ secrets.REPOSITORY_TEST_URL }} + REPOSITORY_TEST_TOKEN: ${{ secrets.REPOSITORY_TEST_TOKEN }} + REPOS_CONFIG_DIR: /etc/yum.repos.d + LINUPDATE_PROFILE: linupdate-ci-rhel-systems + run: bash ${GITHUB_WORKSPACE}/.github/scripts/run-tests.sh diff --git a/.github/workflows/install-and-test-on-rockylinux9.yml b/.github/workflows/install-and-test-on-rockylinux9.yml index aeb46d13..88109fa0 100644 --- a/.github/workflows/install-and-test-on-rockylinux9.yml +++ b/.github/workflows/install-and-test-on-rockylinux9.yml @@ -4,7 +4,7 @@ on: jobs: # Try to install package on Rocky Linux 9 - install-rockylinux9: + install-test-rockylinux9: runs-on: ubuntu-latest container: image: rockylinux/rockylinux:9 diff --git a/.github/workflows/install-and-test-on-ubuntu-2204.yml b/.github/workflows/install-and-test-on-ubuntu-2204.yml index 4d900b22..8334218d 100644 --- a/.github/workflows/install-and-test-on-ubuntu-2204.yml +++ b/.github/workflows/install-and-test-on-ubuntu-2204.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-ubuntu-2204: + install-test-ubuntu-2204: runs-on: ubuntu-latest container: image: ubuntu:22.04 diff --git a/.github/workflows/install-and-test-on-ubuntu-2404.yml b/.github/workflows/install-and-test-on-ubuntu-2404.yml index e1904b83..d831e6f0 100644 --- a/.github/workflows/install-and-test-on-ubuntu-2404.yml +++ b/.github/workflows/install-and-test-on-ubuntu-2404.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-ubuntu-2404: + install-test-ubuntu-2404: runs-on: ubuntu-latest container: image: ubuntu:24.04 diff --git a/.github/workflows/install-and-test-on-ubuntu-2604.yml b/.github/workflows/install-and-test-on-ubuntu-2604.yml index e0e6226a..78cf4ccf 100644 --- a/.github/workflows/install-and-test-on-ubuntu-2604.yml +++ b/.github/workflows/install-and-test-on-ubuntu-2604.yml @@ -3,7 +3,7 @@ on: workflow_call: jobs: - install-ubuntu-2604: + install-test-ubuntu-2604: runs-on: ubuntu-latest container: image: ubuntu:26.04 diff --git a/.github/workflows/packaging/deb/preinst b/.github/workflows/packaging/deb/preinst index d712bd7e..d038279b 100644 --- a/.github/workflows/packaging/deb/preinst +++ b/.github/workflows/packaging/deb/preinst @@ -11,8 +11,8 @@ fi # Delete service symlink if exists rm -f /etc/systemd/system/linupdate.service -# Only if systemd is installed (not the case on github runners) -if [ -f "/usr/bin/systemctl" ];then +# Only if systemd is installed and actually running as init (not the case on github runners) +if [ -f "/usr/bin/systemctl" ] && [ -d "/run/systemd/system" ];then # Stop service if started if /usr/bin/systemctl is-active --quiet linupdate;then # Do not stop if there is a /tmp/linupdate.restart-needed file, the service will restart itself diff --git a/.github/workflows/packaging/rpm/spec b/.github/workflows/packaging/rpm/spec index 6e36739e..57b1dd90 100644 --- a/.github/workflows/packaging/rpm/spec +++ b/.github/workflows/packaging/rpm/spec @@ -46,8 +46,8 @@ fi # Delete service symlink if exists rm -f /etc/systemd/system/linupdate.service -# Only if systemd is installed (not the case on github runners) -if [ -f "/usr/bin/systemctl" ];then +# Only if systemd is installed and actually running as init (not the case on github runners) +if [ -f "/usr/bin/systemctl" ] && [ -d "/run/systemd/system" ];then # Stop service if started if /usr/bin/systemctl is-active --quiet linupdate;then # Do not stop if there is a /tmp/linupdate.restart-needed file, the service will restart itself @@ -94,8 +94,8 @@ ln -sf /opt/linupdate/linupdate.py /usr/bin/linupdate chmod 750 /etc/linupdate chmod 750 /opt/linupdate -# Only if systemd is installed (not the case on github runners) -if [ -f "/usr/bin/systemctl" ];then +# Only if systemd is installed and actually running as init (not the case on github runners) +if [ -f "/usr/bin/systemctl" ] && [ -d "/run/systemd/system" ];then # Copy systemd unit file if not exists if [ ! -f "/lib/systemd/system/linupdate.service" ];then cp /opt/linupdate/templates/linupdate.systemd.template /lib/systemd/system/linupdate.service diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f34e2390..eb705c99 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -182,7 +182,8 @@ jobs: release_name: ${{ env.VERSION }} body: | **Changes**: - - Various UI improvements and syntax errors fixed + - Fixed error while parsing dnf history events on Fedora 41+ + - Added tests for Fedora 41, 42, 43 and 44 draft: false prerelease: false @@ -205,6 +206,7 @@ jobs: curl --fail-with-body -L --post301 -s -q -X POST -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -F "files=@$HOME/assets/linupdate_${{ env.VERSION }}_all.deb" ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/73/upload curl --fail-with-body -L --post301 -s -q -X POST -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -F "files=@$HOME/assets/linupdate_${{ env.VERSION }}_all.deb" ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/925/upload curl --fail-with-body -L --post301 -s -q -X POST -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -F "files=@$HOME/assets/linupdate_${{ env.VERSION }}_all.deb" ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/937/upload + curl --fail-with-body -L --post301 -s -q -X POST -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -F "files=@$HOME/assets/linupdate-${{ env.VERSION }}.noarch.rpm" ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/475/upload curl --fail-with-body -L --post301 -s -q -X POST -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -F "files=@$HOME/assets/linupdate-${{ env.VERSION }}.noarch.rpm" ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/476/upload curl --fail-with-body -L --post301 -s -q -X POST -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -F "files=@$HOME/assets/linupdate-${{ env.VERSION }}.noarch.rpm" ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/541/upload @@ -217,5 +219,6 @@ jobs: curl --fail-with-body -X PUT -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -d '{"gpgSign":"true"}' ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/73/rebuild curl --fail-with-body -X PUT -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -d '{"gpgSign":"true"}' ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/925/rebuild curl --fail-with-body -X PUT -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -d '{"gpgSign":"true"}' ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/937/rebuild + curl --fail-with-body -X PUT -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -d '{"gpgSign":"true"}' ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/475/rebuild curl --fail-with-body -X PUT -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -d '{"gpgSign":"true"}' ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/476/rebuild curl --fail-with-body -X PUT -H "Authorization: Bearer ${{ secrets.REPOSITORY_UPLOAD_TOKEN }}" -d '{"gpgSign":"true"}' ${{ secrets.REPOSITORY_UPLOAD_URL }}/api/v2/snapshot/541/rebuild diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..ca6f6d29 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,16 @@ +## Approach +- Read existing files before writing. Don't re-read unless changed. +- Thorough in reasoning, concise in output. +- Skip files over 100KB unless required. +- No sycophantic openers or closing fluff. +- No emojis or em-dashes. +- Do not guess APIs, versions, flags, commit SHAs, or package names. Verify by reading code or docs before asserting. + +## Token efficiency +- Read only files directly needed. Ask before broad scans. +- Prefer reading specific functions/sections over full files. +- Do not restate context already established in conversation. +- Keep plans to 3-5 steps unless complexity requires more. +- For edits, show only the changed section, not full file. +- Default to brief answers. Expand only if asked. +- Reuse information already gathered unless files changed. \ No newline at end of file diff --git a/copilot-instructions.md b/copilot-instructions.md new file mode 100644 index 00000000..3e4387f9 --- /dev/null +++ b/copilot-instructions.md @@ -0,0 +1,17 @@ +## Instructions for GitHub Copilot + +### Code generation +- Read only files directly relevant to the task +- Prefer minimal, targeted changes +- Do not include unchanged code in responses +- Keep explanations brief unless detail is requested + +### Token efficiency +- Ask before scanning many files +- Reuse context from earlier in conversation +- Default to short answers +- Avoid restating what was already discussed + +### Verification +- Do not guess package versions, API signatures, or CLI flags +- Check project files or docs before asserting \ No newline at end of file diff --git a/src/controllers/Args.py b/src/controllers/Args.py index 9f97b8b1..bbaeda09 100644 --- a/src/controllers/Args.py +++ b/src/controllers/Args.py @@ -897,6 +897,16 @@ def help(self): 'option': 'MODULE', 'description': 'Disable a module' }, + { + 'args': [ + '--mod-configure', + '--mod-exec', + '-mc', + '-me' + ], + 'option': 'MODULE [ARGS]', + 'description': 'Configure/execute a module with the specified arguments' + }, { 'title': 'Service tuning' }, diff --git a/src/controllers/Package/Dnf.py b/src/controllers/Package/Dnf.py index 6d809cf5..3ae23d29 100644 --- a/src/controllers/Package/Dnf.py +++ b/src/controllers/Package/Dnf.py @@ -40,7 +40,7 @@ def get_security_update_package_names(self): try: result = subprocess.run( - [self.dnf_command + ' repoquery --upgrades --latest-limit 1 --security -a -q --qf="%{name}"'], + [self.dnf_command + ' repoquery --upgrades --latest-limit 1 --security -q --qf="%{name}"'], stdout = subprocess.PIPE, stderr = subprocess.PIPE, universal_newlines = True, @@ -95,7 +95,7 @@ def get_source_repository(self, package, version): try: result = subprocess.run( - [self.dnf_command + ' repoquery --upgrades --latest-limit 1 -q -a --qf="%{repoid}" ' + package + '-' + version], + [self.dnf_command + ' repoquery --upgrades --latest-limit 1 -q --qf="%{repoid}" ' + package + '-' + version], stdout = subprocess.PIPE, # subprocess.PIPE & subprocess.PIPE are alias of 'capture_output = True' stderr = subprocess.PIPE, universal_newlines = True, # Alias of 'text = True' @@ -149,7 +149,7 @@ def get_installed_packages(self): # Get list of installed packages # e.g. dnf repoquery -q -a --qf="%{name} %{version}-%{release}.%{arch} %{repoid}" --upgrades result = subprocess.run( - [self.dnf_command + ' repoquery --installed -a --qf="%{name} %{epoch}:%{version}-%{release}.%{arch}"'], + [self.dnf_command + ' repoquery --installed --qf="%{name} %{epoch}:%{version}-%{release}.%{arch}"'], stdout = subprocess.PIPE, # subprocess.PIPE & subprocess.PIPE are alias of 'capture_output = True' stderr = subprocess.PIPE, universal_newlines = True, # Alias of 'text = True' @@ -207,7 +207,7 @@ def get_available_packages(self, useless_dist_upgrade: bool = False): # Get list of packages to update sorted by name # e.g. dnf repoquery --upgrades --latest-limit 1 -q -a --qf="%{name} %{version}-%{release}.%{arch} %{repoid}" result = subprocess.run( - [self.dnf_command + ' repoquery --upgrades --latest-limit 1 -a -q --qf="%{name} %{version}-%{release}.%{arch} %{repoid}"'], + [self.dnf_command + ' repoquery --upgrades --latest-limit 1 -q --qf="%{name} %{version}-%{release}.%{arch} %{repoid}"'], stdout = subprocess.PIPE, # subprocess.PIPE & subprocess.PIPE are alias of 'capture_output = True' stderr = subprocess.PIPE, universal_newlines = True, # Alias of 'text = True' @@ -628,16 +628,13 @@ def parse_history(self, ids: list, entries_limit: int): # ** means that the transaction did not complete successfully event = event.replace('**', '') - # Skip if cannot retrieve event date and time + # Raise error if cannot retrieve event date and time if not re.search(r'^Begin time(.+)', event, re.MULTILINE): raise Exception('error parsing dnf event id #' + id + ': could not retrieve event date and time') - # Skip if cannot retrieve command line - if not re.search(r'^Command Line(.+)', event, re.MULTILINE): - raise Exception('error parsing dnf event id #' + id + ': could not retrieve command line') - - # Skip if cannot retrieve packages altered - if not re.search(r'Packages Altered.*', event, re.DOTALL): + # Raise error if cannot retrieve packages altered + # Note: dnf5 (Fedora 41+) writes 'Packages altered' instead of dnf4's 'Packages Altered' + if not re.search(r'Packages Altered.*', event, re.DOTALL | re.IGNORECASE): raise Exception('error parsing dnf event id #' + id + ': could not find any packages altered in the event') # Retrieve event date and time @@ -645,14 +642,15 @@ def parse_history(self, ids: list, entries_limit: int): # Remove extra spaces and 'Begin time : ' string date_time = str(date_time.replace(' ', '').replace('Begin time : ', '')) - # Retrieve command line - command = re.search(r'^Command Line(.+)', event, re.MULTILINE).group(0).strip() - command = str(command.replace(' ', '').replace('Command Line :', '')).strip() - # Retrieve packages altered - packages_altered = re.search(r'Packages Altered.*', event, re.DOTALL).group(0).strip() + packages_altered = re.search(r'Packages Altered.*', event, re.DOTALL | re.IGNORECASE).group(0).strip() packages_altered = re.sub(r' +', ' ', packages_altered) + # Retrieve command line, leave empty if not found (not always present, e.g. history triggered outside a command) + # Note: dnf5 (Fedora 41+) has no 'Command Line' field, it is replaced by 'Description' + command_match = re.search(r'^Command Line(.+)', event, re.MULTILINE) or re.search(r'^Description(.+)', event, re.MULTILINE) + command = command_match.group(0).strip().replace(' ', '').replace('Command Line :', '').replace('Description:', '').strip() if command_match else '' + # Parsing and formatting # Convert date to %Y-%m-%d format @@ -662,7 +660,8 @@ def parse_history(self, ids: list, entries_limit: int): # Skip if there is no lines containing 'Install', 'Dep-Install', 'Upgraded', 'Upgrade', 'Obsoleting', 'Erase', 'Removed', 'Downgrade', 'Reinstall' # Note: on CentOS7, it was 'Update' and 'Updated' instead of 'Upgrade' and 'Upgraded' - if not re.search(r'^ +(Install|Dep-Install|Upgraded|Upgrade|Obsoleting|Erase|Removed|Downgrade|Reinstall) .*', packages_altered, re.MULTILINE): + # Note: dnf5 (Fedora 41+) uses present tense action words, e.g. 'Remove' instead of dnf4's 'Removed' + if not re.search(r'^ +(Install|Dep-Install|Upgraded|Upgrade|Obsoleting|Erase|Removed?|Downgraded?|Reinstalled?) .*', packages_altered, re.MULTILINE): raise Exception('error parsing dnf event id #' + id + ': could not find any operation lines in the event') # For each lines of packages_altered @@ -688,33 +687,24 @@ def parse_history(self, ids: list, entries_limit: int): package_and_version = re.search(r'^ +Upgrade (.+)', line).group(0).strip().replace('Upgrade ', '') operation = 'upgrade' - # If line starts with Update - # elif re.search(r'^ +Update .*', line): - # package_and_version = re.search(r'^ +Update (.+)', line).group(0).strip().replace('Update ', '') - # If line starts with Obsoleting elif re.search(r'^ +Obsoleting .*', line): package_and_version = re.search(r'^ +Obsoleting (.+)', line).group(0).strip().replace('Obsoleting ', '') operation = 'obsoleting' - # If line starts with Erase - # elif re.search(r'^ +Erase .*', line): - # package_and_version = re.search(r'^ +Erase (.+)', line).group(0).strip().replace('Erase ', '') - # operation = 'erase' - - # If line starts with Removed - elif re.search(r'^ +Removed .*', line): - package_and_version = re.search(r'^ +Removed (.+)', line).group(0).strip().replace('Removed ', '') + # If line starts with Removed (dnf4) or Remove (dnf5) + elif re.search(r'^ +Removed? .*', line): + package_and_version = re.sub(r'^ +Removed? ', '', line).strip() operation = 'remove' - # If line starts with Downgrade - elif re.search(r'^ +Downgrade .*', line): - package_and_version = re.search(r'^ +Downgrade (.+)', line).group(0).strip().replace('Downgrade ', '') + # If line starts with Downgrade or Downgraded + elif re.search(r'^ +Downgraded? .*', line): + package_and_version = re.sub(r'^ +Downgraded? ', '', line).strip() operation = 'downgrade' - # If line starts with Reinstall - elif re.search(r'^ +Reinstall .*', line): - package_and_version = re.search(r'^ +Reinstall (.+)', line).group(0).strip().replace('Reinstall ', '') + # If line starts with Reinstall or Reinstalled + elif re.search(r'^ +Reinstalled? .*', line): + package_and_version = re.sub(r'^ +Reinstalled? ', '', line).strip() operation = 'reinstall' else: @@ -735,9 +725,11 @@ def parse_history(self, ids: list, entries_limit: int): package_name = re.sub(r'-[0-9].*', '', package_and_version).strip() package_version_and_repository = re.sub(r'^-', '', package_and_version.replace(package_name, '')).strip() - # Retrieve repository and package version + # Retrieve package version and repository + # Note: dnf5 (Fedora 41+) adds a 'Reason' column (User/Dependency) between version and repository, so + # repository is taken as the last field instead of the second one to stay compatible with dnf4's 2-field format package_version = package_version_and_repository.split()[0].strip() - repository = package_version_and_repository.split()[1].strip() + repository = package_version_and_repository.split()[-1].strip() # Raise exception if package_name or package_version is empty if package_name == '': diff --git a/version b/version index 0caba260..3e1a3c34 100644 --- a/version +++ b/version @@ -1 +1 @@ -3.17.1 \ No newline at end of file +3.17.2 \ No newline at end of file