Subject: Re: [bug#45104] pull: Add a "with-substitutes" option.

From: Ludovic Courtès <[email-masked]>
Date: Mon, 14 Dec 2020 12:05:54 +0100

Hi!

Christopher Baines <[email-masked]> skribis:

> My first thought is that the option doesn't really do what it says it
> will do. The option is named --with-substitutes, but that actually means
> something like "with successful build on ci.guix.gnu.org". This could
> cause confusion if you're not fetching substitutes from ci.guix.gnu.org,
> and it starts building things, or perhaps if you're fetching substitutes
> from two servers, one of which is ci.guix.gnu.org which doesn't have a
> substitute, but the other server does, this option would fetch an older
> revision than what's truly available.
>
> Maybe part of what I've said above is incorrect if a users substitute
> URLs are used, but there also seems to be an assuption that something
> which provides substitutes provides a Cuirass compatible API, which
> isn't always the case.
>
> One more thought on this is that it's probably important to convey that
> this doesn't pick a revision where substitutes will be available. I
> think this is something some users would be eager to assume, and then be
> confused when it doesn't work.

Agreed on these points.

Another option would be to leave it up to users to customize their
channel file to run pretty much the code you posted, like:

--8<---------------cut here---------------start------------->8---
(use-modules (guix ci)
             (srfi srfi-1)
             (ice-9 match))

(define (latest-commit-successfully-built)
  "Return the latest commit for which substitutes are (potentially)
available."
  (let* ((evaluations (filter (lambda (evaluation)
                                (and (evaluation-complete? evaluation)
                                     (string=? "guix-modular-master"
                                               (evaluation-spec
                                                evaluation))))
                              (latest-evaluations "https://ci.guix.gnu.org"))))
    (any (lambda (evaluation)
           (match (evaluation-checkouts evaluation)
             ((checkout)
              (checkout-commit checkout))
             (_ #f)))
         evaluations)))

;; Pull the latest commit fully built on berlin.guixsd.org.
(list (channel
       (name 'guix)
       (url "https://git.savannah.gnu.org/git/guix.git")
       (commit (pk 'commit (latest-commit-successfully-built)))))
--8<---------------cut here---------------end--------------->8---

We don’t want people to copy/paste all this, so we could instead provide
and document a procedure that takes a channel and substitute URL and
returns a channel, like:

  (channel-with-substitutes-available
    (channel (name 'guix) …)
    "https://ci.guix.gnu.org")

and optionally with a manifest or a list of packages that should be
available as substitutes:

  (channel-with-substitutes-available
    (channel (name 'guix) …)
    "https://ci.guix.gnu.org"
    (specifications->manifest '("emacs" "guile")))

WDYT?

It does mean that we’re asking users to do extra work.  Perhaps there
could still be a command-line option that would call
‘channel-with-substitutes-available’ for you, but at least it would take
an explicit URL and clarify what Chris mentioned?

BTW, doing all this is safer today because ‘guix pull’ will detect and
prevent downgrades.  Though an attacker who manages to break into
ci.guix.gnu.org could cause all the users of
‘channel-with-substitutes-available’ to no longer receive updates or to
receive them more slowly than they appear in Git simply by making CI
even slower than it currently is.

Thoughts?

Ludo’.