Hi Guix,

I'd like to raise concerns about Guix's current approach to software
configuration management. Configuration schemas are inherently public interfaces
of software, valid only for specific package versions. Currently, Guix separates
these interfaces from the software they originate from. We place
=define-configuration= forms directly within Guix's source code, which presents
several drawbacks:

- *Potential breakage upon package updates:* Updating a package version can
  inadvertently break Guix services that rely on it. For example, a removed run
  argument could cause the application to error upon startup.
- *Duplication of documentation:* The documentation for these records often
  duplicates information already provided with the software itself, leading to
  redundancy and potential inconsistencies.

An illustrative example is mpv, where each version can introduce changes to
dozens of configuration options and run arguments:
(see https://github.com/mpv-player/mpv/blob/master/DOCS/interface-changes.rst)

Therefore, I propose the following:

Define "binding" Guix packages that provide Scheme code encompassing:
- Configuration data structures (records, =define-configuration= forms, alists, 
etc.).
- Serializers for converting these structures into the software's native 
configuration format.
- Run arguments specifications, detailing available options and their expected 
types.
- Procedures for generating run commands based on the specified configuration.

So, for e.g. =mpv@0.40.0= we can define =mpv-guix-bindings@0.40.0= package that
depends either on =mpv= or its source:
- in the build phase generate scheme files by parsing the source code or the
  output of =mpv --list-options=
- in the =check= phase verify that no changes happened in the public
  interfaces (e.g. checksum of the input data used to generate code)

Then in Guix:
- remove existing configurations and documentation
- import configurations from binding modules, e.g. =(use-config-bindings pkg)=
  would add =pkg-guix-bindings= modules to =%load-path=
- use the bindings where necessary, e.g.:
--8<---------------cut here---------------start------------->8---
  ; generate config
  (pkg-serialize-config
   (pkg-configuration
    (option-foo? #t)))

  ; prepare run arguments
  (make-forkexec-constructor
   '(#$pkg
     #$@(pkg-run-args
         (pkg-options
          (daemon? #t)))
     #$(pkg-serialize-config cfg)))
--8<---------------cut here---------------end--------------->8---

Thoughts?

Reply via email to