Skip to content

Commit 8edfa53

Browse files
author
Hugo Lecomte
committed
Add Guix buildpack
1 parent 73ab48a commit 8edfa53

File tree

20 files changed

+186
-0
lines changed

20 files changed

+186
-0
lines changed

docs/source/config_files.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,27 @@ to produce a reproducible environment.
231231
To see an example repository visit
232232
`nix binder example <https://github.com/binder-examples/nix>`_.
233233

234+
.. _manifest.scm:
235+
236+
``manifest.scm`` - the Guix package manager
237+
===========================================
238+
239+
Specify packages to be installed by the `Guix package manager <https://guix.gnu.org/>`_.
240+
All packages specified in |manifest|_ will be installed in a container using |guix_package|_.If you do not install Jupyter explicitly, Repo2docker will no be able to start your container. In addition, you can use different `channels <https://guix.gnu.org/manual/en/html_node/Channels.html>`_ rather
241+
than the ones available by default (official channels of GNU Guix 1.3.0).
242+
You must describe such channels in a ``channels.scm`` file which will be used
243+
alongside ``manifest.scm`` with the |guix_time-machine|_ command. Furthermore, using a ``channels.scm`` file lets you `pin a specific revision <https://guix.gnu.org/manual/en/html_node/Replicating-Guix.html>`_ of Guix, allowing you to unambiguously specific the software environment to reproduce.
244+
245+
For more information about Guix please read the `manual <https://guix.gnu.org/manual/en/guix.html>`_.
246+
247+
.. |manifest| replace:: ``manifest.scm``
248+
.. _manifest: https://guix.gnu.org/manual/en/html_node/Invoking-guix-package.html#index-profile-manifesthy
249+
250+
.. |guix_package| replace:: ``guix package``
251+
.. _guix_package: https://guix.gnu.org/manual/en/html_node/Invoking-guix-package.html#Invoking-guix-package
252+
253+
.. |guix_time-machine| replace:: ``guix time-machine``
254+
.. _guix_time-machine: https://guix.gnu.org/manual/en/html_node/Invoking-guix-time_002dmachine.html
234255

235256
``Dockerfile`` - Advanced environments
236257
======================================

repo2docker/app.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
PipfileBuildPack,
3838
PythonBuildPack,
3939
RBuildPack,
40+
GuixBuildPack,
4041
)
4142
from . import contentproviders
4243
from .utils import ByteSpecification, chdir
@@ -95,6 +96,7 @@ def _default_log_level(self):
9596
JuliaProjectTomlBuildPack,
9697
JuliaRequireBuildPack,
9798
NixBuildPack,
99+
GuixBuildPack,
98100
RBuildPack,
99101
CondaBuildPack,
100102
PipfileBuildPack,

repo2docker/buildpacks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
from .legacy import LegacyBinderDockerBuildPack
99
from .r import RBuildPack
1010
from .nix import NixBuildPack
11+
from .guix import GuixBuildPack

repo2docker/buildpacks/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,3 +718,4 @@ def get_start_script(self):
718718
# the only path evaluated at container start time rather than build time
719719
return os.path.join("${REPO_DIR}", start)
720720
return None
721+
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""BuildPack for guix environments"""
2+
import os
3+
4+
from ..base import BuildPack, BaseImage
5+
6+
7+
class GuixBuildPack(BaseImage):
8+
"""A Guix Package Manager BuildPack"""
9+
10+
def get_build_env(self):
11+
""""""
12+
env = super().get_build_env() + [
13+
("GUIX_DIR", "${APP_BASE}/guix")
14+
]
15+
return env
16+
17+
def get_path(self):
18+
"""Return paths to be added to PATH environment variable"""
19+
path = super().get_path()
20+
path.insert(0, "${GUIX_DIR}/bin")
21+
return path
22+
23+
24+
25+
def get_build_scripts(self):
26+
"""
27+
Install a pinned version of Guix package manager,
28+
precised in guix-install.bash.
29+
"""
30+
return super().get_build_scripts() + [
31+
(
32+
"root",
33+
"""
34+
bash /tmp/.local/bin/guix-install.bash
35+
""",
36+
),
37+
38+
]
39+
40+
def get_build_script_files(self):
41+
42+
"""Copying guix installation script on the image"""
43+
return {
44+
"guix/guix-install.bash":
45+
"/tmp/.local/bin/guix-install.bash",
46+
}
47+
48+
def get_assemble_scripts(self):
49+
"""
50+
Launch Guix daemon with --disable-chroot to avoid the need
51+
of root privileges for the user.
52+
Make sure we never use Debian's python by error by renaming it
53+
then, as an user install packages listed in manifest.scm,
54+
use guix time-machine if channels.scm file exists.
55+
Finally set Guix environment variables.
56+
"""
57+
assemble_script ="""
58+
/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon \
59+
--build-users-group=guixbuild --disable-chroot & \
60+
su - $NB_USER -c '{}' && \
61+
echo 'GUIX_PROFILE="/var/guix/profiles/per-user/'$NB_USER'/guix-profile" ; \
62+
source "$GUIX_PROFILE/etc/profile"'>> /etc/profile.d/99-guix.sh
63+
"""
64+
65+
if os.path.exists(self.binder_path("channels.scm")):
66+
assemble_script = assemble_script.format(
67+
"guix time-machine -C " + self.binder_path("channels.scm") +
68+
" -- package -m " + self.binder_path("manifest.scm")
69+
)
70+
else:
71+
assemble_script = assemble_script.format(
72+
"guix package -m " + self.binder_path("manifest.scm")
73+
)
74+
return super().get_assemble_scripts() + [
75+
( "root",
76+
assemble_script,
77+
)
78+
]
79+
80+
def detect(self):
81+
"""Check if current repo should be built with the guix BuildPack"""
82+
return os.path.exists(self.binder_path("manifest.scm"))
83+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
# This downloads and installs a pinned version of Guix using a pinned version of the installation script.
3+
# Here is the commit associated with Guix version 1.3.0 the latest version when this script was written.
4+
set -euxo pipefail
5+
6+
GUIX_COMMIT="a0178d34f582b50e9bdbb0403943129ae5b560ff"
7+
BIN_VER="1.3.0x86_64-linux"
8+
GUIX_SHA256="bcdeaa757cd42d2c9de4791272737e9ee0d518398403955f113611f4a893380a"
9+
10+
wget "https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh?id=$GUIX_COMMIT"
11+
12+
echo "$GUIX_SHA256 guix-install.sh?id=$GUIX_COMMIT" | sha256sum -c
13+
14+
(yes || true) | BIN_VER=$BIN_VER bash guix-install.sh?id=$GUIX_COMMIT

tests/guix/binder-dir/README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
`manifest.scm` in a binder/ directory
2+
-------------------------------------
3+
4+
Check if we can find and use `manifest.scm` when it is ina `binder/` sub-directory.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(specifications->manifest
2+
'("jupyter"
3+
"hello"))

tests/guix/binder-dir/verify

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
hello

tests/guix/ignore-outside/README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
`manifest.scm` in main directory and in `binder/`
2+
-------------------------------------------------
3+
4+
Check if `manifest.scm` located in the `binder/` sub-directory is prefered to the one in the main directory.

0 commit comments

Comments
 (0)