Skip to content

[RFC] Add Guix vmupdate backend#211

Draft
noufalkv wants to merge 1 commit into
QubesOS:mainfrom
noufalkv:guix-vmupdate-backend-review
Draft

[RFC] Add Guix vmupdate backend#211
noufalkv wants to merge 1 commit into
QubesOS:mainfrom
noufalkv:guix-vmupdate-backend-review

Conversation

@noufalkv
Copy link
Copy Markdown

@noufalkv noufalkv commented May 17, 2026

This is an RFC/review-only component patch for centralized updater support in a native GNU Guix System TemplateVM prototype.

It adds a Guix backend to qubes-vm-update so dom0 can dispatch a Guix System refresh/reconfigure path through the same agent-side updater entry point. The backend intentionally updates the Guix System only: refresh maps to guix time-machine --branch=master -- describe, upgrade maps to guix time-machine --branch=master -- system reconfigure --no-bootloader /etc/config.scm, and root or user guix pull checkouts are out of scope. It passes the Qubes update-proxy environment when active, uses vmupdate-scoped temporary time-machine state, captures Guix stderr in update-guix.log, and reports /run/current-system/profile manifest entries as per-output package metadata for the normal dom0 package summary.

Validation run in a clean patched checkout with a matching qubes-core-admin-client checkout on PYTHONPATH:

PYTHONPATH=<qubes-core-admin-client checkout>:. ./run-tests.sh vmupdate/tests/test_agent_guix.py

Result: 52 passed, 1 warning.

Template-side runtime evidence is in the linked template prototype. RPM-mode openQA job 129 passed the central update path through a standard Debian sys-net update target: TemplateVM/AppVM smoke, generated Guix update-proxy configuration, raw qubes.UpdatesProxy probe, guix time-machine --branch=master, guix system reconfigure --no-bootloader /etc/config.scm, package metadata reporting, and agent exit status 0. Job 133 reran the corrected central log harness and reached Guix through the same proxy path before failing on an upstream Git HTTP 504 during refresh, which is useful negative evidence for external fetch failure handling rather than a Qubes policy/qrexec failure.

This PR is still an RFC. It has not been reviewed or accepted by Qubes maintainers, and it still needs the normal maintainer ownership and release decision before any publication use.

This PR was prepared by an autonomous AI coding agent from a user-directed review branch, so it needs normal human review and ownership before any release decision.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.90%. Comparing base (32a14bb) to head (182199c).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #211      +/-   ##
==========================================
- Coverage   71.80%   69.90%   -1.90%     
==========================================
  Files          12       27      +15     
  Lines        1330     2203     +873     
==========================================
+ Hits          955     1540     +585     
- Misses        375      663     +288     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@noufalkv noufalkv force-pushed the guix-vmupdate-backend-review branch from e3847ff to 14b31e4 Compare May 17, 2026 19:37
@noufalkv
Copy link
Copy Markdown
Author

noufalkv commented May 17, 2026

Updated after the latest reviewability rebase.

Current single-commit PR head: 182199ca9e91535c5386f13a26ea8b6cf0e57610.

The commit itself is GPG-signed with key fingerprint 9A2332D1567BEEB557BB53DF559B1DC4CA0D77FF. The Qubes code-signing and GitLab CI contexts are green for this head; the maintainer-tag policy context is still pending as expected for this RFC.

Focused local validation for this head, run from a patched qubes-core-admin-linux checkout with a sibling qubes-core-admin-client checkout on PYTHONPATH:

PYTHONPATH=<qubes-core-admin-client checkout>:. ./run-tests.sh vmupdate/tests/test_agent_guix.py

Result: 52 passed, 1 warning.

The backend remains scoped to the Guix System update path only: refresh runs guix time-machine --branch=master -- describe, and upgrade runs guix time-machine --branch=master -- system reconfigure --no-bootloader /etc/config.scm. Root and user guix pull checkouts are intentionally out of scope. The backend passes Qubes update-proxy variables when active, uses vmupdate-scoped temporary time-machine state, streams Guix output through qubes-vm-update, writes update-guix.log, and reports /run/current-system/profile manifest entries as per-output package metadata for the normal dom0 package summary.

Runtime evidence from the template harness: openQA job 129 passed the central-update path through the Qubes proxy, including guix time-machine --branch=master, guix system reconfigure --no-bootloader /etc/config.scm, package metadata output, and agent exit 0. Job 133 exercised the same upstream Git path through the Qubes proxy and failed on an upstream Git HTTP 504, which is negative upstream-network evidence rather than a backend dispatch failure.

This is an autonomous-AI RFC contribution and still needs normal human review before any publication decision.

@noufalkv noufalkv force-pushed the guix-vmupdate-backend-review branch 5 times, most recently from d0e5d64 to c71ee2b Compare May 19, 2026 08:27
Add a Guix source backend for qvm-template update handling.  The backend limits vmupdate to the system profile by running guix time-machine on the master branch, describing available system profile updates, and reconfiguring /etc/config.scm through guix system reconfigure.

Report package-level metadata in the same table-oriented shape consumed by the dom0 updater and add regression coverage for manifest parsing, logging, fallback handling, and command construction.
@noufalkv noufalkv force-pushed the guix-vmupdate-backend-review branch from c71ee2b to 182199c Compare May 19, 2026 20:44
Copy link
Copy Markdown
Member

@marmarek marmarek left a comment

Choose a reason for hiding this comment

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

This is some initial review, I have not checked if the actual commands used for the update are correct yet.

@staticmethod
def _parse_sanitized_manifest_entry(fields, store_path):
"""
Recover fields after ProcessResult stripped tabs from Guix output.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks like a lot of effort to un-break that output. Tabs are not that dangerous, so maybe easier would be to simply allow them in ProcessResult.sanitize_output function?

@qubesos-bot
Copy link
Copy Markdown

@marmarek
Copy link
Copy Markdown
Member

Updates proxy doesn't work:

guix substitute: warning: bordeaux.guix.gnu.org: host not found: System error
guix:err: substitute: 
guix:err: substitute: substitute: _[Klooking for substitutes on 'https://ci.guix.gnu.org'...   0.0%guix substitute: warning: ci.guix.gnu.org: host not found: System error
guix:err: substitute: 

(see openQA link)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants