diff --git a/datalad_debian/__init__.py b/datalad_debian/__init__.py index 0622faa..b661715 100644 --- a/datalad_debian/__init__.py +++ b/datalad_debian/__init__.py @@ -27,6 +27,12 @@ 'deb-configure-builder', 'deb_configure_builder', ), + ( + 'datalad_debian.bootstrap_builder', + 'BootstrapBuilder', + 'deb-bootstrap-builder', + 'deb_bootstrap_builder', + ), ] ) diff --git a/datalad_debian/bootstrap_builder.py b/datalad_debian/bootstrap_builder.py new file mode 100644 index 0000000..4083e1b --- /dev/null +++ b/datalad_debian/bootstrap_builder.py @@ -0,0 +1,106 @@ +import logging +from pathlib import Path + +from datalad.distribution.dataset import ( + EnsureDataset, + datasetmethod, + require_dataset, +) +from datalad.interface.base import ( + Interface, + build_doc, +) +from datalad.interface.utils import ( + eval_results, +) +from datalad.runner import ( + Runner, + StdOutCapture, +) +from datalad.support.constraints import ( + EnsureNone, +) +from datalad.support.param import Parameter + +lgr = logging.getLogger('datalad.debian.bootstrap_builder') + + +@build_doc +class BootstrapBuilder(Interface): + """Bootstrap a build environment + """ + _params_ = dict( + dataset=Parameter( + args=("-d", "--dataset"), + doc="""specify a distribution dataset to add the package to""", + constraints=EnsureDataset() | EnsureNone()), + ) + + _examples_ = [] + + @staticmethod + @datasetmethod(name='deb_bootstrap_builder') + @eval_results + def __call__(*, dataset=None): + # TODO this could later by promoted to an option to support more than + # singularity + cfgtype = 'singularity' + + builder_ds = require_dataset(dataset) + + # figure out which architecture we will be building for + binarch = Runner().run( + ['dpkg-architecture', '-q', 'DEB_BUILD_ARCH'], + protocol=StdOutCapture)['stdout'].strip() + + buildenv_name = f"{cfgtype}-{binarch}" + + recipe = None + for p in (builder_ds.pathobj / 'recipes' / f"{cfgtype}-{binarch}", + builder_ds.pathobj / 'recipes' / f"{cfgtype}-any"): + if p.exists(): + recipe = p + break + if recipe is None: + raise RuntimeError( + "Cannot locate build environment recipe for " + f"{cfgtype}({binarch})") + + # TODO allow for other types of environments + buildenv = Path('envs', f"{buildenv_name}.sif") + + yield from builder_ds.run( + # TODO allow for other means of privilege escalation + # TODO allow for other means to bootstrap + "sudo singularity build {outputs} {inputs}", + inputs=[str(recipe.relative_to(builder_ds.pathobj))], + outputs=[str(buildenv)], + result_renderer='disabled', + return_type='generator', + # give control flow to caller + on_failure='ignore', + ) + + buildenv_callfmt = \ + 'singularity run ' \ + '--bind builder/cache/var/lib/apt:/var/lib/apt,builder/cache/var/cache/apt:/var/cache/apt,.:/pkg ' \ + '--pwd /pkg ' \ + '--fakeroot ' \ + '--cleanenv ' \ + '--containall ' \ + '--writable ' \ + '--no-home ' \ + '{img} {cmd}' + + # this is a fresh addition of the build env + yield from builder_ds.containers_add( + buildenv_name, + image=str(buildenv), + call_fmt=buildenv_callfmt, + # tolerate an already existing record + update=True, + result_renderer='disabled', + return_type='generator', + # give control flow to caller + on_failure='ignore', + ) diff --git a/docs/source/index.rst b/docs/source/index.rst index e5a0ed3..acc2db8 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -13,8 +13,9 @@ High-level API commands :toctree: generated deb_new_distribution - deb_new_package deb_configure_builder + deb_bootstrap_builder + deb_new_package Command line reference @@ -24,8 +25,9 @@ Command line reference :maxdepth: 1 generated/man/datalad-deb-new-distribution - generated/man/datalad-deb-new-package generated/man/datalad-deb-configure-builder + generated/man/datalad-deb-bootstrap-builder + generated/man/datalad-deb-new-package Indices and tables diff --git a/setup.cfg b/setup.cfg index 2391317..c90b199 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,9 +12,10 @@ classifiers = Programming Language :: Python :: 3 [options] -python_requires = >= 3.6 +python_requires = >= 3.7 install_requires = - datalad >= 0.14.0rc1 + datalad >= 0.16 + datalad-container packages = find: include_package_data = True